緣起
如果你審查過的慢查詢日誌或者網站access日誌中,你可能都會看到如下的語句:
可能就是你網站啟用後大概1小時候內就收到的日誌,或者你Web伺服器(nginx)訪問中看到的。如果你是在Mysql慢查詢日誌中或者access日誌中看到,並且該跳請求返回的狀態碼為200,而不是404,那麼恭喜你可能中標了,被人Sql攻擊了。本文蟲蟲就和大家以sleep()函數為介入來討論。
SLEEP()函數
SLEEP(n),暫停資料庫n秒。
不要混淆MySQL控制臺中的sleep狀態,它描述了連接的狀態,SLEEP()函數做了一件事,就是暫停資料庫的執行,直到設定的時間。那麼該操作有什麼用?為什麼要用它呢?
通常,有一些操作需要一段時間來操作,操作時候需要暫時操作或者更新(比如數據鎖,比如記錄一個Pos點後,備份一個從庫),當然也有可能是黑客攻擊。
漏洞滲透和掃描
如果你的資料庫和網站沒有做安全措施,直接把埠暴露在公網上(比如ssh 22埠,mysql 3306埠),那麼,很快就會能有掃描器對你的埠進行掃描滲透。所以蟲蟲以也提到過在主機防護中的條款:禁止把埠暴露在公網;修改常用埠。專門對於mysql,最常用的掃描滲透和安全審計工具是sqlmap。
sqlmap是使用Python編寫的一款資料庫sql注入掃描工具,目前支持常見的mysql、oracel、postgresql、sql server,access,db2,sqlite等數據的安全漏洞(sql注入)。
在sqlmap盲主掃描中,通常會Fuzzy各種sql語句,通常還會使用sleep命令。比如掃描那些使用舊的mysql或mysqli等非PDO的連接PHP MySQL網站,然後枚舉易受攻擊的AJAX命令列表或GET/POST結果,在輸出掃描結果時候的通常需要中止執行。
sqlmap及同類工具可以並行攻擊幾十個站點,通過對這些網站強制資料庫sleep一段時間(數字設定取決於個人經驗),通過計數sleep的時間,來測試滲透命令中的有效性,這在安全界通常叫基於時間的盲注。
快速解剖
在本文開頭,我們舉了一個sql語句的例子,這是常用的盲注的典型語句。如果執行SELECT語句,其中的條件語句部分被替換為類似以下的內容,那麼它將絕對鎖定資料庫:
注意該語句巧妙地使用各種運算符和分隔符。注意該語句,對只對拼寫sql語句的程序有用,使用PDO該語句可以被過濾,不能執行的 。
PHP mysql注入示例
讓我們寫一個php的示例,來說問題。看以下函數:
上面的示例中,我們使用implode()函數生成以逗號分隔的ID列表。由於對輸入沒有任何驗證,傳入的數組中,可能是非法的具有SLEEP的命令或者dump 資料庫表中的數據到展示頁面。針對這種問題,你需要使用對傳入的數據做驗證,驗證長度(根據實際需要限制參數長度,可以極大防止注入的成功)。
你可以使用PDO等連結框架,利用佔位符代替(綁定)參數生成sql語句,並通過prepare做參數驗,這樣可以阻止絕大多數的SQL注入的值。
PDO並非靈丹妙藥
上面我們也說通過PDO可以預防絕大多數的PHP Sql注入問題,但是他不是100%保證能解決所有問題。
如前所述,自己拼湊Sql的原始動態組合方法,讓很多PHP系統處於危險之中
所以,一無所措的碼農們不可避免地會通過谷歌尋求幫助他們:
上面是網上一個很流行的PDO使用教程之一,該代碼使用PDO,但是和純的手動拼湊Sql的並沒有什麼兩樣,也是非常危險的做法。
還有如下StackOverflow(一個知名的編程問答網站)上的的一個答案:
看到了麼,這也是很糟糕的代碼,但是還被接受了。在碼農們接受的概念是"使用PDO可以防止sql注入",但是他們不知道PDO防止注入也是有前提的,那就是必須是用"?佔位符綁定寫SQL,然後prepare,然後execute",否則等於沒有用。
不要小看sleep()
可能你覺得發現sleep()執行,並沒有什麼的?起碼不會DROP你的資料庫。SLEEP()很容易識別,並且在該階段通常幾乎沒有啥害。但是通過,可以在通過盲注Fuzz測試數據執行大量的查詢,並很快就找到有效的攻擊EXP。
實際上,這就死sqlmap的核心功能。這種思路的一個問題是,在依賴於MySQL for UX/UI的生產Web項目中,通常的做法是將代碼執行用戶限制為僅具有SELECT權限,不給他DROP權限。但是SLEEP()使用只需SELECT權限。
SLEEP怎麼禁止?
因為SLEEP函數的使用只需要SELECT,不需要任何特權權。並且可以作為"最安全的"MySQL命令執行。
它只是一個SQL注入漏洞,無法使用定時攻擊暫停資料庫執行或瀏覽數據(或對其進行dump)。而且一般通過簡單的配置無法禁用SLEEP函數。MySQL可以在資料庫,表和列級別做權限限制。當然如果能有辦法簡單這頂對某些危險函數的禁止也是有意義的(比如php.ini中的disable_functions配置)。
實際上sleep也給了我們一種防禦思路,基於對該函數關鍵字的探測來實現sql攻擊告警和防禦。比如蟲蟲自研了一款web防火牆App-Waf(github:/ bollwarm/App-Waf)就是基於這樣的探測原理,通過分析訪問日誌中的關鍵詞,其中就包括了sleep函數,下面是我用的關鍵字規則(部分)。
本文中蟲蟲和大家一起以Mysql的sleep()函數為介入討論了Sql注入的問題,總體上來說可以使用sleep()來枚舉SQL漏洞,PDO綁定參數的方法擦可以防禦Sql注入,sleep()一般無害,而且不會正常情況下很少用的到,但是可以變廢為寶用他來做為探測攻擊的手段。
關於更多的安全和Sql注入的問題關注蟲蟲,蟲蟲會撰寫文章和大家一起學習。