安全文件上传WEB漏洞—文件上传之后端黑白名单绕过
Yatming的博客WEB漏洞—文件上传之后端黑白名单绕过

文件上传常见验证:
后缀名,类型、文件头等
后缀名:黑名单、白名单
文件类型: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); $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); $file_ext = str_ireplace('::$DATA', '', $file_ext); $file_ext = trim($file_ext);
if(!in_array($file_ext, $deny_ext)) { $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的格式来解析
|

可以看到这里我上传了一个.htaccess,然后我上传了代码中指定的名称的jpg形式,并在里面包含了phpinfo,然后在访问刚刚的jpg格式的文件,结果是按照了php的格式来解析。
第五关,小迪是直接用大小写绕过了,但是这个靶场更新后,第五关加上了这个大小写检测,所以想要绕过,如下图


可以看到已经上传成功了,然后访问也可以成功。。
第六关才是大小写绕过。实在不行可以找找老版

这里直接改一下大小写就可以绕过
第七关:首尾去空
emmm,原理就是跟对方的代码匹配的不一样,因为你加了一个空格,所以呢匹配的是php+空格,而代码中的是php所以不匹配,那么你可能会问,php+空格,这样的后缀怎么执行,windows系统可以知道,是会自动把你的空格去掉的,linux没试

第八关:

相较于之前的关卡,这一关少了一个去点的函数,然后是只需要加上一个“.”,就可以成功绕过,那么你可能会问,这样的后缀是怎么执行的,可以在windows上测试一下,然后如果是1.txt.这样的文件是不允许的会强制转成1.txt
第九关:这一关黑名单,没有对::DATA 进 行 处 理 , 可 以 使 用 : : DATA进行处理,可以使用::DATA进行处理,可以使用::DATA绕过黑名单
1
| 补充知识:php在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持"::$DATA"之前的文件名 他的目的就是不检查后缀名。
|

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