今天在群里看到了几道题,这是其中之一。
PHP文件包含 Session
Task
|
|
Solution
php伪协议读取源码
点击login,发现链接变为:
推测文件包含。
login.php
访问:
得到login.php源码:
register.php
访问:
register.php:
config.php
访问:
config.php:
index.php
index.php源码:
代码审计
SQL注入?
往往注册与登陆操作中会有与数据库交互的地方,这也是sql注入的常见引发点。
看一下register.php,这里仅截取部分代码:
再看一下login.php:
这里都使用了PHP的PDO处理,因此这里存在sql注入的可能性很小。
Session
接着再看看,有哪些参数是可控的。
在login.php中:
这里使用了session来保存用户会话,php手册中是这样描述的:
- PHP 会将会话中的数据设置到
$_SESSION
变量中。 - 当 PHP 停止的时候,它会自动读取
$_SESSION
中的内容,并将其进行序列化,然后发送给会话保存管理器来进行保存。 - 对于文件会话保存管理器,会将会话数据保存到配置项 session.save_path 所指定的位置。
考虑到变量$username
是我们可控的,并且被设置到了$_SESSION
中,因此我们输入的数据未经过滤的就被写入到了对应的sessioin文件中。结合前面的php文件包含,可以推测这里可以包含session文件。关于session包含的相关知识,可以见这篇文章chybeta:PHP文件包含
要包含session文件,需要知道文件的路径。先注册一个用户,比如chybeta。等登陆成功后。记录下cookie中的PHPSESSID的值,这里为udu8pr09fjvabtoip8icgurt85
访问:
这个/var/lib/php5/
的session文件路径是测试出来的,常见的也就如chybeta:PHP文件包含中所述的几种。
base64_encode
能包含,并且控制session文件,但要写入可用的payload,还需要绕过:
如前面所示,输入的用户名会被base64加密。如果直接用php伪协议来解密整个session文件,由于序列化的前缀,势必导致乱码。
考虑一下base64的编码过程。比如编码abc。
考虑一下session的前缀:username|s:12:"
,中间的数字12表示后面base64串的长度。当base64串的长度小于100时,前缀的长度固定为15个字符,当base64串的长度大于100小于1000时,前缀的长度固定为16个字符。
由于16个字符,恰好满足一下条件:
也就是说,当对session文件进行base64解密时,前16个字符固然被解密为乱码,但不会再影响从第17个字符后的部分也就是base64加密后的username。
Get Flag
注册一个账号,比如:
其base64加密后的长度为128,大于100。
|
|
成功getshell。
访问:
访问:
小结
考了几个知识点:
- php文件包含:伪协议利用
- php文件包含:包含session文件
- php-session知识及序列化格式
- base64的基本原理