<![CDATA[Manuel Morfin]]>https://manuelmorfin.com/https://manuelmorfin.com/favicon.pngManuel Morfinhttps://manuelmorfin.com/Ghost 5.49Thu, 08 Jun 2023 16:44:04 GMT60<![CDATA[Exploiting Samba to Gain Root Access on Metasploitable 2]]>

Introduction:

In this lab exercise, I will provide detailed information on how I gained remote access to a target system by exploiting a vulnerable service using the Metasploit Framework. I will specifically discuss how I exploited the Samba service on the Metasploitable 2 system.

Discovery of the Vulnerability:

To determine

]]>
https://manuelmorfin.com/exploiting-samba-to-gain-root-access-on-metasploitable-2/6456f9daad1bd200015df3aaSun, 07 May 2023 02:02:25 GMT

Introduction:

Exploiting Samba to Gain Root Access on Metasploitable 2

In this lab exercise, I will provide detailed information on how I gained remote access to a target system by exploiting a vulnerable service using the Metasploit Framework. I will specifically discuss how I exploited the Samba service on the Metasploitable 2 system.

Discovery of the Vulnerability:

To determine which service to exploit for root access, I began by conducting research on the target system. I used NMAP, a network exploration and security auditing tool, to scan the Metasploitable 2 system. NMAP allowed me to gather more information about the services running on the system by performing an aggressive search.

The command used was:

nmap -T4 -v -A 192.168.232.129
Exploiting Samba to Gain Root Access on Metasploitable 2
nmap -T4 -v -A 192.168.232.129 command results

After analyzing the results of the scan, I discovered that the Metasploitable 2 system was running Samba smdb 3.0.20-Debian on port 445.

I did some research online and found that Samba smdb 3.0.20-Debian had a known exploit related to the username map script.

Exploiting Samba to Gain Root Access on Metasploitable 2
Exploit found associated with Samba smdb 3.0.20-Debian

Exploiting the Vulnerability:

To exploit the username map script vulnerability in the Samba service, I used the Metasploit Framework on my Pentest system. I searched for the Samba service in the Metasploit Framework using the command "search samba". I located the module "exploit/multi/samba/usermap_script" and used it to execute the exploit.

Exploiting Samba to Gain Root Access on Metasploitable 2
Module used to gain root access

To gain more information about the exploit, I used the "info" command, which provided me with more details about the exploit. The reference section of the module had a few links that made finding the exploit easier. Most of the links were dead, but fortunately, https://www.samba.org/samba/security/CVE-2007-2447.html was still up. This helped me identify that I needed to set up RHOST.

Exploiting Samba to Gain Root Access on Metasploitable 2
Info command results
Exploiting Samba to Gain Root Access on Metasploitable 2
https://www.samba.org/samba/security/CVE-2007-2447.html

RHOST is a variable that is used to set the target IP address for the exploit. The following command was used to set RHOST:

set RHOST 192.168.232.129
Exploiting Samba to Gain Root Access on Metasploitable 2
set RHOST 192.168.232.129

After setting RHOST, all that was left was to type "run" to execute the exploit and establish a connection.

The "whoami" command was then ran to confirm that root access was gained.

Exploiting Samba to Gain Root Access on Metasploitable 2
Whoami command 

Conclusion:

Through this lab exercise, I was able to gain root access to the Metasploitable 2 system by exploiting the Samba service using the Metasploit Framework. The vulnerability that allowed me to gain access was related to the username map script in Samba smdb 3.0.20-Debian.

This exercise highlights the importance of identifying and patching vulnerabilities in software to prevent exploitation. It also reinforces the importance of security awareness and the need to be vigilant about the services and ports running on a system.

]]>
<![CDATA[Un-bounded Arrays in C: An exploit analysis]]>

Introduction:

Un-bounded arrays in C can cause memory allocation issues, potentially leading to overwriting locations in memory with extra information. It is crucial for software developers to understand how these issues occur and how to prevent them. In this project, we were given a program called wargames.c that has

]]>
https://manuelmorfin.com/fixing-un-bounded-arrays-in-c-a-lab-report/6456e8bdad1bd200015df309Sun, 07 May 2023 00:24:54 GMT

Introduction:

Un-bounded Arrays in C: An exploit analysis

Un-bounded arrays in C can cause memory allocation issues, potentially leading to overwriting locations in memory with extra information. It is crucial for software developers to understand how these issues occur and how to prevent them. In this project, we were given a program called wargames.c that has multiple issues with un-bounded arrays. Our task was to analyze the flaws in the code and propose solutions to fix it. I extensively examined the wargames program and identified its vulnerabilities, which I will elaborate on in this report and provide solutions to fix them.

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

void launch_missiles(int n)
{
    printf("Launching %d missiles\n", n);
}

void authenticate_and_launch(void)
{
    int n_missiles = 2;
    bool allowaccess = false;
    char response[8];

    printf("Secret: ");
    fgets(response, sizeof(response), stdin);

    if (strcmp(response, "Joshua\n") == 0)
        allowaccess = true;

    if (allowaccess)
    {
        puts("Access granted");
        launch_missiles(n_missiles);
    }

    if (!allowaccess)
        puts("Access Denied");
}

int main(int argc, char **argv)
{
    puts("Wargames Missile Launcher v1.3");
    authenticate_and_launch();
    puts("Operation Complete");
}
Wargame.c source code

Establishing the groundwork

As buffer overflows are usually exploited through reverse engineering, I utilized gdb, a command line-based debugger, to conduct most of my testing. Although I was given the source code, I compiled the wargames program with the -g flag using the gcc compiler to include useful debugging information in the executable. This approach enabled the program to be compiled with minimal optimization.

Additionally, I disabled ASLR and incorporated -no-pie and -fno-stack-protector options to enhance my testing environment.

Un-bounded Arrays in C: An exploit analysis

Finding each error

I began my exploit analysis of the wargames program by running it in gdb and executing the "run" command. The program printed two strings, "Wargames Missile Launcher v1.3" and "Secret," before prompting for user input.

Un-bounded Arrays in C: An exploit analysis

Unfortunately, the program did not specify what value was expected as input. So, I began manually entering and testing random values, starting with a single 'a' character. The program returned "access denied," which suggested that it was looking for a secret key, and the incorrect key led to an "Access Denied" message.

Un-bounded Arrays in C: An exploit analysis

I continued to enter random characters, increasing the length each time until I noticed a change. When I entered a string with thirteen characters, the program responded with "access granted and launching missiles."

When I entered a string with sixteen characters, gdb returned a segmentation fault, indicating that memory addresses were being overwritten. This suggested that the program malfunctioned as the input value got longer, and a string of twelve or more characters granted user access.

Un-bounded Arrays in C: An exploit analysis

I then examined the source code and identified two key issues.

The first was the implementation of the input response as a char array with a size of eight bytes, stored using the gets() method, which is prone to buffer overflow errors. The second issue was with the use of the strcmp() method, which lacked data validation, allowing users to input invalid strings that were not null-terminated, leading to comparison errors and accessing non-accessible parts of memory.

Un-bounded Arrays in C: An exploit analysis

Validating my theory

To validate my theory, I created breakpoints in gdb for each function using my knowledge of the function names in the Wargames program. I ran and traversed through the program line by line, keeping track of variable values using the display command.

Un-bounded Arrays in C: An exploit analysis

I discovered that the authenticate_and_launch function was where the local variables were in use, and the value of n_missiles was initially set as garbage value until a few more lines were executed and stored the correct value of two. The allowaccess variable was initially set as false and returned a value of zero, while the response variable had a general garbage value stored until the strcmp() method was called.

Un-bounded Arrays in C: An exploit analysis

Upon inputting a string of thirteen 'A' characters, n_missiles displayed a value of 1094795585, allowaccess displayed a value of 65, and the response array had a value of 'AAAAAAA.' Using the (p &) command, I obtained the memory address of where each variable's value was stored and looked at the stack using the command x/1x $rsp. I discovered that all the values were stored within close memory ranges from each other, explaining why the remaining 'A' characters were stored in the neighboring memory address and why allowaccess had a decimal value of 65 (an ASCII value of A) and n_missiles returned a decimal value of 1094795585, which is equivalent to four capital 'A' characters.

Un-bounded Arrays in C: An exploit analysis

Explaining why these errors exist

These errors exist because the programmer did not implement proper data validation. It is important to validate user input to ensure that only valid submissions are processed. This involves checking the input size and rejecting anything that exceeds the allocated buffer size, as well as accepting only compatible data submissions. For example, if a program requires an integer input, any submission that comes in as a string should be rejected.

When implementing the wargames program, the programmer used the gets() method but failed to define any data validation. It was crucial to implement a way to reject inputs that surpassed the buffer size, which was not done. As a result, the program stored any submission it was handed, even if it was larger than the buffer.

Similarly, no validation was conducted when using the strcmp method. When comparing a string to another string using strcmp(), the method will continue to compare the string values until reaching a null terminated value. However, if there is no null terminated value, the method will continue to compare the string values until reaching a non-accessible part of memory. Therefore, we need to set a limit on the size of the string we are comparing. In this case, as the user input is being compared to the string value of "Joshua," there is no reason to allow an input that surpasses seven characters, including the null terminator.

By failing to properly implement the gets() and strcmp() methods, the wargames program suffered from a buffer overflow. This was evident when I entered a large string text and was still able to gain access to the program without entering the correct secret key. To prevent such vulnerabilities, it is crucial to implement proper data validation when dealing with user input.

How I exploited the program

Un-bounded Arrays in C: An exploit analysis

To exploit the wargames program, I fed the response array a value that was longer than eight bytes. The gets() method didn't check or validate my input, so it just tried to store the entire string in the array. However, the array could only hold eight characters, so the excess characters spilled over into a neighboring memory address when the strcmp command was executed. As a result, my input overwrote the value stored in the "allowaccess" variable, changing it from 0 to 65. This granted me access to the missile system.

Proposed Solution

To prevent a buffer overflow from occurring, I would recommend using the fgets() method instead of gets() method. This is because fgets() allows us to limit the size of the input, ensuring that the program does not process any data larger than the expected number of bytes. In this case, I recommend setting the limit to eight bytes since the correct password, "Joshua," is only six bytes long, plus two bytes for the newline character.

Once we have restricted the length of the input, we need to address the strcmp() method. While strcmp() compares two strings, it does not have any restrictions in terms of when it stops, which can lead to segmentation faults if the input string does not have an EOF character. To avoid this, we can replace strcmp() with strncmp(), which allows us to set a limit on the number of bytes to be compared. In this case, we want to limit the comparison to the first eight bytes of the input string.

By implementing these changes, the program will be much more secure, preventing any memory buffer overflows and denying access to anyone who tries to enter a long string.

Un-bounded Arrays in C: An exploit analysis
Un-bounded Arrays in C: An exploit analysis

Conclusion

When it comes to data manipulation in programming, it's vital to incorporate secure coding practices to prevent malicious attacks, such as buffer overflows. In the wargames program provided, I was able to gain unauthorized access by overwriting memory values with a long string since the program did not perform any form of data validation. As the response array became full, the extra bytes of data were stored in the neighboring memory addresses containing the values of the local variables used in the program, resulting in unauthorized access.

To prevent similar buffer overflow issues, I recommend limiting the values processed by the program using the fgets() method to ensure only appropriate-sized values are processed. Moreover, we can use the strncmp() method to provide additional safety measures by limiting the number of bytes of data compared between two strings. Unlike the initial program, which kept reading values until it found a null terminator, our updated method ensures that the program doesn't access a non-accessible part of memory.

Overall, the security of a program solely depends on how the developer designs it. It's essential to evaluate how inputs are processed and provide appropriate error handling to prevent any potential security risks.

]]>
<![CDATA[Brute-forcing MD5 Hashes with Python]]>

Have you ever wondered how brute-forcing works? In this project, we will explore one way to brute-forcing MD5 hashes using a distributed approach with Python. We will create a server that sends brute-force tasks to multiple client bots that will perform the cracking and return the result to the server.

]]>
https://manuelmorfin.com/brute-forcing-md5-hashes-with-python/6456032dad1bd200015df299Sat, 06 May 2023 07:35:13 GMTBrute-forcing MD5 Hashes with Python

Have you ever wondered how brute-forcing works? In this project, we will explore one way to brute-forcing MD5 hashes using a distributed approach with Python. We will create a server that sends brute-force tasks to multiple client bots that will perform the cracking and return the result to the server.

How Password Brute-forcing Works

Password brute-forcing is the process of guessing or cracking a password by trying different combinations of characters until the correct one is found. This method is very time-consuming and can take days, weeks, or even months to crack a password, depending on the length and complexity of the password.

Distributed Password Brute-forcing

Distributed password brute-forcing is a method of password cracking that uses multiple computers or nodes to perform the brute-force task simultaneously. This approach can significantly reduce the time required to crack a password, as each node can work on a different set of combinations simultaneously.

Disclaimer

🛑
This project was created as a way for me to learn about distributed systems. The goal was to create a distributed system that would allow me to brute-force 'passwords' that have been hashed. These passwords have been hashed using MD5 for the sake of simplicity. At no point in time should you ever store passwords as MD5 hashes, let alone without some form of salting. That being said, the code presented here can always be modified to bruteforce different hashing algorithims.

Setting up the Server

In this project, we will create a Python server that will send brute force password cracking tasks to multiple client bots. The server will listen on a specific IP address and port for incoming connections from the client bots. When a client bot connects, the server will add it to a list of connected clients and wait for incoming messages from the client bots.

Implementing the Server

# imports the libraries needed
import socket, string
from threading import Thread

# defines the hostname and reserves the port that will be utilized to connect with this server
SERVER_HOST = "192.168.50.5"
SERVER_PORT = 32401 

# Defines a blank global list to store connections
client_sockets = []

## creates a new socket, AF_INET for IPV4 and SOCK_STREAM for TCP 
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((SERVER_HOST, SERVER_PORT))

# listens for incoming connections
s.listen(5)
print(f"[*] Listening as {SERVER_HOST}:{SERVER_PORT}")

# list of characters that will be used to generate permutations
chars = string.ascii_lowercase + string.ascii_uppercase + string.digits + '!@#$%'

# function used to send commands to the bots
def sendCommand():
  # sends the shell command to all the clients on the clientList
        print("Enter an MD5 to crack$", end=" ")
        # sends the MD5 hash received
        command = input()
        # sends it to the clients
        print("Please wait while we crack the password")
        client_sockets[0].send(chars.encode())
        client_sockets[0].send(command.encode())
        client_sockets[1].send(chars[::-1].encode())
        client_sockets[1].send(command.encode())  

# function used to listen for incoming connections from the bots
def listen_for_client(cs):
    while True:
        try:
            # keep listening for a message 
            if(len(client_sockets) == 2):
                sendCommand()
            # receives a message from the client
            msg = cs.recv(1024).decode()
            
            # checks to makes sure the client is not empty 
            if(msg):
                print(msg)
                raise Exception('We found the hash!')
                client_sockets.remove(cs) 	          
          
        except Exception as e:
            # client no longer connected
            # remove it from the list
            print(f"[!] Ending the process: {e}")
            client_sockets.remove(cs)
            break
           
while True:
    #Attends to new connections
    client_socket, client_address = s.accept()
    print(f"[+] {client_address} connected.")
    # Add new connections to a list
    client_sockets.append(client_socket)
    t = Thread(target=listen_for_client, args=(client_socket,))
    t.daemon = True
    t.start()

# close client sockets
for cs in client_sockets:
    cs.close()
# close server socket
s.close()

Implementing the Client Bot

Once the server is set up, we can create the client bot that will perform the brute force password cracking. The client bot will connect to the server, receive the task from the server, perform the cracking, and send the result back to the server.

# imports the libraries needed
import socket, hashlib, string
from itertools import product

# defines the hostname and port to connect to the server
SERVER_HOST = "192.168.50.5"
SERVER_PORT = 32401 

# creates a new socket, AF_INET for IPV4 and SOCK_STREAM for TCP
client = socket.socket()

# connects to the server
client.connect((SERVER_HOST, SERVER_PORT))

while True:
    # receives the character set to use for the brute force from the server
    chars = client.recv(1024).decode()
    
    # receives the MD5 hash to crack from the server
    md5hash = client.recv(1024).decode()
    
    # creates a product of all the characters of the specified length
    for length in range(1, 5):
        for attempt in product(chars, repeat=length):
            # converts the attempt to a string
            attempt = ''.join(attempt)
            
            # calculates the MD5 hash of the attempt
            hashed_attempt = hashlib.md5(attempt.encode()).hexdigest()
            
            # checks if the hashed attempt matches the provided MD5 hash
            if hashed_attempt == md5hash:
                # sends the result to the server
                client.send(f"[*] Password found: {attempt}".encode())
                break
    
    # closes the connection
    client.close()

Running the Project

To run the project, we need to start the server and the client bots. First, we need to start the server by running the server.py file:‌

python server.py

Once the server is running, we can start the client bots by running the client.py file on multiple machines:‌

python client.py

After the connection is established, the server sends a shell command to the client to start the password cracking process. The client receives the command, executes the brute force function, and sends the result back to the server.

Once the result is sent, the client connection is closed. The server receives the result and terminates the connection with the client.

Server:

[*] Listening as 192.168.50.5:32401
[+] ('192.168.50.6', 54321) connected.
[+] ('192.168.50.7', 54322) connected.
Enter an MD5 to crack$ d077f244def8a70e5ea758bd8352fcd8
Please wait while we crack the password

The password is: 1234

[!] Ending the process: We found the hash!
[!] Ending the process: We found the hash!

Bot 1:

List Received: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$% 

The password is: 1234
Total runtime of the program is 5.000279903411865

Bot 2:

List Received: %$#@!9876543210ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba

The password is: 1234
Total runtime of the program is 1.2307019233703613

Conclusion

In this project, we explored one way of cracking passwords using a distributed approach with Python. We created a server that sends brute force password cracking tasks to multiple client bots that will perform the cracking and return the result to the server. This approach can significantly reduce the time required to crack a password and highlights the importance of using strong passwords to protect sensitive information.


]]>