0%

Web安全学习——文件包含漏洞

参考:

https://www.cnblogs.com/0daybug/p/12365559.html

https://www.jianshu.com/p/0cc01ee0d247

简介

程序开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而无需再次编写,这中文件调用的过程一般被称为文件包含。

程序开发人员一般希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。

几乎所有脚本语言都会提供文件包含的功能,但文件包含漏洞在PHP Web Application中居多,而在JSP、ASP、ASP.NET程序中却非常少,甚至没有,这是有些语言设计的弊端。

在PHP中经常出现包含漏洞,但这并不意味这其他语言不存在。

常见文件包含函数

1
2
3
include():执行到include时才包含文件,找不到被包含文件时只会产生警告,脚本将继续执行
require():只要程序一运行就包含文件,找不到被包含的文件时会产生致命错误,并停止脚本
include_once()和require_once():若文件中代码已被包含则不会再次包含

利用条件

  • 程序用include()等文件包含函数通过动态变量的范式引入需要包含的文件
  • 用户能够控制该动态变量

注意:PHP中只要文件内容符合PHP语法规范,包含时不管扩展名是什么都会被PHP解析,若文件内容不符合PHP语法规范则会暴漏其源码。包含不存在的文件则可能暴露路径

漏洞危害

  • 执行任意代码
  • 读取文件源码或敏感信息
  • 包含恶意文件控制网站
  • 甚至控制服务器

漏洞分类

  • 本地文件包含:可以包含本地文件,在条件允许时甚至能执行代码

    • 读敏感文件,读PHP文件
    • 包含日志文件GetShell
    • 上传图片马,然后包含从而GetShell
    • 包含/proc/self/envion文件GetShell
    • 包含data:或php://input等伪协议
    • 若有phpinfo则可以包含临时文件
  • 远程文件包含:可以直接执行任意代码

    • 要保证php.ini中allow_url_fopen和allow_url_include要为On

常见的敏感路径

  • Windows

C:\boot.ini //查看系统版本
C:\windows\system32\inetsrv\MetaBase.xml //IIS 配置文件
C:\windows\repair\sam //存储 windows 系统初次安装的密码
C:\Program Files\mysql\my.ini //mysql 配置
C:\Program Files\mysql\data\mysql\user.MYD //Mysql root
C:\windows\php.ini //php 配置信息
C:\windows\my.ini //mysql 配置文件

  • UNIX/Linux

/etc/passwd // 账户信息
/etc/shadow // 账户密码文件
/usr/local/app/apache2/conf/httpd.conf // Apache2默认配置文件
/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置
/usr/local/app/php5/lib/php.ini // PHP相关配置
/etc/httpd/conf/httpd.conf // Apache配置文件
/etc/my.conf // mysql 配置文件

常用的伪协议

  • php://filter

利用条件:
只是读取,所以只需要开启allow_url_fopen,对allow_url_include不做要求

用法:

1
index.php?file=php://filter/read=convert.base64-encode/resource=xxx.php

通过指定末尾文件,可以读取经base64加密后的文件源码,虽然不能直接获取shell等,但能够读取敏感文件,危害还是是挺大的。

  • php://input

可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行

利用条件:
需要开启allow_url_include=on,对allow_url_fopen不做要求

用法:?file=php://input 数据利用POST传过去。

  • zip://伪协议

zip://可以访问压缩文件中的文件

条件: 使用zip协议,需要将#编码为%23,所以需要PHP 的版本> =5.3.0,要是因为版本的问题无法将#编码成%23,可以手动把#改成%23。

用法:?file=zip://[压缩文件路径]#[压缩文件内的子文件名] zip://xxx.png#shell.php

  • phar://伪协议

与zip://协议类似,但用法不同,zip://伪协议中是用#把压缩文件路径和压缩文件的子文件名隔开,而phar://伪协议中是用/把压缩文件路径和压缩文件的子文件名隔开,即?file=phar://[压缩文件路径]/[压缩文件内的子文件名]

  • data:text/plain

和php伪协议的input类似,也可以执行任意代码,但利用条件和用法不同

条件:allow_url_fopen参数与allow_url_include都需开启

用法1:?file=data:text/plain,<?php 执行内容 ?>
用法2:?file=data:text/plain;base64,编码后的php代码

  • file://伪协议

file:// 用于访问本地文件系统,且不受allow_url_fopen与allow_url_include的影响。
用法:?file=file://文件绝对路径

常见的容易造成命令执行的函数和命令连接符

  • exec():不输出结果,返回最后一行shell结果
  • system():输出并返回最后一行shell结果
  • popen():不会直接返回执行结果,而是返回一个文件指针
  • passthru():调用命令,把命令的运行结果原样返回,直接输出到标准输出设备上,常用在所执行的Linux命令输出二进制数据时
  • proc_open():不直接返回执行结果,而是返回一个文件指针
  • pcntl_exec():执行发生错误时返回FALSE,无错误时不返回
  • shell_exec():将完整的输出以字符串的方式返回
  • ;
  • |
  • &
  • %0a
  • ``

命令执行的防护

  • escapeshellarg():给字符串增加一个单引号且能引用或者转码任何已经存在的单引号,以确保能够直接将一个字符串传入shell函数,并且还是确保安全的
  • escapeshellcmd():对字符串中可能会欺骗shell命令执行任意命令的字符进行转义,保证用户输入的数据在传送到exec()或system()函数或执行操作符前进行转义
  • 黑名单(过滤特殊字符或者替换字符)