|
| 1 | +# PissPoorPool, or p2pool for short |
| 2 | + |
| 3 | +We routinely audit PHP applications which deal with finance, money and digital currencies because nobody likes having their money stolen because of some poorly written web application exposed them to the internet nasties. |
| 4 | + |
| 5 | +Todays winner is [p2pool-node-status](https://github.com/johndoe75/p2pool-node-status), a GUI for the `p2pool` Bitcoin mining pool software. |
| 6 | + |
| 7 | +This also highlights the futility of trying to make PHP applications secure, in many cases trying to fix bugs with software written in PHP will come back to bite you in the arse even if you think you're done it right. |
| 8 | + |
| 9 | +See the following commit: https://github.com/johndoe75/p2pool-node-status/commit/5f9ea51e1647d63c77c691ce8bdd2c6ccc873c28 |
| 10 | + |
| 11 | +``` |
| 12 | +There are two major security holes in the default jsonp.php file. An attacker |
| 13 | +could easily fetch any file off the local server by simply passing in a filename |
| 14 | +into $_GET['report'] variable. Second, an attacker could essentially send out |
| 15 | +and receive web requests on behalf of your server, since theres no validating |
| 16 | +of the hostname. I've added the ability to whitelist a hostname in case anyone |
| 17 | +wants to lock their script down. |
| 18 | +``` |
| 19 | + |
| 20 | +As usual the culprit is a JSONP proxy handler (before the 'fix'): |
| 21 | + |
| 22 | +```php |
| 23 | +$report = $_GET['report']; $host= $_GET['host']; |
| 24 | +$json = file_get_contents($host . $report); |
| 25 | +echo sprintf('%s(%s);', $_GET['callback'], $json); |
| 26 | +``` |
| 27 | + |
| 28 | +After the fix the script still allows you to control the full URL, with a validation check disabled by default which would've prevented this whole escapade. The validation after the fix is as follows: |
| 29 | + |
| 30 | + * `$web_url = $_GET['host'] . $_GET['report']` |
| 31 | + * `if (file_exists($web_url)) ... die()` |
| 32 | + * `if (!filter_var($web_url, FILTER_VALIDATE_URL)) ... die` |
| 33 | + * `file_get_contents($web_url)` |
| 34 | + |
| 35 | +Now, let me see... what magic can PHP do that passes these two checks, oh yea: |
| 36 | + |
| 37 | + * `?host=php://filter/resource=file:///etc/passwd&report=` |
| 38 | + |
| 39 | +Pwned.... |
| 40 | + |
| 41 | +## Recommendations |
| 42 | + |
| 43 | + 1. Change `$force_host = false;` to `$force_host = true;` |
| 44 | + |
0 commit comments