1 |
> > > sendto(6, "<2>ifdhandler: stack smashing attack in function |
2 |
> > > do_transact", 60, 0, |
3 |
> > > {sa_family=AF_UNIX, path="/dev/log"}, 110) = -1 EPROTOTYPE (Protocol |
4 |
> > > wrong type for socket) |
5 |
> > |
6 |
> > hmm, that's another bug somewhere... |
7 |
> |
8 |
> syslog-ng only listens on /dev/log for streams. that is a datagram. |
9 |
> maybe an error in my syslog-ng config? is it supposed to accept |
10 |
> datagrams, too? |
11 |
|
12 |
well, that or stack_smash_handler should use the stream protocol. |
13 |
i don't know the basis for this code, so better ask the hardened-gcc |
14 |
guys. |
15 |
|
16 |
> gcc (GCC) 3.3.4 20040623 (Gentoo Hardened Linux 3.3.4-r1, ssp-3.3.2-2, |
17 |
> pie-8.7.6) |
18 |
> |
19 |
> objdump attached. |
20 |
|
21 |
ok, this is a working gcc/ssp combo and i can confirm that from the |
22 |
disassembly as well, so there is indeed a buffer overrun somewhere. |
23 |
a few relevant bits follow (in the hope that someone might actually |
24 |
find this useful ;-), note that i removed insns that the compiler |
25 |
reordered and are not relevant to the explanation. |
26 |
|
27 |
the function prologue allocates 0x15c bytes for local variables and |
28 |
function argument passing: |
29 |
00000b50 <do_transact>: |
30 |
b50: 55 push %ebp |
31 |
b53: 57 push %edi |
32 |
b54: 56 push %esi |
33 |
b55: 53 push %ebx |
34 |
b56: 81 ec 5c 01 00 00 sub $0x15c,%esp |
35 |
|
36 |
PIC base register setup (the 0x2 has a relocation on it): |
37 |
b63: e8 fc ff ff ff call b64 <do_transact+0x14> |
38 |
b68: 81 c3 02 00 00 00 add $0x2,%ebx |
39 |
|
40 |
get the address of __guard (this isns has a relocation item on it, |
41 |
so the actual offset is not 0): |
42 |
b6e: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax |
43 |
|
44 |
here we save the __guard address in a local variable (0x2c) and |
45 |
store the __guard value itself after the last local variable (0x140): |
46 |
b82: 89 44 24 2c mov %eax,0x2c(%esp,1) |
47 |
b86: 8b 00 mov (%eax),%eax |
48 |
b90: 89 84 24 40 01 00 00 mov %eax,0x140(%esp,1) |
49 |
|
50 |
since the __guard copy is at 0x140 we expect the only local array |
51 |
variable of do_transact() to be at 0x40 (it's 256 bytes long), and |
52 |
indeed that's what we find being passed to ifd_card_command(): |
53 |
bed: b8 00 01 00 00 mov $0x100,%eax |
54 |
bf9: 89 44 24 14 mov %eax,0x14(%esp,1) |
55 |
bfd: 8d 6c 24 40 lea 0x40(%esp,1),%ebp |
56 |
c09: 89 6c 24 10 mov %ebp,0x10(%esp,1) |
57 |
c19: e8 fc ff ff ff call c1a <do_transact+0xca> |
58 |
|
59 |
and to ct_tlv_add_bytes(): |
60 |
c43: 89 6c 24 04 mov %ebp,0x4(%esp,1) |
61 |
c4a: e8 fc ff ff ff call c4b <do_transact+0xfb> |
62 |
|
63 |
then in the epilogue we have the __guard check: |
64 |
c51: 8b 4c 24 2c mov 0x2c(%esp,1),%ecx |
65 |
c57: 8b 94 24 40 01 00 00 mov 0x140(%esp,1),%edx |
66 |
c5e: 3b 11 cmp (%ecx),%edx |
67 |
c60: 74 1e je c80 <do_transact+0x130> |
68 |
|
69 |
so this confirms that the compiler properly allocated 256 bytes for |
70 |
replybuf[256] and placed the canary just afterwards, so even a single |
71 |
byte overrun would damage the canary (well, 255 out of 256 times at |
72 |
least ;-). |
73 |
|
74 |
> I didn't write those parts of openct, but if you can tell me whats |
75 |
> wrong, I'd like to improve the code. |
76 |
|
77 |
based on the above we have to determine where the overrun occurs. to |
78 |
do this, you should add a simple loop that prints out replybuf[] and |
79 |
a few more bytes following it, i.e., make the loop count up to 0x170 |
80 |
or so (this will include the __guard copy, the saved registers, etc). |
81 |
|
82 |
do this once before calling ifd_card_command(), then just after it |
83 |
returned then after ct_tlv_add_bytes() as well, this will isolate the |
84 |
failing function. assuming that it'll be ifd_card_command(), you'll |
85 |
have to track down the 'transceive' callback of your card driver and |
86 |
do the printout in there as well, until you figure out which part of |
87 |
the code fails. |
88 |
|
89 |
alternatively, you can also use gdb and set a hardware breakpoint |
90 |
(hbreak) on the __guard copy (%esp+0x140 when you're after the prologue |
91 |
of do_transact()) to catch the exact moment of overwriting. |
92 |
|
93 |
|
94 |
-- |
95 |
gentoo-hardened@g.o mailing list |