Tutorial 3 - Solution
Tutorial 3 - Solution
Computer Security
Tianwei Zhang
Q1. Circle the correct answers in the
following questions
1. Which of the following security features require hardware support?
(i) Linux ExecShield, as it requires the hardware to control if each memory page is
executable
(ii) ARM MTE, as it requires hardware tags to be attached to the memory regions.
(iii) ASLR, as it requires the hardware to determine if the address space of each
program is randomized
2
Q1. Circle the correct answers in the
following questions
2. Which statement is false about code reuse attack?
3
Q1. Circle the correct answers in the
following questions
3. Which one of the following C functions has the lowest risk in terms of software
vulnerabilities?
A. gets
B. strcpy
C. strncat
D. sprintf
4
Q2. Answer the following questions
1. Why are non-executable stack and heap not enough to defeat buffer
overflow attacks?
The return address can be overwritten to return to any code already loaded. For
instance, the attacker may be able to cause a return into the libc execve() function
with “/bin/sh” as an argument.
5
Q2. Answer the following questions
2. Distinguish three types of fuzzing techniques?
6
Q2. Answer the following questions
3. What is a code reuse attack?
Instead of injecting the malicious code into the memory, the attacker can
compromise the control flow to jump to the existing library for attacks.
7
Q3. Program Analysis
For string copy operation, strncpy is regarded as “safer” than strcpy. However,
improper use of strncpy can also incur vulnerabilities. Please describe the problem in
the following program, and what consequences it will cause.
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "geeksforgeeks";
char dest[8];
strncpy(dest, src, 8);
int len = strlen(dest);
return 0;
}
8
Solution
strncpy does not automatically add the NULL value to dest if n is less than the length
of string src. So it is safer to always add NULL after strncpy.
In this program, dest does not have a terminator at the end. Then the function
strlen will keep counting, which can cause segmentation fault.
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "geeksforgeeks";
char dest[8];
strncpy(dest, src, 8);
int len = strlen(dest);
return 0;
}
9
Q4
StackGuard is a mechanism for defending C programs against stack-based buffer
overflows. It detects memory corruption using a canary, a known value stored in each
function’s stack frame immediately before the return address.
This guarantees the attacker cannot guess canary correctly every time, and cannot corrupt
the stack without changing the canary values.
10
Q4
StackGuard is a mechanism for defending C programs against stack-based buffer
overflows. It detects memory corruption using a canary, a known value stored in each
function’s stack frame immediately before the return address.
b) What is a security drawback to choosing the canary value at compile time instead of
at run time?
After compiling, the canary value will be fixed. The attacker may use brute-force or reverse-
engineering technique to guess the correct value, and then perform the buffer overflow
attack with that value.
11
Q4
StackGuard is a mechanism for defending C programs against stack-based buffer
overflows. It detects memory corruption using a canary, a known value stored in each
function’s stack frame immediately before the return address.
Using terminator canary: {\0, newline, linefeed, EOF}.The attacker cannot copy strings beyond
the terminator.
12
Q4
StackGuard is a mechanism for defending C programs against stack-based buffer
overflows. It detects memory corruption using a canary, a known value stored in each
function’s stack frame immediately before the return address.
The attacker can overwrite the function pointer instead of the return address
13
Q5
One possible solution to defeat buffer overflow attacks is to set the stack memory as
Non-executable (NX). This is usually achieved by the OS and the paging hardware.
However, imagine that a machine does not support the non-executable feature, then we
can implement this functionality at the software level. The compiler can allocate each
stack frame in a separate page, and associate a software-manipulated NX bit at the
bottom of this page, controlling if this page (stack frame) is non-executable. The structure
of a stack frame is shown in the Figure below.
Parameters
Since the NX bit is at the bottom of the memory Return address
page, the buffers inside this stack frame is not Calling stack pointer
able to overwrite this bit to make it executable. buf[3]
buf[2]
Describe a buffer overflow attack that can still buf[1]
overwrite NX bits. buf[0]
……
NX bit
14
Solution: Overflow from callee frame
Although the buffers inside the frame cannot overwrite the Parameters
NX bit. But it can call another function, whose buffer can be Return address
used by the attacker to overwrite the NX bit. Then the Calling stack pointer
caller’s frame will become executable. buf[3]
foo buf[2]
buf[1]
foo( ) { buf[0]
bar( ); ……
}
bar( ) { NX bit
char buf[4]; Parameters
}
Return address
Calling stack pointer
bar buf[3]
buf[2]
buf[1]
buf[0]
……
NX bit
15