文件包含
接下来说以下文件包含:
在程序开发过程当中,很多东西都是会被重复使用的片段,这个时候就可以根据不同语言的语法要求在本文件当中引入程序。
在java当中是import
关键字,在C/C++
当中是#include/#include
,在php
当中是:
include();
require();
include_once();
require_once();
区别是require如果包含错误那么会终止程序,include不会终止程序。
类型
主要有两种包含形式,本地文件包含还有远程文件包含,本地文件是相对于服务器本身来说的,可以包含存在在服务器当中的本地文件。
远程文件包含则是在互联网上可访问到的资源,比如一个网站下存放的某个图片就可以被包含进去,这个功能如果想要使用需要开始php
当中的某个配置:allow_url_include=On/Off
。
在实战和做题当中,很多情况都要去尝试一下,如果可以的话。
寻找的常见文件目标
如果想要寻找flag的话可以考虑在当前目录或者根目录下面寻找例如:
/flag
/flag.txt
flag.php
/var/www/html/flag.php
/var/lib/php/session #session信息默认目录
然后还有就是Linux系统当中的敏感文件。
/etc/passwd // 账户信息
/etc/shadow // 账户密码文件
/usr/local/app/apache2/conf/httpd.conf // Apache2 //默认配置文件
/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置
/etc/httpd/conf/httpd.conf // Apache配置文件
/etc/my.conf // mysql 配置文件
/var/log/nginx/access.log #日志文件,有时候如果该文件当中允许运行相关语言代码,可以通过构造来实现读取。
/var/log/nginx/error.log
/proc/self/cmdline
/proc/self/environ
PHP伪协议
在PHP中,伪协议(或称为流包装器)是一个提供特定上下文的数据访问方法。它允许你以一种与使用常规文件或套接字非常相似的方式访问数据。
伪协议常见于文件系统函数,如 fopen()
, file_get_contents()
, file_put_contents()
等,即里面参数可以写入如下。
以下是具体的伪协议:
file:// — 访问本地文件系统
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams)
phar:// — PHP 归档zlib:// — 压缩流
data:// — 数据(RFC 2397)
zip://
glob:// — 查找匹配的文件路径模式
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音频流
expect:// — 处理交互式的流
这个伪协议可以展示“本地文件系统”,而且需要跟文件的绝对路径。完整地写出来一个读取参数为:file:///var/www/html/index.html
。
这个应该都很熟悉,但仔细讲起来确实目前我也没有这个实力讲出来,暂且跳过。
这是一个可以访问请求原始数据的只读流,并且Content-Type不等于”multipart/form-data”
时,可以使用php://input来获取原始请求的数据。
使用 php://input
与 enctype="multipart/form-data"
一起(主要用于文件上传)可能不会如预期地工作。在这种情况下,使用 $_FILES
和 $_POST
超全局变量是更好的选择。
它是用来读取HTTP原始数据的内容体,post和get都可以,但是一般来说GET形式方法的内容体无数据可读,但你可以自己写。所以一般都是用来读取POST请求内容体的。
这个是一种流封装器,设计用于数据流打开时筛选过滤应用。它允许你通过过滤器对数据进行转换,常用于文件读取时的转换。它可以用于各种文件和网络操作,从而允许数据在读取或写入时被动态地转换。
php://filter
最常见的用途之一是与 file_get_contents()
或 include/require
一起使用,以从文件中读取数据并通过过滤器进行处理。
如果希望同时一个语句当中进行多种操作,可以在read=
后面使用管道符来链式地应用起来。
比如:php://filter/read=string.toupper|convert.base64-encode/resource=flag.php
,这个过滤器的优先级很高,所以如果使用不当会出现绕过代码检验的效果。
上面的那个示例伪协议进行的是对元数据先全部大写然后进行base64
编码。
常见的过滤器如下:
string.strip_tags 将数据流中的所有html标签清除
string.toupper 将数据流中的内容转换为大写
string.tolower 将数据流中的内容转换为小写
convert.base64-encode 将数据流中的内容转换为base64编码
convert.base64-decode 与上面对应解码
string.rot13 转换为rot13 常用于写文件
此外,有读取就有写入,可以这么写php://filter/write=string.rot13/resource=233.txt
,当然这个都是配合一体化函数进行操作的,比如fopen()
等。
其实这里还有一个绕过死亡die
的小巧思,如果各位有兴趣的话可以自行搜索题目以及思考题解的不同方式。
php5.2.0
起,数据流封装器开始有效,主要用于数据流的读取。如果传入的数据是PHP代码,就会执行代码。
data://text/plain,
data://text/plain,
data://text/plain,
data://text/plain,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
base64加密成一句话木马
page=data://text/plain;base64,PD9waHAgc3lzdGVtKCdscycpOyA/PmFh
扫描目录
data://text/plain;base64,PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==
data://text/plain;base64,PD9waHAgZWNobyAxOyA/Pg==
日志包含
这个就是之前提到的一嘴,可能日志当中如果传入的某些HTTP报文字段信息被保存,而且可以被当成代码执行的话就可能会出现问题。
session包含
为了节省客户端的重复登录,我们会在一段时间内维护一个可以校验我们身份的session,在PHP当中是PHPSESSID
。
Linux保存session的地方通常为:
/var/lib/php/sess_PHPSESSID
/var/lib/php/sessions/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
session竞争包含
需要在php.ini当中配置相关选项。
1. session.upload_progress.enabled = on
2. session.upload_progress.cleanup = on
3. session.upload_progress.prefix = "upload_progress_"
4. session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
enabled=on
表示upload_progress
功能开始,也意味着当浏览器向服务器上传一个文件时,php将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中 ;
cleanup=on
表示当文件上传结束后,php将会立即清空对应session文件中的内容,这个选项是竞争的原因;
name
当它出现在表单中,php将会报告上传进度,最大的好处是,它的值可控;
prefix+name
将表示为session中的键名
当浏览器向服务器上传一个文件时,php将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中,当文件上传结束后,php将会立即清空对应session文件中的内容。
有的时候你可以知道到底session放在哪个目录下,有的时候只能根据常用的位置猜测。
这里我们可以使用python脚本来实现自动化的竞争包含。