Rafay asked me to do a guest blog and I tried to guess what would be the most useful for this crowd? I think I got just the thing. Ever scanned a box, wondered if it was a honeypot or found it was a honeypot and dissapointed? Well worry no more, today I'll guide you on how to identify honeypots globally, kippo specifically, and how to abuse the functionality of honeypots to your advantage to perform external/internal attacks. Without further ado:
Attacking Kippo
I was perusing my usual reddits and saw a post about tutorial requests. I was looking for ideas on something to do to kill a couple hours and happened across this:
"Id love to see some stuff on recognizing and breaking out of a honey pot (Kippo?)"
I've never looked at kippo code before and was intrigued if I could actually break out of the honeypot and/or what else I could do with one. Well, I haven't been able to break out of it just yet, but I did find you could abuse them as internal (leaking internal address) and external full connect scanners. Read down for more information.
Stage 1.) Fingerprinting (Kippo)
Fingerprinting honeypots is not hard when you actually know what to look for. Kippo is no exception. It doesn't allow a variety of commands that a normal host would, it uses static replies for several other commands (http://osvdb.org/show/osvdb/78099 *sigh* you really submitted that?) easily found in txtcmds directory and the source all over, it breaks command structure arguments like "wget -o log a.com" would attempt to retrievehttp://log, and allows ssh to any host with any password such as "ssh a". Really, there's no challenge in detecting Kippo nor any other honeypot as it's really meant for kids that don't know linux or automated bots trying to infect machines.
The most stealthy approach I found for Kippo detection is attempting to execute a command on login (ssh root@blah id). When attempting this Kippo causes a NotImplementedError exception and won't allow you to connect:
core/honeypot.py:463
def execCommand(self, protocol, cmd):
raise NotImplementedError
def execCommand(self, protocol, cmd):
raise NotImplementedError
This completely kills the connection attempt and doesn't return the command as normal operation would be.
Stage 2.) Universal Fingerprinting
The problem with honeypots is they are emulated layers. Even if a machine attempted to look as realistic as possible, there's still certain things root can do that will likely not be emulated. The style I've been using for a while is adduser. Kippo likes to toy with people, so it endlessly loops through the adduser screen. Easy spotting.
However, other honeypots simply won't let you add users or they will only emulate that they added them with /etc/passwd, /etc/shadow, emulated su/sudo, and etc. By making sure the user has appropriate rights and going through a new session with the new user you should be able to spot any honeypot so far. A session restart usually just refreshes the emulation as if nothing happened in your previous session. If it didn't do that, one could just deplete your honeypot by rm -rf /*.
However, other honeypots simply won't let you add users or they will only emulate that they added them with /etc/passwd, /etc/shadow, emulated su/sudo, and etc. By making sure the user has appropriate rights and going through a new session with the new user you should be able to spot any honeypot so far. A session restart usually just refreshes the emulation as if nothing happened in your previous session. If it didn't do that, one could just deplete your honeypot by rm -rf /*.
/* Note that this can be worked around. Kippo has a userdb for users one could dynamically populate, I just have yet to see it happen. */
Stage 3.) Let's Toy With Kippo (external port scan)
Kippo allows a 'malicious' user to download external files for malware analysis. This, of course, allows us to go ahead and make connections outbound with the honeypot via wget. We don't have much to go off of as no commands with wget are implemented, but we can do port scans. The emulation shows that wget adds http:// in front of all requests, however these are just passed off to connectTCP from the twisted library:
commands/wget.py:103
self.connection = reactor.connectTCP(
host, port, factory, bindAddress=out_addr)
self.connection = reactor.connectTCP(
host, port, factory, bindAddress=out_addr)
So what we can do is wget test.com:port and see if we get:
"HTTP request sent, awaiting response... Connection was closed cleanly."
For an open port or:
"HTTP request sent, awaiting response... User timeout caused connection failure."
Not the fastest thing in the world considering timeout rate is 20 seconds. You can connect to the same host multiple times if you really wanted to speed that process up. And remember this is a full connect, so in some cases it can be fairly useless.
/* I think it'd be interesting if people did this to issue attacks on large enterprise or government sites known to run ids/ips and see how long it takes to get their account suspended or service dropped. wgetfbi.gov:80/attack_attempts_with_uri would be curious. */
Stage 4.) Let's Toy With Kippo (internal port scan)
I sectioned this off because there's an extra trick in here to find the internal address. Of course, one can just scan .1 and .254 in typical to all rfc1918 ranges and see if they get a response for remote control ports. Assuming they're disabled, even though that's not likely just stick with me for the fun of it, we have another toy to use. We can scan internal ranges under the same honeypot port and use the last command.
Example:
Let's assume the honeypot is running under192.168.1.124 on the default port 2222. By attempting to "wget 192.168.1.124:2222", getting a "Connection was closed cleanly." response back indicates we might have found our own address. We can verify by running the last command and seeing if the internal address is in the log file. If you were to simply try localhost:2222, we'd just see 127.0.0.1 in the logs file.
Let's assume the honeypot is running under192.168.1.124 on the default port 2222. By attempting to "wget 192.168.1.124:2222", getting a "Connection was closed cleanly." response back indicates we might have found our own address. We can verify by running the last command and seeing if the internal address is in the log file. If you were to simply try localhost:2222, we'd just see 127.0.0.1 in the logs file.
/* side note - I think people running Kippo in their home under SOHO routers that have issues like persistent XSS or open config pages that spit back passwords could be interesting to check out. */
Stage 5.) Future Attacks
This framework uses quiet a bit of libraries including twisted. If issues were found in these libraries, one could potentially compromise or crash the honeypots. There's certainly more to toy with in Kippo, I just ran out of time and need to continue other work you'll be seeing here soon. Enjoy!
Misc.) Meta Characters
Kippo doesn't strip or replace all meta characters when writing to file. Depending on what kind of program is used to read these files in (I was using last), issuing \x08 (backspace) multiple times will remove entries. Try "ssh blah.com -p 2222 -l $(echo -e "\x08\x08\x08\x08blah)" and tail -f log/kippo.log to see. It's not likely something you'll know of off hand, but if Kippo interfaces get popular and they correctly treat these meta characters or someone told you how they read log files for analysis on a forum/mailing list, it could be of use.
About The Author
This article has been written by Tyler Borland, He has years of experience in Network, Webapplication security. He is an encyclopedia and researchers on each and every subject.
About The Author
This article has been written by Tyler Borland, He has years of experience in Network, Webapplication security. He is an encyclopedia and researchers on each and every subject.
No comments:
Post a Comment