編程基礎 | PHP代碼審記(下)

v2-29a2c0fc3c187e2191f0747884d3cc1f_1440

——————   上期回顧  ——————  

紅日安全出品|轉載請註明來源

文中所涉及的技術、思路和工具僅供以安全爲目的的學習交流使用,任何人不得將其用於非法用途以及盈利等目的,否則後果自行承擔!

(來源:紅日安全)

1.編程基礎 | PHP代碼審計(上):

image.png

紅日 新書上線了

紅日安全推出的適合新手入門系列教程專刊上線啦!

紅日安全專注新手入門教程。轉眼間紅日安全又成長了一歲,在這一年裏,團隊成長了很多很多。目前團隊所有的文章對外都是公開的,希望可以給新手一個填補空白的地方。2020年,團隊開始新的方向,和一些安全培訓廠商進行合作,希望做出更多安全作品。感謝團隊每一位成員爲團隊的辛勤付出,希望每一個人在團隊裏面有更大的作爲。也感謝一直在後面默默支持我們的紅粉,也祝願你們在新的一年學到更多的乾貨!

1.1.5  PHP安全缺陷

1.1.5.1 PHP 常見安全配置

1.1.5.1.1  php的安全模式

php的安全模式是個非常重要的內嵌的安全機制,能夠控制一些php中的函數,

比如system(),

同時把很多文件操作函數進行了權限控制,也不允許對某些關鍵文件的文件,

比如/etc/passwd,

但是默認的php.ini是沒有打開安全模式的,我們把它打開:

safe_mode = on

1.1.5.1.2  php腳本能訪問的目錄

使用open_basedir選項能夠控制PHP腳本只能訪問指定的目錄,這樣能夠避免

PHP腳本訪問

不應該訪問的文件,一定程度上限制了phpshell的危害,我們一般可以設

置爲只能訪問網站目錄:

open_basedir = D:/usr/www

1.1.5.2 關閉危險函數

如果打開了安全模式,那麼函數禁止是可以不需要的,但是我們爲了安全還是考

慮進去。比如,

我們覺得不希望執行包括system()等在那的能夠執行命令的php函數,或

者能夠查看php信息的

phpinfo()等函數,那麼我們就可以禁止它們:

disable_functions =

system,passthru,exec,shell_exec,popen,phpinfo,escapeshellarg,escapesh

ellcmd,proc_close,proc_open,dl,show_source,get_cfg_var

如果你要禁止任何文件和目錄的操作,那麼可以關閉很多文件操作

disable_functions =

chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen,unlink,delete,c

opy,mkdir,

rmdir,rename,file,file_get_contents,fputs,fwrite,chgrp,chmod,chown

以上只是列了部分不叫常用的文件處理函數,你也可以把上面執行命令函數

和這個函數結合,

就能夠**大部分的phpshell了。

1.1.5.3 關閉註冊全局變量

PHP中提交的變量,包括使用POST或者GET提交的變量,都將自動註冊爲

全局變量,能夠直接訪問

這是對服務器非常不安全的,所以我們不能讓它註冊爲全局變量,就把註冊

全局變量選項關閉:

register_globals = Off

當然,如果這樣設置了,那麼獲取對應變量的時候就要採用合理方式,比如

獲取GET提交的變量var

那麼就要用$_GET['var']來進行獲取,這個php程序員要注意。image.png

1.1.5.4  magic_quotes_gpc 來防止  SQL 注入

SQL注入是非常危險的問題,小則網站後臺被***,重則整個服務器淪陷,所以一定要小心。php.ini中有一個設置:magic_quotes_gpc = Off這個默認是關閉的,如果它打開後將自動把用戶提交對sql的查詢進行轉換,比如把 ’ 轉爲 \’等,這對防止sql注射有重大作用。所以我們推薦設置爲:magic_quotes_gpc = On

image.png 

1.1.6  代碼審計入門

1.1.6.1 代碼審計工具

所有的代碼審計工具只能輔助我們進行漏洞發現,由於現在代碼審計工具邏輯漏

洞是無法發現,只能靠人工進行源代碼審計。審計套路網上也比較多。大概方法

分爲以下幾種:

工具+人工法審計

主要是根據代碼審計工具進行函數遍歷正則匹配,另加上人工對漏洞敏感度進行

查找。

代碼通讀法

主要是根據代碼整體邏輯進行漏洞挖掘,這樣耗費時間比較大,但是可以挖到比

較有價值的漏洞。還有一些商業化工具,這裏暫且不講。講一下本漏洞經常用的

幾款比較免費功能強大的工具。

SeayPHP

image.png

使用方法:直接新建項目,把源代碼拖到裏面即可。

下載地址:https://pan.baidu.com/s/1i3Jw2uL#list/path=%2F

具體使用方法:

https://jingyan.baidu.com/article/54b6b9c0f77e0c2d583b47b1.html

Cobra

程序界面image.pngimage.png

操作方法:直接安裝即可使用,如果安裝麻煩,程序也給出docker安裝方式。

直接利用docker安裝即可。

審計效果:image.png

說明文檔:http://cobra.feei.cn/

附加說明:一般工具都會有一些規則,作爲一名安全研究人員,你可以多看看一

些開源工具的源碼。另外此工具也有一些規則,你可以看一下工具的規則,來提

高代碼審計。另外我們的函數都是採取工具截取,給大家進行演示。

image.png

我們隨便摘取一個,方法是漏洞利用的正則。

image.png

Rips

使用截圖:image.png

使用起來比較簡單,直接上傳源代碼即可。作爲一個靜態審計工具,在審計能力

方面我們發現這款工具還是可以。也可以定位到相關函數。

image.png

下載地址:https://sourceforge.net/projects/rips-scanner/files/

額外說明:大家可以利用此工具進行源碼審計,然後利用手工進行函數查找,漏洞復現等操作。

Burp

Burp本身就是一個神奇。不僅可以配合源代碼審計,也可以進行Web***測試等操作。此工具團隊已經進行詳細說明,大家可以參團隊博客進行參考使用。

BadCode

工具截圖:

image.png

此工具主要是利用subline3插件進行漏洞查找和利用。

下載地址:https://github.com/pwnsdx/BadCode

Ÿ  VulHint subline3插件image.png


安全規則:

image.png

l  Linux系統

大家在***測試工程中,避免會遇到Linux系統,如果遇到了Linux系統,而且系統也不可以外連,也沒有權限進行下載。那這個時候該怎麼辦?

如果遇到這種情況,我們可以利用Linux系統本身的查找命令進行源代碼審計。加入我們有***了一個Linux系統,在相關目錄裏面我們發現了一套源碼。然後利用此命令進行代碼審計。發現可疑函數進行***測試。

Ÿ  XSS漏洞

 -Ri  .
 -Ri  . |  
 -Ri  . |  
 -Ri  . |  
 -Ri  . |

image.png

發現好多函數裏面都用echo這個命令。通過這個顯示符,我們可以去查看一些

配置函數。

Ÿ  命令執行

 -Ri  .
 -Ri  .
 -Ri  .
 -Ri  .
 -Ri  .
 -Ri  .
 -Ri  .

image.png

看到這些函數應該就可以去嘗試一下漏洞

Ÿ  代碼注入

 -Ri  .
 -Ri  .
 -Ri  . |  
 -Ri  .

image.pngŸ  SQL注入

 -Ri  .
 -Ri  . |

image.png

Ÿ  信息泄露

 -Ri  .

image.pngŸ   Debug調式


 -Ri  .
 -Ri  .
 -Ri  .

Ÿ   RFI/LFI

 -Ri  .
 -Ri  .
 -Ri  .
 -Ri  .
 -Ri  .
 -Ri  .
 -Ri  . |


Ÿ     Misc

 -Ri  . |  
 -Ri  .

Ÿ  文件類型

 -Ri file_get_contents .

image.png對於Linux系統源代碼審計,方法多種多樣,只是小編經常採用這用方式來進行

源代碼審計。對整體代碼邏輯性非常鍛鍊人。

1.1.7  代碼審記函數理解

我們根據cobra規則,我們總結了一些PHP常見漏洞威脅函數。

image.pngimage.png

其它工具的規則你可以進行查看。比如我們去查看一下Badcode裏面的一些檢查

規則,發現也類似。

image.png

所以先學習代碼審計,你可以先學習一下PHP常見威脅函數有哪些,然後在查看

這些函數是如何調用的,最後整體進行漏洞挖掘。工具進行測試,也可以手工加

工具進行測試。最後結果漏洞發現,不管採用哪種方式,你都可以達到一個上升。

Ÿ  注入敏感函數

selectfrom 、mysql_connect、mysql_query、mysql_fetch_*、update、insert、

(案例1

爲了講解這些常用函數,臨時寫了一個HRvul小靶場進行漏洞練習。參考了部分

安全靶場。image.png

首先看注入源碼部分

<?php
if(isset($_GET['Submit'])){
// Retrieve data
$conn=mysql_connect("localhost","root","root",3306);
mysql_select_db("hrexp",$conn);
inject_checking(strtolower($_SERVER['QUERY_STRING']));
$id = $_GET['id'];
$getid = "SELECT * FROM users WHERE id = $id";
print_r($getid);
$result = mysql_query($getid) or die('<pre>' . mysql_error() .
'</pre>'  );
echo "<br/>";
print_r(mysql_fetch_array($result));

query_string傳過來字符進行檢查inject_checking函數,我們在看一下這個函數有哪些操作

<?php
function inject_check($str) //防注入函數開始
$check=preg_match('/select|order|insert|update|eval|document|d
elete|injection|jection|link|and|or|from|union|into|load_file|
outfile|<script>/'
,$str);
if($check){
echo
"<script>alert('Filtered!!!');window.history.go(-1);</script>"
;
exit();
}else{
return  $str;
}
}

對常見函數都進行檢查,我們看看能不能進行繞過,可以直接對常見函數進行編碼既可以繞過。

image.png

2)案例2

<?php
$dbuser = "root";
$dbpwd = "";
$db = "test";
//這裏是mysql的密碼
$conn = mysql_connect("localhost",$dbuser,$dbpwd)  or
die("error");
mysql_select_db($db,$conn);
$id = $_GET['id'];
$query = "select * from test where id =$id";
$result = mysql_query($query) or die(mysql_error());
print_r(mysql_fetch_array($result));

這裏我們用到了mysql_query這個函數。由於$id參數在傳參過程中沒有進行修

飾,直接傳給了MySQL。造成了注入。

3)案例3

Simple Down 簡單下載系統 v5.4image.png

從源碼狀態來看,應該沒過濾直接mysql_query或者過濾不嚴格。

文章地址:http://wooyun.jozxing.cc/static/bugs/wooyun-2013-037204.html

Ÿ  寬字節注入

setnamesgbk、character_set_client=gbkmysql_set_charset()、iconv

寬字符是指兩個字節寬度的編碼技術,如UNICODEGBKBIG5等。當MYSQL

據庫數據在處理和存儲過程中,涉及到的字符集相關信息包括:

Ÿ  character_set_client:客戶端發送過來的SQL語句編碼,也就是PHP發送

SQL查詢語句編碼字符集。

character_set_connection:MySQL服務器接收客戶端SQL查詢語句後,在實

施真正查詢之前SQL查詢語句編碼字符集。

Ÿ  character_set_database:數據庫缺省編碼字符集。

Ÿ  character_set_filesystem:文件系統編碼字符集。

Ÿ  character_set_results:SQL語句執行結果編碼字符集。

Ÿ  character_set_server:服務器缺省編碼字符集。

Ÿ  character_set_system:系統缺省編碼字符集。

Ÿ  character_sets_dir:字符集存放目錄,一般不要修改。

寬字節對轉義字符的影響發生在character_set_client=gbk的情況,也就是說,

如果客戶端發送的數據字符集是gbk,則可能會吃掉轉義字符\,從而導致轉義

消毒失敗。

例子3就是一個存在寬字符注入漏洞的PHP程序。

<?php
$name=$_GET['name'];
$name=addslashes($name);
$conn=mysql_connect('localhost','root','root');
if($conn==null){exit("connect error !<br>");}
mysql_query("SET NAMES 'gbk'",$conn);
mysql_select_db("hongri",$conn);
$sql="select * from hongrisec where name='".$name."'";
$result=mysql_query($sql,$conn);
while($val=mysql_fetch_row($result)){
print_r($val);
print("<br>");
}
?>

產生漏洞代碼我們已經利用黃色底紋已經標出來,主要數據庫編碼採用了gbk編碼,導致了寬字節注入。POC如下

http://127.0.0.1/hongri/hongrisec.php?name=a%df‘ or 1=1; %20%23

其原理是mysql_query(“SETNAMES’gbk’”,$conn)語句將編碼字符集修改爲gbk

此時,%df\’對應的編碼就是%df%5c’,即字“運’”,這樣單引號之前的轉義符號“\”就被吃調了,從而轉義失敗。一個漢字就把單引號吃掉了,導致過

濾失敗,注入我們還可以繼續進行。

 二次編碼注入

urldecode、rawurldecode


seay代碼審計書中也描述過二次編碼注入,主要是利用工具採用正則進行編碼

尋找,然後尋找漏洞。

源碼下載:https://pan.baidu.com/s/1c1mLCru

漏洞文章分析:https://www.waitalone.cn/php-code-audit-4.html

代碼分析:

<?php
$a=addslashes($_GET['p']);
$b=urldecode($a);
echo '$a='.$a;
echo '$b='.$b;
?>

主要是urldecode這個函數導致問題。Addslashes函數主要是對單引號、雙引號加反斜線進行註釋。而urlencode這個函數又進行編碼了,導致漏洞產生。比如我們進行編碼,%2527,在這裏%25編碼的結果是%,如果程序使用urldecode函數,會直接和27數字連接上,形成單引號導致繞過addslashes函數,形成注入。image.png

MySQL二次注入講解

在瀏覽文章的時候,發現一個圖片比較好,就給大家放過來更容易理解二次注入。image.png

原文文章:

http://www.beesfun.com/2017/03/28/MySQL%E6%B3%A8%E5%85%A5%E7%B3%BB%E5

%88%97%E4%B9%8B%E4%BA%8C%E6%AC%A1%E6%B3%A8%E5%85%A5-%E4%B8%89/

來段代碼講解一下,比較典型代表了二次注入。

Hrconfig.php

<?php
mysql_connect('localhost''root''root');
mysql_select_db('hongrisec');
mysql_set_charset('utf-8');
if (!get_magic_quotes_gpc()){
//主要判斷GPC是否打開,如果GPC打開就利用GPC過來單引號、雙引號等特
殊字符。如果沒開啓直接去調用addslashes_deep函數,這個函數在下方已經
定義。
if (!empty($_GET)){
$_GET = addslashes_deep($_GET);
}
if (!empty($_POST)){
$_POST = addslashes_deep($_POST);
}
$_COOKIE = addslashes_deep($_COOKIE);
$_REQUEST = addslashes_deep($_REQUEST);
}
function  addslashes_deep($value){
if (empty($value)){
return  $value;
}else  {
return is_array($value) ? array_map('addslashes_deep',
$value): addslashes($value);
}
}
?>

Hrreg.php




 username:
 password:
 email:


image.png二次注入的利用就是把第一次存儲到數據庫裏面的值在此調用然後進行二次利

用。Search.php




search email

image.png代碼已經爲大家分析完畢。現在直接進行操作。首先在輸入表裏面輸入字段。

image.png


我們已經在輸入把單引號已經輸入進去,我們查看一下數據庫。image.png

然後我們重新註冊一個語句。利用MySQL語句進行註冊

image.png

插入數據庫語句。然後在利用查找語句進行查找郵箱語句。

image.png

發現已經查找成功。

Ÿ  文件包含

、 、、

本地包含漏洞

常見漏洞代碼

<?php
if (isset($_GET[page])) {
//這句語句是核心語句,主要利用GET語句進行包含。我們可以構造一些語句
進行繞過,不過現在這樣語句已經非常少了。
include $_GET[page];
else  {
include "home.PHP";
}
?>

案例2


1.包含文件上傳的圖片

Ÿ 文件上傳

move_upload_file

直接看代碼講解:

<?php
if($_FILES['userfile']['type'] != "image/gif"#這裏對上傳的文件
類型進行判斷,如果不是image/gif類型便返回錯誤。
{
echo "Sorry, we only allow uploading GIF images";
exit;
}
$uploaddir = 'uploads/';
$uploadfile=$uploaddir.basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'],
$uploadfile))
//move_uploaded_file主要是把文件移動到一個位置
{
echo "File is valid, and was successfully uploaded.\n";
else  {
echo "File uploading failed.\n";
}
?>

主要是對圖片類型進行判斷,如果不是圖片類型就返回錯誤。上傳內容也比較多。

後續看我們完整版本報告。

任意文件刪除

、session_destory

代碼注入 :

 assert、preg_replace(/e)、 call_user_func、call_user_func_array、
array_map

展示界面:

image.png

然後直接進行代碼講解



PHP Code Injection

 username:
 password:
 email:

image.png直接當成代碼執行。

命令執行

、、shell_exec、passthru 、pctnl_exec、popen、proc_exec、


命令講解

<?php
$cmd=$_GET['hongri'];
echo shell_exec($cmd);
?>


直接當成命令執行。Hongri的值如果可以控制,我們就可以執行我們想執行的命令。image.png

變量覆蓋

extract、parse_str、$$

函數演示

實例演示wooyunfrcms (wooyun 2014-073244)image.png

他會把你從GETPOSTCOOKIE 中的變量註冊爲全局變量,因此我們直接通過

GET 參數提交$insLockfile 變量即可繞過

反序列化

Unserialize、serialize()

代碼講解:

當在php中創建了一個對象後,可以通過serialize()把這個對象轉變成一個字符串,保存對象的值方便之後的傳遞與使用。測試代碼如下;

<?php
class  hongrisec{
var $test = '123';
}
$class1 = new  hongrisec;
$class1_ser = serialize($class1);
print_r($class1_ser);
?>

然後我們查看一下反序列化之後的值

O:9:”hongrisec”:1:{s:4:”test”;s:3:”123″;}

這裏的O代表存儲的是對象(object,假如你給serialize()傳入的是一個數

組,那它會變成字母a9表示對象的名稱有9個字符。“hongrisec”表示對象的

名稱。1表示有一個值。{s:4:”test”;s:3:”123″;}中,s表示字符串,4表示該

字符串的長度,“test”爲字符串的名稱,之後的類似。

unserialize()

serialize() 對應的,unserialize()可以從已存儲的表示中創建PHP的值,

單就本次所關心的環境而言,可以從序列化後的結果中恢復對象(object)。

<?php
class  hongrisec{
var $test = '123';
}
$class2 = 'O:9:"hongrisec":1:{s:4:"test";s:3:"123";}';
print_r($class2);
echo "</br>";
$class2_unser = unserialize($class2);
print_r($class2_ser);
?>

反序列之後,就還原成serialize之後的。反序列化漏洞就在序列化的時候插入

我們需要插入代碼。造成漏洞利用化,但是利用漏洞有一定的限制。具體漏洞講

解請參考完整報告。

隨機數

、mt_rand

將在完整報告中更詳細介紹。

你怎麼看待紅日發佈的這款新專刊?你認爲它有爆紅的潛質嗎?
歡迎在評論區留言享你的觀點和看法

banner.jpg

海量安全課程   點擊以下鏈接   即可觀看 

http://qiyuanxuetang.net/courses/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章