通過一個注入漏洞觀察Apache與Nginx的區別
0x00 前言
你見過你的SQL注入方式被WEB容器影響嗎?
0x01 漏洞分析
打開index.php,看到了include_once,如圖

跟進Include/web_inc.php

前兩行包含的文件我們先翻一下看一下。
Db_conn.php:

定義了一些數據庫配置信息,$db_conn變量為mysqli的實例,我們再來看一下contorl.php

定義了一些函數信息,5-11行進行全局的GET請求過濾。
了解一些東西之后回到Include/web_inc.php下繼續往下翻一翻代碼。

調用了web_language_ml函數?我們跟進看一下。

發送了一次SELECT查詢的SQL語句,攜帶參數1參數2,我們看一看參數的來源。

注入漏洞產生了,$_SERVER[REQUEST_URI]是用來獲取url的(協議://域名/ 除外),如圖:

這不是很正常嗎?為什么會產生SQL注入漏洞問題?
我們都知道,在發送GET請求時,問號后的內容會被當做參數處理,那么符合REQUEST_URI的氣質,問號后的內容也被獲取到了。
如圖:

在程序判斷中通過 斜杠/ 分隔,隨后直接引入程序中的SQL語句中,從而引發SQL注入漏洞。你可能會問,剛剛不是還過濾了全局GET嗎?
我們再仔細看看,只過濾了GET中的VALUE值:

哈哈哈哈?沒注意對吧。
除此之外REQUEST_URI所接收的值不會被url解碼而變化,比如我傳入%0a(換行符)就原封不動的取出。我們舉個例子與$_GET作一下比較。如圖:

可能這時候會問,提這個有什么意義呢?
我們都知道%20為空格,我們通常都會通過空格從注入語句中分隔語句。避免造成語法錯誤。而HTTP請求中GET是不允許出現未urlencode編碼過的字符串的,如圖:

不符合HTTP協議規則,直接爆出400錯誤!這里可以想到Mysql中 [空格]--[空格] 的注釋方式被BAN掉!!!
又因為程序通過 斜杠(/) 分隔來代入SQL語句中,所以/**/這種注釋語句也被BAN掉了!
還有一種#注釋姿勢,很遺憾,HTTP請求依然不允許,如圖:

那么我們只能通過閉合的方式來進行SQL盲注了,
構造Payload:/?'or+if(substr((select+user()),1,1)like'r',sleep(2),1)-'

因為當前處于where條件中,我的閉合語句為-',在MySQL眼里為邏輯減的意思。所以這里可以進行語句閉合。
這里成功完成延時SQL注入。
0x02 開個玩笑
剛剛不是說到HTTP協議的規則嘛,其實標準的HTTP協議規則是那樣子的,完全由于Apache對請求包解析太過于嚴格,下面我們看一下Nginx的請求包情況。~

測試#+無數個空格依然可以正常解析。
然后我們繼續追蹤PHP代碼層

注意圖中的
$Urlink=array('url_link'=>$row['language_url'],'url_ml'=>"../",'ID'=>$row['ID']);
將返回結果返回給url_link下標。
然后我們回到web_inc.php文件

這個時候$urlml攜帶著SQL語句的結果集,我們通過前臺模板看一下在哪里輸出了該結果集。

將SQL語句下標為url_link拼接給web_url_meate變量,好了,我們回到index.php找一下模板文件。

跟進看一下。

喲西,這個時候簡單構造一下聯合注入語句
Payload:?111' UNION SELECT 1,2,3,user(),5,6,7,8,9#

0x03 漏洞信息
使用BurpSuite發送GET請求包:
Apache下的SQL盲注:
GET /?'or+if(substr((select+user()),1,1)like'r',sleep(2),1)-'
Nginx下的聯合注入:

GET /?111' UNION SELECT 1,2,3,user(),5,6,7,8,9# HTTP/1.1
