1. 程式人生 > >PHP程式碼審計01之in_array()函式缺陷

PHP程式碼審計01之in_array()函式缺陷

#前言 從今天起,結合紅日安全寫的文章,開始學習程式碼審計,題目均來自**PHP SECURITY CALENDAR 2017**,講完這個題目,會再用一道有相同問題的CTF題來進行鞏固。下面開始分析。 #漏洞分析 下面我們看第一題,程式碼如下: ``` 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手冊對這個函式的解釋,是檢查陣列中存在某個值,重點是我圈起來的,如果沒有設定第三個引數,那麼就使用寬鬆的檢查,問題就出現在這裡。 ![](https://img2020.cnblogs.com/blog/1996712/202009/1996712-20200924191954777-1736306941.png) 現在看上方程式碼第12行,這裡使用了in_array()函式來檢查檔名,但是沒有設定第三個引數!,只會進行弱型別比較,不會檢查資料型別。比如上面白名單規定,只能上傳1~24的檔名,我們上傳3shell.php,因為3在白名單中,所以它會將3shell轉換成3從而繞過了白名單,達到了任意檔案上傳的目的。 為了加深對in_array()的理解,這裡寫一段簡單的程式碼。 ``` ``` 這裡in_array()也是沒有設定第三個引數,會進行弱型別比較,會將3 and 1=1轉化為3從而繞過了白名單,輸出你通過了。當我設定第三個引數為true時,此時會進行強型別檢查。所以我們將上文第三行程式碼修改為:`if (!in_array($id, $whitelist,true))`,再執行就會輸出:“你想搞事”。 ![](https://img2020.cnblogs.com/blog/1996712/202009/1996712-20200924225232651-754161094.png) 現在是不是對in_array()函式有了一個大概的瞭解呢?那讓我們做一道同類型CTF題目來加深鞏固一下。 #CTF練習 這道題目也是in_array()函式沒有設定第三個引數,導致白名單被繞過,然後被SQL注入。下面我們具體看一下相關程式碼。 **index.php** ``` 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 "
"; foreach ($row as $key=>$value){ echo "
"; echo "
"; } echo "
$key
$value
"; } else{ die($conn->error); } ?> ``` 然後的config.php的相關程式碼。 **config.php** ``` ``` 然後是搭建CTF使用的sql語句。 ``` 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','[email protected]',3000); INSERT INTO users VALUES(2,'Danny','[email protected]',4500); INSERT INTO users VALUES(3,'Alina','[email protected]',2700); INSERT INTO users VALUES(4,'Jameson','[email protected]',10000); INSERT INTO users VALUES(5,'Allie','[email protected]',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來看一下,發現查詢到了資訊。 ![](https://img2020.cnblogs.com/blog/1996712/202009/1996712-20200925110613331-1319640529.png) 現在我們輸入8,它不在白名單中,看看返回什麼。 ![](https://img2020.cnblogs.com/blog/1996712/202009/1996712-20200925110804180-2120035121.png) 上面是正常的輸入,所以白名單是有效的,下面我們構造payload,比如我們輸入:`1'`,發現程式報錯,繞過了白名單的檢查。可以直接報錯注入。 ![](https://img2020.cnblogs.com/blog/1996712/202009/1996712-20200925120104677-1805919929.png) 而關於報錯注入的函式,大約有四個,分別是:`floor()、extractvalue()、updatexml()、exp()`。 雖然繞過了白名單,但是還有過濾函式stop_hack()現在我們定位到這個函式看看: ![](https://img2020.cnblogs.com/blog/1996712/202009/1996712-20200925112927353-422776045.png) 發現過濾了一些危險函式,我們檢視後發現,這裡沒有過濾updatexml()函式,可以用它,但是concat函式被過濾了,我們需要找到可以替換得函數了。這裡我們使用**make_set()函式**,它的用法是make_set()函式是先將x轉化成二進位制,例如: **11的二進位制為1011,將二進位制順序顛倒變成1101,每一位數再與後面的字串相對應,為1的擷取,為0的丟棄。**如下圖: ![](https://img2020.cnblogs.com/blog/1996712/202009/1996712-20200925122233169-34900881.png) 所以我們構造payload,獲取資料,為了避免佔用篇幅這裡直接是獲取到flag的payload。 ``` and updatexml(1,make_set(3,'~',(select flag from flag limit 1)),1) ``` ![](https://img2020.cnblogs.com/blog/1996712/202009/1996712-20200925122738406-757587494.png) #小結 通過這篇文章的講解,是不是對in_array()理解更深了一些呢?下一篇文章會對filter_var函式缺陷導致的漏洞進行學習和分析,一起努力吧! 我的部落格即將同步至騰訊雲+社群,邀請大家一同入駐:[https://cloud.tencent.com/developer/support-plan?invite_code=1pxmil6lphjna](https://cloud.tencent.com/developer/support-plan?invite_code=1pxmil