從今天起,結合紅日安全寫的文章,開始學習代碼審計,題目均來自PHP SECURITY CALENDAR 2017,講完這個題目,會再用一道有相同問題的CTF題來進行鞏固。下面開始分析。php
下面咱們看第一題,代碼以下:mysql
<?php class Challenge{ const UPLOAD_DIRECTORY = './solutions/'; private $file; private $whitelist; public function __construct($file) { $this->file = $file; $this->whitelist=range(1,24); } public function __destruct() { // TODO: Implement __destruct() method. //這裏要特別注意!!! if (in_array($this->file['name'],$this->whitelist)){ move_uploaded_file( $this->file['tmp_name'], self::UPLOAD_DIRECTORY.$this->file['name'] ); } } } $challenge=new Challenge($_FILES['solution']); ?>
這一關考察的是任意文件上傳漏洞,致使這個漏洞發生的是上方代碼中,對in_array()函數使用不規範致使的。這裏詳細說一下in_array()函數的用法。先看一下PHP手冊對這個函數的解釋,是檢查數組中存在某個值,重點是我圈起來的,若是沒有設置第三個參數,那麼就使用寬鬆的檢查,問題就出如今這裏。
如今看上方代碼第12行,這裏使用了in_array()函數來檢查文件名,可是沒有設置第三個參數!,只會進行弱類型比較,不會檢查數據類型。好比上面白名單規定,只能上傳1~24的文件名,咱們上傳3shell.php,由於3在白名單中,因此它會將3shell轉換成3從而繞過了白名單,達到了任意文件上傳的目的。
爲了加深對in_array()的理解,這裏寫一段簡單的代碼。sql
<?php $id =3 and 1=1; $whitelist = range(1, 5); if (!in_array($id, $whitelist)) { echo "你想搞事"; } else { echo "你經過了"; } ?>
這裏in_array()也是沒有設置第三個參數,會進行弱類型比較,會將3 and 1=1轉化爲3從而繞過了白名單,輸出你經過了。當我設置第三個參數爲true時,此時會進行強類型檢查。因此咱們將上文第三行代碼修改成:if (!in_array($id, $whitelist,true))
,再執行就會輸出:「你想搞事」。
如今是否是對in_array()函數有了一個大概的瞭解呢?那讓咱們作一道同類型CTF題目來加深鞏固一下。shell
這道題目也是in_array()函數沒有設置第三個參數,致使白名單被繞過,而後被SQL注入。下面咱們具體看一下相關代碼。
index.php數組
<?php include 'config.php'; $conn = new mysqli($servername,$username,$password,$dbname); if ($conn->connect_error){ die("鏈接失敗"); } $sql="SELECT COUNT(*) FROM users"; $whitelist = array(); $result = $conn->query($sql); if ($result->num_rows > 0){ $row = $result->fetch_assoc(); $whitelist = range(1,$row['COUNT(*)']); } $id = stop_hack($_GET['id']); $sql = "SELECT * FROM users WHERE id=$id"; if (!in_array($id,$whitelist)){ die("id $id is not in whitelist."); } $result = $conn->query($sql); if ($result->num_rows > 0){ $row = $result->fetch_assoc(); echo "<center><table border='1'>"; foreach ($row as $key=>$value){ echo "<tr><td><center>$key</center></td><br>"; echo "<td><center>$value</center></td></tr><br>"; } echo "</table></center>"; } else{ die($conn->error); } ?>
而後的config.php的相關代碼。
config.php安全
<?php $servername = "localhost"; $username = "root"; $password = "XFAICL1314"; $dbname = "day1"; function stop_hack($value){ $pattern = "insert|delete|or|concat|concat_ws|group_concat|join|floor| \/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex| file_put_contents|fwrite|curl|system|eval"; $back_list = explode("|",$pattern); foreach ($back_list as $hack){ if (preg_match("/$hack/i",$value)) { die("$hack detected"); } } return $value; } ?>
而後是搭建CTF使用的sql語句。curl
create database day1; use day1; create table users ( id int(6) unsigned auto_increment primary key, name varchar(20) not null, email varchar(30) not null, salary int(8) unsigned not null ); INSERT INTO users VALUES(1,'Lucia','Lucia@hongri.com',3000); INSERT INTO users VALUES(2,'Danny','Danny@hongri.com',4500); INSERT INTO users VALUES(3,'Alina','Alina@hongri.com',2700); INSERT INTO users VALUES(4,'Jameson','Jameson@hongri.com',10000); INSERT INTO users VALUES(5,'Allie','Allie@hongri.com',6000); create table flag(flag varchar(30) not null); INSERT INTO flag VALUES('HRCTF{1n0rrY_i3_Vu1n3rab13}');
用上面代碼咱們在本地將環境搭建好。而後開始分析,先看index.php文件代碼。再第16行經過$_GET方法接收用戶的輸入,並用stop_hack()來過濾用戶的輸入,而後下方直接拼接到sql語句中進行查詢。而後再向下看,這裏這裏用in_array()來進行一個簡單的檢查,咱們發現它沒有設置第三個參數,進行弱類型檢查。如今咱們來驗證一下,眼見爲實。根據咱們上方白名單規則,咱們如今id只能輸入1~5。如今咱們輸入3來看一下,發現查詢到了信息。
如今咱們輸入8,它不在白名單中,看看返回什麼。
上面是正常的輸入,因此白名單是有效的,下面咱們構造payload,好比咱們輸入:1'
,發現程序報錯,繞過了白名單的檢查。能夠直接報錯注入。
而關於報錯注入的函數,大約有四個,分別是:floor()、extractvalue()、updatexml()、exp()
。
雖然繞過了白名單,可是還有過濾函數stop_hack()如今咱們定位到這個函數看看:
發現過濾了一些危險函數,咱們查看後發現,這裏沒有過濾updatexml()函數,能夠用它,可是concat函數被過濾了,咱們須要找到能夠替換得函數了。這裏咱們使用make_set()函數,它的用法是make_set()函數是先將x轉化成二進制,例如: 11的二進制爲1011,將二進制順序顛倒變成1101,每一位數再與後面的字符串相對應,爲1的截取,爲0的丟棄。以下圖:
因此咱們構造payload,獲取數據,爲了不佔用篇幅這裏直接是獲取到flag的payload。函數
and updatexml(1,make_set(3,'~',(select flag from flag limit 1)),1)
經過這篇文章的講解,是否是對in_array()理解更深了一些呢?下一篇文章會對filter_var函數缺陷致使的漏洞進行學習和分析,一塊兒努力吧!
個人博客即將同步至騰訊雲+社區,邀請你們一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=1pxmil6lphjna學習