php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #76653 Server Side Request Forgery using exif_read_data?
Submitted: 2018-07-22 21:13 UTC Modified: 2018-07-23 12:45 UTC
From: geeknik at protonmail dot ch Assigned: cmb (profile)
Status: Not a bug Package: EXIF related
PHP Version: 7.2.8 OS: Linux
Private report: No CVE-ID: None
 [2018-07-22 21:13 UTC] geeknik at protonmail dot ch
Description:
------------
I believe that I have found a server side request forgery bug in exif_read_data().

From machine A: 
php-7.2.8 -r 'exif_read_data(file_get_contents("http://dtf.pw/php728/poc/722/http.jpeg"));' 

The http.jpeg on Machine B starts with http://@2328211425:8000, which ip2long converts into an IP I happen to control, aka Machine C. 

And if we look at the console over on Machine C:

Serving HTTP on 0.0.0.0 port 8000 ...
138.68.249.154 - - [22/Jul/2018 19:05:18] code 404, message File not found
138.68.249.154 - - [22/Jul/2018 19:05:18] "GET //c&_▒ HTTP/1.0" 404 -

Machine A never contacts Machine C directly but as soon as Machine A requests the "jpeg" from Machine B, a request is simultaneously sent to Machine C.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-07-22 22:08 UTC] cmb@php.net
Presently, it seems to me that B's IP address is 159.65.100.145,
and C's is 138.197.175.225.  C's access log records a request from
138.68.249.154 – are you sure that this isn't A's address?
 [2018-07-22 22:13 UTC] geeknik at protonmail dot ch
Machine A: 138.68.249.154
Machine B: 159.65.100.145
Machine C: 138.197.175.225

A is where the php request originates, B is where the "jpeg" resides, and when A requests that "jpeg" from B, a request from A is logged on C.
 [2018-07-22 22:30 UTC] cmb@php.net
> A is where the php request originates, B is where the "jpeg"
> resides, and when A requests that "jpeg" from B, a request from A
> is logged on C.

This is expected.  file_get_contents() retrieves the “image”, and
passes its result to exif_read_data(), which accepts stream
wrapper URLs as of PHP 7.2.0.  So, basically, this is like

    file_get_contents("http://dtf.pw/php728/poc/722/http.jpeg");
    exif_read_data('http://@2328211425:8000');

Since this doesn't trigger a request from B to C, I don't see a
problem here.
 [2018-07-22 23:31 UTC] geeknik at protonmail dot ch
Okay, I think I understand what is happening now. So in order for this to be a valid issue, I need to make a request from A to B which triggers a request from B to C?
 [2018-07-23 12:45 UTC] cmb@php.net
-Status: Open +Status: Not a bug -Assigned To: +Assigned To: cmb
 [2018-07-23 12:45 UTC] cmb@php.net
> So in order for this to be a valid issue, I need to make a
> request from A to B which triggers a request from B to C?

See <https://en.wikipedia.org/wiki/Server-side_request_forgery>.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Fri Jul 10 01:01:27 2020 UTC