R3CTF-2025 r3note 学习笔记

R3CTF-2025 r3note 学习笔记

tag: nginx配置 CSP配置

看目录应该类似xss加bot的组合

先尝试弱口令爆破,没结果,正常流程fuzz也没结果

找到了一份wp

勉强看懂

关键点是利用nginx缓存js文件的配置问题

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
./nginx/default.conf

proxy_cache_path /tmp/nginx keys_zone=static_cache:10m;

server {
listen 8080;

# report route
location = /api/share/report {
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

# no direct access to the upload directory
location /files/upload/ {
deny all;
}

# cache frontend js and css files
location ~ \.(css|js)$ { #规定缓存类型
proxy_cache static_cache; # 开启缓存功能
proxy_cache_key $uri$is_args$args;
proxy_cache_valid 200 1h;
proxy_cache_bypass $cookie_nocache $arg_nocache;
proxy_http_version 1.1;

proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

# reverse proxy for the main application
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

这里的正则是css|js
用.js#后缀名上传,绕过上传文件时的限制,而当有用户访问时,文件名会被nginx正则解析,被缓存为 .js

由于

1
location ~ \.(css|js)

优先级高于

1
2
3
location /files/upload/ {
deny all;
}

所以还是能访问,服务器还是会将其缓存

从而成功让服务器上有了一个我们能控制的js文件

此时由于CSP 配置 script-src ‘self’,允许同源脚本执行。
并且在./app/middleware/jwt.go 中并没有配置

1
c.Writer.Header().Set("X-Content-Type-Options", "nosniff")   

就会导致浏览器根据文件内容猜测解析方式,只要文件里有html等标签,就会被解析成html文件,从而让客户端浏览器将里面的js代码执行

我们再上传一个伪装成JS的HTML文件并在其中引用前面缓存好的js文件,即可执行js代码。

关键点: 上传时文件名设置为 .js#。这样既能绕过后端黑名单(因为后缀是 .js#),又能利用 Nginx 的正则优先级漏洞(在请求时被视为 .js),从而允许外部访问。假设得到文件 ID 为 html_id。

问题

上传恶意 HTML (伪装成 JS),不能在里面直接写好js代码吗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# ./app/middleware/jwt.go  
func SecureMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type,Authorization")
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
c.Writer.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';")
c.Writer.Header().Set("X-Frame-Options", "DENY")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}

c.Writer.Header().Set(“Content-Security-Policy”, “default-src ‘self’; script-src ‘self’; style-src ‘self’ ‘unsafe-inline’;”)
这里script-src允许引用同源js文件,但是没有’unsafe-inline’,所以不能引用内联的js代码

ai问答:https://gemini.google.com/share/452cce0a5469


R3CTF-2025 r3note 学习笔记
https://aidemofashi.github.io/2026/02/01/R3CTF-2025-r3note-学习笔记/
作者
aidemofashi
发布于
2026年2月1日
许可协议