任意文件读取/删除
很多网站由于业务需求,往往需要提供文件下载、读取、删除等功能块,但是如果对下载的文件没有做限制,直接通过绝对路径、相对路径对其文件进行读取,那么,用户就可以利用这种方式读取服务器的敏感文件、获取网站源代码、进行SSRF漏洞攻击。
产生原因
- 存读取文件的函数
- 读取文件的路径用户可控,且未校验或校验不严
- 输出了文件内容
文件读取函数
- show_source() 高亮显示文件内容
- highlight_file() 高亮显示文件内容(别名)
- readfile() 读取文件内容并输出
- file_get_contents() 将文件读取为字符串
- file() 将文件安行读取为数组
绝对路径与相对路径
文件路径就是文件在电脑中的位置,表示文件路径的方式有两种,相对路径和绝对路径。在网页设计中通过路径可以表示链接,插入图像、CSS文件,或者用来读取、下载、包含文件。
漏洞产生位置
读取/下载图片、文件内容;
下载附件;
预览文档;
导出文档;
修改、保存文档等
删除文件、附件、图片、替换、配置等
利用方式
读取web源码
读取数据库文件
读取服务器配置文件
读取日志文件
读取proc文件系统
… …
Linux系统配置文件
/etc/passwd 系统用户账号
/etc/shadow 系统用户密码
/etc/hosts ip地址与域名快速解析的文件
/root/.bash_history root的bash历史记录
/root/.mysql_history mysql的bash历史记录
/opt/nginx/conf/nginx.conf nginx的配置文件
/etc/my.cnf mysql配置文件
/etc/httpd/conf/httpd.conf httpd的配置文件
Windows系统配置文件
C:\boot.ini 查看系统版本
C:\Windows\System32\inetsrv\MetaBase.xml IIS配置文件
C:\Windows\php.ini php配置信息
C:\Windows\my.ini Mysql配置信息
常见服务器日志
Apache日志文件
/var/log/apache2/access.log
/var/log/apache2/error.log
Nginx日志文件
/var/log/nginx/access.log
/var/log/ nginx/error.log
Mysql日志文件
/var/lib/mysql/
文件包含
文件包含原理
服务器执行PHP文件时,可以通过文件包含函数加载另一个文件中的内容,将之当成PHP脚本来执行。而由于包含的文件名没有经过合理的校验,从而包含了预想之外的文件,导致意外的文件泄露甚至恶意的代码注入,主要包括本地文件包含和远程文件包含两种形式。
产生原因
文件包含函数加载的参数没有经过过滤或者严格的定义,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码。
文件包含函数
PHP中文件包含函数有以下四种:
require()
require_once()
include()
include_once()
include和require区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错(fatal error)并退出程序的执行。
include_once(),require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。
PHP中文件包含函数特点:
文件包含不需要考虑文件名是否为php
包含的文件当中,存在符合php语法的内容,则执行这些内容。
包含的文件当中,不存在符合php语法的内容,则原封不动的输出这些内容
符合php语法的内容:
从PHP脚本声明标签开始到结束
默认标签:<?php phpinfo(); ?>
短标签:<? phpinfo(); ?>
脚本风格:<script language=‘php’> phpinfo(); </script>
文件包含利用
本地文件包含
本地文件包含漏洞 LFI(Local File Inclusion),顾名思义,指的是能打开并包含本地文件的漏洞。大部分情况下遇到的文件包含漏洞都是LFI。
本地文件包含利用
- 包含本地文件,读取敏感文件
- 将shell写入日志,包含日志文件getshell
- 将shell写入session文件,包含session文件getshell
- 结合PHP伪协议getshell
- 结合文件上传getshell
- 远程文件包含getshell
session利用
如果环境为php且开启了session,可以尝试包含php的session文件
session会保存在服务器中,可以将代码写入到session中,在使用一些方法执行这个session可以代码执行
默认情况下,php.ini 中设置的 SESSION 保存方式是 files(session.save_handler = files),即使用读写文件的方式保存 SESSION 数据,而 SESSION 文件保存的目录由 session.save_path 指定,文件名以 sess_ 为前缀,后跟 SESSION ID,如:sess_c72665af28a8b14c0fe11afe3b59b51b。文件中的数据即是序列化之后的 SESSION 数据了。
Linux默认路径是储存在/tmp 或 /var/lib/php/sessions(受版本影响)
http://192.168.1.2/lesson/include/include.php?file=/Applications/MAMP/tmp/php/sess_fdcf5a5ae05368ba2b44ef0824b2e130
文件路径可以再phpinfo()中查看
包含日志利用
包含apache、nginx、mysql、php日志getshell
远程文件包含利用
PHP的配置文件allow_url_fopen和allow_url_include设置为ON,include/require等包含函数可以加载远程文件,如果远程文件没经过严格的过滤,导致了执行恶意文件的代码,这就是远程文件包含漏洞。
PHP伪协议
PHP 带有很多内置 URL 风格的封装协议,可用于类似 file() 、show_source() 、 fopen()、 copy()、 file_exists() filesize() 等等的文件系统函数,以及文件包含函数。在PHP的官方手册中,共有12种伪协议。
PHP默认配置:
allow_url_fopen=On(默认为On) 规定是否允许从远程服务器或者网站检索数据
allow_url_include=Off(php5.2之后默认为Off) 规定是否允许include/require远程文件
file:// 用于访问本地文件系统
php:// 访问各个输入/输出流(I/O streams)
- php://filter是一种元封装器,可以在读取文件之前对文件编码、转换、压缩、加密等
- php://input是个可以访问请求的原始数据的只读流,可以读取到post没有解析的原始数据。
data:// data伪协议是一个数据流封装器,通过协议可以将读取的数据当成一个文件
http:// https:// 允许通过 HTTP 1.0 的 GET方法,以只读访问文件或资源。
phar:// 可以访问zip、phar格式包内容
php://filter
=php://filter/read=convert.base64-encode/resource=
php:// 要使用的伪协议
filter 要使用的
read 要读取文件
convert.base64-encode 使用base64编码
resource= 后接文件url
php://input和data://
在开启 可以执行一些代码
漏洞防御
- 配置文件:
- 在配置文件中限制访问的文件目录,比如PHP中php.ini配置open_basedir
- 尽量关闭allow_url_include配置
- 特殊字符过滤:
- 检查用户输入,过滤或转义含有“…/”、“…\”、“http”、“%00”,“…”,“.”,“#”等跳转目录或字符终止符、截断字符、url的输入
- 合法性判断:
- 严格过滤用户输入字符的合法性,比如文件类型、文件地址、文件内容等
- 白名单:
- 白名单限定访问文件的路径、名称及后缀名
文件上传
原理
由于对上传文件类型未过滤或过滤机制不严,导致恶意用户可以上传脚本文件,通过上传⽂件可达到控制网站权限的目的,该漏洞⼀般结合解析漏洞。 攻击者可获得网站控制权限(getshell)
网站WEB应用都有⼀些文件上传功能,比如文档、图片、头像、视频上传,当上传功能的实现代码没有严格校验上传文件的后缀和文件类型时,就可以上传任意文件甚至是可执行文件后门webshell。
后门 webshell:
webshell就是以asp、php、jsp或者cgi等网页文件形式存在的一种代码执行环境,也可以将其称做为⼀种网页后门。黑客在入侵了一个网站后,通常会将asp或php等后门文件与网站服务器WEB目录下正常的网页文件混在一起,然后就可以使用浏览器来访问后门webshell,得到一个命令执行环境,以达到控制网站服务器的目的。
<?php @eval($_GET[‘a’]); ?>
<?php @assert($_POST[‘a’]); ?>
<?php @$_POST[‘fun’]($_POST[‘a’]);?>
利用条件
利用条件
有上传功能
知道文件上传后的路径
上传后的文件可以访问
上传后的文件可以执行
request包
一个 HTML 表单中的 enctype 有三种类型
- application/x-www-urlencoded
- multipart/form-data
- text-plain
multipart/form-data
multipart/form-data是一种规范,统一表达文件上传请求的格式。
- boundary 用来分割数据,把下面数据和上面数据分开
- Content-Disposition 传递文件信息
包含了 type 和 一个名字为 name 的 parameter,type 是 form-data,name 参数的值则为表单控件(也即 field)的名字,如果是文件,那么还有一个 filename 参数,值就是文件名。 - Content-Type 标记文件类型
- text/plain 文本类型
- image/jpeg 图片格式
- application/octet-stream 脚本类型
PHP文件上传
文件上传检测
针对与文件上传,主要分为客户端检测与服务端检测,而客户端检测可以轻易绕过,且服务端检测的方式多种多样,所以文件上传WAF多针对服务端检测。
客户端javascript校验
- 校验文件后缀名
服务端校验
- MIME检测(content-type头检测)
- 文件内容检测
- 文件幻数检测
- PHP脚本标签
- 危险函数
…
- 后缀名检测
- 黑名单
- 白名单
- 图片渲染
- 图片裁剪
客户端验证绕过
- Javascript验证后缀名
- 禁用浏览器js
- 抓包修改后缀名
服务端验证绕过
-
MIME检测
- 上传php文件,抓包修改content-type
- 上传图片格式文件,抓包修改文件后缀名
-
文件幻数检测
- 上传php的文件前面加入图片的幻术头
服务端验证绕过
- 上传php的文件前面加入图片的幻术头
-
PHP脚本标签检测
- PHP 短标签 <? ?>
- PHP js风格标签
-
后缀名黑名单
-
后缀名大小写绕过
-
php别名:php2, php3, php4, php5, phps, pht, phtm, phtml
-
配合".htaccess"、".user.ini"绕过
.htaccess文件(或者”分布式配置文件”)提供了针对目录改变配置的方法, 即Apache在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。所以一个特定目录下的.htaccess文件中的指令可能会覆盖其上级目录中的.htaccess文件中的指令,即子目录中的指令会覆盖父目录或者主配置文件中的指令
-
user.ini
自 PHP 5.3.0 起,PHP 支持基于每个目录的 .htaccess 风格的 INI 文件。此类文件仅被 CGI/FastCGI SAPI 处理。
利用条件
服务器使用CGI/FastCGI模式
上传目录下要有可执行的php文件 -
Windows命名特性
1.php:.jpg
1.php\x20
1.php.
1.php::$DATA
1.php\x00 (php<5.3.4 magic_quotes_gpc=Off)
-
-
后缀名白名单
- Windows命名特性
php:.jpg - 配合文件解析漏洞
- Windows命名特性
-
图片完整性
- 图片马(需要结合文件包含漏洞使用)
Windows:
copy /b w.jpg+hack.php shell.jpg
Mac/linux:
cat shell.php >> shell.png - 二次渲染绕过
GIF格式的图片绕过是最简单的,只需要上传GIF图片,将源文件和二次渲染过的文件进行比较,找出源文件中没有被修改的那段区域,在那段区域写入php代码即可。
- 图片马(需要结合文件包含漏洞使用)
-
利用WAF特性
大致思路,就是考虑到WAF在检测的时候,是正则常规request请求包,但是服务器中间件处理request包的时候有容错,这就造成了差异性,构造异常requests请求包,WAF就会提取不出应该提取的部分,从而绕过。- 文件后缀名换行
- 双写filename后面的‘=’
- 多加一个‘filename;‘
- 去掉或修改Content-Disposition值
- Content-Disposition name filename 大小写
- 多个boundary
- %00截断
- 交换name和filename的顺序
文件上传防御
服务端验证绕过防御
使用白名单限制可以上传的文件扩展而不是黑名单
验证文件内容,正则匹配恶意代码
对上传后的文件统一随机命名
上传后的目录不能执行脚本
限制.htaccess .user.ini等配置文件上传
php版本更新,避免出现截断漏洞
避免出现文件包含漏洞