Discuss Scratch
- Discussion Forums
- » Advanced Topics
- » CVE-2020-14000: Script Injection vulnerability in scratch-vm
- apple502j
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
On June 9th, 2020, me, apple502j, found a vulnerability in scratch-vm, a library used in Scratch 3.0 that handles project.json deserialization. This is patched on July 14th, and has a CVE ID of CVE-2020-14000.
Summary
A malicious project.json could load and execute arbitrary JavaScript file on the Internet.
Am I affected?
For most users, no. There is one thing that prevented it from happening on this website (scratch.mit.edu). However, if you are modding Scratch, it is likely that your mod is vulnerable to CVE-2020-14000.
Affected Versions
scratch-vm from 0.1.0-prerelease.1524239808 to 0.2.0-prerelease.20200709173451 (both inclusive). This is patched in 0.2.0-prerelease.20200714185213.
Note that this only affects environments that has Web Workers enabled. If you don't serve the web worker file (extension-worker.js), you are not affected. This is the case for the scratch.mit.edu.
How to Fix
If you can, upgrade your scratch-vm to 0.2.0-prerelease.20200714185213. If you cannot, apply changes made in the pull request.
Causes
When a project with extension loads, it passes the project.json's “opcode” field to a function called getExtensionIdForOpcode. This splits the opcode by underscore and returns the first part. This is a project.json with pen extension blocks:
It will return “pen”. For most blocks, the first part is extension ID, so this is fine. But, what if, I crafted a project.json so that getExtensionIdForOpcode returns a URL?
The returned value for getExtensionIdForOpcode goes to VirtualMachine.installTargets which loads the extension using a function called loadExtensionURL.
getExtensionIdForOpcode didn't have sanitation or validation, so the returned URL - https://apple502j.github.io/files/SheepMakerUtil.js - is passed to loadExtensionURL. In ExtensionManager.loadExtensionURL, first it checks if the ID is in “built-in extensions” list - which isn't (obviously, it's an URL, not ID) and then, it allocates a Web Worker for the extension, and tells it to load the JavaScript file.
Inside ExtensionWorker we have importScripts - which loads the JavaScript file. This is loaded inside Web Worker, so attackers can only do stuff that Web Workers can - but it is definitely not an intended behavior, and can be considered a vulnerability.
Timeline
Summary
A malicious project.json could load and execute arbitrary JavaScript file on the Internet.
Am I affected?
For most users, no. There is one thing that prevented it from happening on this website (scratch.mit.edu). However, if you are modding Scratch, it is likely that your mod is vulnerable to CVE-2020-14000.
Affected Versions
scratch-vm from 0.1.0-prerelease.1524239808 to 0.2.0-prerelease.20200709173451 (both inclusive). This is patched in 0.2.0-prerelease.20200714185213.
Note that this only affects environments that has Web Workers enabled. If you don't serve the web worker file (extension-worker.js), you are not affected. This is the case for the scratch.mit.edu.
How to Fix
If you can, upgrade your scratch-vm to 0.2.0-prerelease.20200714185213. If you cannot, apply changes made in the pull request.
Causes
When a project with extension loads, it passes the project.json's “opcode” field to a function called getExtensionIdForOpcode. This splits the opcode by underscore and returns the first part. This is a project.json with pen extension blocks:
It will return “pen”. For most blocks, the first part is extension ID, so this is fine. But, what if, I crafted a project.json so that getExtensionIdForOpcode returns a URL?
The returned value for getExtensionIdForOpcode goes to VirtualMachine.installTargets which loads the extension using a function called loadExtensionURL.
getExtensionIdForOpcode didn't have sanitation or validation, so the returned URL - https://apple502j.github.io/files/SheepMakerUtil.js - is passed to loadExtensionURL. In ExtensionManager.loadExtensionURL, first it checks if the ID is in “built-in extensions” list - which isn't (obviously, it's an URL, not ID) and then, it allocates a Web Worker for the extension, and tells it to load the JavaScript file.
Inside ExtensionWorker we have importScripts - which loads the JavaScript file. This is loaded inside Web Worker, so attackers can only do stuff that Web Workers can - but it is definitely not an intended behavior, and can be considered a vulnerability.
Timeline
- June 9th: discovered this vulnerability
- June 9th: contacted the Scratch Team
- June 10th: obtained a CVE ID
- June 10th: notified the Scratch Team about the CVE ID
- June 10th: notified npm about the vulnerability
- June 12th: notified the Scratch Team about the vulnerability again, got response
- June 12th: npm's response
- June 15th: pull request https://github.com/LLK/scratch-vm/pull/2476 created
- July 1st: sent a proof-of-concept file to the ST
- July 14th: PR merged, disclosing
- novice27b
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
Congrats!
You got the CVE assigned very quickly, what process did you have to go through to apply for one?
You got the CVE assigned very quickly, what process did you have to go through to apply for one?
- apple502j
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
I just filled MITRE's form. It seems like it's actually harder to get ST's attention than MITRE's. Congrats!
You got the CVE assigned very quickly, what process did you have to go through to apply for one?
- SausageMcSauce
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
Is there any mention of the vulnerability outside of Scratch and the scratch-vm repository?
- apple502j
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
Is there any mention of the vulnerability outside of Scratch and the scratch-vm repository?https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-14000 should soon be updated.
- novice27b
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
Yeah, I've had mixed experiences with reporting vulnerabilities to the scratch team.I just filled MITRE's form. It seems like it's actually harder to get ST's attention than MITRE's. Congrats!
You got the CVE assigned very quickly, what process did you have to go through to apply for one?
If anyone from the team is reading this, please set up a dedicated security email address (ideally with a pgp pubkey available too).
- noverify
- Scratcher
15 posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
Very interesting that scratch just allowed to load an url out of nowhere!
- apple502j
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
The CVE entry is published at https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-14000
- Capitan_Florida_2
- Scratcher
100+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-14000woah that's crazy The CVE entry is published at
show me a test of it
- herohamp
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
So who does this apply to then if it does not apply to Scratch?
- A-E-
- Scratcher
100+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
It applies to mods with extention support, though many such mods allow loading from URLs anyway. So who does this apply to then if it does not apply to Scratch?
- ElsieBreeze
- Scratcher
100+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
I'd imagine Scratch Mods that use workers, as I imagine some might do. So who does this apply to then if it does not apply to Scratch?
- apple502j
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
CVSS v3.1 Scores
By my calculation: 6.1 (Medium) - CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Attack Vendor: Network - scratch-vm is (in most cases) used in web applications.
Attack Complexity: Low - One crafted file can be reused indefinitely, and nothing complicated.
Privileges Required: None - Anyone can load a .sb3 file.
User Interaction: Required - Victims need to load crafted .sb3 files.
Scope: Changed - While the techniques are not the same, the results are the same as Cross-Site Scripting, but in a sandboxed worker.
Confidentiality: Some information that can be accessed inside an worker can be obtained.
Integrity: Attackers can modify data (for example, send fetch() requests)
Availability: None - While not impossible, it is very hard to crash the computer.
Here are some of the scores provided by third parties:
- NVD: 9.8(Critical) - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
To be honest, this is too big. You know, it's not OS command injection or something.
- Snyk: 2.9(Low) - CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
Attack Complexity and User Interaction seems incorrect.
By my calculation: 6.1 (Medium) - CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Attack Vendor: Network - scratch-vm is (in most cases) used in web applications.
Attack Complexity: Low - One crafted file can be reused indefinitely, and nothing complicated.
Privileges Required: None - Anyone can load a .sb3 file.
User Interaction: Required - Victims need to load crafted .sb3 files.
Scope: Changed - While the techniques are not the same, the results are the same as Cross-Site Scripting, but in a sandboxed worker.
Confidentiality: Some information that can be accessed inside an worker can be obtained.
Integrity: Attackers can modify data (for example, send fetch() requests)
Availability: None - While not impossible, it is very hard to crash the computer.
Here are some of the scores provided by third parties:
- NVD: 9.8(Critical) - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
To be honest, this is too big. You know, it's not OS command injection or something.
- Snyk: 2.9(Low) - CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
Attack Complexity and User Interaction seems incorrect.
- AmazingMech2418
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
Wouldn't the system for loading from a URL be used for extensions? Also, this is not really a huge deal unless it can access storage and/or cookies though. The best way to sanitize the input would probably to use an allowlist for domains instead of just sanitizing any URLs.
- apple502j
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
This is not the intended mechanics, because getExtensionIdForOpcode is, well… for getting extension ID and not opcode. Ability to make fetch() request itself is enough to be considered as a vulnerability.
- AmazingMech2418
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
Why would there be loadExtensionURL function then that is called by getExtensionIdForOpcode? If it weren't for including extensions not directly in scratch-vm, it must be for loading extensions from URLs. Also, it is sandboxed, so even a fetch request wouldn't be too bad. It's really kind of like the experimental extensions in Scratch 2.0 except that it automatically loads the extension instead of you having to copy and paste into the console. This is not the intended mechanics, because getExtensionIdForOpcode is, well… for getting extension ID and not opcode. Ability to make fetch() request itself is enough to be considered as a vulnerability.
- apple502j
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
I think this is because developers either wanted to add “extension URL” field to project.json (but they didn't) - or too lazy to promisify sync API. The problem is there is no warning or similar stuff before loading such extensions.
- Sheep_maker
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
Perhaps it could be used to DDOS a target if a project abusing this got popular by just constantly spamming requests from every user with the project open. Alternatively, it could be used to spam requests from a different IP (if CORS were enabled on the target). Also, it is sandboxed, so even a fetch request wouldn't be too bad.
I think cryptocurrency miners can also be run inside a web worker if they're just math and a bunch of requests
- AmazingMech2418
- Scratcher
1000+ posts
CVE-2020-14000: Script Injection vulnerability in scratch-vm
Yeah, but, again, CORS would have to be enabled on the target and most largely targeted websites have CORS disabled as is the default normally.Perhaps it could be used to DDOS a target if a project abusing this got popular by just constantly spamming requests from every user with the project open. Alternatively, it could be used to spam requests from a different IP (if CORS were enabled on the target). Also, it is sandboxed, so even a fetch request wouldn't be too bad.
I think cryptocurrency miners can also be run inside a web worker if they're just math and a bunch of requests
- Discussion Forums
- » Advanced Topics
- » CVE-2020-14000: Script Injection vulnerability in scratch-vm