漏洞重溫之sql注入(六)
漏洞重溫之sql注入(六)
sqli-labs通關之旅
Less-26
進入第26關,首先我們可以從網頁的提示看出本關是get型注入。

我們給頁面添加上id參數後直接去查看源碼。

需要關注的東西我已經標註在上面了。
首先,我們先來觀察第一個紅框內的程式碼。
$id=blacklist($id);
這行程式碼表示,我們通過get請求傳輸的id參數,在放到程式碼中執行的時候,是被blacklist函數給轉義過了,當然,這個blacklist函數可能是原有函數,也可能是自定義函數。
為了驗證這個猜測,我們可以仔細觀察程式碼,或者直接按ctrl+f在程式碼中搜索這個名稱,看能否發現,如果發現了封裝函數的程式碼塊,就說明這個函數是自定義,如果沒有,則為原有函數。

根據函數的內容,我們可以發現,網頁將id參數中的or,and,/*,--,#,空格,正反斜杠都過濾了。
也就是說,我們這次想要進行注入的難度比上只過濾了or and 的第二十五關困難的多。
然後我們接著看其他紅框內的程式碼。
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
這行程式碼告訴我們,如果想要在這個位置進行注入,我們需要使用單引號閉合。
if($row)
{
echo "<font size='5' color= '#99FF00'>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
這段程式碼告訴我們,如果程式碼正常執行,我們是會收穫回顯的,所以在這個位置,我們可以使用聯合查詢。同時,因為程式碼執行成功與否返回的結果不同,所以這裡我們也可以使用布爾型盲注。
print_r(mysql_error());
最後的這行程式碼,是講資料庫錯誤列印出來,讓我們可以在網頁上看到,所以我們在這裡也可以使用報錯注入。
明白了這些之後,首先我們先觀察一下幾種注入payload的語法。
聯合查詢:
union select 執行語句,佔位,佔位 --
布爾型盲註:
length((database()))>1 --
報錯注入:
updatexml(1,concat(0x7e,(執行語句),0x7e),1) --
首先,我們可以看到,這三條語句的後面,都使用到了注釋。但是同時我們也清楚,注釋是被轉義。所以,可以將注釋換成 or ' 來閉合語句中原有的單引號,這樣我們就不需要用到注釋了。
然後,我們還知道網頁過濾了空格,所以可以看到,payload裡面有兩條不使用空格就可以完成,所以我們就可以直接將聯合查詢排除,選擇使用另外兩條語句。
因為盲注的步驟相比於報錯植入要多的多,所以這裡我們使用報錯注入。
構造payload:
' || updatexml(1,concat(0x7e,(database()),0x7e),1) oorr '

PS:這裡要注意的是,||就是or的意思,為什麼前面使用雙豎杠,就是因為如果使用雙寫來繞過對or的過濾的話,那原本應該是||updatexml的語句就會變成orupdatexml,這樣會導致程式碼出錯,致使無法執行出我們希望看到的結果,所以之前我們才沒有選擇使用空格較多的聯合查詢。
第二十六關,通關。
Less-26a

查看源碼。

程式碼幾乎和第二十六關一致,唯一有區別的地方,我已經用紅框圈出來了。
首先我們可以第一行被紅框圈起來的程式碼中知道,這裡的閉合需要使用括弧加單引號。
其次,因為報錯資訊列印的那一條被注釋掉了,所以這裡,我們無法使用報錯注入獲得我們希望獲得的數據,所以這裡只能使用盲注。
構造payload如下:
1000')||length((database()))>1||('


這裡要注意,讓id等於11000的原因,是因為我們要讓前面的程式碼出錯,不使用複數是因為橫杠屬於程式碼過濾內容。
第26a關,通關。
Less-27

27關源碼。


第27關的過濾,相比於26關,有額外多了聯合查詢的關鍵字union的大小寫,以及select的大小寫和兩個關鍵字首字母大寫的情況。
但是,根據我們之前的分析,因為程式碼塊執行成功與否所返回的程式碼塊不同,我們可以使用布爾型盲注。以及執行失敗的程式碼塊中,有列印資料庫報錯資訊的程式碼,所以我們可以使用報錯注入來完成注入。
這裡,我們先使用報錯注入來進行。
構造payload:
' || updatexml(1,concat(0x7e,(database()),0x7e),1) or '

第27關,通關。
第27a關卡相對於27關,和26a相對於26關一樣。
源碼如下。

這裡,我們只需要使用雙引號閉合程式碼,並且使用盲注就可以了。
第27a,通關。
Less-28


28關的程式碼格式和前面幾關基本一致,區別,在於這個自定義函數的過濾內容。
程式碼過濾了/*,--,#,空格等,但按照之前的邏輯。既然你過濾了這些東西,那我不使用就完全不影響我的注入了。
但是,根據上面的圖片,我們看到列印資料庫報錯資訊的位置被注釋掉了。
也就是說,在這個位置,我們沒辦法直接使用報錯注入獲取我們希望獲取的內容,所以,直接使用盲注構造payload:
1000') || length((database()))>1 ||('


第28關,通關。
因為28a跟28關破關方式幾乎一樣,程式碼層的區別只在於注釋,而且相比較於28關,注釋減少,所以這裡就不做演示,按照28關的思路即可成功通關。
Less-29

29關的index頁面,基本沒有防禦,我們可以直接使用單引號閉合,隨後直接通過聯合查詢,盲注,報錯注入等方式獲取結果。
payload如下:
1' and 1=2 union select 1,2,3 --

1' and 1=2 union select 1,version(),database() --

而29關的login頁面,則是基於單引號的參數污染。
payload如下:
id=1&id=-1' union select 1,version(),database() --

Less-30
30關相對於29關,只是閉合從單引號換成了雙引號,其他內容完全一致,步驟是完全一致,這裡就不過多贅述了。
index頁面payload如下:
1" and 1=2 union select 1,version(),database() --

login頁面payload如下:
id=1&id=1' and 1=2 union select 1,version(),database() --

第30關,通關。

