This tutorial is created to show how simple penetration can become and promote constructive hacking/pen-testing (putting things together and combining knowledge to hack). Hacking/Pen-testing without the need to know how to program (at least not good programming skills :) ). I also got bored (one that is wearingly dull, repetitive, or tedious) not being able to find a decent buffer overflow tutorial to start learning what a want. Any way this article is going to show you how to identify buffer overflow the easiest way, after all you know (if you read my post that fuzzing is what I love doing). Fuzzing can help you to generically approach a wide variety of technologies, from Web Applications to C compiled programs.
In order to be able to follow through this tutorial you have to understand basic assembly, Python (again I will write basic Python scripts) and a few stuff about buffer overflows.
Why IMAP (Internet Message Access Protocol)?
Text based protocols are the simplest to fuzz (yea lets become fUzZy) because all information is in the internet, meaning all the interaction commands, how to log-in, how get e-mail and all that stuff. You can basically use even a telnet command prompt to interact with an Internet Message Access Protocol server.
So for our purposes I am going to use a software that has a vulnerable IMAP4 demon and has a published vulnerability, the Eudora Qualcomm WorldMail 3.0. The exploit for that software can be found at Exploit-DB very neat and clean exploit not to much trouble to exploit.
So here we go, first we will research how can we interact with the mail server, what are the text based commands to use from lets say a telnet session. The exploit says that this is a pr-authentication exploit which means that we do not have to log-in to exploit the vulnerability no need to create account or whatever.
But how do we inTeRaCt? Well lets see, if you type to the Google interact with IMAP you get this info:
Note: Hmm accessing IMAP with telnet,cool.
More about IMAP
IMAP is an email protocol for organizing, storing and retrieving emails on a remote server. It was developed after POP and is a much more advanced system, one of the main differences being that all the mail is stored on the server so it remains accessible from many different locations. With POP you have to download the mail to your local computer in order to read it and therefore you cannot synchronize your mail across many different machines.It may be more complex than POP but there are still only a few core commands we need to know in order to access our mail on an IMAP server.
The IMAP command syntax
Before the actual command is typed into the terminal we need to type a command tag, this could be anything (without spaces) and the server will tag its response with the tag we give it. This seems to be because IMAP allows multiple connections and so multiple commands, by tagging you know which response refers to which command.In our case we use only 1 connection and we send single commands so it's not really relevant (ououo I feel like I am in the matrix, understand IMAP4!! :PPP ), however we need to type something as a tag. I usually you can use a period'.' but you could use a number or whatever suits you.
Setting up our environment
First we install Eudora Qualcomm WorldMail 3.0 (I am not going to show you the installation process :P), you can download WordMail 3.0 from here. Then we check out the status of the server in the control panel services:
Note: We go to Control panel --> Services as you can see Eudora IMAP4 Server is running.
The next thing to do will be to verify that we can interact through a telnet session, first we verify that it is listening in port 143 (if you Google it, the port is splashed into your screen).
The second best thing to do is to initiate a telnet connection with the IMAP4 server through telnet session:
Note: So our environment shows that it is working fine. We installed and run correctly our IMAP4 Server. Then we started interacting the right way through telnet session now I will issue a few commands to see how and why we can exploit the server. Lets try to login with a user that does not exist:
Note: The server interact normally to the failed lo-gin. What do we do know. We need to read more about commands.
More about IMAP4 commands
Once an IMAP session is established, all communication between the client and server takes place in the form of commands sent by the client and responses returned by the server. Like is mentioned earlier, commands and responses are sent as strings of ASCII text and terminated with a CRLF sequence, making them compatible with the way data is sent using the Telnet Protocol.
The first interesting thing about IMAP4 commands is that most are not abbreviated into codes of three or four letters they are spelled out in full. Commands are normally shown in upper case, but are in fact case-insensitive.
IMAP also uses a command tagging to explicitly match client commands with certain server responses. Each time a client sends a command, it prefixes it with a tag that is unique for the particular session. The tags are usually short strings with a monotonically increasing number in them; the examples in the IMAP4 standards have the first command tagged a0001, then the second a0002 and so on. When the server needs to send a response that is specific to a command, it tags the reply with the appropriate command tag.
Note: The tag does not seem to play a significant role for the IMAP4 interaction so I will use the same tag for the exploit.
After a few hours of research I found all the set of the commands needed to start fuzzing the protocol:
Command | Description |
LOGIN | Specifies a user name and password to use for authentication. |
AUTHENTICATE | Tells the server that the client wants to use a particular authentication mechanism and prompts the client and server to exchange authentication information appropriate for that mechanism. |
STARTTLS | Tells the IMAP4 server to use the Transport Layer Security (TLS) protocol for authentication, and prompts TLS negotiation to begin. |
SELECT | Selects a particular mailbox so that messages within it can be accessed. If the command is successful, the session transitions to the Selected state. The server will also normally respond with information for the client about the selected mailbox; see below. |
EXAMINE | Exactly the same as the SELECT command, except that the mailbox is opened “read-only”; no changes are allowed to it. |
CREATE | Creates a mailbox with the given name. |
DELETE | Deletes the specified mailbox. |
RENAME | Renames a mailbox. |
SUBSCRIBE | Adds the mailbox to the server's set of “active” mailboxes. This is sometimes used when IMAP4 is employed for Usenet message access. |
UNSUBSCRIBE | Removes the mailbox from the “active” list. |
LIST | Requests a partial list of available mailbox names, based on the parameter provided. |
LSUB | The same as LIST but only returns names from the “active” list. |
STATUS | Requests the status of the specified mailbox. The server responds providing information such as the number of messages in the box and the number of recently-arrived and unseen messages. |
APPEND | Adds a message to a mailbox. |
Show here is the list of the unauthenticated commands IMAP4 is using to interact with the telnet client (identified from the table above, more info can be found here) and based in our previous research and some clever assumptions that I made I am using this format to sent the commands through telnet (pr-authentication commands):
- A login donotexist pass (attempt log-in)
- a001 CAPABILITY
- a001 LOGOUT
- a001 STARTTLS
- a001 AUTHENTICATE
- a001 STATUS
- a001 APPEND
- a001 LSUB
- a001 UNSUBSCRIBE
- a001 SUBSCRIBE
- a001 RENAME
- a001 DELETE
- a001 CREATE
- a001 EXAMINE
- a001 SELECT
- a001 LIST
Sending the identified commands
Again I open a telnet and type the commands to see how I connect, lets start with CAPABILITY command:
Note: As we can see the unauthenticated command executed successfully.
Now lets try an authenticated commands such as the EXAMINE and the rest to see the results:
Note: See the message BAD command "NAME OF COMMAND" unrecognized or not valid in the current state.
Now the next step to do would be to start fuzzing each command separately to identify the vulnerable commands. So we need a way to automate the process, and we are going to do that by using Python scripting. For our Python we are going to use the socket library.
First a little about fuzzing
Fuzz testing or fuzzing is a software testing technique, often automated or semi-automated, that involves providing invalid, unexpected, or random data to the inputs of a computer program. The program is then monitored for exceptions such as crashes, or failing built-in code assertions or for finding potential memory leaks. Fuzzing is commonly used to test for security problems in software or computer systems.
There are two forms of fuzzing program; mutation-based and generation-based, which can be employed as white-, grey- or black-box testing. File formats and network protocols are the most common targets of testing, but any type of program input can be fuzzed. Interesting inputs include environment variables, keyboard and mouse events, and sequences of API calls. Even items not normally considered "input" can be fuzzed, such as the contents of databases, shared memory, or the precise interleaving of threads.
Python Fuzzing our IMAP4 demon
First we need to open a socket connection then load all IMAP4 commands to send and then forward the traffic to the server. The Python interface is a straightforward transliteration of the Unix system call and library interface for sockets to Python’s object-oriented style: the socket() function returns a socket object whose methods implement the various socket system calls. Parameter types are somewhat higher-level than in the C interface: as with read() and write() operations on Python files, buffer allocation on receive operations is automatic, and buffer length is implicit on send operations.
With the Python script we will create an array of B's (I never liked A's for buffer overflows) and start stuffing the potentially vulnerable variable in order to crush the server. When the server is going to crash it is going to cause a memory fault also called memory crash meaning it will cause a Denial of Service (DoS) attack and it will stop responding, possibly generating an error in the event viewer (definitely create a memory dump), so that is what we are looking for.
What I will do with the following Python code is I will sent ASCII TEXT inputs terminated with a CRLF (the characters '\r\n') meaning this string a001 COMMAND [plus increasing B's] CRLF then close legitimately the connection and go through all commands again by increasing B's by 100 until the server crashes (e.g. first payload 1+100 B's, second payload 1+200 B's e.t.c). This means that I will generate an array (containing B characters) that each element of the array will increase by 100, then take each IMAP4 command separately and try to fuzz the command by sending sequentially the array elements, one each time. But first we will have to find out how is implemented IMAP4 in our vulnerable software.
Investigating the way IMAP4 represent strings
From IMAP4 RFC 3501 I got this information that a string is in one of two forms: either literal or quoted string. The literal form is the general form of string. The quoted string form is an alternative that avoids the overhead of processing a literal at the cost of limitations of characters which may be used.
A literal is a sequence of zero or more octets (including CR and LF), prefix-quoted with an octet count in the form of an open brace ("{"), the number of octets, close brace ("}"), and CRLF. In the case of literals transmitted from server to client, the CRLF is immediately followed by the octet data. In the case of literals transmitted from client to server, the client MUST wait to receive a command continuation request before sending the octet data (and the remainder of the command).
Note: By reading the above information I can make an assumption on how is represented the string in the program and try to crush or cause an error.
I am going to replace B's with the special character { and } to see what happens, so the final version of my Python fuzzer will have this look (click to enlarge):
Note: The { did not work so I tried the ending bracket and boom crushed the server finally, this is the output of the Python shell.
Note: The command vulnerable to the buffer overflow is LIST, which makes my initial assumptions wrong about tampering commands without authentication. In Oder to do that I reduced the bracket increment by 4 and found the exact amount of characters that overwrite our vulnerable buffer (that is not exactly true but I will explain evertything in laters posts). The LIST command crushed in 126 brackets. Xmmm we will see in a later post how to exploit that. You do also realize that it is relatively easy to code an almost generic fuzzer that is going to get as an input an array containing all keyboard characters along with an array of protocol commands and fuzz the protocol. Further investigation will so that not only the LIST command is vulnerable to buffer overflow! (try for yourself to identify which COMMANDS are vulnerable).
Character representation
A more curious person (than the average person) would want to find out in what other ways the bracket character can be represented. Well if you have a question like that your answer can be found here. But do not waste your time clicking to the link just read through. The bracket character looks like this:
ASCII character } To Octal Conversion 175
ASCII character } To Decimal Conversion 125
ASCII character } To Hex Conversion 7D
ASCII character } To Binary Conversion 0111 1101
Now what would happen if we would forward this values instead of the ASCII Text characters (any exercise for you?). The need to understand how a character is represented lets say in hexadecimal arises from the need to be able to see the debugger and understand where is what.
Epilogue
To be continued (it is too late I have to go to sleep)... Watch out for part 2 and 3 (over writing EIP, generating and injecting the payload).
References:
- http://bobpeers.com/technical/telnet_imap
- http://www.eudora.com/download/worldmail/3.0/
- http://networking.ringofsaturn.com/Protocols/imap.php
- http://tools.ietf.org/html/rfc5258
- http://www.tcpipguide.com/free/t_IMAP4SelectedStateMessageManipulationProcessandCom.htm
- http://docs.python.org/library/socket.html
- http://tools.ietf.org/html/rfc3501
- http://www.csgnetwork.com/asciiset.html
- http://pydoc.org/2.2.3/imaplib.html
- http://en.wikipedia.org/wiki/Fuzz_testing