首先漏洞存在於app\system\message\web\message.class.php文件中,變量{$_M[form][id]} 直接拼接在SQL語句中,且驗證碼檢測函數是在SQL語句查詢以後,這也就形成了咱們能夠無視驗證碼檢測函數,進行SQL注入。具體問題函數代碼以下:php
$met_fd_ok=DB::get_one("select * from {$_M[table][config]} where lang ='{$_M[form][lang]}' and name= 'met_fd_ok' and columnid = {$_M[form][id]}");
這行中$_M[form][id]}沒有被單引號保護拼接在sql語句中,存在安全隱患。咱們跟跟蹤這個變量看是否有過濾操做。mysql
首先這個類的基類是web類web
跟進web類,沒有對用戶傳入的數據進行過濾等操做,卻初始化了common類sql
咱們繼續看看common類數據庫
在common類初始化時調用了表單過濾的函數load_form()安全
此函數中又調用了過濾SQL注入的函數sqlinsertapp
那咱們來看看這個sqlinsert函數過濾了什麼dom
能夠看到sqlinsert函數對sleep關鍵字進行了處理,可是咱們仍是能夠使用MYSQL中的benchmark函數輕鬆繞過。固然咱們本文繞過的姿式不是用函數繞過這個函數,而是讓代碼不執行這個過濾的函數來達到繞過。函數
咱們回到daddslashes函數裏:this
daddslashes()定義在app/system/include/function/common.func.php第51行,對傳遞的參數進行addslashes()操做。這裏注意,在else語句中,若是以前定義了IN_ADMIN常量,進行trim(addslashes(sqlinsert($string)))操做,反之則進行trim(addslashes($string))。
以前所述的安全隱患點爲int型,因此addslashes()函數沒有做用,因此這裏主要是要繞過sqlinsert(),須要尋找到定義過IN_ADMIN常量的入口。
這裏經過搜索找到了admin/index.php,文件第5行定義了IN_ADMIN常量。接着看從admin/index.php入口文件如何調用add()函數的,index.php定義了4個常量,而且包含了app/system/entrance.php。
進入app/system/entrance.php,38-44行,入口文件沒有定義M_TYPE,這裏會設置M_TYPE常量爲system;54-59行,因爲定義了M_TYPE爲system,進行設置PATH_OWN_FILE常量爲PATH_APP.M_TYPE.'/'. M_NAME.'/'.M_MODULE.'/',其中M_NAME、M_MODULE都可控。88-99行包含app/system/include/class/load.class.php,並調用了module()方法。
因爲調用module()方法時缺省了參數,所以$path、$modulename、$action均有以前定義的常量賦值,而後再調用_load_class()方法。_load_class()方法能夠引用並實例化一個類,
當action爲空的時候,只引用文件。當action爲new時候,會實例化這個類。當action爲do開頭時候,會實例化類,並執行這個方法。
那麼到這裏咱們理一下條件:
要想包含app/system/message/web/message.class.php文件,須要知足
M_NAME = $_GET['n'] = message; M_MODULE = $_GET['m'] = web; M_CLASS = $_GET['c'] = message;
要想調用add(),必須實例化類並執行方法,但這裏限定只能實例化並執行do開頭的方法。這裏找到了message.class.php中的domessage(),它調用了add()方法。
在調用add()方法前,須要知足$this->check_field();,這裏發現只要抓取正常的留言參數填充就能夠了,驗證碼的判斷是在add()方法中執行完漏洞語句以後。
爲了實現布爾注入而不是時間盲注,須要正常時$met_fd_ok的值不爲空,從而繞過46行判斷,彈出"驗證碼錯誤",而異常時$met_fd_ok值爲空,彈出"反饋已關閉"。
在數據庫中執行一下存在漏洞的SQL語句,看看符合條件的id參數有哪些,知足的columnid有42和44。
mysql> select * from met_config where name = 'met_fd_ok' and lang='cn'; +-----+-----------+-------+--------------+----------+---------+------+ | id | name | value | mobile_value | columnid | flashid | lang | +-----+-----------+-------+--------------+----------+---------+------+ | 470 | met_fd_ok | 1 | | 44 | 0 | cn | | 490 | met_fd_ok | 1 | | 42 | 0 | cn | +-----+-----------+-------+--------------+----------+---------+------+
最終能夠構造以下GET請求注入,注入點爲id:
admin/index.php?m=web&n=message&c=message&a=domessage&action=add&lang=cn¶137=1¶186=1@qq.com¶138=1¶139=1¶140=1&id=42 and 1=1
sqlmap.py -u "192.168.5.172/admin/index.php?m
=web&n=message&c=message&a=domessage&action=add&lang=cn¶137=1¶186=1@qq.com¶138=1¶139=1¶140=1&id=42"
最後附上一個思惟導圖,更好理解邏輯