WEB漏洞—文件上传之后端黑白名单绕过

WEB漏洞—文件上传之后端黑白名单绕过

7e72e06d9f7ec67e130c726bfc2715a3

文件上传常见验证:
后缀名,类型、文件头等
后缀名:黑名单、白名单
文件类型:M工ME信息
文件头:内容头信息
方法:查看源码、抓包修改包信息

黑名单:明确不让上传的脚本格式后缀,没有拒绝一律允许

白名单:明确可以上传的脚本格式后缀,没有允许一律拒绝

MIME

MIME(Multipurpose Internet Mail Extensiions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

注:Tomcat的安装目录\conf\web.xml中就定义了大量MIME类型。

类型 后缀 MIME
Microsoft Word文件 .word application/msword
PDF文件 .pdf application/pdf
GIF图形 .gif image/gif
JPEG图形 .jpeg .jpg image/jpeg
au声音文件 .au audio/basic
MIDI音乐文件 .mid .midi audio/midi audio/x-midi
RealAudio音乐文件 .ra .ram audio/x-pn-realaudio
MPEG文件 .mpg .mpeg video/mpeg
AVI文件 .avi video/x-msvideo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$_FILES数组内容
$_FILES['myFile']['name'] 客户端文件的原名称。

$_FILES['myFile']['type'] 文件的 MIME 类型,需要浏览器提供该信息的支持,例如"image/gif"

$_FILES['myFile']['size'] 已上传文件的大小,单位为字节。

$_FILES['myFile']['tmp_name'] 文件被上传后在服务端储存的临时文件名,一般是系统默认。可以在php.ini的upload_tmp_dir 指定。

$_FILES['myFile']['error'] 和该文件上传相关的错误代码。['error'] 是在 PHP 4.2.0 版本中增加的。下面是它的说明:(它们在PHP3.0以后成了常量)
UPLOAD_ERR_OK 值:0; 没有错误发生,文件上传成功。
UPLOAD_ERR_INI_SIZE 值:1; 上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。
UPLOAD_ERR_FORM_SIZE 值:2; 上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。(我们可以在form表单中指定input type='hidden' name='MAX_FILE_SIZE' value='附件的最大字节数')
UPLOAD_ERR_PARTIAL 值:3; 文件只有部分被上传。
UPLOAD_ERR_NO_FILE 值:4; 没有文件被上传。

php中各个函数的作用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
trim:
trim() 方法用于删除字符串的头尾空白符,空白符包括:空格、制表符 tab、换行符等其他空白符等。
trim() 方法不会改变原始字符串。
trim() 方法不适用于 null, undefined, Number 类型。

strrchr:
strrchr:函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符
注释:该函数是二进制安全的。

strtolower:强制转换为小写

str_ireplace() 函数替换字符串中的一些字符(不区分大小写)。
实例
把字符串 "Hello world!" 中的字符 "WORLD"(不区分大小写)替换成 "Peter":
<?php
echo str_ireplace("WORLD","Peter","Hello world!");
?>
//把这个helloworld里面的world替换成peter,不区分大小写


GET方式会自动解码,POST方式不会自动解码。

%00截断:可以把这个放在文件名内,绕过检测。get:会自动解码 post:不会自动解码,所以想以post提交数据%00需要把它进行url编码变成%25%30%30

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
%00截断原理
因为这个字符在很多编程语言里作为字符串结束的标识,所以读取到%00,就会认为数据已经结束
关于00截断区别,直接摘取前辈的文章
漏洞影响版本必须在5.4.x<= 5.4.39,5.5.x<= 5.5.23,5.6.x <= 5.6.7 ,且magic_quotes_gpc是off状态
对于的漏洞CVE编号:https://nvd.nist.gov/vuln/detail/CVE-2015-2348
利用原理方式:https://www.cnblogs.com/cyjaysun/p/4390930.html

具体关于0x00截断原理
在C/PHP等语言中,截断的核心,就是chr(0)。chr()是一个函数,这个函数是用来返回参数所对应的字符的,也就是说,参数是一个ASCII码,返回的值是一个字符,类型为string。
那么chr(0)就很好理解了,对照ASCII码表可以知道,ASCII码为0-127的数字,每个数字对应一个字符,而0对应的就是NUT字符(NULL),也就是空字符,而截断的关键就是于这个空字符。
当一个字符串中存在空字符的时候,在被解析的时候会导致空字符后面的字符被丢弃。换句话说就是会误把它当成结束符,后面的数据直接忽略,这就导致漏洞产生。可能有时候我们会看到%00截断和0x00截断等说法。
那么 %00截断和0x00截断有啥区别呢?
其实他们的截断原理都一样,%00只不过是对ascii码中的0对应的字符编码后的结果。0x开头表示16进制,0在十六进制中是00, 0x00则是%00解码成的16进制。
需要注意:当url中的参数是通过GET方式获取时,%00会被自动解码。而当参数是通过POST方式获取时,是不会自动解码的,也就是说%00只会原样被当成字符串来输出。
所以通过POST方式请求此类参数的时候,我们需要手动将它的十六进制改写为0x00。


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
<?php
include '../config.php';
include '../common.php';
include '../head.php';
include '../menu.php';

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array('.asp','.aspx','.php','.jsp');//设置黑名单的格式
$file_name = trim($_FILES['upload_file']['name']);//这个是去除你上传的文件名两边的空格之类的
$file_name = deldot($file_name);//删除文件名末尾的点,这个是杜绝类似于:x.jpg.zip.php这样就有可能实现绕过
$file_ext = strrchr($file_name, '.');//找到“.”最后一次出现的位置,返回最后一个点到字符串结尾的所有字符,这样做的目的是为了从右到左检查文件名后缀,防止攻击者用多个后缀进行绕过
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空

if(!in_array($file_ext, $deny_ext)) {//判断你上传的文件是否符合这个deny里面的规则,如果在规则中就拒绝,如果不在就上传,因为前面有一个!是取反的意思
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
?>

htaccess(只有apache可以用,其他是没有的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.htaccess是什么

.htaccess文件(或者"分布式配置文件")提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。

概述来说,htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。

启用.htaccess,需要修改httpd.conf,启用AllowOverride,并可以用AllowOverride限制特定命令的使用。如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:AccessFileName .config。

笼统地说,.htaccess可以帮我们实现包括:文件夹密码保护、用户自动重定向、自定义错误页面、改变你的文件扩展名、封禁特定IP地址的用户、只允许特定IP地址的用户、禁止目录列表,以及使用其他文件作为index文件等一些功能。


代码:
<FilesMatch "shana">
SetHandler application/x-httpd-php
</FilesMatch>
将其保存为一个.htaccess的文件
代码解析:如果有文件名有“shana”的就将他按照php的格式来解析

Snipaste_2022-05-09_14-46-00

可以看到这里我上传了一个.htaccess,然后我上传了代码中指定的名称的jpg形式,并在里面包含了phpinfo,然后在访问刚刚的jpg格式的文件,结果是按照了php的格式来解析。

第五关,小迪是直接用大小写绕过了,但是这个靶场更新后,第五关加上了这个大小写检测,所以想要绕过,如下图

Snipaste_2022-05-09_14-59-41

Snipaste_2022-05-09_14-59-53

可以看到已经上传成功了,然后访问也可以成功。。

第六关才是大小写绕过。实在不行可以找找老版

Snipaste_2022-05-09_15-04-32

这里直接改一下大小写就可以绕过

第七关:首尾去空

emmm,原理就是跟对方的代码匹配的不一样,因为你加了一个空格,所以呢匹配的是php+空格,而代码中的是php所以不匹配,那么你可能会问,php+空格,这样的后缀怎么执行,windows系统可以知道,是会自动把你的空格去掉的,linux没试

Snipaste_2022-05-09_15-10-29

第八关:

Snipaste_2022-05-09_15-14-38

相较于之前的关卡,这一关少了一个去点的函数,然后是只需要加上一个“.”,就可以成功绕过,那么你可能会问,这样的后缀是怎么执行的,可以在windows上测试一下,然后如果是1.txt.这样的文件是不允许的会强制转成1.txt

第九关:这一关黑名单,没有对::DATA 进 行 处 理 , 可 以 使 用 : : DATA进行处理,可以使用::DATA进行处理,可以使用::DATA绕过黑名单

1
补充知识:php在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持"::$DATA"之前的文件名 他的目的就是不检查后缀名。

Snipaste_2022-05-09_15-26-45

后面的关卡,打算直接创建一个专题,里面是靶场的通过教程。