Overview
Vue is an HTML, CSS, and JS framework for developing web applications with fine-grained reactivity.
A cross-site scripting (XSS) vulnerability (CVE-2024-6783) has been identified within the Vue 2 template compiler, which is present in the “full build” of Vue 2. The full build allows user code to compile string templates to Vue components and render functions dynamically within the browser, where they are then executed.
Per OWASP: Cross-Site Scripting attacks are a type of injection, in which malicious scripts are injected into otherwise benign and trusted websites. XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. An attacker can use XSS to send a malicious script to an unsuspecting user.
Details
Module Info
- Product: Vue
- Affected packages: vue-template-compiler
- Affected versions: >=2.0.0 <3.0.0
- GitHub repository: https://github.com/vuejs/vue
- Published packages: https://www.npmjs.com/package/vue-template-compiler
- Package manager: npm
- Fixed in: Vue NES v2.6.17 and v2.7.19
Vulnerability Info
This Medium-severity level exploit can be found in Vue versions greater than or equal to 2.0.0 and before 3.0.0. It is found inside of the in-browser Vue template compiler which is shipped inside the “full build” of Vue. The in-browser Vue template compiler is responsible for creating a string of code to be executed so that component templates like <div>{{ variables }}</div> can be parsed and turned into render functions. These render functions are then executed by Vue when it evaluates the render functions within a stringified eval statement, thus allowing a third-party script to run arbitrary code.
Only certain properties are susceptible to Client-side XSS vulnerabilities when extending the Object.prototype. One such property is staticClass, which is retrieved during the AST construction phase when a template string uses the class attribute with a non-dynamic class.
There are optimizations in place dependent on the entire template string which may or may not trigger this code path. See “Steps to Reproduce” for an example of a component susceptible to this attack.
Steps To Reproduce
The AST Codegen pathway for Vue’s in-browser template compiler relies on properties that are initially unset. Eventually, properties are consumed by a function that stringifies the values and passes them to an eval statement during render. If these properties were explicitly set to undefined or checked for hasOwnProperty then the prototype pollution would not be possible. Currently, almost every property on ASTElement (the primary data structure used for creating codegen nodes during SSR, in-browser compilation, and the Vue SFC file parser) is optional and may be susceptible to this XSS vulnerability.
The template compiler code consumes the AST and does not properly sanitize the content that will be placed in properties eventually called during render. The Example Code and Proof of Concept in the next section are not exhaustive.
<head>
<script>
window.Proxy = undefined // Not necessary, but helpfull in demonstrating breaking out into `window.alert`
Object.prototype.staticClass = `alert("Polluted")`
</script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
</head>
<body>
<div id="app"></div>
<script>
new window.Vue({
template: `<div class="">Content</div>`,
}).$mount('#app')
</script>
</body>
Proof Of Concept
A full reproduction with the above code in a proof of concept website can be viewed here: https://stackblitz.com/edit/cve-2024-6783?file=index.html
Credits
- Zifeng Kang (finder)
- Muxi Lyu (finder)
- Yinzhi Cao
Mitigation
Vue 2 has reached End-of-Life.
Users of the affected components should apply one of the following mitigations:
- Migrate to a newer version of Vue.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.