logo头像

黑客的本质就是白嫖

web知识巩固(篇一)-文件包含篇

前言

因为一些不可抗力影响,我需要在短时间里学习很多不懂或者不是非常理解的知识,这算是系列第一篇吧

文件包含简介

文件包含函数

php文件执行时,可以通过文件包含函数加载另一个文件,而整个文件包含漏洞也就是基于这些函数,一共有四种

1
2
3
4
require()
require_once()
include()
include_once()

include()require()的主要区别就是,require()在在包含出错时,会直接报错并退出程序运行,而include()则只会抛出警告,并继续往下运行,从这里看的话,实际使用的时候使用require()会安全一点,因为出现错误就直接退出了,不给执行下面代码的机会

include_once()require_once()与前面两个不同的地方在于只会对文件包含一次,我参考的文章里面说用来在脚本执行期间一个文件可能被包含超过一次的情况,如果要保证只被包含一次避免函数被重定义,就可以使用这个函数

漏洞产生原因

web漏洞的产生原因以我现在的知识积累来说,大部分都是由于对用户输入参数处理不当造成的,这个也不例外

本地文件包含漏洞

无限制本地文件包含漏洞

顾名思义,没有任何限制的文件包含,读取就完事了

代码:

1
2
3
4
<?php
$filename = $_GET['filename'];
include($filename);
?>

1556007355109

包含成功

常见敏感信息路径

因为自己实际上没有太多实战经验,所以不清楚具体有哪些敏感信息可以包含的,所以这里直接复制参考的文章的内容

Windows系统

c:\boot.ini // 查看系统版本

c:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件

c:\windows\repair\sam // 存储Windows系统初次安装的密码

c:\ProgramFiles\mysql\my.ini // MySQL配置

c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密码

c:\windows\php.ini // php 配置信息

Linux/Unix系统

/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 配置文件

session文件包含漏洞

一开始看这个觉得很新奇,因为之前没见过,细细了解了一下才知道,只是通过包含phpsession存储文件,相当于是如果没有写入权限的话可以通过这样的方式来getshell

代码:

1
2
3
4
5
6
7
8
9
10
11
//session.php
<?php
session_start();
$usrname = $_GET['usrname'];
$_SESSION['usrname'] = $usrname;
?>
//index.php
<?php
$filename = $_GET['filename'];
include($filename);
?>

1556008111391

1556008175372

可以看到在/var/lib/php/sessions目录下多了一个以我们session命名的文件

1556008326015

可以看到这里存放着我们的用户名信息,这样只要把用户名设置成一句话,就可以getshell了,这里就测试一下phpinfo

1
http://192.168.220.145/session.php?usrname=%3C?php%20phpinfo();?%3E

1556008654257

有限制本地文件包含

上面学习了具体原理,这边就主要学一下绕过

%00截断

这里我在做之前大哥交给我的任务——DVWA的时候碰到过,那时候碰到的是通过%00截断绕过上传,但是当时只知道可以用来绕过,还以为是解析问题,后来大哥和我说就是因为%00截断的问题,在php版本低于5.3.4,并且配置文件中magic_quotes_gpc = Off时存在这个漏洞,函数代码解析到%00处会以为代码已经结束,不会再往下解析,所以就造成了截断,具体代码之类的就不演示了,这个算是比较基础的东西了

路径长度截断

这个问题我也碰到过,但是当时一知半解没有思考原理也没有事后去了解(看来该学的东西迟早还是要学的

原理貌似很简单:

Windows下目录最大长度为256字节,超出的部分会被丢弃;

Linux下目录最大长度为4096字节,超出的部分会被丢弃。

这意思是如果服务器端通过在文件名后拼接一个文件类型来引入文件的话,可以通过在传入的文件后面接一长串的./来绕过

点号截断

原理同上,只不过是用.号来截断,但是我看这边好像只能在windows下,长度超过256,那还是路径截断好一些

远程文件包含漏洞

php配置文件中的allow_url_fopenallow_url_include设置为On时,include/require等函数可以加载远程文件,若加载的文件中包含有恶意代码,就会导致远程文件包含漏洞

allow_url_fopen = On(是否允许打开远程文件)

allow_url_include = On(是否允许include/require远程文件)

无限制远程文件包含漏洞

测试用代码

1
2
3
4
<?php
$filename = $_GET['filename'];
include($filename);
?>

1556093855905

本地index1.txt文件内容为<?php phpinfo();?>

成功引入了文件

有限制远程文件包含漏洞

其实就是一些绕过姿势,正好学习一波

一下绕过只能用于简单的后缀拼接方式:

问号绕过

顾名思义,在url后接问号,这样后面拼接的文件后缀就被当成是目标网址的参数了

#号绕过

这里的#号应该不是注释的意思,url中的#我记得是有特殊含义的,是叫锚点来着,相当于是文章目录的节点

空格绕过

%20,空格还是能绕过挺多东西的,比如说…我还真比如不出来

PHP伪协议

php伪协议在ctf里面还是挺常见的,我也用过不少次数其中的一个php://filter,但是一直都是一知半解的状态,既不知道伪协议是啥,也不知道我用的这个是怎么回事,那这次就了解个痛快吧(并不

首先先来看一下官方文档的解释吧

PHP 带有很多内置 URL 风格的封装协议,可用于类似 fopen()copy()file_exists()filesize() 的文件系统函数。 除了这些封装协议,还能通过 stream_wrapper_register() 来注册自定义的封装协议。

伪协议包含以下几种

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:// — 处理交互式的流

如果都要看起来的话大概新开一篇文章也会写的很长,这里就先只看php://

php://

php:// — 访问各个输入/输出流(I/O streams)

这是官方文档的解释,没有太多好解释的

php://stdin, php://stdout 和 php://stderr

这三个东西貌似就是三个常量,类似于获取输入、输出和错误的函数

php://input

这是用来访问输入流的,在HTTP中,可以用来访问POST的数据,示例如下

1
2
3
<?php
echo file_get_contents("php://input");
?>

wjbh_7

一般看到file_get_contents这个函数时就可以考虑一下是否可以使用php://input绕过了

如果有直接include某个GET传入的参数,也可以通过此协议来传马或者命令执行等等

php://output

官方说明

php://output 是一个只写的数据流, 允许你以 printecho 一样的方式 写入到输出缓冲区。

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://filter

上面几个都是直接引用的官方说明,一是基本上没有碰见过,二是感觉也没什么好写的,这一个才是经常会出现并且被利用的伪协议

首先还是看一下官方说明吧

php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()file()file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。

下面是php://filter的一些参数

名称 描述
resource=<要过滤的数据流> 这个参数是必须的。它指定了你要筛选过滤的数据流。
read=<读链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符。
write=<写链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符。
<;两个链的筛选列表> 任何没有以 read=write= 作前缀 的筛选器列表会视情况应用于读或写链。

老实说我对这个协议其实不是非常了解,只是在印象中会用到它去读取一些无法直接读取的文件,比如说php后台代码,lorexxar师傅的博客里写到,这个协议在任意文件读取,也就是我上面描述的这种情况,以及getshell中都有利用的机会,getshell笔者没有过这样的经验,任意文件读取这里就按着几篇博客,边学边记录吧

首先看一下常用的payload

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

比赛wp中这个payload还是挺常见的,但是之前只知道用不知道缘由,现在看了一下参数说明再加上参考博客,差不多明白了一二

首先这resource=index.php指定了要操作的文件,这里指定的是index.php,前面的read=convert.base64-encode首先指定了操作方式是读取,=后面的字符串就是所谓的过滤器了

过滤器是个啥东西呢,参考链接里面附了官方文档,有兴趣可以自行参考,这里就不贴上来了

依我看,与其说是过滤倒不如说是数据处理,虽说过滤也算是数据处理,但毕竟只是算子类,这相当于一个读取数据之后对所读取的数据进行何种操作的部分

文档中给了四种过滤器类型,其中我们用的是一种名为转换过滤器的,常用的就是里面的base64-encodebase64-decode了,没有太多东西好说,就相当于是对数据进行了一个base64的编码或解码,与调用函数是一样的

至于其余几个过滤器,不写也罢,没有太大的记录下来的必要

结语

这篇文章断断续续写了两周,因为各种各样的事情以及自己的怠惰于五月二日才写完,特留此言以警自身。


参考链接:

Web安全实战系列:文件包含漏洞

php 伪协议

支持的协议和封装协议

php://

可用过滤器列表

转换过滤器

评论系统未开启,无法评论!