• Aucun résultat trouvé

Sécurité des logiciels

N/A
N/A
Protected

Academic year: 2022

Partager "Sécurité des logiciels"

Copied!
38
0
0

Texte intégral

(1)

Sécurité des logiciels

NX? Not on the stack? Still pwnd!

Samuel Thibault <samuel.thibault@u-bordeaux.fr>

CC-BY-NC-SA

(2)

Stack overflow exploit needs...

Stack overflow exploit needs

Executable stack

Buffer on the stack

Known position

0x0fac 0x0fac 0x1000

0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

0x0fac

...

0x0fac 0x0fac 0x0fac 0x0fac shell code

0x0fac

0x0fac ... ...

0x0fac 0x0fac

(3)

Stack overflow exploit needs...

Stack overflow exploit needs

Executable stack

Buffer on the stack

Known position

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac

0x0fac 0x0fac 0x0fac

0x0fac 0x0fac 0x0fac 0x0fac shell code

0x0fac 0x0fac 0x0fac

(4)

Not executable? Still pwnd!

How to execute stuff

without being executable?

Remember what our shell code was:

Basically

execve(“/bin/sh”, {“/bin/sh”, NULL}, {NULL});

Do we really need to write code for this?

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac ... ...

0x0fac 0x0fac 0x0fac

0x0fac 0x0fac 0x0fac 0x0fac shell code

0x0fac 0x0fac 0x0fac

(5)

Not executable? Still pwnd!

How to execute stuff

without being executable?

Remember what our shell code was:

Basically

execve(“/bin/sh”, {“/bin/sh”, NULL}, {NULL});

Do we really need to write code for this?

What if we just ret to execve?

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac

execve

...

...

...

...

...

...

ESP

(6)

Not executable? Still pwnd!

How to execute stuff

without being executable?

Remember what our shell code was:

Basically

execve(“/bin/sh”, {“/bin/sh”, NULL}, {NULL});

Do we really need to write code for this?

What if we just ret to execve?

Result of ret to execve

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac ... ...

execve ESP

(7)

Not executable? Still pwnd!

How to execute stuff

without being executable?

Remember what our shell code was:

Basically

execve(“/bin/sh”, {“/bin/sh”, NULL}, {NULL});

Do we really need to write code for this?

What if we just ret to execve?

Result of ret to execve

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac

0x0fac

execve

0 0x0fac /bin/sh 0x0fb4 0x0fb8

ESP

(8)

Not executable? Still pwnd!

How to execute stuff

without being executable?

Overflow exactly like this!

Ret-into-libc hack

What if we want to do more than just one system call?

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac ... ...

0x0fac ...

execve

...

...

0 0x0fac /bin/sh

...

0x0fb4 0x0fb8

(9)

Not executable? Still pwnd!

How to execute stuff

without being executable?

Overflow exactly like this!

Ret-into-libc hack

What if we want to do more than just one system call?

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac

0x0fac

!!!

execve

...

...

0 0x0fac /bin/sh

...

0x0fb4 0x0fb8

(10)

Not executable? Still pwnd!

How to execute stuff

without being executable?

A second chance...

First “return to” foo

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac ... ...

...

bar foo

...

...

...

...

...

...

...

...

ESP

(11)

Not executable? Still pwnd!

How to execute stuff

without being executable?

A second chance...

First “return to” foo

Now in foo, then “return to” bar

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac

...

bar foo

...

...

...

...

...

...

...

...

ESP

(12)

Not executable? Still pwnd!

How to execute stuff

without being executable?

A second chance...

First “return to” foo

Now in foo, then “return to” bar Now in bar

Err, but then bar’s parameters need to be almost the same as foo’s...

But bar does not have to be a proper function!

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac ... ...

...

bar foo

...

...

...

...

...

...

...

...

ESP

(13)

Not executable? Still pwnd!

How to execute stuff

without being executable?

SP lifting hack

A lot of glibc functions end with cleaning the stack, e.g.:

bar:

addl $12,%esp ret

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac

bar foo ...

...

...

...

...

...

...

...

ESP

(14)

Not executable? Still pwnd!

How to execute stuff

without being executable?

SP lifting hack

A lot of glibc functions end with cleaning the stack, e.g.:

bar:

addl $12,%esp ret

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac ... ...

...

...

...

...

...

bar foo ...

...

...

ESP

(15)

Not executable? Still pwnd!

How to execute stuff

without being executable?

SP lifting hack

A lot of glibc functions end with cleaning the stack, e.g.:

bar:

addl $12,%esp ret

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac

...

...

...

bar foo ...

...

...

...

...

ESP

(16)

Not executable? Still pwnd!

How to execute stuff

without being executable?

SP lifting hack

A lot of glibc functions end with cleaning the stack, e.g.:

bar:

addl $12,%esp ret

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac ... ...

...

...

...

bar foo ...

...

...

...

...

ESP

(17)

Not executable? Still pwnd!

How to execute stuff

without being executable?

SP lifting hack, complete story:

First ret-into-libc

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac

42

sp_lift creat

...

exit

arg1 arg3 arg2

...

...

ESP

(18)

Not executable? Still pwnd!

How to execute stuff

without being executable?

SP lifting hack, complete story:

First ret-into-libc

Now in creat, ..., returns to sp_lift

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac ... ...

42

sp_lift creat

...

exit

arg1 arg3 arg2

...

...

ESP

(19)

Not executable? Still pwnd!

How to execute stuff

without being executable?

SP lifting hack, complete story:

First ret-into-libc

Now in creat, ..., returns to sp_lift Now in sp_lift, cleans stack

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac

42

sp_lift creat

...

exit

arg1 arg3 arg2

...

...

ESP

(20)

Not executable? Still pwnd!

How to execute stuff

without being executable?

SP lifting hack, complete story:

First ret-into-libc

Now in creat, ..., returns to sp_lift Now in sp_lift, cleans stack

Stack cleaned, returns to exit

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac ... ...

42

sp_lift creat

...

exit

arg1 arg3 arg2

...

...

ESP

(21)

Not executable? Still pwnd!

How to execute stuff

without being executable?

SP lifting hack, complete story:

First ret-into-libc

Now in creat, ..., returns to sp_lift Now in sp_lift, cleans stack

Stack cleaned, returns to exit Now in exit, exits nicely

pwnd!

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac

42

sp_lift creat

...

exit

arg1 arg3 arg2

...

...

ESP

(22)

Not executable? Still pwnd!

How to execute stuff

without being executable?

SP lifting hack

Call chain can be arbitrarily long

Just need to find in libc what you need

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac ... ...

42

sp_lift creat

...

exit

arg1 arg3 arg2

...

...

ESP

(23)

Not executable? Still pwnd!

What is the basic problem?

We can overflow

from a data buffer

into a control area

0x1000 0x0ffc 0x0ff8 0x0ff4 0x0ff0 0x0fec 0x0fe8 0x0fe4

...

0x0fac

0x0fac

!!!

execve

...

...

0 0x0fac /bin/sh

...

0x0fb4 0x0fb8

(24)

Stack overflow exploit needs...

Stack overflow exploit needs

Executable stack

Buffer on the stack heap

Known position

(25)

Heap overflow?

int litentier(void) { int i;

char buf[64];

printf("> ");

fflush(stdout);

gets(buf);

i=atoi(buf);

return i;

}

(26)

26

Heap overflow?

int litentier(void) { int i;

char *buf = malloc(64);

printf("> ");

fflush(stdout);

gets(buf);

i=atoi(buf);

free(buf);

return i;

}

No way to overflow into the stack Something else?

(27)

Heap overflow?

Heap structure (simplified)

When you call malloc three times

data1

data2

data3

(28)

28

Heap overflow?

Heap structure (simplified)

When you call malloc three times

There are actually some additional headers

data1

data2

data3

data4 data0

(29)

29

Heap overflow?

Heap structure (simplified)

When you call malloc three times

There are actually some additional headers Which allow to jump between allocations:

BK (back)

FD (forward)

data1

data2

data3 FD BK

BK FD FD BK

BKFD data0

(30)

30

Heap overflow?

Heap structure (simplified)

When you call malloc three times

There are actually some additional headers Which allow to jump between allocations:

BK (back)

FD (forward) Now free(data2)

Have to update BK/FD

data1

data3 BK FD FD BK

BKFD

data4 data0

(31)

31

Heap overflow?

Heap structure (simplified)

When you call malloc three times

There are actually some additional headers Which allow to jump between allocations:

BK (back)

FD (forward) Now free(data2)

Have to update BK/FD

data1

data3 BK FD FD BK

BKFD data0

(32)

32

Heap overflow?

Heap structure (simplified)

When you call malloc three times

There are actually some additional headers Which allow to jump between allocations:

BK (back)

FD (forward) Now free(data2)

Have to update BK/FD

BK = data2->BK;

FD = data2->FD;

BK->FD = FD;

FD->BK = BK;

data1

data2

data3 FD BK

BK FD FD BK

BKFD

data4 data0

(33)

33

Heap overflow?

So basically free(data2) does

BK = data2->BK;

FD = data2->FD;

BK->FD = FD;

FD->BK = BK;

data1

data2

data3 FD BK

BK FD FD BK

BKFD data0

(34)

34

Heap overflow?

So basically free(data2) does

BK = data2->BK;

FD = data2->FD;

BK->FD = FD;

FD->BK = BK;

Now, what if I overflow data1?

I can choose data2’s BK at will

I can choose data2’s FD at will

...

...

...

data2

data3 FD BK

BK FD FD BK

BKFD

data4 data0

(35)

35

Heap overflow?

So basically free(data2) does

BK = data2->BK;

FD = data2->FD;

BK->FD = FD;

FD->BK = BK;

Now, what if I overflow data1?

I can choose data2’s BK at will

I can choose data2’s FD at will

...

...

...

data2

data3 FD BK

BK FD FD BK

BKFD data0

(36)

Heap overflow?

So basically free(data2) does

BK = data2->BK;

FD = data2->FD;

BK->FD = FD;

FD->BK = BK;

Now, what if I overflow data1?

I can choose data2’s BK at will

I can choose data2’s FD at will

In the end, I can divert the control in the stack

(37)

Countermeasures

Libc checks for coherency of headers

More expensive free

Static code analysis / compiler-provided information

Check for array bounds

(38)

Stack overflow exploit needs...

Stack overflow exploit needs

Executable stack

Buffer on the stack

Known position

Next week!

Références

Documents relatifs

– Step 2: The server receive the message and reply by sending back the minimal string and part of the process memory;. – Step 3: The client get the string back

Programs have their own uid, inherited from uid of parent, except when the program is

● Disassemble functions objdump -d test. ● Disassemble everything objdump

Pieces from Emmanuel Fleury

● Local variable (aka automatic variable): a variable whose scope is not getting outside of the function. ● Parameters (aka arguments): Data set by the caller for the

But shell code can lookup the random value ... The game never

● behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements.

● Putting a stack guard to prevent clash.