Upcoming Hardening in PHP

(dustri.org)

150 points | by mmsc 9 days ago ago

31 comments

  • p4bl0 2 hours ago

    Something I'd really like is for PHP to somehow be stricter on the number of arguments passed to a function.

    As of now, PHP emits an error if arguments are missing but not if there are too many.

    A way to bake that in without breaking old code would be to allow function definition to put an explicit stop to the argument list, for example using the void type keyword:

        function foo (int $a, string $b, void) : bool
        { ... }
    
    
    A few month ago I discussed this on the development mailing list and people seemed to agree and even suggested that this would be a good idea by default without the keyword thing I suggested. But I never got the time to properly write an RFC. There is already an old one from years ago that was voted against but In was told it was from before anything strict and typing related was considered important in PHP. If anyone's up to it, please write this RFC :) !
    • withinboredom an hour ago

      I don’t really understand the issue. Already if you have a mismatch, the only way you’d ever know is through static analysis. It will run and maybe crash during run time. I always joke that changing a function signature is the single most risky thing you can do in php (especially if you have any dynamic dispatch). Making it even more risky isn’t the right answer, IMHO.

      Oh, and doing this would literally break class autoloading in symfony, and even the engine itself, which relies on this feature.

    • MH15 an hour ago

      I'd be curious to read about what percentage of active PHP devs use the recent features. The last time I worked in a PHP codebase (2020?) was half PHP 5 (bad) and half PHP 7 (much nicer). Curious if there's any real info out there on this

      • post_below 20 minutes ago

        PHP 5 is as close to phased out as it gets at this point. No doubt it's still in a lot of legacy enterprise codebases (lots of breaking changes going from 5 to 7 or 8), but outside of that no one is using it.

      • zuppy an hour ago

        php 7 has been released 9 years ago.

      • reddalo 44 minutes ago

        The Laravel ecosystem folks seem to be always up to date in recent PHP developments. At least, that's my impression.

  • metadat 7 hours ago

    The linked CVE-2024-2961 article is a pretty fantastic read on its own:

    https://www.ambionics.io/blog/iconv-cve-2024-2961-p1

    People are so creative, I can't help but feel some hope for our future :)

    • MBCook 6 hours ago

      That’s for that. I’ve never seen it before. What a neat path they took.

  • ChrisMarshallNY 7 hours ago

    > I find it fascinating that people are putting so much efforts optimizing exploitation techniques, yet ~nobody bothers fixing them, even if it only takes a couple of lines of code and 20 minutes.

    There's definite reward in having a 0-day. Either you can get a bounty, or sell it in the hacker-souk.

    That "couple of lines of code and 20 minutes" is sort of in the eye of the beholder. If you are a highly-experienced language developer, the fixes are likely to be a lot more obvious, simpler, more comprehensive, and robust, than if you are a relatively junior IC.

    • maple3142 4 hours ago

      I think it is probably because a lot of things are deemed as acceptable. For example, the stream filter chain one is only exploitable if the input to some php IO functions like file_get_contents are attacker-controlled, and those things are already treated as LFR vulnerabilities in application, not the language runtime. Also some of the them (e.g. stream filter chain) are fun and useful enough (turning LFI into RCE), so I bet there definitely some people would rather those thing is not fixed. Given that a properly-secured application wouldn't be affected.

    • est 3 hours ago

      Breaking something is easier than protecting everything from all fronts.

      Hackers write the worst code, but all the mess needs only one successful hit to become a 0day.

    • eru 3 hours ago

      Well, you can produce the exploit all on your own and showcase it.

      But to get your fix in, you'd have to interact with the PHP ecosystem.

  • EZ-E 4 hours ago

    > I find it fascinating that people are putting so much efforts optimizing exploitation techniques, yet ~nobody bothers fixing them, even if it only takes a couple of lines of code and 20 minutes.

    Like it or not, exploiting seems just more fun and rewarding. A lot of people will be interested to learn on your blog how you came to find and exploit a vulnerability. The 10 line of code patch gets little attention. Not even taking into consideration bug bounties...

  • justinclift 6 hours ago

    > Suggestion to make those parts read-only was rejected as a 0.6% performance impact was deemed too expensive for too little gain.

    Big Oof. :( :( :(

    • ipaddr 3 hours ago

      I'm okay with the tradeoff. PHP prioritizing speed over uncommon security is the right call here.

    • bigtimesink 2 hours ago

      At a large PHP shop, 0.6% can be tens of millions of dollars.

      • kortilla an hour ago

        Over what time period? You’re implying they are spending at least a billion dollars on hardware costs for 0.6% to be tens of millions.

  • urban_alien 7 hours ago

    Are these issues very particular to PHP? Honest question, this is all above my current programming knowledge.

    • wbl 4 hours ago

      Yes. Most languages don't have anything like the filter notation for arbitrary reads to escalate through.

  • mgaunard 7 hours ago

    The real question is why does PHP have so many bugs that it's so trivial to exploit?

    • craigmcnamara 4 hours ago

      Seems like an attitude problem.

    • that_guy_iain 3 hours ago

      Honestly, the development of the PHP core has always been rather amateur. From historically just adding features whenever to know adding hundreds of breaking changes per minor release. This results in a terrible codebase and a language where upgrading minor versions is so painful and costly for some firms they end up stuck on old version.

      The last part makes the fact their could be massive security holes like RCE in the core language very worrying.

      • ipaddr 2 hours ago

        Historically they have been one of the languages that added very few breaking changes and were criticized for that. You can't have it both ways.

        Going from php 4 to php 8 isn't even that painful and there are twenty years between. It's the one language where what you wrote 20 years ago probably still works today.

        Upgrading a php application is one of the least expensive and uneventful things you can do. Try upgrading that java swing application or that react app that's 15 months old. Go, haskell, vue, python 2 to 3 are more difficult because of syntax changes where in php you have some breaking changes like globals being removed or ereg removal or mysql_ being removed. The changes were small like using mysqli instead of mysql or using preg instead of ereg.

        • JodieBenitez 2 hours ago

          Surprised to see Go in your list though.

        • that_guy_iain 2 hours ago

          My complaint was adding lots of breaking changes to minor version upgrades. The fact, that historically they didn’t do breaking changes in major version upgrades does not excuse going against industry standards.

          There are literally companies stuck on PHP 7 because going to 8 is too painful. And honestly with my decade of experience your claim that going from 4 to 8 isn’t that painful sounds like nonsense and something you haven’t done. And the claim that php 4 code will work on php 8 is 100% nonsense. The syntax for how classes were defined in 4 is not supported in 8.

          I’ve upgraded the code to the major versions of other languages without hassle. But they generally had fewer breaking changes in their major versions when I upgraded to Vue3 which was super painless.

          And can you point to a minor upgrade where Go changed the syntax to the point the old one no longer works? With Go normally it's the tooling that changes. I can't remember the syntax changing on me. Especially since they have a Compatability Promise[1] it seems weird.

          [1] https://go.dev/doc/go1compat

          • arkh 28 minutes ago

            > There are literally companies stuck on PHP 7 because going to 8 is too painful.

            Usually due to frameworks. Those tend to do play fast and loose with language constructs so small changes can make them not work anymore. And as those same framework will also break a lot more things between version, you cannot easily upgrade them, so you cannot upgrade your php version.

            Currently maintaining an internal symfony 1 website so I know the pain. At least the documentation of old symfony is still available unlike many more modern frameworks.

          • hparadiz 2 hours ago

            Like everything... It depends.

            Just use rector

            https://github.com/rectorphp/rector

            • that_guy_iain 2 hours ago

              I've previously used that to do something. Fell flat on its face. But the fact they literally had to create a tool to solve this problem confirms my point.

              • hparadiz an hour ago

                I use it all the time and it works great. You need to know what you're doing.

          • chx an hour ago

            You are right, going from 4 to 8 is a huge challenge.

            Minor point: classes are using the same syntax but you are right they typically won't work because the constructor have changed, in PHP4 it was a function named the same as the class, in PHP5 and on it's __construct, the PHP4 version was deprecated in PHP 7 and removed in PHP 8.0.

            create_function is just gone. So is each(). Oh and HTTP_RAW_POST_DATA. The list is long.

            If you have used == and in PHP4 we did that, come on, don't be holier than holy and claim you only used === in PHP4 then PHP8 will have some surprises for you.

            In my experience rector became usable last year-ish, if you tried before, give it another whirl.