学习日志(三)【php语法学习,iscc校赛wp】

1. 任务

1.1.1.1.1.1. 知识部分
  1. rce看【之前的笔记?】
  2. php的知识点学习继续
  3. jwt token好像是比赛的题目考察内容,我看看
  4. php伪协议
1.1.1.1.1.2. 题目
  1. 参加iscc比赛【五一】
  2. rce题目
1.1.1.1.1.3. 环境配置
  1. 把vscode搞好,上学期没有把Php配置弄好

2. 知识点学习

2.1. php继续学习

https://www.runoob.com/php/php-variables.html

2.1.1. php if-else

2.1.2. lfelse语句

2.1.2.1. 条件语句
  • if 语句 - 在条件成立时执行代码
  • if...else 语句 - 在条件成立时执行一块代码,条件不成立时执行另一块代码
  • if...elseif....else 语句 - 在若干条件之一成立时执行一个代码块
  • switch 语句 - 在若干条件之一成立时执行一个代码块
2.1.2.2. 其实c语言里面已经讲过,简单带过

2.1.3. php switch语句

复制代码
<?php
switch (expression) {
    case value1:
        // 代码块1
        break;
    case value2:
        // 代码块2
        break;
    // 更多的 case 语句
    default:
        // 如果没有匹配的值
}
?>
  • expression 是要被比较的表达式。
  • case value: 是可能的值,如果 expression 的值等于某个 case 的值,就执行相应的代码块。
  • break; 用于终止 switch 语句,防止继续执行下一个 case
  • default: 是可选的,用于指定当没有匹配的 case 时执行的代码块。
2.1.3.1.1. 栗子
复制代码
<?php
$favcolor="red";
switch ($favcolor)
{
case "red":
    echo "你喜欢的颜色是红色!";
    break;
case "blue":
    echo "你喜欢的颜色是蓝色!";
    break;
case "green":
    echo "你喜欢的颜色是绿色!";
    break;
default:
    echo "你喜欢的颜色不是 红, 蓝, 或绿色!";
}
?>

2.1.4. php 数组

数组是一个能在单个变量中存储多个值的特殊变量。

  • 数值数组 - 带有数字 ID 键的数组
  • 关联数组 - 带有指定的键的数组,每个键关联一个值
  • 多维数组 - 包含一个或多个数组的数组
2.1.4.1. 数值数组

自动从0开始计数,可以更加便捷地去表示这个位置内容数据

2.1.4.1.1. 获取长度

count($cars)

2.1.4.1.2. 遍历

使用For循环

2.1.4.2. 关联数组

指代,,

2.1.4.2.1. 遍历数组
2.1.4.2.1.1. 补充【使用函数foreach】
复制代码
// 格式1:只获取元素值,不需要键名
foreach (要遍历的数组 as $当前元素值) {
         // 循环体逻辑
         }

// 格式2:同时获取元素的键和值
foreach (要遍历的数组 as $当前键名 => $当前元素值) {
                  // 循环体逻辑
                  }

栗子:

复制代码
$userInfo = [
    "username" => "admin",
    "role" => "root",
    "id" => 1
];

foreach ($userInfo as $key => $value) {
    echo "{$key}:{$value}<br>";
}
// 输出:
// username:admin
// role:root
// id:1

$userInfo = [
    "username" => "admin",
    "role" => "root",
    "id" => 1
];

// 只拿值,不拿键
foreach ($userInfo as $value) {
    echo "{$value}<br>";
}
// 输出:
// admin
// root
// 1


foreach ($userInfo as $key => $value) {
    echo "{$key}<br>";
}
//输出
// username
// role
// id

2.1.5. php数组排序

  • sort() - 对数组进行升序排列
  • rsort() - 对数组进行降序排列
  • asort() - 根据关联数组的值,对数组进行升序排列
  • ksort() - 根据关联数组的键,对数组进行升序排列
  • arsort() - 根据关联数组的值,对数组进行降序排列
  • krsort() - 根据关联数组的键,对数组进行降序排列
2.1.5.1. sort(),rsort()

0\]=\>2,,,\[1\]=\>4 ##### 2.1.5.2. asort(),arsort(),ksort(),krsort() a:是值,后面那个=\> # k:是键,前面那个 # =\> ![](https://i-blog.csdnimg.cn/img_convert/cde967e0b792c5a3931bb124c00754f2.png) #### 2.1.6. PHP 表单 - 验证邮件和URL ###### 2.1.6.1.1. preg_match --- 进行正则表达式匹配 `int preg_match ( string $pattern , string $subject [, array $matches [, int $flags ]] )` |------------|--------|------------------------------------------------------------------| | **参数** | **作用** | **说明** | | `$pattern` | 正则规则 | 必填,必须是完整的**正则表达式** ,需要用分隔符包裹(常用`/` ,例如`/test/i`) | | `$subject` | 目标字符串 | 必填,要**匹配的原始字符串** | | `$matches` | 匹配结果 | 可选,存储匹配到的结果:`$matches[0]`是整个正则匹配到的内容,`$matches[1]`是第一个分组的结果,以此类推 | | `$flags` | 标记位 | 可选,用来修改匹配行为,常用值:`PREG_OFFSET_CAPTURE` 会同时返回匹配结果在字符串中的偏移位置 | 匹配成功,输出=\>1,对应内容, 若`!preg_match($pattern, $username)`则是不符合,不匹配时进行的操作 |--------|--------|----------------------------------------| | **符号** | **含义** | **作用** | | `/` | 正则定界符 | PHP正则必须用分隔符把规则包起来,常用`/`,只是语法要求,本身不匹配内容 | | `^` | 匹配开头 | 代表必须从字符串的**第一个字符**就开始符合规则,不能在开头插入其他内容 | | `\d` | 匹配数字 | 和`[0-9]`一个意思,代表只能匹配0\~9的阿拉伯数字 | | `+` | 量词 | 代表前面的`\d`至少出现1次,不允许空字符串 | | `$` | 匹配结尾 | 代表必须匹配到字符串的**最后一个字符**,不能在结尾留其他非数字内容 | ###### 2.1.6.1.1.1. 例子1:获取URL中的参数值(CTF代码审计常考) 提取URL路径中`/flag_xxxxxx`格式的flag编号: $url = "/api/flag_1a2b3c4d/get.php"; // 正则匹配flag_后面的任意字符 $pattern = '/flag_([a-zA-Z0-9]+)/'; preg_match($pattern, $url, $matches); echo "匹配到的flag:flag_" . $matches[1]; // 输出:匹配到的flag:flag_1a2b3c4d *** ** * ** *** ###### 2.1.6.1.1.2. 例子2:用户名正则校验(绕过场景) 场景:要求用户名只能是字母,不能包含特殊字符,且必须以字母开头: $username = "admin123"; // 正则规则:开头到结尾只能是字母 $pattern = '/^[a-zA-Z]+$/'; if (!preg_match($pattern, $username)) { echo "用户名不合法,不能包含数字!";//匹配不成功 } else { echo "用户名合法"; } // 这里$username是admin123,输出:用户名不合法,不能包含数字! 对应PHP 5.2下的绕过例子: 如果正则要求必须只包含字母,但我们想插入攻击代码,可以用空字节截断绕过: // 插入了\0(%00)截断,后面的攻击代码不会被检查 $username = "admin\0"; $pattern = '/^[$/'; if (!preg_match($pattern, $username)) { echo "用户名不合法!"; } else { echo "用户名合法"; } // 在PHP 5.2中会输出"用户名合法",成功绕过正则检测 *** ** * ** *** ###### 2.1.6.1.1.3. 例子3:WAF绕过(数组绕过) a-zA-Z\]+场景:WAF用preg_match检测POST参数中是否有`eval`等危险关键词: // 服务端检测逻辑 if (preg_match('/eval|union|select/i', $_POST['content'])) { die("检测到恶意内容,已拦截");//匹配成功 } echo "请求通过"; // 绕过方法:把content传成数组,而不是字符串: // content[0]=test,此时preg_match匹配数组会直接返回false,WAF拦截不生效 // 最终会输出"请求通过",绕过成功 这也是你做Web渗透测试时非常实用的绕过技巧。 ##### 2.1.6.1. 验证 URL,邮箱,名称 #### 2.1.7. php 时间 `string date ( string $format [, int $timestamp ] )` |-----------|-----------------------| | 参数 | 描述 | | format | 必需。规定时间戳的格式。 | | timestamp | 可选。规定时间戳。默认是当前的日期和时间。 | date() 函数的第一个必需参数 *format* 规定了如何格式化日期/时间。 ![](https://i-blog.csdnimg.cn/img_convert/9d7230bbb0a4711b306f14274ddc3a7e.png) |---------------|----------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------| | `format` 字符 | 说明 | 返回值例子 | | *日* | --- | --- | | *d* | 月份中的第几天,有前导零的 2 位数字 | *01* 到 *31* | | *D* | 星期中的第几天,文本表示,3 个字母 | *Mon* 到 *Sun* | | *j* | 月份中的第几天,没有前导零 | *1* 到 *31* | | *l*("L"的小写字母) | 星期几,完整的文本格式 | *Sunday* 到 *Saturday* | | *N* | ISO-8601 格式数字表示的星期中的第几天(PHP 5.1.0 新加) | *1* (表示星期一)到 *7*(表示星期天) | | *S* | 每月天数后面的英文后缀,2 个字符 | *st* ,*nd* ,*rd* 或者 *th* 。可以和 *j* 一起用 | | *w* | 星期中的第几天,数字表示 | *0* (表示星期天)到 *6*(表示星期六) | | *z* | 年份中的第几天 | *0* 到 *365* | | *星期* | --- | --- | | *W* | ISO-8601 格式年份中的第几周,每周从星期一开始(PHP 4.1.0 新加的) | 例如:*42*(当年的第 42 周) | | *月* | --- | --- | | *F* | 月份,完整的文本格式,例如 January 或者 March | *January* 到 *December* | | *m* | 数字表示的月份,有前导零 | *01* 到 *12* | | *M* | 三个字母缩写表示的月份 | *Jan* 到 *Dec* | | *n* | 数字表示的月份,没有前导零 | *1* 到 *12* | | *t* | 给定月份所应有的天数 | *28* 到 *31* | | *年* | --- | --- | | *L* | 是否为闰年 | 如果是闰年为 *1* ,否则为 *0* | | *o* | ISO-8601 格式年份数字。这和 *Y* 的值相同,只除了如果 ISO 的星期数(*W*)属于前一年或下一年,则用那一年。(PHP 5.1.0 新加) | Examples: *1999* or *2003* | | *Y* | 4 位数字完整表示的年份 | 例如:*1999* 或 *2003* | | *y* | 2 位数字表示的年份 | 例如:*99* 或 *03* | | *时间* | --- | --- | | *a* | 小写的上午和下午值 | *am* 或 *pm* | | *A* | 大写的上午和下午值 | *AM* 或 *PM* | | *B* | Swatch Internet 标准时 | *000* 到 *999* | | *g* | 小时,12 小时格式,没有前导零 | *1* 到 *12* | | *G* | 小时,24 小时格式,没有前导零 | *0* 到 *23* | | *h* | 小时,12 小时格式,有前导零 | *01* 到 *12* | | *H* | 小时,24 小时格式,有前导零 | *00* 到 *23* | | *i* | 有前导零的分钟数 | *00* 到 *59*\> | | *s* | 秒数,有前导零 | *00* 到 *59*\> | | *u* | 毫秒 (PHP 5.2.2 新加)。需要注意的是 **date()** 函数总是返回 *000000* 因为它只接受 integer 参数, 而 DateTime::format() 才支持毫秒。 | 示例: *654321* | | *时区* | --- | --- | | *e* | 时区标识(PHP 5.1.0 新加) | 例如:*UTC* ,*GMT* ,*Atlantic/Azores* | | *I* | 是否为夏令时 | 如果是夏令时为 *1* ,否则为 *0* | | *O* | 与格林威治时间相差的小时数 | 例如:*+0200* | | *P* | 与格林威治时间(GMT)的差别,小时和分钟之间有冒号分隔(PHP 5.1.3 新加) | 例如:*+02:00* | | *T* | 本机所在的时区 | 例如:*EST* ,*MDT*(【译者注】在 Windows 下为完整文本格式,例如"Eastern Standard Time",中文版会显示"中国标准时间")。 | | *Z* | 时差偏移量的秒数。UTC 西边的时区偏移量总是负的,UTC 东边的时区偏移量总是正的。 | *-43200* 到 *43200* | | *完整的日期/时间* | --- | --- | | *c* | ISO 8601 格式的日期(PHP 5 新加) | 2004-02-12T15:19:21+00:00 | | *r* | RFC 822 格式的日期 | 例如:*Thu, 21 Dec 2000 16:01:07 +0200* | | *U* | 从 Unix 纪元(January 1 1970 00:00:00 GMT)开始至今的秒数 | 参见 time() | #### 2.1.8. php过滤器 ##### 2.1.8.1. 过滤器是什么 PHP 过滤器用于**验证和过滤**来自非安全来源的数据。 测试、验证和过滤用户输入或自定义数据是任何 Web 应用程序的重要组成部分。 PHP 的过滤器扩展的设计目的是使数据过滤更轻松快捷。 ##### 2.1.8.2. 函数和过滤器 * `filter_var()` - 通过一个指定的过滤器来过滤单一的变量 * `filter_var_array()` - 通过相同的或不同的过滤器来过滤多个变量 * `filter_input` - 获取一个输入变量,并对它进行过滤 * `filter_input_array` - 获取多个输入变量,并通过相同的或不同的过滤器对它们进行过滤 ###### 2.1.8.2.1. 栗子 * `FILTER_VALIDATE_INT`:验证**是否是整数**,验证数字参数最常用 // 验证id是否是整数 $id = $_GET['id']; if(filter_var($id, FILTER_VALIDATE_INT)){ echo "合法参数"; } * `FILTER_SANITIZE_STRING`:过滤字符串,去除标签和特殊字符,用来防止XSS * `FILTER_VALIDATE_URL`:验证URL格式,代码题中经常用来考URL绕过【`FILTER_VALIDATE_URL`要求必须有http://协议头,我们可以通过在URL中嵌入`@`来绕过host验证,例如`http://example.com@127.0.0.1`,会被误认为访问`example.com`实际解析的是`127.0.0.1`,可以触发SSRF绕过。】 * `FILTER_VALIDATE_IP`:验证IP地址格式 ##### 2.1.8.3. Validating 和 Sanitizing 有两种过滤器: Validating 过滤器: * 用于验证用户输入 * 严格的格式规则(比如 URL 或 E-Mail 验证) * 如果成功则返回预期的类型,如果失败则返回 FALSE Sanitizing 过滤器: * 用于允许或禁止字符串中指定的字符 * 无数据格式规则 * 始终返回字符串验证输入 * **第一段:** **FILTER_VALIDATE_EMAIL** * * 属于**验证类过滤器** :只做格式验证,返回结果是 `true`(合法) 或 `false`(非法),不会修改你的原始输入。 * **第二段:** **FILTER_SANITIZE_URL** * * 属于**净化类过滤器**:会直接修改输入内容,自动删除URL中不允许的特殊字符(比如空格、非ASCII字符、#、\<\>这些符号),返回处理后的干净字符串。 ##### 2.1.8.4. 验证输入 上面的实例有一个通过 "GET" 方法传送的输入变量 (email): 1. 检测是否存在 "GET" 类型的 "email" 输入变量 2. 如果存在输入变量,检测它是否是有效的 e-mail 地址 ![](https://i-blog.csdnimg.cn/img_convert/77737caca64ab72640afb4a3d38c9ce5.jpeg) ##### 2.1.8.5. 净化输入 上面的实例有一个通过 "GET" 方法传送的输入变量 (url): 1. 检测是否存在 "GET" 类型的 "url" 输入变量 2. 如果存在此输入变量,对其进行净化(删除非法字符),并将其存储在 $url 变量中 ![](https://i-blog.csdnimg.cn/img_convert/fc4306a295226780c9d3a79506a3f7b0.jpeg) ##### 2.1.8.6. 过滤多个输入 array ( "filter"=>FILTER_SANITIZE_STRING ), // age字段:验证是否是整数,同时限制范围1-120 "age" => array ( "filter"=>FILTER_VALIDATE_INT, "options"=>array ( "min_range"=>1, "max_range"=>120 ) ), // email字段:直接验证邮箱格式 "email"=> FILTER_VALIDATE_EMAIL ); $result = filter_input_array(INPUT_GET, $filters); //一次性从INPUT_GET(也就是URL参数)中获取三个参数, //按照上面定义的规则分别过滤,结果会按字段名存回到$result数组中。 if (!$result["age"]) { echo("年龄必须在 1 到 120 之间。
"); } elseif(!$result["email"]) { echo("E-Mail 不合法
"); } else { echo("输入正确"); } ?> `filter_input_array() `函数的第二个参数可以是**数组** 或**单一过滤器的 ID**。 如果该参数是单一过滤器的 ID,那么这个指定的过滤器会过滤输入数组中所有的值。 如果该参数是一个数组,那么此数组必须遵循下面的规则: * 必须是一个关联数组,其中包含的输入变量是数组的键(比如 "age" 输入变量) * 此数组的值必须是过滤器的 ID ,或者是规定了过滤器、标志和选项的数组 ##### 2.1.8.7. 使用 Filter Callback 通过使用 `FILTER_CALLBACK `过滤器,可以调用自定义的函数,把它作为一个过滤器来使用。 ## 3. 题目 ### 3.1. iscc题目一 #### 3.1.1. 题目 ![](https://i-blog.csdnimg.cn/img_convert/407de7c0b65dc0871f8d9b84102d2af4.png) #### 3.1.2. 解题 ##### 3.1.2.1. 第一步 随便输入一个数 ![](https://i-blog.csdnimg.cn/img_convert/45144f299c6aa60426627783f69cbdae.png) ##### 3.1.2.2. 第二步 看不懂,这个知识点我应该是不会,一番查询过后,好像考察的是JWT的token? 查博客 * [token与JWT详细介绍_jwt token-CSDN博客](https://blog.csdn.net/m0_56750901/article/details/125493359?ops_request_misc=elastic_search_misc&request_id=3fb593d6064a4909eba9bb42df5ea3a4&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-125493359-null-null.142^v102^pc_search_result_base3&utm_term=jwt%20token&spm=1018.2226.3001.4187 "token与JWT详细介绍_jwt token-CSDN博客") * [基于jwt的token验证、原理及流程_jwt token-CSDN博客](https://blog.csdn.net/z_ssyy/article/details/130971321?ops_request_misc=elastic_search_misc&request_id=3fb593d6064a4909eba9bb42df5ea3a4&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-130971321-null-null.142^v102^pc_search_result_base3&utm_term=jwt%20token&spm=1018.2226.3001.4187 "基于jwt的token验证、原理及流程_jwt token-CSDN博客") * [一篇了解什么是Token、什么是Jwt_jwt token-CSDN博客](https://blog.csdn.net/weixin_44147535/article/details/135167800?ops_request_misc=&request_id=&biz_id=102&utm_term=jwt%20token&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-135167800.142^v102^pc_search_result_base3&spm=1018.2226.3001.4187 "一篇了解什么是Token、什么是Jwt_jwt token-CSDN博客") * [JWT(JSON Web Token)全维度渗透测试实战与防御体系构建_cve-2020-26160-CSDN博客](https://blog.csdn.net/weixin_42376192/article/details/157578373?ops_request_misc=&request_id=&biz_id=102&utm_term=jwt%20token%E5%AE%9E%E6%88%98&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-157578373.142^v102^pc_search_result_base3&spm=1018.2226.3001.4187 "JWT(JSON Web Token)全维度渗透测试实战与防御体系构建_cve-2020-26160-CSDN博客") 应该可能使用的工具 [JWT在线工具 - kjson在线工具](https://www.kjson.com/jwt/ "JWT在线工具 - kjson在线工具") [在线JWT Token生成](https://www.lddgo.net/encrypt/jwt-generate "在线JWT Token生成") ##### 3.1.2.3. 放弃 ##### 3.1.2.4. 额,看了眼别人的答案 得知,没有我想的那么复杂,只是一个简单的key过滤【我竟然还想了那么多】 首先输入`key123`,发现key没了,说明被绕过了,这个其实在题目也有提示 ![](https://i-blog.csdnimg.cn/img_convert/9188b24d553248dfdd6ebfed4f3af33a.png) 然后想办法绕过这个key,如双写kkeyey ![](https://i-blog.csdnimg.cn/img_convert/1ee4743f493a66fbecc8c5e9a7aeeb75.png) 第一关过了,接下来让你用post写a a[key]=1337 ![](https://i-blog.csdnimg.cn/img_convert/bef237063c9b60a466b35a5d6c9fe4fa.png) 下一关,用get来写,要使得a,b相等,md5的哈希碰撞(有专门的计算方式,一查就可) a=240610708 b=314282422 ![](https://i-blog.csdnimg.cn/img_convert/ab94bc351a817315e79a2c7637f0f403.png) ### 3.2. iscc题目二 #### 3.2.1. 题目 我们上线了一个"JSON 美化 + 预览"小工具:提交数据后会生成一个临时预览文件,方便复查内容。 #### 3.2.2. 解答过程 ##### 3.2.2.1. 第一步,我先照抄了一下json ![](https://i-blog.csdnimg.cn/img_convert/61df3395d8872a0f56700e36e258d783.png) ![](https://i-blog.csdnimg.cn/img_convert/c822037b169037c2b4873d66001a7218.png) ##### 3.2.2.2. 第二步,发现错误提示 ![](https://i-blog.csdnimg.cn/img_convert/c799164bddfb88de216119c62c33b8f1.png) `/robots.txt` ##### 3.2.2.3. 第三步,前往 ![](https://i-blog.csdnimg.cn/img_convert/e5815429e010452c9efd9614b05b58c4.png) `preview.php``beautify.php`发现这两个地方也是不可访问,可能是没写完整 ![](https://i-blog.csdnimg.cn/img_convert/8925b833286a9c313ee8849c80700945.png) ![](https://i-blog.csdnimg.cn/img_convert/e1606c65f7caee1380204c67cf165c8c.png) ##### 3.2.2.4. 第四步,根据`preview.php`要求,查找`preview.php`源代码 使用**伪协议** ,去看`preview.php`的源代码,因为之前只看见`beautify.php`的源代码 ![](https://i-blog.csdnimg.cn/img_convert/cafbc4e04cfe2ade5b450836349dc9ec.png) 根据提示,可能是层级不对 ![](https://i-blog.csdnimg.cn/img_convert/6ad933b271efc6a54bb4e0c892470b55.png) 找到源代码了 \n\n" . "有些东西离这里有点远,也许换个路径层级再看看,会遇到更有意思的文件。\n" ); } $file = (string)$_GET['file']; $file = str_replace("\0", '', $file); $requested = TMP_DIR . '/' . $file; if (strpos($requested, TMP_DIR) !== 0) { out(400, "Bad path\n"); } $real = realpath($requested); if ($real === false || !is_file($real)) { out(404, "Not Found\n"); } $tmpPrefix = rtrim(TMP_DIR, '/') . '/'; $srcPrefix = rtrim(SRC_API_DIR, '/') . '/'; if (!startsWith($real, $tmpPrefix) && !startsWith($real, $srcPrefix)) { out(403, "Forbidden\n"); } $content = file_get_contents($real); if ($content === false) { out(500, "Read error\n"); } $isTmp = startsWith($real, $tmpPrefix) && preg_match('/\.tmp$/', $real) === 1; $line = trim((string)$content); if ($isTmp) { $scheme = schemeOf($line); if ($scheme !== null) { $deny = [ 'http', 'https', 'ftp', 'ftps', 'phar', 'expect', ]; if (in_array($scheme, $deny, true)) { out(403, "Forbidden scheme\n"); } $pos = stripos($line, 'resource='); if ($pos === false) { out(400, "Bad reference\n"); } $resource = rawurldecode(substr($line, $pos + 9)); if ($resource !== FLAG_PATH) { out(403, "Forbidden resource\n"); } $data = @file_get_contents($line); if ($data === false) { out(500, "Resource read error\n"); } echo $data; exit; } } echo $content; ###### 3.2.2.4.1.1. 补充知识点 **读取网站当前目录的源码** 当不确定网站的绝对路径时,不需要爆破路径,直接通过`php://filter/read=convert.base64-encode/resource=/proc/self/cwd/xxx.php`,就可以直接读取当前目录下任意PHP文件的源码,完美解决路径未知的问题。 ##### 3.2.2.5. 第五步,进行代码审计 我打包给ai了, 1. declare(strict_types=1); 开启PHP严格类型模式,强制函数参数和返回值必须匹配声明的类型, 避免隐式类型转换导致的安全问题,是现代PHP安全编码的标准写法。 1. header('Content-Type: text/plain; charset=utf-8'); header('X-Powered-By: JSON Preview'); 第一行:强制响应内容为纯文本UTF8编码,避免乱码 第二行:自定义响应头,模拟成JSON预览工具的后端接口 1. require_once __DIR__ . '/config.php'; 作用:加载当前目录下的config.php配置文件, 通常这里会定义TMP_DIR、SRC_API_DIR、FLAG_PATH等题目核心常量。 1. 漏洞点1 $deny = [ 'http', 'https', 'ftp', 'ftps', 'phar', 'expect', ]; **没有过滤** **php://****流协议** ,尤其是`php://filter`\[伪协议绕过

  1. 漏洞点2

    pos = stripos(line, 'resource=');
    //resource=就是9
    resource = rawurldecode(substr(line, pos + 9)); //做了一次URL解码 if (resource !== FLAG_PATH) {
    out(403, "Forbidden resource\n");
    }

复制代码
$data = @file_get_contents($line);

用file_get_contents直接读取用户传入的URI内容

file_get_contents解析URI时,PHP自动对URI进行第二次解码【所以要编码两次】
3.2.2.6. 第六步,答案

php://filter/convert.base64-encode/resource=/secret/flag

|-------------------------|-----------------------------|
| convert.base64-encode | 过滤器,作用是将读取到的文件内容做Base64编码转换 |

对上面进行base64编码

data:text/plain;base64,cGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9yZXNvdXJjZT0vc2VjcmV0L2ZsYWc=

去访问,在preview.php的页面中传入**?file=preview文件**

https://www.toolhelper.cn/EncodeDecode/Base64解码

相关推荐
星夜夏空996 小时前
STM32单片机学习(16) —— 中断相关概念
stm32·单片机·学习
plainGeekDev6 小时前
Kotlin协程面试题:suspend原理都说不清,协程你真会用?
android·面试·kotlin
青春喂了后端7 小时前
Go Sidecar Repository 并发锁改造:让并发请求安全地进入 Git 仓库层
git·安全·golang
KobeSacre7 小时前
UML 学习
学习·uml
Kapaseker7 小时前
Android 官方开始拥抱 WebView
android
祁白_7 小时前
PHP无参读取文件与RCE总结
安全·php·writeup·总结·rce
无风听海7 小时前
Cookie 深度技术指南:从原理到安全实践
安全
2501_931803757 小时前
Go 接口学习笔记:从语法到心法
笔记·学习·golang
汤愈韬7 小时前
IP安全 SEC VPN_2
网络·网络协议·安全·网络安全·security