Skip to main content

Automate Local Fuzzing To Find Bug in Vulnerable Linux Command Line using Python for Fun (day 74) (ง ͠° ͟ل͜ ͡°)ง


Disclaimer: This post only for education only ! not to cause any destruction on any living system. Be smart!

In the previous post about fuzzing we take a look at how we can conduct network fuzzing using boofuzz to find a bug that leads to us to get Remote Code Execution in one of the old software in windows XP (check the post) but that was just an introduction and we only scratch the surface on how we can utilize fuzzing.

So in this post, we are going to take a deeper look on what is actually fuzzing we will cover how many types of fuzzing out there, rule of thumbs on fuzzing and how we can create our own fuzzing to fit our objectives using python

so put on your black hoodie because we are going to hacker mode

This post is inspired by this paper: https://www.exploit-db.com/papers/12965

What is Fuzzing


There are lots of good definition that explain what is the meaning fuzzing but if you asked me, fuzzing is a process of identifying bugs by delivering an unexpected input/data that is handled by the target, the target here can be considered as software, firmware, network protocol, network service and etc

the two highlighted passages already explain the aim and the process of fuzzing respectively.

Basically, We do fuzzing to find bugs although there are numerous way to find a bug in a system such as a taint analysis but fuzzing is the most favorable technique use by many security testers because it's fast and you don't have to really care about the detail

To find bugs in software you need to think outside of the box, meaning you must supply them with unexpected data that could possibly crash the program

Types of Fuzzing

In terms of execution, we can categorize fuzzing into two types:
|
|_______[ Dumb (like the name it's fuzz without any context or guideline but it is easy to write and easy to use) ]
|
|_______[ Smart (the opposite of dumb fuzz so it knows how to handle the target data for fuzzing and of course in this post, the fuzzer that we create will be based on smart fuzzer)]


In terms of deliverance, fuzzing can be done locally or remotely:
|
|_______[ Local (test the software that installed locally through the command line, manipulating file format, user interface input, etc) ]
|
|_______[ Remote (usually test the protocol of the service)]

Little Bit of Jargon


in the world of fuzzing you need to be familiar with terms of "Fuzzing Oracle", this is basically just the data that you used to test with and having a high-quality fuzzing oracle is essential to nail your fuzzing. if the name of fuzzing oracle is too fancy for you, you can consider it as a list test case

Fuzzing oracle could contain random data or not random data at all is up to you which proportion you want the most as long as it still provides reliable angle to fuzz and triggering a bug

In terms of software security you want your Fuzzing oracle to be able to cover this test:
  • Buffer overflow
  • Format String Exploit
  • Integer Overflow
  • Out of bounds breakage (command injection) 
you can custom this list based on your target 

Rule of thumbs in Fuzzing 


 When you conducting fuzzing or creating your own fuzzer always remember that "There is no standard when conducting a fuzzing", you either do it or don't that what's really matter. It's going to include a lot... a lot ... a lot... of testing that could make you spend hours just modifying, compiling and running the same but slightly different code just to get a better result.

but of course, although there is no standard you want your fuzzer to have this quality:
  • It must contain a robust fuzzing oracle (Test case)
  • Able to handle specific data format to be delivered to the target
  • Know how to communicate with the target
Another important point that you must remember is that if the system or software takes input it can be certainly be fuzzed

Get your Hands Dirty

For the demonstration, we will fuzz mbse-bbs program (download: https://www.exploit-db.com/exploits/3154) it is a command-line program that acts as a wrapper for useradd utility, according to the vulnerability database there is a local buffer overflow in its suid "mbuseradd" program

Notes:
You should be aware that this is an old vulnerability it might not be relevant in today's attack but nevertheless what we want to achieve here is the concept of how security researchers can use fuzzing to find the vulnerability in the software.

Also if you follow along with the paper(https://www.exploit-db.com/papers/12965) that I just show you at the beginning of the post you notice that it used 32-bit Linux environment for delivering POC but in this post, I will be using 64 bit environment in Kali Linux OS.

It's up to you which one of the environment that you want to use I used 64-bit environment because I'm curious with what kinda results that I will get but the overall process is still the same for both of the architecture

Setting up the environment




after downloading the source code, extract the package in your current directory



then go to Unix directory and type "make" to build the executable. Once it is done you need to create a directory of "/opt/mbse/bin" in your machine (make sure you have a root privileges to this step)





after creating the directory you can type "make install" to let the binary store in the /opt/mbse/bin path





In the directory, you can see that mbuseradd is set with SUID this means that you can execute the program with the privilege of the user who created it, in this case it will be the root



To call the binary you need to provide a full path of the program like the above figure.

Time to nut up or shut up

Like every technical project the first step is to conduct information gathering, from the previous figure we can see that the program need 4 arguments in order to run

According to the "Secure Programming with Static Analysis" book we are dealing with a "privilege programs" there are two ways to generally the programs interact with the user it's either through command line like we saw earlier or the environment. Since we have the original source code of the package we can do a simple a static analysis to find this out using grep




from the result, we can see that most of the input is tied with the command line which is represented with argv or args but take a look at the fifth line we can see that the program did take a value from the environment using getenv() function and the environment path that they use is "MBSE_ROOT"

from this information, we have enough detail to create our own fuzzing tools

the following code is created using python script


from subprocess import Popen,PIPE
import os

#just a global variable that will be used to as the input for all of the 4 parameter needed by the program
GID = "1"
NAME = "mbsefuzz"
COMMENT = "fuzzing"
USERSDIR = "/tmp"

#mbuseradd [gid] [name] [comment] [usersdir]
bin_location = "/opt/mbse/bin/mbuseradd"

#test case for the program to fuzz the parameter
fuzz_oracle = [
    #buffer overflow testing
    "A" * 512,"A" * 1024,"A" * 2048,"A" * 4096,"A" * 8012,
    #format string exploit testing
    "%n%n%n%n","%5$n","%1024$p","%.1024d",
    #integer overflow testing
    "-1,32767","65535","-2416647762","0xfffffff",
    #command injection
    "a|id > /tmp/FZ|b","a`id > /tmp/FZ`b","a'id > /tmp/FZ'b","a;id > /tmp/FZ;b","a&&id > /tmp/FZ&&b"
]

#for handling the environment settings since mbuseradd also take input from environment variable
def set_env(data):
   
    print "--------------------------------------------"
    os.environ['MBSE_ROOT'] = data
    print "environment: " + str(data)
   
#execute the fuzzing based on the parameter passed in the function
def fuzz(bin_path,gid,name,comment,usersdir):
    shell_command =  ' '.join([bin_path, gid, name, comment, usersdir])
    proc = Popen(shell_command, shell=True, stdout=PIPE, stderr=PIPE)
    out,err = proc.communicate()
   
    print shell_command   
    print "error: " + err
    print "\n"

def main():
    #try to fuzz every parameters
    print "#############################fuzz parameter"
    for x in range(len(fuzz_oracle)):
        fuzz(bin_location,fuzz_oracle[x],NAME,COMMENT,USERSDIR)
    for x in range(len(fuzz_oracle)):
        fuzz(bin_location,GID,fuzz_oracle[x],COMMENT,USERSDIR)
    for x in range(len(fuzz_oracle)):
        fuzz(bin_location,GID,NAME,fuzz_oracle[x],USERSDIR)
    for x in range(len(fuzz_oracle)):
        fuzz(bin_location,GID,NAME,COMMENT,fuzz_oracle[x])

    #try to fuzz the environment
    print "#############################fuzz environment path"
    for x in range(len(fuzz_oracle)):
        set_env(fuzz_oracle[x])
        fuzz(bin_location,GID,NAME,COMMENT,USERSDIR)
   

main()

You can use the above source code or you can make your own python script

if you execute the script it will overflow with many results but with a quick skimming through the result, we can see that the parameter did not contain any buffer overflow







but once we start fuzzing the environment by inputting a large chunk of character it shows segmentation fault in the error status (Gotcha !!)



we can verify this finding by manually set the environment and run the program in gdb as the root user







there you go! when we run the program in gdb we can see it hit segfault and the register is overwritten without our value but notice that we weren't able to overwrite the RIP register at this point I try to adjust the length of the payload but the result always the same it seems that we only able to overwrite the instruction pointer if it's in 32-bit binary. But all it matters that we were able to found the crash using our own fuzzing tools

That's all folks :)

If you have any thoughts or suggestion that could be used to make this post better, Leave a comment below :)

Hope you enjoy this post :)

Comments

Popular posts from this blog

Having fun analyzing nginx log to find malicious attacker in the net (ง'̀-'́)ง (day 37)

  What makes you sleepless at night? is it because of a ghost or scary stories? is it because you have an important meeting tomorrow? or is it because you have an exam? For me, what keeps me up all night is that I keep thinking about what happens to a website that I just created, is it safe from an attacker (certainly not) or did I missing some security adjustments that lead to vulnerability? well I'm not the best secure programmer in the world, I'm still learning and there is a big possibility that I can make a mistake but for me, a mistake can be a valuable investment to myself or yourself to be better so from this idea, I want to know more about what attackers casually do when attacking a website. Here in this post, I'm going to show you how I analyzed attack to the website that I have permission to design and also some interesting findings that I could get from the analysis Background: All of this analysis comes from the traffic that is targeted to th...

Utilize Pwntools for crafting ROP chain :') (day 69)

who doesn't like pwntools? it is a very versatile tool and can be customized according to our need using the python script but did you need to know that pwntools itself can help us to automatically craft a rop chain for us? so in this post, I will show you how to make rop chain less painful and make pwntools do all the heavy lifting. To demonstrate this I will use the binary challenge callme 64 bit from ropemporium link: https://ropemporium.com/challenge/callme.html Crashing the app: Like any other exploitation process, we need to crash the program by generating a long string pattern to determine the offset. based on the information from the above figure we can see that we required to provide 40 bytes of offset Fun stuff: now this where the fun stuff began write the following python script: as in the guideline of the challenged said we need to chain the function call by first to call the callme_one function, callme_two function and then callme_three funct...

Bypassing stack canaries protection :') (day 51)

In my previous blogs, I show you guys how to bypass some common protection usually used in Linux binary such as NX and ASLR but this time we are going to take it to the next level we are going to talk about protection employ in the modern Linux OS which is "The Canaries" and how to bypass it. note: this post was not originally mined it was inspired by the following resources https://ctf-wiki.github.io/ctf-wiki/pwn/linux/mitigation/canary/ (Credit goes to the author) we are going to start this post about what is stack canaries and types of different implementation of it then move to the implementation about how to bypass this protection. We are going to focus on "leak canaries" technique What is stack canary: In layman terms, canaries are just another protection mechanism to prevent stack overflow implemented by appending 4/8 bytes value (depend on the architecture) into the stack when a function is entered. When the function is at the end of its exec...