BUFFER OVERFLOW AND THEIR COUNTERMESUREMENT Review from library function and memmory stack
15/06/2020 Views : 246
KADEK SUAR WIBAWA
Description
Attacks on computer security systems often occur on
local computers and computers connected to network systems and are not realized
by the owners and / or computer users. Buffer overflow is often used as a
target for attacks by exploiting security bugs in application programs that are
run [1]. Buffer overflow itself has occurred since the early appearance of the
Von-Neuman architecture [2] and became very popular among computer users in
1998 as a result of MORRIS worm attacks. Since the beginning of its emergence
until now the vulnerability to buffer overflow attacks is still widely found.
The attack on the security system using buffer
overflow technique aims to get access rights to the system by changing the
control flow of a program so that the program will execute code that has been
made very carefully by the attacker [3]. This code can be inserted by the
attacker in the memory address slot of the program and the code is inserted as
if it were a valid code from program input. After the attacker successfully
inserts the code, the attacker will damage the pointer code in the memory
address slot by using the excess data input into the program and create a gap
to inject the code to carry out the attack. When this condition is fulfilled,
an attack on buffer overflow will result in a very serious security system
breach. The consequences arising from this attack vary from the simplest such
as modifying the value of variabe, performing unauthorized memory access
(segmentation fault) and even mastering root privileges.
This buffer overflow attack results from a lack of
checks on the bounds of a variable in the function contained in library C. For
example: using the strcpy () function in the program without ensuring that the
destination variable has at least the number of buffers that match data length
inputted. If seen from the effects caused by buffer overflow attacks and basic
techniques to do a very simple attack then this paper will try to explore an
understanding of attack techniques and how to overcome them that are focused on
the use of functions from library C.
Overview
Basic Concept of Buffer Overflow
Buffer or literally means buffer is a process of
temporarily storing data in memory for subsequent data usage [4]. Buffer
overflow itself can be interpreted as a condition of the occurrence of excess
data filling from the data storage capacity (data buffer) provided [5]. Because
the buffer can only hold data with a certain capacity, when the data entered
into the buffer exceeds the specified data capacity, the excess data can
overwrite or fill the buffer that is nearby so that it can damage or change the
value contained in the previous buffer. To show the basic concept of overflow
can be illustrated as follows:
A variable named arrayInput input of an array type
having an size of 8 bytes (totaling 8) is prepared to store data strings that
have a char data type (8 bits). As seen in the gray block table 1 below. While
the light blue blocks are previous data that has been stored in a particular
memory address.
When the user collects data in the prepared buffer
array with a data string in the form of the word "HALLO WORD"
(consisting of 10 bytes char 8 bits + 1 null null;). Then the data stored now
will look like table 2
red block is the excess of data entered by the user
overwriting the old data stored in the memory address next to the buffer array
memory address provided. This condition is called buffer overflow.
This buffer overflow problem often occurs in
programs created using asembler or high-level languages such as C, which put more emphasis on machine
language. Basic knowledge about C language programming or other high level
languages is very important to be discussed. This
basic knowledge will be very useful in designing and implementing programs to
avoid bugs in the program that can open security holes. High-level languages such as C are not like other programming languages,
which do not automatically check the length and size of arrays and pointers in
the program. In addition, the FreeBSD manual explains that the C library
standard is filled with a number of very dangerous functions such as [2]:
strcpy(char
*dest, const char *src) |
Possible overflow occurs in the Buffer dest |
strcat(char
*dest, const char *src) |
Possible overflow occurs in the Buffer dest |
getwd(char
*buf) |
Possible overflow occurs in the Buffer dest |
gets(char
*s) |
Possible overflow occurs in the Buffer s |
[vf]scanf(const
char *format, ...) |
Possible overflow occurs in the argument |
realpath(char
*path, char resolved_path[]) |
Possible overflow occurs in the buffer path |
[v]sprintf(char
*str, const char *format, ...) |
Possible overflow occurs in the buffer str |
The following is an example of a
program piece created using C language that takes input from the first line
through the variable "argv" and writes to "inputted data"
by using the "strcpy" (string copy) function without checking limits.
If the user inputs data more than 8, the excess data input can overwrite or
change the memory value that is next to it, as illustrated above.
/* Example buffer overflow code */
#include
#include
int main(int argc, char *argv[]){
char dataYangDiinputkan[8];
strcpy(dataYangDiinputkan, argv[1]);
return o;
}
Memory Organization
Buffer overflow attacks usually refer
to memory allocation usage such as arrays, pointers and strings [6]. Memory
allocation is important to know because when a program is compiled into a
binary number and then executed, each section such as program code, constants,
data and different types of data variables will be placed in different
segmentation within the memory. The division of memory allocation segmentation
can be seen as shown
Examples of programs and memory
allocation placements used.
int abc =
1; ----> Initialized Read-Write
Data
char
*str; ----> BSS
const int i = 10; ---->
Initialized Read-Only Data
main(){
int ii,a=1,b=2,c; ----> Local Variables on Stack
char *ptr;
ptr = malloc(4); ----> Allocated Memory in
Heap
c=
a+b; ----> Text
}
Code
Code segmentation or also known as text
segmentation is one part of the program in the object file or in memory that
contains instructions or commands on the program to be executed. In memory,
code segmentation must be placed at the bottom of the heap or stack segment.
This is intended to avoid the heap and stack overflow from program overwriting.
Besides that, Code segmentation also has read only properties to avoid the
occurrence of syntax to modify the program. Because of the above
characteristics, the possibility of an attack on this segmentation is very
small.
BSS
Uninitialized data segment or often
called the bss segment (Block Started by Symbol) is part of a data segment that
contains variables and compilers that constantly and periodically need a value
when the program is run. When the BSS section is initialized for the first time
loading, all variables in it will be given a value of 0
Data
Initialized data segment or better
known as data segment is part of the virtual address space of the program. The
data segment contains global variables and static variables declared by the
programmer. The thing to note is that the Initialized data segment is not read
only because the value of the variable can change when the program is in a run
time condition. For area division, this segmentation is further divided into
initialized read-only and initialized read-write.
Stack
Declaration of variables in a program
can be divided into global variables and local variables. Local variables are
usually declared within a function, this means that local variables can only be
accessed by program instructions within the function itself. This local
variable is placed on a temporary stack segmentation. Stack segmentation is
also known as last-in-first-out (LIFO). This term describes one of the basic
properties of the stack: the element that first enters the stack will be stored
at the bottom of the segment so that it will be accessed at the end because
access will be done at the top of the segment first. In the process of storing
and accessing elements in the stack, two terms are known: Push and Pop.
1. Push: is the process of saving or
adding elements to the stack. An error will occur in this process when the
stack cannot store more data elements or better known as stack overflow.
2. Pop: is the process of retrieving
data from the stack or can also be seen as a process of removing elements from
the stack. An error will occur in this process if the stack is empty so it is
unable to issue any data or commonly known as stack underflow.
Heap
A heap is an area of memory that is allocated dynamically during the
binary execution process (using a function called malloc (); memory alocation).
The heap will occupy part or all of the remaining memory space that has not
been used. The heap has a structure similar to a stack that starts from the
lowest remaining bytes (the lowest memory on the heap) and will expand to the
memory address above depending on the use of memory address allocation added
inside. Because the use of heap memory allocation is dynamic, it can be a full
heap memory allocation. To avoid this, it is necessary to monitor the remaining
memory allocation on the heap first before this memory is used. Checks can be
performed with the MaxAvail function, this function gives the heap the largest
block size. This check aims to avoid run time errors when the heap memory
allocation is used up while the program is running.
Programs, Libraries and Binary
Whether we realize it or not, the
programs we use everyday are formed from constants, variables and instructions
related to the data to be processed. Instructions are usually grouped into
small units called modules, subroutines, methods, and in C language are usually
known as functions that each have certain tasks (functions). For now with the
open source and open code functions for common tasks needed do not need to be
programmed in detail because most of the functions are available in the
library.
A special program called a compiler is
used to translate high-level language instructions such as the C programming
language into machine code that is intended to be recognized and executed by
the processor so that the desired target program can be achieved. Other
programs called linkers (sometimes embeded or directly called by the compiler)
are used to integrate all parts of the program, including all the reference
functions of the libraries. The overall results of the above activities are
usually referred to as binary. as a note besides changing to
int main(int argc, char *argv[]) {
char
passwd_ok = 0;
char
passwd[8];
strcpy(passwd, argv[1]);
Related Article