php的一些不安全函数,php中可能会产生安全问题一些函数
php中可能會產生安全問題的一些函數
本文章適合正在學習代碼審計的朋友,或者準備學習安全的朋友,大佬就可以繞過了,寫的比較基礎。我也是一個小白,總結一下對于php函數的理解,也分享一些自己覺得好用的方法給大家,歡迎大家幫我補充,有什么好用的技巧也可以分享一下,大家共同進步。本篇有自己的理解,如果有什么不對的或者不好的地方希望大家不要噴我,但是歡迎幫我指正。最后希望大家可以關注我的專欄
1:in_array函數
in_array?:(PHP 4, PHP 5, PHP 7)
功能?:檢查數組中是否存在某個值
定義?:?bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )
可能會產生安全問題的場景:
1:對于sql語句參數的檢查,如果僅僅使用沒有true參數的in_array()函數去檢測整數類型,那么很有可能會被繞過
2:利用in_array?函數檢測文件后綴
為了便于大家的理解,下面準備幾個例子
Demo1:<?php
$xiaobao = $_POST['xiaobao'];
$dic['xiaobao_items'] = array(0,1,2,3,4,5,6);
if (in_array($xiaobao,$dic['xiaobao_items']))
{
echo 'success1';
}
else
{
echo 'false1';
}
?>
這里由于沒有對in_array的第三個參數進行設置,導致了數據類型的轉換,從而成功繞過了if的判斷語句。
正確使用方法
Demo2:
這一次我們設置第三個參數為True,強制讓其不進行數據類型轉換<?php
$xiaobao = $_POST['xiaobao'];
$dic['xiaobao_items'] = array(0,1,2,3,4,5,6);
if (in_array($xiaobao,$dic['xiaobao_items'],true))
{
echo 'success2';
}
else
{
echo 'false2';
}
?>
2:filter_var函數
filter_var?: (PHP 5 >= 5.2.0, PHP 7)
功能?:使用特定的過濾器過濾一個變量
定義?:mixed?filter_var?(?mixed?$variable?[, int?$filter?= FILTER_DEFAULT [,?mixed?$options?]] )
可能會產生安全問題的場景:
1:使用filter_var來判斷url,導致偽協議繞過問題
filter_var繞過
Demo:<?php
$xiaobao_url = filter_var($_GET['url'],FILTER_VALIDATE_URL);
var_dump($xiaobao_url);
$xiaobao_url1 = htmlspecialchars($xiaobao_url);
var_dump($xiaobao_url1);
echo "xiaobao";
?>
這里的//是為了滿足filter_var($_GET['url'],FILTER_VALIDATE_URL);對于url的判斷,但是在js當中//表示注釋,因此需要加入%0a,利用換行符去繞過注釋的限制,同時對%進行url編碼。最后的payload就是http://127.0.0.1/testphp/flitervar.php?url=javascript://xiaobao%250aalert(1)
這對XSS漏洞,最好的解決方案就是過濾關鍵詞,將特殊字符進行HTML實體編碼替換,這個網上已經有提供了很多防御的方法了。
3:parse_str()函數
parse_str
功能?:parse_str的作用就是解析字符串并且注冊成變量,它在注冊變量之前不會驗證當前變量是否存在,所以會直接覆蓋掉當前作用域中原有的變量。
定義?:void?parse_str(?string?$encoded_string?[,?array?&$result?] )
如果?encoded_string?是 URL?傳入的查詢字符串(query string),則將它解析為變量并設置到當前作用域(如果提供了 result?則會設置到該數組里 )。
可能會產生安全問題的場景:
1:parse_str函數導致的變量覆蓋問題
parse_str函數導致的變量覆蓋問題
Domo1:<?php
$xiaobao = "xiaobao";
parse_str('xiaobao=baobao');
var_dump($xiaobao);
?>
在調試過程我們可以清楚的看到之前定義的$xiaoboa變量被后面的parse_str函數中的給覆蓋掉了。
再來看個例子加深理解
Domo2:<?php
$xiaobao = 'fail';
parse_str($_GET['baobao']);
echo $xiaobao;
?>
實際上php中造成變量覆蓋的情形遠不止這么一種,大家下去可以自行研究。
4:strpos()函數
strpos?—?查找字符串首次出現的位置
作用:主要是用來查找字符在字符串中首次出現的位置。
結構:int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )
可能會產生安全問題的場景:
1:利用數組繞過判斷條件
2:第一次匹配字符下標為0去繞過判斷條件
利用數組繞過判斷條件
Demo1:<
?php
$flag = "{xiaobao success}";
if(strpos($_GET["url"],"secxiaobao") !== FALSE)
{
echo $flag;
}
else
{
echo 'fail';
}
?>
strpos()函數需要的是一個字符串,如果傳一個數組給它會發生什么呢?strpos()會出錯返回null,而判斷條件null!==false,所以符合我們的要求。成功得到flag。
利用匹配下標去繞過
Demo2:
這次我們再看另一種繞過情況,先來看一下strpos()正常使用方法<?php
echo strpos("I love liebao, I love liebao too!","liebao");
?>
執行結果為7,也就是去匹配liebao字符串首次出現的位置下標。
我們試一下下標不為0的情況<?php
$flag = "{xiaobao success}";
$a = strpos($_GET["url"],"secxiaobao");
if(!$a == true)
{
echo $flag;
}
else
{
echo 'fail';
}
?>http://127.0.0.1/testphp/strops.php?url=123secxiaobao
看到獲得的下標為3,非運算之后當然和true不相等了
那么,首次出現位置的下標為0又會發生什么?http://127.0.0.1/testphp/strops.php?url=secxiaobao
這里獲得的下標為0,非運算之后等于true,成功的輸出flag。
5:MD5函數
提到php中的MD5函數小豹會想起幾個字符串,ffifdyop和129581926211651571912466741651878684928,QNKCDZO,240610708
這些字符串有什么神奇的地方?小豹先留個懸念,我們接著往下看
首先是php中MD5函數官方釋義
md5?— 計算字符串的 MD5 散列值
string md5 ( string $str [, bool $raw_output = false ])
可能會產生安全問題的場景:
1:MD5函數true繞過
2:MD5函數==弱比較繞過
MD5函數true繞過
Demo1:<?php
$password = $_POST['password'];
$sql = "SELECT * FROM xiaobao WHERE username = 'baobao' and password ?= '".md5($password,true)"'";
$result = mysql_query($link,$sql);
if(mysql_num_rows(($result)>0){
echo 'success';
}
else{
echo 'login fail'
}
?>
這部分代碼是模擬對數據庫進行操作的真實情景。
從代碼中我們可以看出,只有查詢后的sql數據不為空也就是大于0的時候,才會輸出success。同時這部分代碼里出現了需要關注的MD5函數,當$raw_output設置為true的時候,md5函數會返回前16字節長度的原始二進制,并會將二進制轉換成字符串。而在這個轉換為字符串的過程中是否可能帶來問題?例如原始的二進制轉換為字符串后會不會影響本來的sql語句?答案當然是會的,這里已經有大佬幫我們找到了,小豹在前邊也提到了,不過這次可以了解他們的真實面貌:ffifdyop
129581926211651571912466741651878684928
接下來看下實際效果:<?php
$password = md5("ffifdyop",true);
echo $password;
$password1 = md5("129581926211651571912466741651878684928",true);
echo "";
echo $password1;
$sql = "SELECT * FROM xiaobao WHERE username = 'baobao' and password ?= '$password'";
$sql1 = "SELECT * FROM xiaobao WHERE username = 'baobao' and password ?= '$password1'";
var_dump($sql);
var_dump($sql1);
?>
回到上面的問題,我們的sql語句變成了SELECT * FROM xiaobao?WHERE username = 'baobao' and password = ''or'xxxx'
前邊的條件執行后會與后邊的or?'xxxx'進行或運算,導致整個where條件為真,從而繞過了密碼的限制。
MD5函數==弱比較繞過
Demo1:<?php
$flag = 'flag{xiaobao}';
$p = '/^[A-Za-z0-9]{6,12}$/';
$a = $_POST['password'];
if (preg_match($p, $_POST['password'])) {
if(md5($_POST['password'])=="0")
{
echo $flag;
}
else
{
echo 'fail';
}
}
else
{
echo 'Password format is wrong';
}
?>
從上面的代碼中可以看出對post形式獲取到的password進行了限制,只能是6-12位由數字和大小寫字母組成的字符串。對滿足條件的參數值進行MD5
加密,加密后與字符0進行比較,如果相等,就會輸出flag。http://127.0.0.1/testphp/MD5test.php
Post數據分別為:
password =240610708
password =QNKCDZO
為什么MD5加密后的這兩個特殊字符會與字符0相等?
來看一下這兩個特殊字符串MD5加密后的樣子
因為==對比的時候會進行數據轉換,0eXXXXXXXXXX 被轉換成了字符0。
總結
以上是生活随笔為你收集整理的php的一些不安全函数,php中可能会产生安全问题一些函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 马斯克想要在得州建乌托邦,遭不少居民反对
- 下一篇: 最新百元神机?Redmi A2现身Goo