4.3 Vulnerability Remediation

Note

Tuesday, January 27, 2009

After I told the FFmpeg maintainers about the bug, they developed the following patch:[42]

--- a/libavformat/4xm.c
+++ b/libavformat/4xm.c
@@ −166,12 +166,13 @@ static int fourxm_read_header(AVFormatContext *s,
                 goto fail;
             }
             current_track = AV_RL32(&header[i + 8]);
+            if((unsigned)current_track >= UINT_MAX / sizeof(AudioTrack) - 1){
+                av_log(s, AV_LOG_ERROR, "current_track too large
");
+                ret= −1;
+                goto fail;
+            }
             if (current_track + 1 > fourxm->track_count) {
                 fourxm->track_count = current_track + 1;
-                if((unsigned)fourxm->track_count >= UINT_MAX / sizeof(AudioTrack)){
-                    ret= −1;
-                    goto fail;
-                }
                 fourxm->tracks = av_realloc(fourxm->tracks,
                     fourxm->track_count * sizeof(AudioTrack));
                 if (!fourxm->tracks) {

The patch applies a new length check that restricts the maximum value for current_track to 0x09249247.

(UINT_MAX   / sizeof(AudioTrack) - 1) - 1 = maximum allowed value for current_track
(0xffffffff / 0x1c               - 1) - 1 = 0x09249247

When the patch is in place, current_track can’t become negative, and the vulnerability is indeed fixed.

This patch eliminated the vulnerability at the source code level. There’s also a generic exploit mitigation technique that would make it much harder to exploit the bug. To gain control of the execution flow, I had to overwrite a memory location to gain control over EIP. In this example, I used a GOT entry. The RELRO mitigation technique has an operation mode called Full RELRO that (re)maps the GOT as read-only, thus making it impossible to use the described GOT overwrite technique to gain control of the execution flow of FFmpeg. However, other exploitation techniques that are not mitigated by RELRO would still allow control over EIP.

Note

See Section C.2 for more information on the RELRO mitigation technique.

To make use of the Full RELRO mitigation technique, the FFmpeg binary would need to be recompiled with the following additional linker options: -Wl,-z,relro,-z,now.

Example of recompiling FFmpeg with Full RELRO support:

linux$ ./configure --extra-ldflags="-Wl,-z,relro,-z,now"
linux$ make

Get GOT entry of memalign():

linux$ objdump -R ./ffmpeg_g | grep memalign
0855ffd0 R_386_JUMP_SLOT   posix_memalign

Adjust Example 4-1 and use brute force to get the value for current_track:

linux$ ./addr_brute_force
Value for 'current_track': 806ab330

Make a new proof-of-concept file (poc_relro.4xm) and test it in the debugger (see Section B.4 for a description of the following debugger commands):

linux$ gdb -q ./ffmpeg_g

(gdb) set disassembly-flavor intel

(gdb) run -i poc_relro.4xm
Starting program: /home/tk/BHD/ffmpeg_relro/ffmpeg_g -i poc_relro.4xm
FFmpeg version SVN-r16556, Copyright (c) 2000-2009 Fabrice Bellard, et al.
  configuration: --extra-ldflags=-Wl,-z,relro,-z,now
  libavutil     49.12. 0 / 49.12. 0
  libavcodec    52.10. 0 / 52.10. 0
  libavformat   52.23. 1 / 52.23. 1
  libavdevice   52. 1. 0 / 52. 1. 0
  built on Jan 24 2009 09:07:58, gcc: 4.3.3

Program received signal SIGSEGV, Segmentation fault.
0x0809c89d in fourxm_read_header (s=0xa836330, ap=0xbfb19674) at libavformat/4xm.c:178
178     fourxm->tracks[current_track].adpcm = AV_RL32(&header[i + 12]);

FFmpeg crashed again while trying to parse the malformed media file. To see what exactly caused the crash, I asked the debugger to display the current register values as well as the last instruction executed by FFmpeg:

(gdb) info registers
eax            0xbbbbbbbb    −1145324613
ecx            0xa83f3e0     176419808
edx            0x0           0
ebx            0x806ab330    −2140490960
esp            0xbfb194f0    0xbfb194f0
ebp            0x855ffc0     0x855ffc0
esi            0xa83f3a0     176419744
edi            0xa83f330     176419632
eip            0x809c89d     0x809c89d <fourxm_read_header+509>
eflags         0x10206       [ PF IF RF ]
cs             0x73          115
ss             0x7b          123
ds             0x7b          123
es             0x7b          123
fs             0x0           0
gs             0x33          51

(gdb) x/1i $eip
0x809c89d <fourxm_read_header+509>:    mov    DWORD PTR [edx+ebp*1+0x10],eax

I also displayed the address where FFmpeg had attempted to store the value of EAX:

(gdb) x/1x $edx+$ebp+0x10
0x855ffd0 <_GLOBAL_OFFSET_TABLE_+528>:    0xb7dd4d40

As expected, FFmpeg tried to write the value of EAX to the supplied address (0x855ffd0) of memalign()’s GOT entry.

(gdb) shell cat /proc/$(pidof ffmpeg_g)/maps
08048000-0855f000 r-xp 00000000 08:01 101582     /home/tk/BHD/ffmpeg_relro/ffmpeg_g
0855f000-08560000 r--p 00516000 08:01 101582     /home/tk/BHD/ffmpeg_relro/ffmpeg_g
08560000-0856c000 rw-p 00517000 08:01 101582     /home/tk/BHD/ffmpeg_relro/ffmpeg_g
0856c000-0888c000 rw-p 0856c000 00:00 0
0a834000-0a855000 rw-p 0a834000 00:00 0          [heap]
b7d60000-b7d61000 rw-p b7d60000 00:00 0
b7d61000-b7ebd000 r-xp 00000000 08:01 148202     /lib/tls/i686/cmov/libc-2.9.so
b7ebd000-b7ebe000 ---p 0015c000 08:01 148202     /lib/tls/i686/cmov/libc-2.9.so
b7ebe000-b7ec0000 r--p 0015c000 08:01 148202     /lib/tls/i686/cmov/libc-2.9.so
b7ec0000-b7ec1000 rw-p 0015e000 08:01 148202     /lib/tls/i686/cmov/libc-2.9.so
b7ec1000-b7ec5000 rw-p b7ec1000 00:00 0
b7ec5000-b7ec7000 r-xp 00000000 08:01 148208     /lib/tls/i686/cmov/libdl-2.9.so
b7ec7000-b7ec8000 r--p 00001000 08:01 148208     /lib/tls/i686/cmov/libdl-2.9.so
b7ec8000-b7ec9000 rw-p 00002000 08:01 148208     /lib/tls/i686/cmov/libdl-2.9.so
b7ec9000-b7eed000 r-xp 00000000 08:01 148210     /lib/tls/i686/cmov/libm-2.9.so
b7eed000-b7eee000 r--p 00023000 08:01 148210     /lib/tls/i686/cmov/libm-2.9.so
b7eee000-b7eef000 rw-p 00024000 08:01 148210     /lib/tls/i686/cmov/libm-2.9.so
b7efc000-b7efe000 rw-p b7efc000 00:00 0
b7efe000-b7eff000 r-xp b7efe000 00:00 0          [vdso]
b7eff000-b7f1b000 r-xp 00000000 08:01 130839     /lib/ld-2.9.so
b7f1b000-b7f1c000 r--p 0001b000 08:01 130839     /lib/ld-2.9.so
b7f1c000-b7f1d000 rw-p 0001c000 08:01 130839     /lib/ld-2.9.so
bfb07000-bfb1c000 rw-p bffeb000 00:00 0          [stack]

This time FFmpeg crashed with a segmentation fault while trying to overwrite the read-only GOT entry (see the r--p permissions of the GOT at 0855f000-08560000). It seems that Full RELRO can indeed successfully mitigate GOT overwrites.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.178.157