当前位置: 首页 > article >正文

BUUCTF_[RoarCTF 2019]Easy Calc(RCE/waf绕过/PHP字符串解析特性/代码审计)

打开靶场

查看源代码

 

// 为 ID 为 calc 的表单的 submit 事件绑定一个处理函数
$('#calc').submit(function(){
    // 使用 jQuery 的 $.ajax 方法发起一个 AJAX 请求
    $.ajax({
        // 请求的 URL,拼接了一个参数 num,其值是 ID 为 content 的输入框的值并进行了 URI 编码
        url:"calc.php?num="+encodeURIComponent($("#content").val()),
        // 请求的类型为 GET
        type:'GET',
        // 请求成功时的回调函数
        success:function(data){
            // 将返回的数据插入到 ID 为 result 的元素中,以一个带有成功提示样式的 HTML 结构呈现
            $("#result").html(`<div class="alert alert-success">
                <strong>答案:</strong>${data}
            </div>`);
        },
        // 请求失败时的回调函数
        error:function(){
            // 弹出一个警告框提示请求失败
            alert("这啥?算不来!");
        }
    });
    // 阻止表单的默认提交行为
    return false;
});

 这段代码是用 jQuery 编写的,其主要功能是当 ID 为 calc 的表单被提交时,阻止表单的默认提交行为,然后通过 AJAX(异步的 JavaScript 和 XML)向 calc.php 发送一个 GET 请求。请求的参数 num 是 ID 为 content 的输入框中的值,并且对该值进行了 URI 编码处理。如果请求成功,会将返回的数据显示在 ID 为 result 的元素中,以一个带有成功提示样式的 HTML 结构呈现;如果请求失败,会弹出一个警告框提示 “这啥?算不来!”。

 

 思路

注释<!--I've set up WAF to ensure security.-->,我以设置waf确保安全。说明要waf绕过。源代码里并没有给出过滤的规则,发现提到了calc.php文件,这个文件负责处理传进来的参数,所以我们尝试访问它。

WAF

WAF 即 Web 应用防火墙(Web Application Firewall)

  • 防范常见攻击
    • SQL 注入防护:通过对请求中的 SQL 语句进行分析,检测是否存在恶意的 SQL 注入代码,防止攻击者通过构造恶意的 SQL 语句来获取、篡改或删除数据库中的数据。
    • 跨站脚本攻击(XSS)防护:识别请求中是否包含恶意的脚本代码,当用户访问受影响的页面时,这些脚本可能会在用户的浏览器中执行,从而窃取用户的敏感信息。
    • 跨站请求伪造(CSRF)防护:验证请求的来源,确保请求是由合法的用户发起的,防止攻击者通过诱导用户在已登录的网站上执行恶意操作。
  • 访问控制:可以根据 IP 地址、地理位置、用户代理等条件对访问进行控制。例如,禁止来自特定 IP 段的访问,或者只允许特定地区的用户访问某些资源。
  • 流量监控和日志记录:对 Web 应用的访问流量进行实时监控,记录所有的请求和响应信息。这些日志可以用于安全审计、故障排查和攻击溯源。

php代码审计

1.错误报告设置

  • error_reporting(0);
    
     

    这行代码将 PHP 的错误报告级别设置为 0,意味着关闭所有的错误报告,这样在代码执行过程中出现的错误不会显示给用户。

2.参数检查与源码显示

  • if(!isset($_GET['num'])){
        show_source(__FILE__);
    }
    
     

    检查是否通过 GET 请求传递了 num 参数。如果没有传递,使用 show_source 函数显示当前 PHP 文件的源代码。

3.输入过滤与执行

else{
    $str = $_GET['num'];
    $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
    foreach ($blacklist as $blackitem) {
        if (preg_match('/' . $blackitem . '/m', $str)) {
            die("what are you want to do?");
        }
    }
    eval('echo '.$str.';');
}

如果传递了 num 参数,将其赋值给变量 $str

然后定义了一个黑名单数组 $blacklist,包含了一些特殊字符。

通过 foreach 循环遍历黑名单,

使用 preg_match 函数检查 $str 中是否包含黑名单中的字符

如果包含则终止程序并输出提示信息what are you want to do?。

如果 $str 不包含黑名单中的字符,使用 eval 函数执行 echo $str; 代码,将 $str 的内容输出。

函数

foreach

循环主要用于遍历数组或对象,为数组或对象中的每个元素执行一次循环体中的代码。

foreach 循环有两种基本语法形式:

形式一:只获取数组的值

 
foreach ($array as $value) {
    // 循环体,使用 $value 进行操作
}
 

这里的 $array 是要遍历的数组,$value 是每次循环时从数组中取出的当前元素的值。

形式二:同时获取数组的键和值

 
foreach ($array as $key => $value) {
    // 循环体,使用 $key 和 $value 进行操作
}
 

在这种形式中,$key 是当前元素的键,$value 是当前元素的值。

执行 foreach ($blacklist as $blackitem) 时,具体步骤如下:

  1. $blacklist 数组中取出第一个元素。
  2. 将该元素的值赋给变量 $blackitem
  3. 执行循环体中的代码。
  4. 重复步骤 1 - 3,直到遍历完 $blacklist 数组中的所有元素。

preg_match
用于执行正则表达式匹配的函数。
语法:preg_match(pattern, subject[, matches[, flags = 0[, offset = 0]]])
-  pattern :要匹配的正则表达式模式。
-  subject :要进行匹配操作的目标字符串。
-  matches :可选参数,用于存储匹配结果的数组。如果匹配成功, matches[0] 将包含完整的匹配文本, matches[1] 等将包含正则表达式中捕获组匹配的内容。
-  flags :可选参数,用于指定匹配的标志,常用的有 PREG_OFFSET_CAPTURE ,会使 matches 数组中的每个元素成为一个包含匹配文本和其在 subject 中偏移量的数组。
-  offset :可选参数,指定从 subject 字符串的哪个位置开始匹配,默认为0。

eval() 

作用是把字符串作为 PHP 代码来执行。

 
eval(string $code);
 
  • $code:这是一个必需的参数,代表要被执行的 PHP 代码字符串。该字符串必须是合法的 PHP 代码,并且通常需要以分号 ; 结尾,否则可能会导致语法错误。
  • 函数返回值:如果代码字符串执行过程中没有错误,eval() 函数返回 NULL;如果执行过程中出现错误,则返回 false

代码注入风险:由于 eval 函数会执行任意的 PHP 代码,攻击者可以通过构造恶意的 num 参数来执行任意代码,例如执行系统命令、读取敏感文件等。虽然代码中设置了黑名单,但攻击者仍然可能通过绕过黑名单的方式注入恶意代码。

RCE

即远程命令 / 代码执行,是一种严重的网络安全漏洞。

RCE 漏洞通常源于应用程序对用户输入的验证和过滤不严格,使得攻击者可以通过构造恶意输入,绕过应用程序的安全机制,将恶意命令或代码注入到目标系统并执行。常见的触发方式有以下几种:

  • 代码注入:当应用程序使用动态代码执行函数(如 PHP 的 eval()、Python 的 exec() 等)处理用户输入时,如果没有对输入进行严格的验证和过滤,攻击者就可以注入恶意代码并让系统执行。
  •  命令注入:应用程序在执行系统命令时,如果将用户输入直接拼接到命令中,而没有进行适当的处理,攻击者就可以构造恶意输入来执行额外的命令。

 

做题步骤

1.waf绕过

经过简单的测试,会发现如果输字符字符会直接WAF禁止,用php字符串解析特性,在num前面加上空格或者+号。

calc.php?num=system('ls');

calc.php? num=system('ls'); 

 

服务器会认为传入的参数是 空格num ,而不是 num 。当 空格num 参数传入到后端,被 PHP 代码处理时,会被去除多余空格及特殊字符:如空格、制表符、回车换行符以及某些特殊字符等。这样一来仍然是 num 参数了。

php参数的字符串解析特性:

 在php中传参时,PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:删除空白符和将某些字符转换为下划线(包括空格)

2.构造命令查看

显示用var_dump()或print_r()都行,

当前目录用scandir

屏蔽的/可以用chr(47)

calc.php? num=print_r(scandir(chr(47)))

print_r() 函数用于以人类可读的格式输出变量。对于数组和对象,它会递归地显示其结构和元素;对于其他类型的变量,它会直接显示其值。

chr() 函数把 ASCII 码值转换为对应的字符。码值 47 对应的字符是斜杠 /

scandir() 用于列出指定目录中的文件和目录

发现疑似文件f1agg

查看文件用file_get_content()或者highlight_file()都行 

 ? num=file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103));

 其中chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)分别是 ‘/’ ‘f’ ‘1’ ‘a’ ‘g’ ‘g’ 的 ASCII 值转字符,‘.’ 用作字符串连接。每一个 chr() 函数返回的结果由于是字符,所以自带了一对引号,不需要额外再加。

 

highligh_file 函数会读取指定文件的内容,将其中的关键字用黄色背景的 <span> 标签包裹,实现高亮显示,并将结果输出。

 页面源码高亮


http://www.kler.cn/a/539206.html

相关文章:

  • 如何在Vscode中接入Deepseek
  • 代码随想录算法训练营day38
  • (done) openMP学习 (Day13: 线程私有数据和如何支持库(Pi again),蒙特卡洛计算 Pi,线性同余法)
  • Maven插件—flatten-maven-plugin:工程模块统一版本依赖
  • 浅析Ruby类污染及其在Sinatra框架下的利用
  • 如何参与开源项目
  • webpack配置之---入口
  • 基于深度学习的视觉检测小项目(十八) 图像标注界面的初步规划
  • 深入浅出:机器学习的全面解析
  • 离散型变量的 PSI-群体稳定性指标计算
  • C# 创建 Windows 应用程序教程
  • 辛格迪客户案例 | 安领生物医药(苏州)有限公司电子合约系统(eSign)项目
  • 洛谷P8681 [蓝桥杯 2019 省 AB] 完全二叉树的权值
  • 李飞飞团队 S1 与 DeepSeek R1 技术对比
  • 基于Python实现的完整解决方案,用于对包含四个类别的1500张图像数据集进行分割、训练模型,并提供简易前端和可视化结果
  • Java 网络原理 ⑤-DNS || 以太网
  • 【RocketMQ 存储】- 异步刷盘服务 FlushRealTimeService
  • Python 报错分析:IndexError: list index out of range
  • Node.js 中模块化
  • 什么是Prompt工程?
  • 蓝耘智算平台与DeepSeek R1模型:推动深度学习发展
  • 企业如何利用DeepSeek提升网络安全管理水平
  • 【JAVAFX】textarea插入数据后滚动条自动到底部
  • 量化交易数据获取:xtquant库的高效应用
  • Transformer中的嵌入位置编码
  • Golang:Go 1.23 版本新特性介绍