Hello,
Chaining filters is becoming an increasingly popular primitive to
exploit PHP applications:
-
+ GitHub - synacktiv/php_filter_chain_generator
-
PHP filter chains: file read from error-based oracle
+ GitHub - synacktiv/php_filter_chains_oracle_exploit: A CLI to exploit parameters vulnerable to PHP filter chain error based oracle.
- Introducing wrapwrap: using PHP filters to wrap a file with a prefix and suffix +
GitHub - ambionics/wrapwrap: Generates a `php://filter` chain that adds a prefix and a suffix to the contents of a file.
- Introducing lightyear: a new way to dump PHP files +
GitHub - ambionics/lightyear: lightyear is a tool to dump files in tedious (blind) conditions using PHP filters
They provide increasingly powerful primitives ranging from arbitrary
file read to arbitrary code execution, and are tedious to protect
against, as filters can be used in a lot of places.
The easiest way to kill this vector is to simply limit the number of
filters that can be chained, as attacks require a at least a couple of
them, while legitimate use usually use one or two tops, as highlighted
by arnaud-lb's analysis:
php:master
← jvoisin:limit_filters
Looked at usages of `php://filter` in [the wild](https://sourcegraph.com/search?… q=context%3Aglobal+%22php%3A%2F%2Ffilter%2F%22&patternType=keyword&sm=0&df=%5B%22lang%22%2C%22PHP%22%2C%22lang%3Aphp%22%5D&__cc=1), and here is what I've noticed:
- Most uses are either fully static URLs with a single filter such as `'php://filter/write=string.rot13/resource=data:text/plain,hello'`, or only the resource part is dynamic, e.g. `'php://filter/write=string.rot13/resource=' . $file`. This is often used in unit tests.
- Most uses in which the filter part is dynamic, or in which there are more than one filter, are exploit tools or exploits
- The few legitimate uses in which the filter part is dynamic only allow a single filter.
So the proposed change will not break any of the code indexed by sourcegraph and is unlikely to break any code if this is representative of private code bases, even with a limit of 3.
The idea and the change look good to me, but I think that you need to write to the mailing list. If there are objections this may require an RFC.
I sent a pull-request to implement this:
php:master
← jvoisin:limit_filters
opened 03:58PM - 04 Nov 24 UTC
Chaining filters is becoming an increasingly popular primitive to exploit PHP ap… plications. Limiting the usage of only a few of them at the time should, if not close entirely, make it significantly less attractive.
I hardcoded the number of filters to `5` for now, but this can be changed to an ini preference if wanted/needed, albeit I fail to see a valid usecase for anything requiring chaining 5 filters or more. I'd love to keep it hardcoded, and to lower the number to 3.
This should close #10453
/cc @arnaud-lb @cfreal
What do y'all think about this?
--
Julien (jvoisin) Voisin
GPG: 04D041E8171901CC
dustri.org
On Thu, 7 Nov 2024, jvoisin wrote:
The easiest way to kill this vector is to simply limit the number of
filters that can be chained, as attacks require a at least a couple of
them, while legitimate use usually use one or two tops, as highlighted
by arnaud-lb's analysis:
Limit the number of filters by jvoisin · Pull Request #16699 · php/php-src · GitHub
I sent a pull-request to implement this:
Limit the number of filters by jvoisin · Pull Request #16699 · php/php-src · GitHub
What do y'all think about this?
I am not a fan of hardcoding arbitrary limits, or having an ini setting
for such a limit. I especially think that the suggested limit of 5, or
even 3, is not a good idea.
The example that the issue links to to fix a vulnaribility in is:
include $_GET['page'];
Which is... yeah.
cheers,
Derick
--
https://derickrethans.nl | https://xdebug.org | https://dram.io
Author of Xdebug. Like it? Consider supporting me: Xdebug: Support
mastodon: @derickr @phpc.social @xdebug @phpc.social