Luckily for us, it is not necessary for the typical penetration tester to spend months and years preparing the perfect fuzzer. The community has already provided us with an abundance of these wonderful tools, and compared to writing them, their usage is a breeze!
The Bruteforce Exploit Detector (BED) does exactly what the name implies. The program will allow you to send data to the target application in hopes that a crash will occur. Although this method does work in certain situations, at times more control is needed when trying to find vulnerable applications. Kali has BED preinstalled; BED provides the ability to fuzz several, often using protocols without modification:
BED 0.5 by mjm( www.codito.de ) & eric ( www.snake-basket.de ) Usage: ./bed.pl -s <plugin> -t <target> -p <port> -o <timeout> [ depends on the plugin ] <plugin> = FTP/SMTP/POP/HTTP/IRC/IMAP/PJL/LPD/FINGER/SOCKS4/SOCKS5 <target> = Host to check (default: localhost) <port> = Port to connect to (default: standard port) <timeout> = seconds to wait after each test (default: 2 seconds) use "./bed.pl -s <plugin>" to obtain the parameters you need for the plugin. Only -s is a mandatory switch.
Besides the plugins provided by the developers of the Bruteforce Exploit Detector, you may also easily create your own plugins. Take a look at the /usr/share/doc/bed
directory dummy.pm
file. This skeleton provides you with a skeleton that can be modified to suit our needs. Change directory to /usr/local/share/bed/bedmod
and cat
a couple of the files that you see, such as ftp.pm
, to get a better idea of what a fully functional plugin looks like. When you are comfortable with the format, create a new file in the bedmod
folder and name it vserver.pm
. The following code has been created using the dummy.pm
example template. Enter this code into vserver.pm
:
packagebedmod::vserver; use Socket; sub new{ my $this = {}; # define everything you might need bless $this; return $this; } sub init my $this = shift; %special_cfg=@_; $this->{proto} = "tcp"; if ($special_cfg{'p'} eq "") { $this->{port}='4444'; } else { $this->{port} = $special_cfg{'p'}; } $iaddr = inet_aton($this->{target}) || die "Unknown host: $host "; $paddr = sockaddr_in($this->{port}, $iaddr) || die "getprotobyname: $! "; $proto = getprotobyname('tcp') || die "getprotobyname: $! "; socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die "socket: $! "; connect(SOCKET, $paddr) || die "connection attempt failed: $! "; send(SOCKET, "HELP", 0) || die "HELP request failed: $! "; $this->{vrfy} = "HELP "; } sub getQuit{ return("EXIT "); } # what to test without doing a login before sub getLoginarray{ my $this = shift; @login = (""); return(@login); } # which commands does this protocol know ? sub getCommandarray { my $this = shift; # the XAXAX will be replaced with the buffer overflow / format string #data # place every command in this array you want to test @cmdArray = ( "XAXAX ", "STATS XAXAX ", "RTIME XAXAX ", "LTIME XAXAX ", "SRUN XAXAX ", "TRUN XAXAX ", "GMON XAXAX ", "GDOG XAXAX ", "KSTET XAXAX ", "GTER XAXAX ", "HTER XAXAX ", "LTER XAXAX ", "KSTAN XAXAX " ); return(@cmdArray); } # How to respond to login prompt: sub getLogin{ # login procedure my $this = shift; @login = ("HELP "); return(@login); } # Test anything else you would like to sub testMisc{ return(); } 1;
At first glance, this code may seem complicated. If you take a look at the highlighted code, you will see the most important aspect of our particular plugin. We instructed bed
to send data to each of the inputs that were provided to us by the HELP
command. The default port is set to 4444
, and the login is blank because it is not required for this type of application. There is one more modification that needs to occur before we can use the vserver.pm
plugin. Open up the /usr/share/bed/bed.pl
file for editing and add vserver
to the @plugins
variable on line #14:
@plugins = ( "ftp", "smtp", "pop", "http", "irc", "imap", "pjl", "lpd", "finger", "socks4", "socks5", "vserver" );
Save the changes you made to bed.pl
and exit your editor. Assuming you have already started vulnserver.exe
on port 4444
, let's give our new plugin a try:
# bed -s vserver -t <IP of the Server> BED 0.5 by mjm( www.codito.de ) & eric ( www.snake-basket.de ) * Normal tests + Buffer overflow testing: testing: 1 XAXAX ........... testing: 2 STATS XAXAX ........... testing: 3 RTIME XAXAX ........... testing: 4 LTIME XAXAX ........... testing: 5 SRUN XAXAX ........... testing: 6 TRUN XAXAX ........... testing: 7 GMON XAXAX ........... testing: 8 GDOG XAXAX ........... testing: 9 KSTET XAXAX ...
The bed.pl
is definitely doing something, but we do not really get any feedback on precisely what is occurring. If you wait long enough, you will receive a notice of a crash. An example of this is shown in the following image:
Unfortunately, the vulnserver application is still receiving connections and thus, bed.pl
will continue the brute forcing process. Also, at this point we do not know what caused the crash. When we click on Close, we are rewarded with some debugging information from the vulnserver console, but this behavior should not always be expected when working with client-modified or created applications. Often debugging will be disabled on production applications to avoid giving potential attackers too much information.
We did not code in anything that would stop the program if certain statements (such as GOODBYE) did not appear after the EXIT
command was initiated. Because of this, the Bruteforce Exploit Detector did not detect that there was an issue! Challenge yourself to add this functionality to your plugin!
Let's take a look at the terminal that is providing usage feedback from stdout
:
Waiting for client connections... Unhandled exception: page fault on read access to 0x41414141 in 32-bit code (0x41414141). Register dump: CS:0073 SS:007b DS:007b ES:007b FS:0033 GS:003b EIP:41414141 ESP:00c0e4c0 EBP:41414141 EFLAGS:00210202( R- -- I - - - ) EAX:00c0e470 EBX:7bc9cff4 ECX:00000000 EDX:00000065 ESI:7ffccf10 EDI:00401848 Stack dump: 0x00c0e4c0: 41414141 41414141 41414141 41414141 0x00c0e4d0: 41414141 00000000 00000000 00000000 0x00c0e4e0: 00000000 00000000 00000000 00000000 0x00c0e4f0: 00000000 00000000 00000000 00000000 0x00c0e500: 00000000 00000000 00000000 0018ff48 0x00c0e510: 696c6156 6f432064 6e616d6d 0a3a7364 Backtrace: 0x41414141: -- no code accessible -- Modules: Module Address Debug info Name (22 modules) PE 400000- 407000 Deferred vulnserver PE 62500000-62508000 Deferred essfunc ELF 7b800000-7b97d000 Deferred kernel32<elf> -PE 7b810000-7b97d000 kernel32 ELF 7bc00000-7bcb9000Deferredntdll<elf> -PE 7bc10000-7bcb9000 ntdll ELF 7bf00000-7bf04000 Deferred <wine-loader> ELF 7ed60000-7ed7f000 Deferred libgcc_s.so.1 ELF 7ed90000-7edbd000 Deferred ws2_32<elf> -PE 7eda0000-7edbd000 ws2_32 ELF 7edbd000-7ee3f000Deferredmsvcrt<elf> -PE 7edd0000-7ee3f000 msvcrt ELF 7ef9c000-7efa8000 Deferred libnss_files.so.2 ELF 7efa8000-7efb2000 Deferred libnss_nis.so.2 ELF 7efb2000-7efc9000 Deferred libnsl.so.1 ELF 7efc9000-7efef000 Deferred libm.so.6 ELF 7eff8000-7f000000 Deferred libnss_compat.so.2 ELF b7593000-b7597000 Deferred libdl.so.2 ELF b7597000-b76f1000 Deferred libc.so.6 ELF b76f2000-b770b000 Deferred libpthread.so.0 ELF b771c000-b785c000 Deferred libwine.so.1 ELF b785e000-b787b000 Deferred ld-linux.so.2 Threads: process tidprio (all id:s are in hex) 0000000e services.exe 00000014 0 00000010 0 0000000f 0 00000011 winedevice.exe 00000018 0 00000017 0 00000013 0 00000012 0 00000074 (D) Z: ootvulnserver.exe 0000004d 0 00000048 0 <== 00000076 0 00000075 0 0000004b explorer.exe 0000004c 0 Backtrace: Send failed with error: 10054 Received a client connection from 192.168.75.173:41190 Waiting for client connections...
It is of note that EIP
has been overwritten with 41414141
. This is a good indicator that an exploit of this stack overflow is likely to be possible. Also, notice that the server output indicates that connectivity requests are occurring. The server did not completely crash, only this connection. This can be used to your advantage if you need to create your own exploit later.
Now that we know there is an issue with the application, we need to get an idea of what was sent to cause the crash. Usually your fuzzer would provide this information for you, but in this case, bed.pl
just keeps on chugging:
# wireshark
Wait until the Wireshark GUI has completely loaded and selected the option that captures eth0
(this will allow you to witness the traffic) from the middle of the screen.
Let's reproduce the error, but this time we will watch the packets in Wireshark as they traverse the local loopback interface. Restart the vulnserver
, and then start bed.pl
again using the vserver
plugin. Once everything has started, click over to Wireshark and take a look at the packets that are being passed. You can right-click on any of the messages in Wireshark and select Follow TCP Stream to see the messages in an easy to read format.
If you wait until the crash occurs, you can search the stream in Wireshark that looks to be the most obvious cause of the crash. Keep in mind that we do not have any delays in the code, so the last connection made is not necessarily the connection that caused the error to occur. In this particular case, it was noted in the vulnserver
console that the last connection to be made before the crash was:
Received a client connection from 192.168.75.173:41041 Waiting for client connections... wine: Unhandled page fault on read access to 0x41414141 at address 0x41414141 (thread 0048), starting debugger...
If you go to Wireshark and enter tcp.stream eq 41041
into the Filter menu, you will be presented with only those packets that make up the messages we are interested in. Pick one of the filtered messages, right-click on it, and take a look at the TCP stream.
An example of this is shown in the following image:
It looks like the last message to be sent to vulnserver was:
KSTET AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
We can determine that KSTET
typically sends a response (KSTET SUCCESSFUL
) upon successful acceptance of input by reviewing previous messages without using the filter:
EXIT KSTET AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA HELP EXIT KSTET SUCCESSFUL
We can test this input to see if we can manually replicate the error. Stop and restart the vulnserver, and manually netcat
to port 4444
on the machine running the vulnserver:
# nc 192.168.75.134 4444 Welcome to Vulnerable Server! Enter HELP for help. KSTET AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA KSTET SUCCESSFUL KSTET AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
At this point, the application will crash and the Program Error pop up will appear once more. Click on Close in the Program Error window. Once again, we can review the output from the debugger and note that EIP
(the current instruction being processed) has been overwritten by 41414141
.
These are the type of repeatable errors we should be looking for when attempting to ensure the security posture of the environments being tested. Depending on the scope of the test, at this point, the business may only require the details of the potential vulnerability. If the scope allows, an exploit for the application could be created to prove that the vulnerability could lead to loss of important data, assets, or revenue.
Simple fuzzer, known as sfuzz, created by Aaron Conole is a great tool if you want to start taking the fuzzing business seriously, and. sfuzz is powerful and useful to someone who is not ready to expend the time needed to properly learn how to fully use spike. Also, there are times when using a smaller, simpler tool is just more efficient.
If you are still learning about exploit development, then sfuzz makes a great stepping stone and will definitely continue to be a valuable addition to your penetration testing knowledge base throughout the years ahead; at times, it is very convenient to have tools that are quick and easy to configure!
Browse to the /usr/share/sfuzz
directory and familiarize yourself with the directory structure. If sfuzz
is invoked without arguments, you will be presented with the available startup switches:
sfuzz [23:11:45] error: must specify an output type. Simple Fuzzer By: Aaron Conole version: 0.7.0 url: http://aconole.brad-x.com/programs/sfuzz.html EMAIL: [email protected] Build-prefix: /usr/local -h This message. -V Version information. networking / output: -v Verbose output -q Silent output mode (generally for CLI fuzzing) -X prints the output in hex -b Begin fuzzing at the test specified. -e End testing on failure. -t Wait time for reading the socket -S Remote host -p Port -T|-U|-O TCP|UDP|Output mode -R Refrain from closing connections (ie: "leak" them) -f Config File -L Log file -n Create a new logfile after each fuzz -r Trim the tailing newline -D Define a symbol and value (X=y). -l Only perform literal fuzzing -s Only perform sequence fuzzing
Although there are example scripts available, we will need to create our own if we would like to be able to fuzz the vulnserver application. Create the following script, named basic.verserver
, in the sfuzz-sample
directory:
include basic-fuzz-strings.list reqwait=800 maxseqlen=2010 endcfg KSTET FUZZ -- FUZZ -- LHLO FUZZ --
In this script, we instruct sfuzz
to use basic-fuzz-strings.list
when performing the fuzzing activity. We then add a delay of 200 milliseconds and restrict the sequence length to 2010. This fuzzer is so simple that we then list the commands to be sent, followed by the fuzz variable, which is replaced by the application with fuzzed output. We must save the file, ensure that the vulnserver is running on port 4444
, and then proceed with starting the sfuzz
script:
# sfuzz -e -S <IP of vulnserver> -p 4444 -TO -f /sfuzz-sample/basic.vserver
This will start the fuzzing process and will also let you see the data that is being passed. One technique that could be used is to perform a very fast scan to see if any crashes occur, and then rerun the scan again using more refined parameters and at a slower pace. This will ensure that the exception is caught easily.
As expected, our fuzzer script was able to crash the vulnserver with the following output:
============================================================== [23:58:30] attempting fuzz - 31. KSTET AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA [23:58:30] info: tx fuzz - (2017 bytes) - scanning for reply. [23:58:31] read: Welcome to Vulnerable Server! Enter HELP for help.
Once again, the test did not catch the failure and sfuzz
continued to send data to the application. As previously stated, the art of fuzzing can be extremely useful, but the path to mastering it will take dedication and continual practice.