知识点:session 反序列化,代码审计
代码分析
flag.php
中有个 is_admin
函数的判断。
在 lib.php
中有 is_admin
函数,需要 session['admin'] 为 true
,或者通过文件读取的方式。
在 index.php
中的 include
并不能使用伪协议读取 flag.php
,那么要怎么使得 session['admin']
为 true
呢?是不是可以通过 session
反序列化来绕过,我们可以全局搜一下有没有 session_start
。
存在 sesson_start
那么也许真的存在 session
反序列化。
在 init.php
中我们可以看到 session 保存的目录,在 /var/www/tmp
下,那这个目录有什么特殊的呢?
session
保存的目录竟然和 node
的保存目录一样,那么怎么控制保存的文件名,怎么使得我们上传的内容 session
反序列化后能通过 is_admin
呢?
我们先看一下它的上传代码,在 add.php
中利用 add_note
函数来处理上传的信息。
而 add_note
函数功能就是把接收的 title
和 body
以及 hash
的 id
,存入 $_SESSION['notes']
列表里。
然后当我们访问 export.php
的时候,选择 tar 它就把 $_SESSION[‘notes’] 里的信息转换为 json 数据写入 TEMP_DIR / get_user() . '-' . bin2hex(random_bytes(8)) . '.' . 'tar';
文档里最后输出出来。
我们上传个测试一下,这边用户名是 test
,内容如下。
可以看到确实如讲的一样,那么我们是不是令用户名为 sess_
也就是 session
文件保存的格式,这样就变成了 sess_-xxxxxx.tar
,这个 tar
怎么处理?
我们只需要令 type
为 .
,这样就会因为 str_replace
把 ..
替换为空,自然就消除了,文件名的问题解决了,那内容呢?内容就很简单了,因为 php
默认的 session
反序列化模式是 php
也就是以 |
符号为分界线,前面的是键名后面的是键值.
构造如下 title
,把前面多余的值设为空,设置 admin
为 bool(true)
|N;admin|b:1;
操作步骤
以 sess_
为用户名登录。
写入反序列化值
把反序列化值,写入 session
格式的文件里。
获取我们伪造的 session
文件名。
修改 PHPSESSID 访问 flag,成功。