Software attacks Lorenzo Dematte’ ([email protected]) Software Attacks Buffer Overflow.

41
Software attacks Lorenzo Dematte’ ([email protected]) Software Attacks Buffer Overflow

Transcript of Software attacks Lorenzo Dematte’ ([email protected]) Software Attacks Buffer Overflow.

Software attacks

Lorenzo Dematte’ ([email protected])

Software Attacks

Buffer Overflow

Software attacks

Lorenzo Dematte’ ([email protected])

Outline of the seminaries• 8 hours, 4 lessons• Buffer overflow, introduction:

– Stack smashing, concepts, practical example (Blaster) – Mitigations

• Buffer overflow: new techniques – Heap smashing, concepts, the heap in Win32 – Countermeasures: WinXP SP2

• Integer overflow and DLL injection – A Win32 process memory layout– An example: IAT patching, memory walking

• Countermeasures: managed languages (Java, .NET) – An example: .NET Code Access Security

+ 2-3 hours seminars by YOU =)

Software attacks

Lorenzo Dematte’ ([email protected])

Software attacks• A VULNERABILITY is a security flaw caused by a

software defect.

• An EXPLOIT is a technique that take advantage of a vulnerability. A malicious hacker uses them to ATTACK a system.

• For each vulnerability, many EXPLOIT may exist

Buffer overflow is the most frequent vulnerability (ca 50% of security problems)

See for example, MS bulletins, CERT, BugTraq.

Software attacks

Lorenzo Dematte’ ([email protected])

Software attacks

Microsoft Security Bulletin MS03-26 (buffer overflow vulnerability exploited by

Blaster)

Last Stage of Delirium Unknown Original reportNever published

Xfocus Stack smashing Apparently same as Blaster

www.xfocus.org/

D. Litchfield Pointer subterfuge

Cigital Pointer subterfuge

K-oitic Arc injection

Pincus, Baker Arc injection +Pointer subterfuge

Author Technique Notes

Software attacks

Lorenzo Dematte’ ([email protected])

Buffer overflow: some basic

• A buffer is a contiguous block of memory, that holds multiple instances of the same data type

• To a C programmer, a buffer is usuallychar buffer[200];

• [Or char* buffer = (char*)malloc(200);]

– In the latter case, we have a dynamically allocated buffer -> we’ll consider this case later

– In fact, it is possible to overflow (and exploit) various types of buffers.

• The first one we’ll see, is the stack buffer overflow

Software attacks

Lorenzo Dematte’ ([email protected])

Buffer overflow: some basic (2)

Buffers are commonly used, especially in network programming.

char recvbuf[32];bytesRecv = recv(ConnectSocket, recvbuf, 32, 0);

What if str is more than 20 characters?

void printFunc(char* str) {char buffer[20];strcpy(buffer, str);...

}

A buffer overflow is a condition created by a defect in a program.

Software attacks

Lorenzo Dematte’ ([email protected])

What is a Buffer Overflow? In most cases, if it’s a programming error, a buffer overflow

results in a Segmentation Fault / Memory Access error

void func() { char buffer[20]; char* current = buffer;

for (int i = 0; i < 256; ++i) { *current = 'A'; ++current; }}

What about this address? We’ll see in a moment…

Software attacks

Lorenzo Dematte’ ([email protected])

How can this lead to a software attack?

You can use it to inject code/data in a program and thenChange the program control flow.

(If used bad) you can crash a system process (DoS)

(If used well) Can lead to privilege escalation / Malicious Code execution.

Software attacks

Lorenzo Dematte’ ([email protected])

How can this lead to a software attack?(2)

In the stack smashing exploit, a buffer allocated on the stack is overflowed to overwrite a particular area of the stack.

This approach is very architecture dependent: So, let’s see how is the stack configuration of a process (x86, but is valid for every architecture)

Software attacks

Lorenzo Dematte’ ([email protected])

Memory layout• The attack is architecture dependent• We take as an example Win32 on an x86 CPU• Each process has its own Virtual Address Space,

which is divided into several areas: text, bss, stack, heap, etc…

Exe image

stack

heap

0x00000000

0x00400000

0x00130000

0x00140000 • We’ll see the heap in more detail in another lesson

0x7FFFFFFF

0x00030000

Software attacks

Lorenzo Dematte’ ([email protected])

The Stack

• Why the stack? Function calls!• Pop, push, EBP, ESP• Stack grow from 0x00130000 to

0x0003000 (from high to low) <- this is due to x86 stack instructions

Page guard

2 pages committed

0x00130000

0x00030000

Software attacks

Lorenzo Dematte’ ([email protected])

Stack configuration (1)

Let’s see what asm code the following (simple) program generates:

void f(int a, int b)

{

char buffer[20];

int i;

int j;

j = a;

i = a + b;

}

int main()

{

f(2, 3);

return 0;

}

Do it by yourself! /Fas (VC) –save_temps (gcc)

push  ebp   mov   ebp, esp   sub   esp, 0

; 13   :    f(2, 3);

   push  3   push  2   call  _f

; 14   :    return 0;

   xor   eax, eax

   mov   esp, ebp   pop   ebp   ret   0

   push  ebp   mov   ebp, esp   sub   esp, 28                 ; 4    :    char buffer[20];; 5    :    int i;; 6    :    int j;   ; 7    :    j = a;; 8    :    i = a + b;

   mov   eax, DWORD PTR [ebp + 8h] ; a   mov   DWORD PTR [ebp - 8], eax ; j EBP - 8   add   eax, DWORD PTR [ebp + 0Ch] ; b   mov   DWORD PTR [ebp - 4], eax ; i EBP - 4

   mov   esp, ebp   pop   ebp   ret   0

Software attacks

Lorenzo Dematte’ ([email protected])

Stack configuration (2)

004119A20x0012FE84

0x0012FE88

0x0012FE8C

00000003

00000002

ESP Return address

a

b

And now let’s see how a function call is made

Software attacks

Lorenzo Dematte’ ([email protected])

Stack configuration (2)

004119A20x0012FE84

0x0012FE88

0x0012FE8C

00000003

00000002

ESPReturn address

a

b

0012FE900x0012FE80 EBP saved

PUSH EBP

Software attacks

Lorenzo Dematte’ ([email protected])

Stack configuration (2)

004119A20x0012FE84

0x0012FE88

0x0012FE8C

00000003

00000002

ESPReturn address

a

b

0012FE900x0012FE80 EBP saved

MOV EBP, ESP

EBP

Software attacks

Lorenzo Dematte’ ([email protected])

Stack configuration (2)

004119A20x0012FE84

0x0012FE88

0x0012FE8C

00000003

00000002

ESP

Return address

a

b

0012FE900x0012FE80 EBP saved

SUB ESP, 28

EBP

unitiliazed

unitiliazed

Unitiliazed

j

i

buffer

NB! EBP let us know where local variables and parameter are located!

EBP – offset -> localsEBP + 8 + offset -> params

Software attacks

Lorenzo Dematte’ ([email protected])

Stack configuration (3)

   push  ebp   mov   ebp, esp   sub   esp, 28                 ; 4    :    char buffer[20];; 5    :    int i;; 6    :    int j;   ; 7    :    j = a;; 8    :    i = a + b;

   mov   eax, DWORD PTR [ebp + 8h] ; a   mov   DWORD PTR [ebp - 8], eax ; j    add   eax, DWORD PTR [ebp + 0Ch] ; b   mov   DWORD PTR [ebp - 4], eax ; i

   mov   esp, ebp   pop   ebp   ret   0

Do you remember? Let’s see a slightly more complex example

void f(int a, int b, char* str)

{

char buffer[12];

int i;

int j;

j = a;

i = a + b; strcpy(buffer, str);

}

Where str = “averyverylongstring”

Software attacks

Lorenzo Dematte’ ([email protected])

Stack smashing

004119A20x0012FE84

0x0012FE88

0x0012FE8C

00000003

00000002

ESP

Return address

a

b

0012FE900x0012FE80 EBP saved

EBP

j

i

buffer

Before strcpy…

Return address

a

b

EBP saved

j

i

buffer

004119A20x0012FE84

0x0012FE88

0x0012FE8C

00000003

00000002

ESP

0012FE900x0012FE80

EBP

ing\0

gstr

averyverylon

…and after!

unitiliazed

unitiliazed

Unitiliazed

Software attacks

Lorenzo Dematte’ ([email protected])

Overwriting return address

• If we go further, we have the saved frame pointer, plus the return address

• Go overwrite it, placing an address of our choice!

• The buffer could be filled with code of our own choice!

Software attacks

Lorenzo Dematte’ ([email protected])

Overwriting return address//00401090static char message[] = "AAAAAAAAAAAAAAAAAAAAAAAA\x90\x10\x40\x00";

void handleRequest() { char buffer[20]; strcpy(buffer, message); printf("Request: %s\n", buffer);}

void doNastyThings() { printf("He he!!\n");}

int main() { while(1) {

handleRequest(); } return 0;}

DD DD DD DD

DD DD DD DD

DD DD DD DD

DD DD DD DD

Old sfp

20 10 40 00

Fill bufferAA AA AA AA

AA AA AA AA

AA AA AA AA

AA AA AA AA

Old sfp

20 10 40 00

owr sfpAA AA AA AA

AA AA AA AA

AA AA AA AA

AA AA AA AA

AA AA AA AA

20 10 40 00

owr retAA AA AA AA

AA AA AA AA

AA AA AA AA

AA AA AA AA

AA AA AA AA

90 10 40 00

Software attacks

Lorenzo Dematte’ ([email protected])

Shellcode writing

• We have only injected an arc, modifying the control flow of a program, but we can inject code as well

• This requires us to write some shellcode

• A shellcode is a small portion of machine code we write by hand, and then insert in the buffer

Software attacks

Lorenzo Dematte’ ([email protected])

Shellcode injection

• The shellcode has to be small, and it must not contain terminators for the function overflowing the buffer (ex: \n, \x00, \r,…)

• We “send” it in the buffer before the return address, and then point the return address back in the buffer

SSSSSSSSSSSSSSSSSSSPPPPP20FF1200

0x0012FF20

S = shellcode; P = padding

Software attacks

Lorenzo Dematte’ ([email protected])

NOPProblem: At what address our code will be? What do we (over)write as ret?

Answer: (1)Estimate (stack start always at the

same address (0x00130000 on Win32))(2)Use nop(s) to have a margin

(otherwise) Trampolining (more on this later)

int f() { }

int g() { f(); }

int main() {

f(); g();}

main stack frame

f stack frame

main stack frame

g stack frame

f stack frame

0x00130000

?

Software attacks

Lorenzo Dematte’ ([email protected])

NOP (2)

NNNNNSSSSSSSSSSSSSSSSSSS40FF1200

0x0012FF20

S = shellcode; N = NOP

Our estimate is not precise, but it works nonetheless

[How to write a shellcode?]

Software attacks

Lorenzo Dematte’ ([email protected])

Exploits possible

• Overwrite ret with an address pointing back to the buffer, use NOPs to increment probabilities (stack protection)

• Overwrite ret with an absolute address, taken by a Win32 dll (ex: WinExec in kernel32.dll) (but the params? – hardcoded addresses change)

• Find a trampoline (jmp reg, call reg) at an absolute address (same as before)

Software attacks

Lorenzo Dematte’ ([email protected])

A simple example

(Demo?)

Software attacks

Lorenzo Dematte’ ([email protected])

A real world example: Blaster

Software attacks

Lorenzo Dematte’ ([email protected])

(Brief COM introduction)

• What is COM? Component Object Model: object are in DLLs and can be used locally or invoked remotely (ex: DirectX, Active Directory, ADO, etc.)

• Component implement some interfaces• The COM runtime provides function to load/locate/create

components• These functions MUST work for both locally avalable AND

server-side components

Software attacks

Lorenzo Dematte’ ([email protected])

The COM modelCoCreateInstance

IClassFactory

IUnknown

IClassFactory::CreateInstancereturn IUnknown* to client

CoGetInstanceFromFileIPersistFile

IUnknown

IPersistFile::Loadreturn IUnknown* to client

Software attacks

Lorenzo Dematte’ ([email protected])

The RPC-DCOM interface vulnerability (1)

HRESULT CoGetInstanceFromFile( COSERVERINFO * pServerInfo, CLSID * pclsid, IUnknown * punkOuter, DWORD dwClsCtx, DWORD grfMode, OLECHAR * szName, ULONG cmq, MULTI_QI * rgmqResults );

Includes name of server

Name of file containing persistant object

Message is packed for RPC request, and the string passed to server is assembled in this way “\\servername\filename”

Software attacks

Lorenzo Dematte’ ([email protected])

The RPC-DCOM interface vulnerability (2)

GetPathForServer

GetMachineName

At server side

String is assembled by system, BUT we can assemble a malicious request building an ad-hoc packet!

Here buffer is 32 only!(max length of a NETBIOS name)

Here the only check done is‘\’ (cmp ax, 5Ch)!

Software attacks

Lorenzo Dematte’ ([email protected])

The RPC-DCOM interface vulnerability (3)

GetPathForServer;.text:761543DA                 push    ebp.text:761543DB                 mov     ebp, esp.text:761543DD                 sub     esp, 20h  <-----the length is only 0x20.text:761543E0                 mov     eax, [ebp+arg_4].text:761543E3                 push    ebx.text:761543E4                 push    esi.text:761543E5                 mov     esi, [ebp+hMem].text:761543E8                 push    edi.text:761543E9                 push    5Ch.text:761543EB                 pop     ebx.text:761543EC                 mov     [eax], esi.text:761543EE                 cmp     [esi], bx.text:761543F1                 mov     edi, esi.text:761543F3                 jnz     loc_761544BF.text:761543F9                 cmp     [esi+2], bx.text:761543FD                 jnz     loc_761544BF.text:76154403                 lea     eax, [ebp+String1] <----addr to place servername, only 0X20.text:76154406                 push    0.text:76154408                 push    eax.text:76154409                 push    esi        <------------here is the parameter of filename .text:7615440A                 call    GetMachineName

GetMachineName:.text:7614DB6F                 mov     eax, [ebp+arg_0].text:7614DB72                 mov     ecx, [ebp+arg_4].text:7614DB75                 lea     edx, [eax+4].text:7614DB78                 mov     ax, [eax+4].text:7614DB7C                 cmp     ax, 5Ch     <-----------check if it is 0X5C,if yes,the servername is over

Software attacks

Lorenzo Dematte’ ([email protected])

The exploit

One of the published exploits is by Xfocus.org (many others, remember?)

It uses a trampoline (jmp esp)On XP SP1, there is one at 0x77d737db

More details, plus the documentation and thecomplete exploit, on their website

Software attacks

Lorenzo Dematte’ ([email protected])

Workarounds

• So, how can we avoid such situations?• Some over-simplistic recommendations:

– Move-to-heap -> heap smashing!– Use “safe” functions: avoid using C library

functions (like strcpy) -> is not a panacea!

Remember Blasterstrncpy vulnerabilitiesvoid ConcatString(char *buf1, char *buf2, size_t len1, size_t len2) { char buf[256]; if((len1 + len2) > 256) return -1; memcpy(buf, buf1, len1); memcpy(buf + len1, buf2, len2); }

Software attacks

Lorenzo Dematte’ ([email protected])

Mitigations

• What is a mitigation? Instead of letting malicious hackers obtain control over a machine, kill process

• If the program/OS is aware that there is a buffer overflow, terminate program

• It can have a DoS effect, but arbitrary code excecution is MUCH worse!

Software attacks

Lorenzo Dematte’ ([email protected])

StackGuard

• The first to introduce canaries

004119A20x0012FE84

0x0012FE88

0x0012FE8C

00000003

00000002

Return address

a

b

0012FE900x0012FE80 EBP saved

unitiliazed

unitiliazed

j

i

StackCanary

Stack grows memory grows

locals

params

Canaries is checked before the asm ret instruction

The StackGuard idea: terminator canary Is a word “\x00\n\r\xFF”

Software attacks

Lorenzo Dematte’ ([email protected])VC 7.X stack canary

(Windows XP SP2 & Windows 2003 Server)

• Recently introduced in Visual C++• Canary is a random word, so it works

better then StackGuard• However, stack protection has still

several vulnerabilities– Double Cookie Overwrite– Security Handler Overwrite– Replacing the Windows System Directory– Ldr* function pointer overwrites

• See http://www.nextgenss.com/papers/defeating-w2k3-stack-protection.pdf

Software attacks

Lorenzo Dematte’ ([email protected])

They can be defeated

• Heap overflow• Trampolines over canary• (StackGuard) terminators (Blaster)• Arc injection, function pointer

overwrites, new buffer overflow techniques (next lessons)

Software attacks

Lorenzo Dematte’ ([email protected])

NX bit

• http://en.wikipedia.org/wiki/NX• NX bit may prevent the stack and

heap memory areas from being executable, and may prevent executable memory from being writable

• Not available on x86-32 (but available on x86-64)

Software attacks

Lorenzo Dematte’ ([email protected])

Conclusions

• The network is populated with untrustworthy people– All input should not be trusted until proven

otherwise• Do not trust input that comes from non-

validated sources– If user/caller does not authenticate, do not

extend trust• Use a "white list" instead of a "black list"

– Determine what is legal and reject the rest– Test carefully with illegal values (fault

injection)• Limit maximum characters length

((some advices by G. McGrawsome advices by G. McGraw))

Software attacks

Lorenzo Dematte’ ([email protected])

[Overwriting function pointers]

Attack known as pointer subterfuge

void func(void* arg, size_t len){ char buffer[100]; void (*f)() = ...;

memcpy(buff, arg, len); //buffer overflow f(); ...}

It may seems not so common.. But it has no mitigations and in other forms is very widely used…

…but we’ll see it in another lesson!