Thursday, October 9, 2014

Buffer Overrun Vulnerabilities and Exploits, Part 1

Hello,

Since we will be delving deeper into the Vortex wargames in the near future, I figured this would be a good time to bring everyone up to speed on buffer overruns. So this will be the first posting in a multi-part series. In this first part, we will cover basic buffer overrun vulnerabilities, as well as simple exploits. Subsequent posts will cover how to execute the actual attacks, as well as return-to-libc theory, which comes into play when the stack is NX (not-executable).

I will cover everything you need to know to have a basic understanding of buffer overruns here. If you want to delve more deeply, here is some suggested reading:
http://www.phrack.com/issues/49/14.html#article
https://www.ethicalhacker.net/columns/heffner/smashing-the-modern-stack-for-fun-and-profit

To learn buffer overruns, and to play Vortex or any other wargame server, you must know how to use gdb to examine memory. I will show some tips/tricks here.

Okay, buffer overruns. What's wrong with this code snippet?

vulnerable1.c                                                                                                                                             

#include <stdio.h>
#include <string.h>
int main(){
  char buffer[80];
  strcpy(buffer,argv[1]);
  return 1;
}

buffer is a char array of size 80. We then use strcpy to take argv[1] (whatever input the user supplies at the command line) and copy it into the buffer variable. No bounds checking is performed here, so the user can write an arbitrary length of data into the buffer variable. This will generally lead to a seg fault, and will crash the program. Unless the attacker is clever...

Let's look at how the stack is laid out for this particular program:

Usually, the stack grows from higher memory (return address) to lower memory (buffer). The function stack layout is:
higher memory -------------------------------------------------------------------------------lower memory
[arguments to the function][return address][saved framepointer(%ebp)][local variables]

A new stack is generated every time we call a function. Further, the memory address of the next instruction to be executed by the cpu after we return from the called function is pushed onto the stack. So if we had code like:
int x = 1;
<call to function>
x += 1;
Then the address of the instruction x+= 1; would be pushed onto the stack when we call <call to function>. This is so that when we return from <call to function>, the cpu knows where to resume execution.
Now, if you were somehow able to gain control of that return address, then you could point it to any accessible address in memory. Basically, you control the program at that point. But, how do we gain control of the return address?
In this case, since no bounds checking is enforced on our input, it is trivial. If you want to follow along, compile vulnerable1.c with the following options:
gcc -ggdb -fno-stack-protector -mpreferred-stack-boundary=2 -o vulnerable1 vulnerable1.c

This will align the stack and turn of stack-smashing detection, necessary if you want these examples to work on a modern Linux system. You will also need to disable stack randomization (ASLR). Do this by running the following command:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
This will not persist through a reboot.

Now, let's run it:
root@bt: ./vulnerable1 $(python -c 'print "A"*80+"B"*4+"C"*4')

We get a seg fault, predictably.
Let's fire up gdb:
root@bt: gdb ./vulnerable1
gdb: break main
gdb: run AAAA...ABBBBCCCC  (that's 80 A's, 4 B's, and 4 C's)
gdb: x/90xw $esp  (look at the top 90 words in hex of the stack ($esp))
gdb: s  (single step past the strcpy)
gdb: x/90xw $esp (look at the top of the stack again, should see our input)
gdb: c (continue)
seg fault, 0x43434343 in ?

Note, 0x41 is "A" in hex, 0x42 is "B" in hex, and 0x43 is "C" in hex, so our 4 "C"s overwrote the return address! The "B"s overwrote ebp, and the 80 "A"s filled in the buffer. Thus, we have successfully overwritten the return address with 0x43434343 by writing past the buffer (supplying 88 pieces of data instead of only 80 or less).

That's all for this round. We've seen that the entire goal in a buffer overrun attack is to gain control of the return address on the stack. Once we have that, we can take care to point it to something else (like, our own function that spawns a shell). We will see in the next posting just how to do that.

Wednesday, October 1, 2014

Vortex level 0

"If looks could kill they probably will, in games without frontiers - war without tears"

Wargame time. Vortex is the first target (probably regrettable, since that server is notoriously hard).
Here is the walkthrough for level0. Problem description can be found here:
http://overthewire.org/wargames/vortex/vortex0.html

I will try to cover all of the levels on this machine. I will post my complete answer, but I'm going to refrain from posting the actual passwords (just run the code if you really want them). Part of the fun of wargames is the agony that comes from trying to solve the damn things, so spoiler alert, use these resources sparingly. It's very easy to read the answer and cheat yourself out of the solution.
Big thanks to overthewire.org for continuing to host these games!

Some suggested reading for this level:
http://www.tutorialspoint.com/python/python_networking.htm
https://docs.python.org/2/library/struct.html
http://teaching.idallen.com/cst8214/08w/notes/bit_operations.txt

This level wants us to connect to a remote host on a specified port, and read four unsigned integers in host-byte order. We are told that the machine is little-endian format. Host-byte order is just a standard used to avoid confusion among little endian and big endian machines. We will read the four unsigned ints, add them together, send back the sum, and receive the solution. There's a catch though, the numbers we receive are quite large, and adding them together will almost always overflow past 32 bits. Thus, at each intermediate stage, we keep our answer to 32 bits by masking it with a 32-bit mask (0xffffffff)

Here's the code. I went with Python over C since I value my sanity;)

#!/usr/bin/python
from socket import *
from struct import *

host = "vortex.labs.overthewire.org" #Target host
port = 5842 #Target port
integer_sum = 0  #This will hold the sum of the received integers
s = socket(AF_INET, SOCK_STREAM) #create a socket connection
s.connect((host,port)) #connect to remote host
#We receive 4 unsigned ints, each 32 bit (4 byte) in Little Endian
for i in range(4): 
data = s.recv(4)
integer_sum += unpack("<I",data)[0]
integer_sum &= 0xffffffff
#unpack handles the network data in Little Endian format
s.send(pack("<I",(integer_sum)))
print s.recv(1024) #username:password
s.close()

We start by importing socket and struct (used for packing and unpacking network data).
We create variables for the host and the port, and then an int that will hold our sum.
we then create a connection-oriented socket and connect to the remote host and port.
The 4 loop will read call recv four times, each time reading in 4 bytes (32 bits) of data.
unpack("<I",data)[0] will take the network stream data in little-endian ( "<" ) format, read it as an unsigned int ("I") and store it in sum. We then consider only the first 32 bits of integer_sum by hitting it with the mask 0xffffffff (this could also be done only once at the end, before sending the sum to the host).
We then send it off (as a little endian unsigned int "<I"), receive the answer (or a "bzzzt, wrong" if you've made a mistake) and call it good. Level0 down, on to the next one!

Wednesday, September 10, 2014

Address Space Layout Randomization in Linux 2.6+

Hi all, this post is intended as a primer for the Vortex wargames I will be hacking here in the coming weeks. If you want to follow along with the wargames, they can be found at www.overthewire.org. I figured this would be a good place to briefly review virtual memory and ASLR in the Linux kernel, since some of the vulnerabilities in Vortex will require us to use buffer overruns, and ASLR is one of the techniques used to prevent such attacks.

Let's start off with a claim that we will then verify below: Roughly all processes run in the same virtual memory space, and are given the illusion that they are the only program running on the computer.

What this means, quite literally, is that if you run a program and look at its start location in virtual memory, and then run another program and look at its location in virtual memory, they should be the same. Let's see if we can verify this by hand:

First, fire up a Linux terminal and type the following:
cat
but don't provide the cat program with any arguments (this should keep it running, so that we can go investigate its memory usage). Now, from a seperate terminal on the same computer, type:
ps -a | grep 'cat'

Read the man pages for more details on the commands ps and grep. This basically lists all of the processes running on your system, and then filters them for the word "cat". Now, you should have a result that looks similar to this:
28733 pts/3    00:00:00 cat

The first number, in this case 28733 (will likely be different when you run this), is the process id for the cat command that we ran a moment ago. Now, from the same terminal, go ahead and run:
cat /proc/28733/maps
Which will produce the following (note when you run the example, substitute the process id on your system in place of 28733):
00400000-0040b000 r-xp 00000000 08:03 7077907                            /bin/cat
0060a000-0060b000 r--p 0000a000 08:03 7077907                            /bin/cat
0060b000-0060c000 rw-p 0000b000 08:03 7077907                            /bin/cat
00e5d000-00e7e000 rw-p 00000000 00:00 0                                  [heap]
7f6d015f1000-7f6d018ba000 r--p 00000000 08:03 12067216                   /usr/lib/locale/locale-archive
7f6d018ba000-7f6d01a6f000 r-xp 00000000 08:03 28053024                   /lib/x86_64-linux-gnu/libc-2.15.so
7f6d01a6f000-7f6d01c6e000 ---p 001b5000 08:03 28053024                   /lib/x86_64-linux-gnu/libc-2.15.so
7f6d01c6e000-7f6d01c72000 r--p 001b4000 08:03 28053024                   /lib/x86_64-linux-gnu/libc-2.15.so
7f6d01c72000-7f6d01c74000 rw-p 001b8000 08:03 28053024                   /lib/x86_64-linux-gnu/libc-2.15.so
7f6d01c74000-7f6d01c79000 rw-p 00000000 00:00 0
7f6d01c79000-7f6d01c9b000 r-xp 00000000 08:03 28053004                   /lib/x86_64-linux-gnu/ld-2.15.so
7f6d01e85000-7f6d01e88000 rw-p 00000000 00:00 0
7f6d01e99000-7f6d01e9b000 rw-p 00000000 00:00 0
7f6d01e9b000-7f6d01e9c000 r--p 00022000 08:03 28053004                   /lib/x86_64-linux-gnu/ld-2.15.so
7f6d01e9c000-7f6d01e9e000 rw-p 00023000 08:03 28053004                   /lib/x86_64-linux-gnu/ld-2.15.so
7fffe41c9000-7fffe41ea000 rw-p 00000000 00:00 0                          [stack]
7fffe41ff000-7fffe4200000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]



That is a snapshot of the virtual memory in use by cat. A couple of things to note here are that memory starts at 0x00400000, and that the [stack] is located at 0x7fffe41c9000.
Great, let's do this entire process again, but for a different program (you can even do this while your instance of cat is still running):
vim
and then, from another terminal:
ps -a | grep 'vim'
cat /proc/29569/maps
which gives:
00400000-005d6000 r-xp 00000000 08:03 12059867                           /usr/bin/vim.basic
007d5000-007d6000 r--p 001d5000 08:03 12059867                           /usr/bin/vim.basic
007d6000-007ec000 rw-p 001d6000 08:03 12059867                           /usr/bin/vim.basic
007ec000-007f8000 rw-p 00000000 00:00 0
00972000-00a36000 rw-p 00000000 00:00 0                                  [heap]

...
...
7f6489602000-7f6489604000 rw-p 00023000 08:03 28053004                   /lib/x86_64-linux-gnu/ld-2.15.so
7fffbcbb0000-7fffbcbd1000 rw-p 00000000 00:00 0                          [stack]
7fffbcbff000-7fffbcc00000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]


To note, the vim program also starts at 0x00400000! So both processes, vim and cat, start at the same location in virtual memory, even when they are both running at the same time. This is in general true of all processes. Note that I am using a 64-bit version of Linux, so the start location may be different on your system, but it should be the same for all of your processes. If you have been paying close attention, you may have noticed that the [stack] has moved from cat to vim, as it is now at 0x7fffbcbb0000. Let's run another instance of cat and see if the [stack] is still at 0x7fffe41c9000.
When I check on a new instance of cat, I find that its virtual memory looks like:
00400000-0040b000 r-xp 00000000 08:03 7077907                            /bin/cat
0060a000-0060b000 r--p 0000a000 08:03 7077907                            /bin/cat
0060b000-0060c000 rw-p 0000b000 08:03 7077907                            /bin/cat
00d0e000-00d2f000 rw-p 00000000 00:00 0                                  [heap]
7ffe3b35c000-7ffe3b625000 r--p 00000000 08:03 12067216                   /usr/lib/locale/locale-archive
7ffe3b625000-7ffe3b7da000 r-xp 00000000 08:03 28053024                   /lib/x86_64-linux-gnu/libc-2.15.so
7ffe3b7da000-7ffe3b9d9000 ---p 001b5000 08:03 28053024                   /lib/x86_64-linux-gnu/libc-2.15.so
7ffe3b9d9000-7ffe3b9dd000 r--p 001b4000 08:03 28053024                   /lib/x86_64-linux-gnu/libc-2.15.so
7ffe3b9dd000-7ffe3b9df000 rw-p 001b8000 08:03 28053024                   /lib/x86_64-linux-gnu/libc-2.15.so
7ffe3b9df000-7ffe3b9e4000 rw-p 00000000 00:00 0
7ffe3b9e4000-7ffe3ba06000 r-xp 00000000 08:03 28053004                   /lib/x86_64-linux-gnu/ld-2.15.so
7ffe3bbf0000-7ffe3bbf3000 rw-p 00000000 00:00 0
7ffe3bc04000-7ffe3bc06000 rw-p 00000000 00:00 0
7ffe3bc06000-7ffe3bc07000 r--p 00022000 08:03 28053004                   /lib/x86_64-linux-gnu/ld-2.15.so
7ffe3bc07000-7ffe3bc09000 rw-p 00023000 08:03 28053004                   /lib/x86_64-linux-gnu/ld-2.15.so
7fff2c34c000-7fff2c36d000 rw-p 00000000 00:00 0                          [stack]
7fff2c3ff000-7fff2c400000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]


 Same start address, but the stack has moved to 0x7fff2c34c000! Why is this? Well, this is the hallmark of Address Space Layout Randomization (ASLR). Linux kernels 2.6 and above randomize parts of virtual memory so that the stack is not always in the same place. But why do this? Well, when you try to perform a buffer overrun attack, one of your goals is to take control of a vulnerable program's stack. From there, you can steal control of the return address, and point it to the location of your malicious shellcode. However, if memory layout is randomized, then the relative locations of the stack and your shellcode will not remain constant, which will make it more difficult to jump to your shellcode! Don't worry if that doesn't make too much sense right now, as I will cover it in much greater detail when I move through the Vortex wargames (I may even do a brief tutorial on buffer overruns before that). Just know that there are ways around ASLR (known as NOP sleds).

That's all for this round. It feels great to be back on this blog again after so much time. I will be covering systems level stuff for a little while, and then might branch into some rootkit discussions, as well as memory forensics, which has really been catching my eye lately. Keep hacking.
ITNOT.
-G3n3s1s



Friday, January 4, 2013

The Dangers of Web Anonimity

Let me start by saying it's technically impossible, in most cases at least, to be truly anonymous on the web(short of having your own botnet, but even that's not a sure thing). There are some common measures you can take, but there are several inherent risks in doing so, that I find are rarely discussed.

I generally assume a technical audience on this blog, just because hacking and security exploits demand that you understand the basics. Indeed, finding vulnerabilities and exploiting them really only becomes practical once you've mastered the basics enough that you can recognize a deviation when you see one.

That said, as this topic applies to anyone who uses the Internet, since everyone has a right to claim whatever threads of privacy they can these days, I'll briefly provide some background knowledge about how web browsing works. Skip it if you know it.

--Begin skip section -- 

A web browser is a program(Firefox, Chrome, Safari...and god help us Internet Explorer) that runs on your computer. You use it to view web pages like Google, SecurityTube.net(which honestly, if you want to know hacking go there. It's where I learned a lot of what I know), etc. These web pages are usually a combination of HTML, CSS, Javascript, PHP, etc. They're just files, really. But they have to live somewhere physically, and that somewhere is a web server. How do you connect to a web server to retrieve these pages? You'll have to know it's name(eg, google.com). In reality, through DNS lookup this name becomes an IP address(something of the form ###.###.###.### under IPv4), which is what layer 3 of the Internet actually knows how to route. Great, now you've contacted the server and requested a webpage, the server has to send it back to you somehow, but how does it know where you are? Well, you have an IP address as well(generally, if you check your own ip via ifconfig or ipconfig you'll see something of the form 192.168.x.y, which is only your private ip address, the real public facing ip is whatever local gateway router you've connected to, which can be found by going to some website that tells you your ip. NAT'ing handles both ways of this translation from public ip space to private ip space).

--End skip section--

So, all that means is that your ip address is what a remote server sees. It can be traced back to you relatively easily unless some measures are taken to obfuscate it. So, to don a veil of secrecy, you should simply change your ip address right? But how?

Enter proxies.

A proxy is nothing more than an intermediate server that you connect to en route to your desired server. You simply reroute all of your traffic through this server so that the server you actually want to retrieve information from sees the request as having originated from the proxy and not from you(it will see the proxies ip address only...maybe). Proxies are commonly used to bypass firewall settings that block a particular set of ip addresses. A proxy generally serves to alter the header of your original HTTP request some way.

There are three types of proxies, each with an increasing degree of anonymity.

Transparent proxies, which actually do little to nothing to the header of the HTTP request. Your ip address will still be available to whatever final server you are trying to contact. This is quite worthless in terms of maintaining secrecy.

Anonymous proxies, which will usually modify the HTTP header to display their ip address instead of yours. While this is desirable, an anonymous proxy will often indicate in the header that a proxy is being used on behalf of the request, which is technically information you probably don't want revealed to someone if you are still reading this.

Highly Anonymous proxies are really the living end. They will modify the HTTP to display only their ip address, and will not usually indicate that a proxy is even in use. This is the best you can ask for when using a proxy.

But wait, proxies are all well and good, but isn't there some other common way of maintaining anonymity on the web? Something to do with onions?

Tor(The onion routing project) is a way of routing requests through the Internet in hopes of obfuscating the origin of the request. Briefly, when you connect to a Tor network, your message is encrypted multiple times(hence the onion theme), and bounced through a "private" network of Tor servers, eventually resurfacing into the "public" internet through an exit node that will contact whatever server you originally wanted to access(facebook.com, for instance). That's a very high overview, and if you are interested in learning more about Tor, just google up the projects website.

Now, after how ever many paragraphs of run up that was, let's discuss where these things can go wrong.

With Tor, the primary concern is in your inability to establish the validity of the exit node of the network. Indeed, if this is being run by some shady operator, they will be able to read all of your traffic. The best way to combat this is to use some transport layer security like TLS to encrypt everything. Another potential pitfall is that the ip addresses of exit nodes are publicly available, and some websites will use this information to block all requests from a Tor network. I've not tested this myself, but you could more than likely bypass this by directing Tor to a proxy that then contacts the server you want. If I ever check on this I'll let you all know. If you check on this you should let me know in the comments section.

But that brings up the dangers of using a proxy service in the first place. A common way of using a proxy is to find a list of publicly available, free servers that will act as proxies and then connect to one of them, alternatively, there are some browser based proxy websites that will simply forward all of your requests directly through your browser. In both cases, the vulnerability is that you can't establish the validity of whomever is running the service. Indeed, you are potentially walking directly into a MITM attack whenever you use one of these services. Any information you send can be viewed by these proxy services, and further, they control your request(you gave it to them, after all), so they may choose to reroute you to any malicious phishing or malware-laced drive-by site of their choosing. SSL will not necessarily save you in the face of a MITM attack either, as it's pretty trivial to set up cert-spoofing. I'll do an article on Evil Twins and MITM attacks one of these days, if for nothing else to make sure none of you ever use public wifi again(whoever coined the term "hot spot" was probably being scanned and infected on every port at the time. Yea, that's right. An MITM will have layer 3 connectivity with you on a LAN. Metasploit much?).

So, what's the consensus? It all depends on the risks you are willing to take based on your need for privacy. I would say that Tor is probably your safest option, unless you have a proxy server somewhere that you know you can trust. There are "paid" proxy services out there, but that doesn't necessarily mean that they are any more trustworthy. At the end of the day, you decide.

In the name of Turing,
-G3n3s1s

Saturday, December 22, 2012

Wargames - Bandit

Time for some wargames. Bandit is the absolute beginner of beginner machines hosted on overthewire.org's wargame servers(http://www.overthewire.org/wargames/bandit/). But, it seems like a fun way to brush up on the basics of linux cli usage and port scanning, so I will go through them all here in this post. I'm not going to dump passwords here though(unless there are like a ton of requests), so you'll have to play though these yourself. Use the man pages as needed if this stuff is new to you. This stuff really will be second nature on future machines.

Level 1: cat the file in the current directory. GG.

Level 2: cat ./- . GG     (that's "cat dot-slash-dash"). The reason being that if you give simply "cat -", the cat program will think you are trying to pass it an option. Similarly, attempting to escape the '-' with slashes or quotes or anything of that nature won't work, as bash will simply strip those before passing the '-' to cat, which will still fail. Specifying the current directory is the best way to go

Level 3: cat plus tab auto completion. Or just backslash to escape the spaces. GG. I never said this article would actually be exciting:)

Level 4: cd into the inhere dir and ls -a to view hidden files. cat the hidden file. GG.

Level 5: cat ./-file0* to wild card and cat all the files at once. There's a pretty obvious password in there somewhere. Alternatively, you could use find with the option to specify an ascii file. Or to filter out binary(not-human readable) files as well.

Level 6: Now I actually have to man find to make this easier. I will search by the size option, and the command find -size 1033c gives the filename to cat.

Level 7: After reading the description I figure it's probably best to use a combination of find and grep. So, going once again off of the size of the file, I try the command find / -size 33c | grep 'bandit7'
which will, starting from the root of the server, find all files of size 33 bytes and then filter them by ones that have the string 'bandit7'. There are probably better ways, such as passing a group name parameter to find instead, but this works. Look though the output of that command, the file that you need to cat is in there somewhere.

Level 8: I bothered with a couple of man pages for sorting options...finally I just cat data.txt | grep "millionth". GG.

Level 9: After a couple of man page visits, uniq -u seems like the command I want to use, but running it directly on data.txt doesn't yield the expected results. Turns out uniq -u works only over a sorted list, at least in this context. Thus, sort it first and pipe it into uniq. Thus, the command is sort data.txt | uniq -u. Victory.

Level 10: Trying to cat the file through grep '=' returns some complaint about a binary file. Easy, just use strings data.txt to find all ascii strings in the binary file. GG

Level 11: base64 -d data.txt aaaaaaand we're off. GG

Level 12: ohhhh, ciphertext(the Krypton wargames will be better, I promise). I simply used a lookup table to reverse it by hand. Writing a basic program to perform the conversion would've been cake of course, but eh, sometimes it's fun to break these things by hand and pretend you are at Bletchley Park or something. Just remember, in 13ROT the "encryption" algo is it's own inverse. And leave the numbers as is.

Level 13: Lot's of stupidity in reversing the hexdump, and then uncompressing over and over. If you are motivated, have at it. If you just want to move on, as you don't really learn anything here, then here ya go: 8ZjyCRiBWFYkneahHwxCv3wb2a1ORpYL

Level 14: The basics of public key cryptography are something you should consider looking into briefly if you are not acquainted with it already. It's not necessary to beat this level or anything, but it's a very interesting bit of cs nonetheless. Anyways, here I have an ssh private key and want to log into bandit14. man ssh reveals the -i option, which enables one to specify a key file in lieu of a password at login. Since I'm already ssh'd into bandit as bandit13, I simply type: ssh -i sshkey.private bandit14@localhost, which beats the level. Alternatively, you could've used something like scp to copy the key file to your own machine, then ssh in from there, that way you wouldn't have to use localhost...not that it matters.

Level 15: Here I simply use a network utility to connect to a port on bandit, which in this case must be localhost. That is, you must already be ssh'd into bandit for this to work. I use netcat to bind to port 3000, with nc localhost 3000, then I simply past the level14 password after the connection is made, and it will dump the level15 password.

Level 16: In order to obtain the level16 password, I have to connect to port 30001 of localhost, which is expecting an ssl communication. The easiest way to establish this is using the openssl tool with the s_client option, which basically creates a simple ssl client, good enough for our purposes here.
openssl s_client -host localhost -port 30001
After some connection info flashes down the screen, I simply past the level15 password.

Level 17: This level was actually quite a bit of fun. First, start by man'ing nmap to get a feel for how port scanning works. From there, the command I execute is along the lines of: nmap -A -T4 -p31000-32000 localhost

Which dumps a list of 5 or so open ports. Several of which are running an echo client, so those can safely be ignored. There are two ports that appears to be running something that speaks ssl, so try connecting to those using the technique from level 16. Eventually, there is a dump of an RSA private key, so we now use the technique from level 14, copy this RSA key into a file in the /tmp directory, chmod it so that is has restricted permissions(say, chmod 700), and then ssh -i path_to_your_temp_file bandit17@localhost.

Once in, I dump the password from /etc/bandit_pass/bandit17, which looks like: xLYVMN9WE5zQ5vHacb0sZEVqbrp7nBTn

Level 18: Simply diff the two files to print the line where they diverge.
kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd

Level 19: .bashrc is modified to log us out whenever we ssh in...so hell with bash, let's specify /bin/sh as our login shell.
ssh bandit18@bandit.labs.overthewire.org /bin/sh
then cat the readme file. GG.
IueksS7Ubh8G3DCwVzrTd8rAVOwq3M5x

Level 20: The binary sitting in the current directory is setuid, which is something you should look into a bit if you are not familiar with it, as it is used a lot in several wargame simulations. The basic idea is that in a setuid program, you usually "run" as a more privileged user, so if you can take control of that program and say, spawn a shell, then you now own that user. Anyways, this one is far less glamorous. A simple strings lev_20_binary_file reveals an example string. It looks as though the program executes whatever program you give to it. So, predictably, I give "/bin/sh" and drop to a shell as bandit20. Simply cat the password file from here. Note use /bin/sh and not /bin/bash, as bash will drop effective setuid privileges. That is a very, very important fact to remember.
GbKksEFF4yrVs6il55v6gwY5aVje5f0j

Level 21: Simple netcat shenanigans. You will need 2 ssh sessions to pull off this level. Simply ssh in as bandit20 on one and open a listening netcat port via: nc -l localhost port#
then, from your other level20, simply connect to that port via: ./suconnect port#
now they are connected, so go back to the original nc instance(the one you used to open the port), and paste the level20 password, then hit enter to send it. You will receive the level21 password in return.
gE269g2h3mw3pwgrj0Ha9Uoqen1c9DGr

Level 22: Looking at the cronjob, it appears to be executing the file /usr/bin/cronjob_bandit22. Upon cat'ing that file, it appears to be writing the contents of the level22 password into a file in the /tmp directory. Simply cat that file. GG
Yk7owGAcWjwMVRwrTesJEwB7WVOiILLI

Level 23: Simply find the file the cron job is executing under /usr/bin. From there, simply copy the echo | md5 | cut command into a different shell, and run it with the $mytarget variable set to bandit23. This will produce an md5 digest, which you then append to /tmp and cat to read the password.
jc1udXuA1tiHqjIsL8yaapX5XIAI6i0n

Level 24:Here the level24 cronjob is simply set to execute every file in the /var/spool/bandit24 directory. Predictably, this runs with level24 permissions, so if we can simply write a script that cat's the bandit24 password file into a place where we can read it, then we've won.
In order to do this, use the steps from the previous 2 levels to find where the cronjob is, and which program it is executing. Then, begin by writing a shell script in the /var/spool/bandit24 directory. Something like the following should do the trick:
#!/bin/bash
mkdir /tmp/saitou/lev24.txt
cat /etc/bandit_pass/bandit24 > /tmp/saitou/lev24.txt

Once the cron job runs, you'll have a lovely, although somewhat worthless(as level25 does not exist at the time of this writing) password for user bandit24 sitting in /tmp/saitou/lev24.txt.
UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ

That's it for bandit. Hardly a harrowing experience. But still, it was nice to relearn some of the basics of port scanning and whatnot. Future wargames will be considerably more hackish I am thinking. I will probably go after Behemoth next, or maybe either Semtex or Vortex. Krypton or Maze will be thrown in for good measure at some point. Ja mata...

In the name of Turing
-G3n3s1s