Skip to content

Commit 940a0e2

Browse files
committed
20260509-1820
1 parent e906a40 commit 940a0e2

4 files changed

Lines changed: 207 additions & 99 deletions

File tree

CCW-Code-Injection-Risk-Warning.user.js

Lines changed: 166 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -2,130 +2,199 @@
22
// @name CCW-Code-Injection-Risk-Warning
33
// @description CCW代码注入风险警告,让你的账号更安全。
44
// @author bddjr
5-
// @version 20260127-1658
5+
// @version 20260509-1820
66
// @match https://www.ccw.site/*
7-
// @icon https:/m.ccw.site/community/images/logo-ccw.png
7+
// @match https://learn.ccw.site/*
8+
// @match https://m.ccw.site/*
9+
// @icon https://m.ccw.site/community/images/logo-ccw.png
810
// @grant none
911
// @run-at document-start
1012
// @updateURL https://bddjr.github.io/CCW-Code-Injection-Risk-Warning/CCW-Code-Injection-Risk-Warning.user.js
1113
// @downloadURL https://bddjr.github.io/CCW-Code-Injection-Risk-Warning/CCW-Code-Injection-Risk-Warning.user.js
1214
// ==/UserScript==
15+
//@ts-nocheck
1316

1417
// Source Code:
1518
// https://github.com/bddjr/CCW-Code-Injection-Risk-Warning
1619

20+
if (location.hostname == 'learn.ccw.site') {
21+
// 自动防御基于 iframe 的代码注入攻击,仅允许白名单网址
1722

18-
//@ts-nocheck
23+
// 创作者学院编辑器提示:暂时只支持bilibili和西瓜视频以及站内链接
24+
// 查找并分析js文件
25+
// https://learn.ccw.site/_next/static/chunks/708-9a7dbfbb32eca7d3.js
26+
// https://learn.ccw.site/_next/static/chunks/5191-e0df96b8928838d4.js
27+
// https://learn.ccw.site/_next/static/chunks/app/(normal)/home/layout-a9cb46b1ff2d4762.js
28+
// 创作者学院前端支持插入的 URL origin :
29+
// [
30+
// "https://scratch.mit.edu",
31+
// "https://youtube.com",
32+
// "https://www.facebook.com",
33+
// "https://www.twitch.tv",
34+
// "https://twitter.com",
35+
// "https://qa.cocrea.world",
36+
// "https://www.ixigua.com",
37+
// "https://ixigua.com",
38+
// "https://bilibili.com",
39+
// "https://player.bilibili.com",
40+
// "https://www.bilibili.com",
41+
// "https://www.ccw.site",
42+
// "https://ccw.site",
43+
// "https://learn.ccw.site",
44+
// "https://learn-qa.xiguacity.cn"
45+
// ]
46+
// 或者 origin 包含 "ccw.site" 或 "xiguacity.cn" 。
47+
// 仅在编辑器里插入的时候会校验,但查看文章的时候加载iframe前不会校验。
48+
// 我不知道服务器会不会校验。
49+
50+
// 定义自己的白名单
51+
// 参考 https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/frame-src
52+
const whitelist = [
53+
"https://www.ccw.site/embed",
54+
"https://ccw.site/embed",
55+
"https://player.bilibili.com/player.html",
56+
"https://www.bilibili.com/video/",
57+
"https://bilibili.com/video/",
58+
]
59+
const meta = document.createElement('meta')
60+
meta.setAttribute('http-equiv', 'content-security-policy')
61+
meta.setAttribute('content', `frame-src ${whitelist.join(' ') || "'none'"};`)
62+
document.head.appendChild(meta)
63+
console.log('【脚本 CCW代码注入风险警告】自动防御基于 iframe 的代码注入攻击,仅允许白名单网址\n', meta, '\n', whitelist)
1964

20-
const allowExtensionURLPrefix = "https://static.xiguacity.cn/h1t86b7fg6c7k36wnt0cb30m/static/js/"
65+
} else if (location.hostname == 'm.ccw.site') {
66+
// 基于svg的代码注入攻击
67+
// 脚本无法防御该攻击,因为攻击者的代码先执行。
68+
// 参考 https://github.com/bddjr/CCW-Code-Injection-Risk-Warning/issues/3
69+
if (document.contentType == 'image/svg+xml') {
70+
try {
71+
window.stop()
72+
} catch (e) { }
73+
alert(`【脚本 CCW代码注入风险警告】
2174
22-
// let hasCCWDataCodeInjectionFix = null
23-
// /** 检测是否已安装 CCWData-Code-Injection-Fix.user.js */
24-
// function checkHasCCWDataCodeInjectionFix() {
25-
// if (hasCCWDataCodeInjectionFix !== null) return hasCCWDataCodeInjectionFix
26-
// const head = document.createElement('head')
27-
// const script = document.createElement('script')
28-
// script.src = "https://static.xiguacity.cn/h1t86b7fg6c7k36wnt0cb30m/static/js/scratch3_ccw_data.cbf43b4e.js"
29-
// head.appendChild(script)
30-
// return hasCCWDataCodeInjectionFix = !!(!script.hasAttribute("src") && script.innerHTML?.includes('ccwdataExtensionSafeEval'))
31-
// }
75+
您正在使用标签页访问svg,恶意代码可能已经执行。
76+
建议您关掉该标签页,然后尽快修改您的账号的密码。
77+
如果攻击者已经使用您的账号捣乱,请及时向共创世界管理员或鸭鸭院长申诉。`)
78+
}
3279

33-
function checkHasExt(extensions, id) {
34-
id = id.toLowerCase()
35-
return extensions?.some(v => (String(v).toLowerCase() == id))
36-
}
80+
} else {
81+
// www.ccw.site
3782

38-
let acceptLoadExt = null
83+
const allowExtensionURLPrefix = "https://static.xiguacity.cn/h1t86b7fg6c7k36wnt0cb30m/static/js/"
3984

40-
const { parse } = JSON
85+
// let hasCCWDataCodeInjectionFix = null
86+
// /** 检测是否已安装 CCWData-Code-Injection-Fix.user.js */
87+
// function checkHasCCWDataCodeInjectionFix() {
88+
// if (hasCCWDataCodeInjectionFix !== null) return hasCCWDataCodeInjectionFix
89+
// const head = document.createElement('head')
90+
// const script = document.createElement('script')
91+
// script.src = "https://static.xiguacity.cn/h1t86b7fg6c7k36wnt0cb30m/static/js/scratch3_ccw_data.cbf43b4e.js"
92+
// head.appendChild(script)
93+
// return hasCCWDataCodeInjectionFix = !!(!script.hasAttribute("src") && script.innerHTML?.includes('ccwdataExtensionSafeEval'))
94+
// }
4195

42-
JSON.parse = function myParse() {
43-
const out = parse.apply(this, arguments)
44-
if (acceptLoadExt !== true && out?.targets?.[0]?.blocks) {
45-
if (acceptLoadExt === null) {
46-
const { targets, extensions, extensionURLs } = out
47-
const hasCCWData = checkHasExt(extensions, "CCWData")
48-
const hasWitCatJSSandBox = checkHasExt(extensions, "WitCatJSSandBox")
49-
let hasCustomExt = false
50-
let needWarn = false
51-
const msg = ['【脚本 CCW代码注入风险警告】']
52-
// CCWData
53-
if (hasCCWData) {
54-
// needWarn = true
55-
if (hasWitCatJSSandBox) {
56-
needWarn = true
57-
msg.push('漏洞链警告!作品可能会使用“白猫的JS沙箱”扩展调用“Gandi云数据”扩展的代码注入漏洞积木!')
58-
}
59-
// 检测代码注入漏洞积木
60-
let hasCodeInjectionBlock = false
61-
const codeInjectionBlocksCount = {
62-
CCWData_getValueInJSON: 0,
63-
CCWData_setValueInJSON: 0
64-
}
65-
for (const target of targets) {
66-
const { blocks } = target
67-
for (const id in blocks) {
68-
const block = blocks[id]
69-
const { opcode } = block
70-
if (codeInjectionBlocksCount.hasOwnProperty(opcode)) {
71-
hasCodeInjectionBlock = true
72-
codeInjectionBlocksCount[opcode]++
96+
function checkHasExt(extensions, id) {
97+
id = id.toLowerCase()
98+
return extensions?.some(v => (String(v).toLowerCase() == id))
99+
}
100+
101+
let acceptLoadExt = null
102+
103+
const { parse } = JSON
104+
105+
JSON.parse = function myParse() {
106+
const out = parse.apply(this, arguments)
107+
if (acceptLoadExt !== true && out?.targets?.[0]?.blocks) {
108+
if (acceptLoadExt === null) {
109+
const { targets, extensions, extensionURLs } = out
110+
const hasCCWData = checkHasExt(extensions, "CCWData")
111+
const hasWitCatJSSandBox = checkHasExt(extensions, "WitCatJSSandBox")
112+
let hasCustomExt = false
113+
let needWarn = false
114+
const msg = ['【脚本 CCW代码注入风险警告】']
115+
// CCWData
116+
if (hasCCWData) {
117+
// needWarn = true
118+
if (hasWitCatJSSandBox) {
119+
needWarn = true
120+
msg.push('漏洞链警告!作品可能会使用“白猫的JS沙箱”扩展调用“Gandi云数据”扩展的代码注入漏洞积木!')
121+
}
122+
// 检测代码注入漏洞积木
123+
let hasCodeInjectionBlock = false
124+
const codeInjectionBlocksCount = {
125+
CCWData_getValueInJSON: 0,
126+
CCWData_setValueInJSON: 0
127+
}
128+
for (const target of targets) {
129+
const { blocks } = target
130+
for (const id in blocks) {
131+
const block = blocks[id]
132+
const { opcode } = block
133+
if (codeInjectionBlocksCount.hasOwnProperty(opcode)) {
134+
hasCodeInjectionBlock = true
135+
codeInjectionBlocksCount[opcode]++
136+
}
73137
}
74138
}
75-
}
76-
// 生成警告消息
77-
const thisMsgPrefix = '作品试图加载“Gandi云数据”扩展,'
78-
if (hasCodeInjectionBlock) {
79-
needWarn = true
80-
const thisMsg = [thisMsgPrefix + '并使用以下代码注入漏洞积木:']
81-
for (const opcode in codeInjectionBlocksCount) {
82-
const count = codeInjectionBlocksCount[opcode]
83-
if (count) thisMsg.push(JSON.stringify(opcode) + ' × ' + count + ' 块')
139+
// 生成警告消息
140+
const thisMsgPrefix = '作品试图加载“Gandi云数据”扩展,'
141+
if (hasCodeInjectionBlock) {
142+
needWarn = true
143+
const thisMsg = [thisMsgPrefix + '并使用以下代码注入漏洞积木:']
144+
for (const opcode in codeInjectionBlocksCount) {
145+
const count = codeInjectionBlocksCount[opcode]
146+
if (count) thisMsg.push(JSON.stringify(opcode) + ' × ' + count + ' 块')
147+
}
148+
msg.push(thisMsg.join('\n'))
149+
} else {
150+
// msg.push(thisMsgPrefix + '但未检测到代码注入漏洞积木。')
84151
}
85-
msg.push(thisMsg.join('\n'))
86-
} else {
87-
// msg.push(thisMsgPrefix + '但未检测到代码注入漏洞积木。')
88152
}
89-
}
90-
// 自制扩展
91-
if (extensionURLs instanceof Object) {
92-
const customExtDisplayArray = ['作品试图加载自制扩展:']
93-
for (const key in extensionURLs) {
94-
const url = new URL(extensionURLs[key], location).href;
95-
if (!url.startsWith(allowExtensionURLPrefix)) {
96-
hasCustomExt = true
97-
customExtDisplayArray.push(JSON.stringify(key) + '\n' + url)
153+
// 自制扩展
154+
if (extensionURLs instanceof Object) {
155+
const customExtDisplayArray = ['作品试图加载自制扩展:']
156+
for (const key in extensionURLs) {
157+
const url = new URL(extensionURLs[key], location).href;
158+
if (!url.startsWith(allowExtensionURLPrefix)) {
159+
hasCustomExt = true
160+
customExtDisplayArray.push(JSON.stringify(key) + '\n' + url)
161+
}
162+
}
163+
if (hasCustomExt) {
164+
needWarn = true
165+
msg.push(...customExtDisplayArray)
98166
}
99167
}
100-
if (hasCustomExt) {
101-
needWarn = true
102-
msg.push(...customExtDisplayArray)
103-
}
104-
}
105-
// 警告
106-
if (needWarn) {
107-
console.warn(msg.join('\n\n'))
108-
if (hasCustomExt) msg.push('如果要复制链接,请打开DevTools,查看控制台(Console)。\n如果控制台没有内容,请刷新页面。')
109-
msg.push('如果要继续加载作品,请输入“继续加载”,然后点击“确定”,\n否则点击“取消”。')
110-
for (const message = msg.join('\n\n'); ;) {
111-
let input = window.prompt(message)
112-
if (input == null) {
168+
// 警告
169+
if (needWarn) {
170+
if (window !== window.top && !location.pathname.startsWith('/embed')) {
113171
acceptLoadExt = false
114-
break
115-
}
116-
input = input.trim().toLowerCase()
117-
if (["继续加载", "繼續加載", "jixujiazai"].includes(input)) {
118-
acceptLoadExt = true
119-
break
172+
console.log('【脚本 CCW代码注入风险警告】检测到在 iframe 里,且网址路径开头不是 /embed ,自动阻止加载可疑作品')
173+
} else {
174+
console.warn(msg.join('\n\n'))
175+
if (hasCustomExt) msg.push('如果要复制链接,请打开DevTools,查看控制台(Console)。\n如果控制台没有内容,请刷新页面。')
176+
msg.push('如果要继续加载作品,请输入“继续加载”,然后点击“确定”,\n否则点击“取消”。')
177+
for (const message = msg.join('\n\n'); ;) {
178+
let input = window.prompt(message)
179+
if (input == null) {
180+
acceptLoadExt = false
181+
break
182+
}
183+
input = input.trim().toLowerCase()
184+
if (["继续加载", "繼續加載", "jixujiazai"].includes(input)) {
185+
acceptLoadExt = true
186+
break
187+
}
188+
}
120189
}
121190
}
122191
}
192+
if (acceptLoadExt === false) throw Error("Reject by user script: CCW-Code-Injection-Risk-Warning")
123193
}
124-
if (acceptLoadExt === false) throw Error("Reject by user script: CCW-Code-Injection-Risk-Warning")
125-
}
126-
if (acceptLoadExt === true && JSON.parse === myParse) {
127-
// 取消劫持
128-
JSON.parse = parse
194+
if (acceptLoadExt === true && JSON.parse === myParse) {
195+
// 取消劫持
196+
JSON.parse = parse
197+
}
198+
return out
129199
}
130-
return out
131200
}

README.md

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,49 @@ CCW代码注入风险警告,让你的账号更安全。
33
安装TamperMonkey,然后点击下方链接,安装脚本:
44
https://bddjr.github.io/CCW-Code-Injection-Risk-Warning/CCW-Code-Injection-Risk-Warning.user.js
55

6+
该脚本支持检测并拦截以下攻击:
7+
- 基于作品使用 “Gandi 云数据” 扩展的代码注入漏洞攻击
8+
- 基于作品加载第三方扩展的代码注入漏洞攻击
9+
- 基于创作者学院的文章里嵌入 iframe 的代码注入漏洞攻击
10+
11+
> [!CAUTION]
12+
> 该脚本无法拦截使用标签页访问 m.ccw.site 加载恶意 svg 的代码注入攻击。
13+
> 使用 iframe 嵌入 m.ccw.site 加载恶意 svg 也可以执行恶意代码。
14+
> 该漏洞可以被攻击者用于盗号。
15+
> 漏洞演示:https://m.ccw.site/user_projects_assets/a8039314e7b97ea48e176b34090b680e.svg
16+
> 建议根据按照以下步骤操作,增强安全性:
17+
>
18+
> - 如果您使用 Google Chrome 浏览器:
19+
> 访问 https://m.ccw.site ,然后点击网址左侧的按钮,然后点击“网站设置”,然后将“JavaScript”权限改为“阻止”。
20+
>
21+
> - 如果您使用 Microsoft Edge 浏览器:
22+
> 访问 https://m.ccw.site ,然后点击网址左侧的🔒按钮,然后点击“此网站的权限”,然后将“JavaScript”权限改为“阻止”。
23+
>
24+
> - 如果您使用 Mozilla Firefox 浏览器:
25+
> 无法禁用网站的 JavaScript 权限,建议更换浏览器。
26+
27+
> [!CAUTION]
28+
> 攻击者成功注入恶意代码之后,可以盗取浏览器自动填充的账号密码,即使网页未显示输入框。
29+
> 建议禁用浏览器的自动填充密码,或者改为“在查看或填写网站密码之前提示设备登录选项。始终征求许可”
30+
>
31+
> ![3](readme-image/3.png)
32+
33+
> [!CAUTION]
34+
> 该脚本暂时不能检测或拦截基于 Scratch 编辑器编辑造型的代码注入攻击。
35+
> 参考 https://muffin.ink/blog/scratch-vulnerability-disclosure/
36+
> 漏洞演示 https://www.ccw.site/detail/69f73e772a7d36316189ef73
37+
38+
---
39+
40+
参考 https://github.com/bddjr/CCW-Code-Injection
41+
642
---
743

844
效果图:
945

10-
![image](readme-image/0.png)
46+
![0](readme-image/0.png)
47+
48+
![1](readme-image/1.png)
49+
50+
![2](readme-image/2.png)
1151

12-
![image](readme-image/1.png)

readme-image/2.png

67.4 KB
Loading

readme-image/3.png

66.1 KB
Loading

0 commit comments

Comments
 (0)