[HN Gopher] Google results for PHP tutorials contain SQL injecti...
       ___________________________________________________________________
        
       Google results for PHP tutorials contain SQL injection
       vulnerabilities
        
       Author : phil294
       Score  : 536 points
       Date   : 2021-07-25 19:27 UTC (1 days ago)
        
 (HTM) web link (waritschlager.de)
 (TXT) w3m dump (waritschlager.de)
        
       | axelfreeman wrote:
       | I checked the first page of google results for "php sql login" in
       | german and all examples are talking about escaping or prepared
       | statements.
        
       | unobatbayar wrote:
       | W3Schools seems to be a great developers source while being quite
       | reliable in terms of teaching best practices, avoiding exploits,
       | and vulnerabilities.
        
       | omgitsabird wrote:
       | Let me show you how to do a mysql query for a web app in nodejs.
       | const express = require('express');       const app = express();
       | const mysql = require('mysql');            app.get('/', (req,
       | res) => {         const connection = mysql.createConnection({
       | host: 'localhost',           user: 'me',           password:
       | 'secret',           database: 'my_db'         });
       | connection.connect();              connection.query(
       | `SELECT a FROM b WHERE x = ${req.query.y}`,           (err,
       | results) => {             res.send(results[0]?.a);
       | connection.end();         });       });
       | app.listen(1234);
       | 
       | Now this will be a google result _somewhere_ for how to do a
       | query that contains an SQL injection vulnerability.
       | 
       | I fail to see the point of this article, as pretty much anyone
       | who enters into web programming understands that there is
       | something called an SQL injection vulnerability that they need to
       | be aware of.
        
       | soheil wrote:
       | I don't know, I feel like people love to pile on PHP nowadays. Do
       | people actually think those who are learning PHP by searching
       | Google for tutorials are going to be creating production ready
       | applications that would be so critical that a simple SQL
       | injection attack would be so catastrophic to? There will be a
       | million other ways mistakes can be made before anything is up and
       | running with actual users. Better a simple attack to wipe out
       | their db early on instead of a more nuanced bug somewhere down
       | the road that is so hard to catch because they're trying to
       | figure out what stateless composition of a single purpose
       | component means. At least PHP makes it simple to write some code
       | and start thinking about what you want to do instead of total BS
       | React style esoteric f*ckry.
       | 
       | Let the poor newbies learn to code by seeing the simple beauty
       | before drowning them in security nightmare scenarios.
        
         | fencepost wrote:
         | _Do people actually think those who are learning PHP by
         | searching Google for tutorials are going to be creating
         | production ready applications that would be so critical that a
         | simple SQL injection attack would be so catastrophic to?_
         | 
         | Abso-freakin-lutely. It may not be direct copy pasting of code,
         | but often it'll start as that then be tweaked as appropriate
         | for the project at hand.
         | 
         | Even programmers not doing this are frequently going back and
         | looking at their own code doing similar things or other similar
         | code in codebases they have access to (eg internal libraries).
         | Better programmers will do similar things but also recognize
         | the flaws in what they're using.
        
         | acdha wrote:
         | > Do people actually think those who are learning PHP by
         | searching Google for tutorials are going to be creating
         | production ready applications that would be so critical that a
         | simple SQL injection attack would be so catastrophic to?
         | 
         | Yes. I've seen this from highly-paid staff and contractors at
         | multiple places in .com, .edu, and .gov. This includes
         | commercial licensed software, big name consulting companies,
         | and ostensible security experts. I've also seen them "fix" the
         | problem by looking for the PoC test string and only rejecting
         | that value.
         | 
         | Unsafe defaults make it much easier to get something to "work"
         | without noticing problems because the happy path works and is
         | what most people focus on testing.
        
       | gregjor wrote:
       | I freelance fixing and maintaining legacy web apps, almost always
       | PHP.
       | 
       | Anecdotally I see SQL injection vulnerabilities in about half the
       | code I look at. It's one type of problem among many other
       | problems and vulnerabilities in code written by amateurs and
       | often copy/pasted.
       | 
       | PHP programmers can find lots of resources online. Some of those
       | are terrible, either very old or written by amateurs excited to
       | show how they got something to work.
       | 
       | I have seen the same kind of thing with Java and Python, but the
       | popularity of PHP means there's a lot of junk info and examples
       | online.
       | 
       | PHP has supported safe SQL and safe HTML for decades, but the
       | programmer has to understand the problem and the solution.
        
         | tannhaeuser wrote:
         | > _PHP has supported [...] safe HTML for decades, but the
         | programmer has to understand the problem and the solution._
         | 
         | That's not good enough for a language advertising as "Hypertext
         | Preprocessor" though. PHP's distinguishing feature is that's
         | kicked off from SGMLish processing instructions in otherwise
         | static HTML, and it has all context available for perfect
         | injection-free HTML-aware templating. Eg escaping quotes when
         | it's outputting into attributes, escaping "]]>" when outputting
         | into CDATA sections, or with the help of a _real_ markup
         | processor, suppressing /escaping <script> elements or onclick
         | or other event handler attributes where advised through a
         | grammar such as an SGML DTD. But it doesn't because it's just
         | such a hack job of a language, by the developer's own
         | admission.
        
           | gregjor wrote:
           | I won't disagree that PHP has its flaws. A lot of them are
           | legacy problems to support old code. Every language and tool
           | with a big installed base has this problem -- just look at
           | the legacy crap in Windows.
           | 
           | It's fairly easy to write clean and safe PHP. Any number of
           | libraries and frameworks exist to do safe SQL queries and
           | escape HTML. The problem is a lot of programmers don't even
           | know the vulnerability, not that it's hard to fix.
           | 
           | I could bitch and moan about PHP or make a good living fixing
           | bad code. Complaining won't make that legacy code better or
           | magically rewrite it.
        
             | tannhaeuser wrote:
             | Fair enough, but in the case of PHP, the target that XSS
             | attacks are after are not the PHP sites themselves most of
             | the time, but weaponizing those for c&c attacks on third-
             | party sites. Thus merely using PHP, with its well-known
             | combination of copy/paste culture, popularity among newbs,
             | and poor security practices opens site owners up to
             | liability claims (if nothing else, such as gross negligence
             | with PII). And PHP's defense is weak, with not even an
             | attempt to bring its built-in web templating into something
             | that could remotely be called state of the art, considering
             | that eg SGML is 35 years old.
             | 
             | Not saying this to diss PHPers; in fact, I like the PHP
             | community for their get stuff done mentality, and I think
             | they deserve better. If I were contracting for PHP, though,
             | I'd make sure to negotiate strong liability disclaimers.
        
               | gregjor wrote:
               | Are you aware of an actual case of an owner of a web site
               | getting sued because their site was used to attack other
               | sites, without their knowledge? This could (and has)
               | happened with other tools besides PHP. Is Microsoft
               | liable because Windows is used as a launchpad for
               | attacks?
        
               | tannhaeuser wrote:
               | IANAL, much less a judge, but I think there's a plausible
               | legal theory for suing isn't there?
        
             | [deleted]
        
           | DaiPlusPlus wrote:
           | Further evidence of this is the fact that `<?= $foo ?>`, and
           | the long-form `<?php echo $foo ?>`, don't offer a way to
           | easily HTML-encode the output; instead you have to use
           | `htmlentities()`. Whereas ASP.NET has had `<%: foo %>` to
           | encode output for almost 15 years now, and Razor defaults to
           | encoding: they make it harder to render unrecoded output.
        
             | wvenable wrote:
             | Actually only 12 years since that syntax came out with
             | ASP.NET version _4.0_. ASP.NET went a long time without it
             | (and classic ASP before that).
             | 
             | And, like with razor, you can use plenty of libraries with
             | PHP that will encode by default.
        
               | DaiPlusPlus wrote:
               | Razor is stock though, but there is still no in-box way
               | using PHP's own syntax to auto-encode output.
        
             | corobo wrote:
             | Comparing a language to a framework is a bit wonky isn't
             | it? Laravel (PHP framework) for instance has {{ $foo }}
        
               | DaiPlusPlus wrote:
               | PHP is simultaneously a framework _and_ a language,
               | though. It features a very simple framework, though, and
               | has been supplanted by others, including those that
               | resort to reimplementing their own templating system,
               | which defeats the point of using PHP in the first place
               | as that was its main goal: to be a templating system for
               | Personal Home Pages.
        
               | [deleted]
        
               | arp242 wrote:
               | PHP started life as a template engine for CGI
               | applications written in C. And some pretty major projects
               | like WordPress use PHP as a "template language".
               | 
               | There are various constructs in the language rarely seen
               | in PHP code that make this easier, such as <?=, but also
               | also "if (..):" which can be ended with "endif", and
               | "foreach (...):" which can be ended with "endforeach".
               | 
               | It's not a hard feature to add. PHP devs want to move
               | away from this "PHP as a template language" (I think they
               | tried to remove the <?= a few years back); that's all
               | fine, but fact of the matter is that people _ARE_ using
               | it as a template language and will continue to do so in
               | the foreseeable future. Not supporting that with
               | something as simple as  "automatic escape special HTML
               | characters" is extremely disappointing, and would
               | actually prevent a lot of problems.
        
             | [deleted]
        
         | makeitdouble wrote:
         | At this point there's a ton of CI tools to check for injection
         | and dangerous patterns, and serious companies have been using
         | them for years/decades now, ranging from local options to
         | online tools like Scrutinizer or Sonarqube. I'd wager even
         | PHPCs would catch the copy/pasted ones.
         | 
         | To me the language or online examples is no excuse for SQL
         | injections for a long time now.
        
           | gregjor wrote:
           | It's no excuse for professional developers working at
           | "serious" companies. It is an excuse for the legions of
           | amateur developers just trying to get something to work.
           | 
           | If Google and Amazon can't find and hire enough developers
           | imagine what that supply/demand and cost problem means for
           | small companies. I have clients who have been trying to hire
           | a f/t or p/t programmer for years. They can't pay $100/hr for
           | a simple web site. So they hire amateurs trying to get that
           | experience needed to get a real job at a serious company.
           | 
           | Yes, they leave a trail of crappy code full of
           | vulnerabilities and bugs. The only way to blame that on PHP
           | is to criticize its low bar to entry, which is a good thing
           | for beginners.
        
         | gerdesj wrote:
         | I run a small IT company and the Windows sysadmin stock answer
         | to nearly all problems:                 C:\Windows\System32>
         | sfc /scannow
         | 
         | ... followed by "reinstall your operating system". OK so no
         | harm done apart from rather a lot of downtime, assuming you can
         | put it back together again. The number of times I see "disable
         | your AV" still is frightening.
         | 
         | I have a browser plugin that I discovered thanks to this parish
         | called uBlacklist which you can use to try and clean up your
         | search results by banning known bad sites from your results.
         | social.microsoft.whatever was first ... 8)
         | 
         | I also note an awful lot of Linux related link farms and
         | "blogs" with ads and cloned content from other sources have
         | surfaced over the last few years. WordPress is another
         | quagmire. I could go on but basically, search is very close to
         | completely screwed (but not quite.)
        
           | voltagex_ wrote:
           | Yeah, but what are your other options?
           | 
           | * procmon, if you're lucky you'll catch WTF is going on
           | somewhere deep in the registry
           | 
           | * Hoping Microsoft still has the answer in a KB article
           | somewhere (hope you didn't need any Server 2008/2012 stuff
           | that was on UserVoice, it's gone now)
           | 
           | * WinDBG if you're that good
           | 
           | Which brings us back to cargo culted answers like sfc
           | /scannow
           | 
           | I wouldn't compeltely discount social.microsoft, very very
           | occasionally it's had a tiny tidbit of information in between
           | the people incorrecting each other.
        
             | arp242 wrote:
             | I used to fix Windows computers for a living; this was 10
             | years ago and I don't really know what changed in Windows
             | 8/10 as I never used it, but I imagine it's roughly similar
             | to XP and 7.
             | 
             | With some knowledge and experience it's possible to fix a
             | lot of problems. Actually, a lot of problems people chuck
             | up to "Micro$ucks bad" are just hardware problems. If
             | someone comes in with "I get random BSODs" then there's a
             | good chance it's just faulty a faulty RAM module, disk, or
             | something like that. The first step for random issues
             | should always be to run memtest and a disk check tool (I
             | don't recall the name of the tool I used for that, but
             | there are some subtleties involved in testing this well,
             | and I don't know the status of SSDs as this was kind of
             | before they became common). Checking hardware is easy,
             | checking software isn't.
             | 
             | Software problems can be a bit trickier to solve, depending
             | on what the issue is. They're very hard to debug remotely
             | over the internet: but there's a lot more you can do than
             | "sfc /scannow" if you're sitting in front of the computer.
             | 
             | You really don't need WinDBG in most cases.
        
               | pixl97 wrote:
               | Most problems can be solved if you want to put massive
               | amounts of time in it. The issue you state, without
               | realizing you've stated it, is that 'knowledge and
               | experience' is in demand and expensive. So I have the
               | option of investing a few hundred bucks of someone's time
               | into fixing the issue, or running 'sfc /scannow' and
               | surprisingly often fixing the problem.
        
           | pixl97 wrote:
           | Disable your AV is a perfectly cromulent suggestion. It is a
           | root kit that operates at the lowest level of your operating
           | system, and any issue with it and it will affect every layer
           | above it.
           | 
           | Now, if disabling works you should set reasonable exclusions
           | and enable the product again.
        
             | Aeolun wrote:
             | So I install a rootkit... to save me from rootkits?
        
               | gerdesj wrote:
               | Yes you do. You install something with all privileges on
               | your system that claims to keep the baddies out.
               | 
               | Hopefully you choose wisely on what to install on your
               | system. Hopefully you even know what is "wise" to install
               | on your system.
               | 
               | If you find out what is wise to use on your system,
               | please let us know.
        
               | DaiPlusPlus wrote:
               | Microsoft Defender is pretty legit
        
             | gerdesj wrote:
             | Disabling your AV is never a good starter for 10 and is
             | often proffered as the canonical fix for a problem. I
             | shudder to think how many people have been debagged and
             | radished (I'll take your cromulent and raise you really
             | odd) as a result of following "sage" advice.
             | 
             | I read the logs and set exclusions until the damn thing
             | works. I have briefly disabled the whole
             | AV/firewall/browser plugin thing sometimes to double check
             | but that is quite rare. When I smile my teeth make a "ping"
             | sound and briefly flash white.
        
           | BeFlatXIII wrote:
           | Blog spam is the bane of the n00b programmer. Even if you're
           | not totally new and are merely picking up a new language, it
           | turns tutorial hell into eternal Hell.
           | 
           | Raspberry Pi tips is another quagmire of replicated garbage.
        
             | gregjor wrote:
             | I've been mentoring a couple of junior programmers for a
             | couple of years and I have seen the kind of junk tutorials
             | and online misinformation they find. Some of it is useful
             | because it shows so many bad ideas and implementations --
             | like studying a plane crash to find out what went wrong.
             | 
             | I wrote an article about this back in 2007, regarding
             | Javascript examples in an O'Reilly book -- a source I used
             | to recommend because of the quality of their writing and
             | editing (I no longer have that opinion).
             | 
             | https://typicalprogrammer.com/learning-by-example-how-bad-
             | co...
        
               | arp242 wrote:
               | It's not just an issue with blogspam, plenty of
               | "bookspam" as well. A few years ago a friend of my then-
               | girlfriend was learning C for some project. The book she
               | had was so badly written even I could hardly follow it,
               | and I can already program in C. It's no surprise this
               | part of her project failed.
               | 
               | I started programming on MSX-BASIC (kind of like C64),
               | and when we finally got a PC in 2000 or so I got a book
               | titled "Learn C++ in 10 minutes". It was so bad hat I was
               | turned off from programming for a few years, as I thought
               | I just didn't have what it takes (it also didn't help
               | that the tooling and "getting started" was much harder
               | back then, especially on Windows; if I had known you
               | could just download e.g. Python instead of mucking about
               | with this pirated Visual Studio I probably would have had
               | an easier time - but I didn't know about that. It wasn't
               | until I started playing with FreeBSD a few years later
               | that I got back in to programming).
        
             | cerved wrote:
             | also csharp, python, JavaScript
        
           | syshum wrote:
           | Now Now...
           | 
           | The Sysadmin stock answer to nearly all problems is
           | shutdown /r /t 0
           | 
           | If that fails, then                   sfc /scannow
        
         | paulddraper wrote:
         | > PHP has supported safe SQL and safe HTML for decades, but the
         | programmer has to understand the problem and the solution.
         | 
         | The ecosystem has a _ton_ of exposed wires in builtins and
         | libraries.
         | 
         | When the function's name is literally
         | `mysql_real_escape_string` ... what does that tell you?
        
           | chipotle_coyote wrote:
           | While you're not wrong, per se, this has a bit of that "never
           | give PHP credit for getting better when it's still possible
           | to do bad things with it" vibe to it. I mean, it's fairly
           | well-established PHP did some pretty boneheaded things in its
           | history and one could argue they didn't get serious about
           | cleaning those up until rather late in PHP 5's life cycle.
           | (Some would say not until PHP 7.)
           | 
           | In the case of your example, what it tells me is that they
           | had a "mysql_escape_string()" that they needed to remove but
           | had to deprecate first to avoid breaking existing code,
           | however bad it might be, and so replaced it with
           | "mysql_real_escape_string()" -- which itself hasn't been in
           | PHP for over 5 years, since that whole MySQL driver was
           | deprecated. There's still a "mysqli_real_escape_string()",
           | but that name is likely a quirk of history, as there's no
           | matching "mysqli_escape_string()" for people who would like
           | to use the supported driver but continue screwing up the
           | charset.
           | 
           | (Edit: another comment reminded me of something that I knew
           | once but had forgotten. The MySQL C API has the
           | "escape_string" and "real_escape_string" functions in it
           | which do precisely the same things the old PHP functions did.
           | So this actually tells us even _less_ about PHP the language,
           | although it may tell us something more about MySQL.)
        
             | paulddraper wrote:
             | > "never give PHP credit for getting better when it's still
             | possible to do bad things with it" vibe to it
             | 
             | I was trying to go for the "PHP has tons and tons of
             | terrible shoddy baggage" vibe.
             | 
             | https://preview.redd.it/v53przfht6n01.png?width=960&crop=sm
             | a...
        
               | gregjor wrote:
               | What language anyone uses that's older than a couple of
               | years doesn't have terrible shoddy baggage in at least
               | someone's opinion? I have the same opinion about
               | node.js/npm, and Java. My opinion doesn't make anyone
               | stop using those languages.
               | 
               | Stroustrup quipped "There are only two kinds of
               | languages: the ones people complain about and the ones
               | nobody uses." PHP is the first kind. Like every language
               | and tool before it that came with a low barrier to entry
               | it led to a proliferation of bad code. My friends who
               | work in ML/data science make the same complaints about
               | Python -- it's easy to get something to work but the code
               | quality -- ugh. And in a few years lots of that code will
               | face the "upgrade and break it or keep it and cross our
               | fingers" point that so much legacy PHP is at already.
        
               | paulddraper wrote:
               | That's true. PHP just started so, so, so far down, it's
               | had more to overcome than most.
        
               | gregjor wrote:
               | Not sure if you're just trolling the low-hanging fruit or
               | not but I'll assume not.
               | 
               | When PHP came out in 1997 the other available products
               | for putting web sites together, at least for smaller
               | organizations, were:
               | 
               | - ASP (classic, not .Net)
               | 
               | - ColdFusion
               | 
               | - Perl
               | 
               | The first two were proprietary packages that required a
               | license for the software and a license for the operating
               | system (Windows). I got into PHP when a customer wanted
               | to migrate away from Windows/ASP because of licensing
               | fees -- they took the leap with open source, which was a
               | big gamble at the time. The CTO had read "The Cathedral
               | and the Bazaar" and swallowed the kool-aid. We still had
               | to use SQL Server though, that company was committed to
               | it across all of their applications, so I got to use PHP
               | + ODBC for a while. Fun.
               | 
               | Perl had a fairly big base of CGI scripts but in most
               | respects seemed worse than ASP, CF, PHP because Perl had
               | a steep barrier to entry. PHP was an easy choice for
               | shops looking to get off of ASP -- which Microsoft was
               | making noises about discontinuing -- and ColdFusion,
               | which several of my customers back then used, but
               | complained about the cost (Adobe now owns CF).
               | 
               | So it was PHP. Then along came WordPress and the PHP
               | world exploded. As you point out the language has had a
               | hard time keeping up with the demands placed on it
               | (Rasmus certainly didn't imagine Facebook-scale sites
               | back then), and the evolving security threats (lots of
               | web sites were purely internal back then, not exposed on
               | the public internet, and the script kiddie hackers were
               | still in nursery school in Kiev). Hosting providers
               | sprung up to offer turn-key PHP/MySQL hosting, with the
               | proviso that the site owner and developers did not
               | control the PHP configuration.
               | 
               | Since 1997 a lot has changed and it's easy to point to
               | problems in PHP and say "That could have been done a lot
               | better." And that's true, but no one had that crystal
               | ball back in the mid-90s. The push was to get something
               | on the web. Planning for future maintainability has never
               | been an aspect of software development we can boast about
               | and the PHP code out there today is no different, there's
               | just a lot of it.
               | 
               | For my part I push my customers to upgrade to the latest
               | version and to do a security analysis and vulnerability
               | test so we can find and fix the most egregious problems.
               | Even this level of upgrading can get expensive and risky.
               | I wish no one was still running PHP 5.4 in production in
               | 2021 but wishing won't change that it's still fairly
               | common, and companies using that code are only going to
               | call someone like me after they've had a serious problem.
        
               | pjmlp wrote:
               | Nah, writing CGIs in C, that was my first handling of
               | FORM submits.
        
               | chipotle_coyote wrote:
               | > PHP just started so, so, so far down, it's had more to
               | overcome than most.
               | 
               | This is probably fair. :) I think PHP tried to combine
               | Python's "batteries included" approach with Perl's "more
               | than one way to do it" style, but did it in a pretty
               | disorganized way that created lots of Catch-22 issues
               | later -- when you get that popular, it makes backward-
               | incompatible changes fraught with peril, even if you're
               | addressing obviously craptacular past mistakes.
               | 
               | I think PHP has become pretty solid in version 7+ on,
               | although my feelings about using it remain mixed. I've
               | joked in the past that it's stopped being a cargo cult
               | version of Perl and is now a cargo cult version of Java.
        
           | wvenable wrote:
           | > The ecosystem has a ton of exposed wires in builtins and
           | libraries.
           | 
           | PHP is a light wrapper around C libraries.
           | 
           | > When the function's name is literally
           | `mysql_real_escape_string` ... what does that tell you?
           | 
           | That it comes from the MySQL directly:
           | 
           | https://dev.mysql.com/doc/c-api/8.0/en/mysql-real-escape-
           | str...
        
             | paulddraper wrote:
             | That doesn't surprise me.
             | 
             | MySQL is the PHP of databases.
        
               | gregjor wrote:
               | Exactly. Free, well-supported, useful, widely-deployed,
               | used by lots of developers.
        
           | zzt123 wrote:
           | It makes me wonder if there's a mysql_fake_escape_string or
           | mysql_doesnt_actually_escape_string function. And why those
           | functions would even exist in a language.
        
             | hnick wrote:
             | It exists because "mysql_escape_string() does not take a
             | connection argument and does not respect the current
             | charset setting."
        
               | zzt123 wrote:
               | I thought the security of escaping is dependent on not
               | having mismatched charsets? In which case, not respecting
               | charset settings seems potentially not actually escaping?
               | 
               | Seems like a strange function to have, although I could
               | be foggy on my charsets.
        
               | SilverRed wrote:
               | It shows the culture in PHP. They would rather keep a
               | function around that doesn't work properly just so
               | existing code still works instead of making everyone test
               | that the new function works.
        
               | ericbarrett wrote:
               | As another commenter points out, this is actually a quirk
               | of the underlying MySQL C library, which has (or had)
               | both functions.
        
               | heurisko wrote:
               | That's not completely true. Over its evolution, PHP has
               | removed some functions completely to provide better and
               | more secure functionality, such as mysql_* in PHP 7.
        
               | paulddraper wrote:
               | https://www.reddit.com/r/ProgrammerHumor/comments/8667lt/
               | sta...
        
               | tored wrote:
               | No, every PHP release deprecates functions or fixes
               | functions that is either considered bad or not working as
               | intended. Quick search & I found these (note that some of
               | the rfc's include multiple deprecations), but there is
               | more if you bother to actually look. Stop spreading
               | misinformation.
               | 
               | https://wiki.php.net/rfc/deprecations_php_8_1
               | 
               | https://wiki.php.net/rfc/deprecations_php_7_4
               | 
               | https://wiki.php.net/rfc/deprecations_php_7_3
               | 
               | https://wiki.php.net/rfc/deprecations_php_7_2
               | 
               | https://wiki.php.net/rfc/remove_deprecated_functionality_
               | in_...
               | 
               | https://wiki.php.net/rfc/deprecate_curly_braces_array_acc
               | ess
               | 
               | https://wiki.php.net/rfc/ternary_associativity
               | 
               | https://wiki.php.net/rfc/deprecate_null_to_scalar_interna
               | l_a...
               | 
               | https://wiki.php.net/rfc/deprecate-png-jpeg-2wbmp
               | 
               | https://wiki.php.net/rfc/mcrypt-viking-funeral
               | 
               | https://wiki.php.net/rfc/removal-of-deprecated-features
               | 
               | https://wiki.php.net/rfc/deprecate_mb_ereg_replace_eval_o
               | pti...
        
               | gregjor wrote:
               | It shows a trade-off between arbitrarily breaking code in
               | production or not. Lots of PHP sites are hosted on
               | services that don't give the programmer control over the
               | PHP version. If the hosting provider upgrades and breaks
               | a bunch of sites that's a problem every bit as serious
               | (to the site's owner) as unescaped HTML opening up XSS
               | attacks.
        
               | SilverRed wrote:
               | This is not sustainable or a desirable thing to keep. By
               | accepting this state of things, no security fix with
               | breaking changes can ever be implemented.
        
               | gregjor wrote:
               | With all respect your comment is both arrogant and
               | unrealistic. Exactly how do we not accept this state of
               | things? No one claims it's desirable, it just is: bad
               | code is out there, and it's not easy to fix.
               | 
               | What would you tell a small business that relies on
               | clunky 10-year-old code to run their business? To rewrite
               | it in a more modern language at huge expense and risk
               | (given that a majority of rewrite projects fail)? Can you
               | guarantee the new thing won't be just as obsolete and
               | vulnerable and buggy in ten years?
               | 
               | These kinds of problems -- poorly-written and vulnerable
               | code, amateur programmers, lack of professionalism,
               | maintaining back-compatibility with an installed base --
               | are not specific to PHP. They afflict the entire software
               | industry, and always have. Who could have seen into the
               | future back in 2000 (when I first got exposed to PHP)
               | that a new site would get probed by an army of bots
               | within five minutes of going live? Or that it would be
               | even harder today than back then to find and hire
               | experienced programmers?
               | 
               | PHP has had many security fixes implemented since the
               | early releases, but how can anyone force users of an
               | open-source language to upgrade for their own good? Or
               | pay someone to ferret out and fix vulnerabilities they
               | have never got hit by?
               | 
               | Even brand new code has this problem. Look at all of the
               | cryptocurrency code written in the last few years. We
               | read about hacks and thefts and vulnerabilities every
               | day, and that was written by supposedly smart people with
               | access to modern languages and with knowledge of the
               | contemporary security issues. And it still gets hacked.
               | If we knew how to write perfect code that would still be
               | perfect into the future I'm sure we would do that but
               | until then we'll have to live with what we have. So far
               | it has been sustainable, just less than optimal, if by
               | optimal we mean what we can imagine rather than what we,
               | as programmers, actually deliver.
        
               | eska wrote:
               | Yes, yes, the poor companies. But do you ever consider
               | the poor customers/users that put private information in
               | the companies' databases? Or that the price they pay
               | assumes the companies do not let their software rot for
               | 10 years?
               | 
               | Then there's the typical logical fallacy of taking a
               | trivial problem of escaping SQL and conflating it with
               | something more complicated, and comparing to eternal
               | perfection.. yawn.
        
               | gregjor wrote:
               | Look at the major data breaches over the past decade --
               | TransUnion, Experian, multiple US government sites, etc.
               | and point to one that was caused by a PHP SQL injection
               | attack. This kind of thing can happen to anything
               | accessible on the public internet.
               | 
               | Do you know how old the software your bank uses is?
               | Pretty much every government agency and utility you rely
               | on? What price do you pay for that? A lot of that code
               | has been rotting longer than any PHP web site.
               | 
               | There's no logical fallacy. I wrote multiple times that
               | escaping SQL is essentially trivial in PHP, and has been
               | not only easy but the recommended best practice. The
               | problem is lots of inexperienced programmers don't know
               | the problem to begin with. They would write vulnerable
               | code in any language. I had to work on a Rails site a few
               | years ago that was vulnerable to XSS and SQL injection,
               | even though Rails by default protects against those
               | things. Someone had gone around all of that because they
               | didn't understand the problem in the first place. I don't
               | know that any language can protect us from that.
        
               | eska wrote:
               | Again, frantic hand-waving and pointing fingers, filled
               | to the brim with logical fallacies. I can only imagine
               | what kind of work culture exists in your company that you
               | keep repeating the same tired, generic excuses that I've
               | heard thousands of times before, thinking that they're
               | not fallacies.
               | 
               | The fact that you and many others in this industry think
               | these arguments are in any way rational or defensible
               | puts our industry to shame.
        
               | gregjor wrote:
               | I freelance supporting legacy software. I wrote that
               | already. There's no culture in my company, just me.
               | 
               | There's a difference between an explanation and an
               | excuse, and between counterexamples and "hand waving."
               | I'm sure it makes you feel superior to dismiss opinions
               | and comments with vague references to logical fallacies
               | or indefensible arguments, but just hauling out big words
               | doesn't make you right, or even make any sense.
               | 
               | I can't fix everything wrong with software development.
               | I've been doing it for 40 years and we just keep making
               | the same mistakes. My small contribution is fixing broken
               | code one customer at a time, at least leaving the
               | campsite cleaner than I found it. I don't lose a lot of
               | sleep over our collective failure to write perfect
               | software.
        
               | SilverRed wrote:
               | >companies do not let their software rot for 10 years?
               | 
               | I think that one of the big mistakes made in the last 20
               | years is that every company needs its own custom software
               | and that software is like an asset that you buy once and
               | not a constant cost source.
               | 
               | The vast majority of businesses have no need for custom
               | software and should be using 3rd party services. Then
               | those 3rd parties have the income to dedicate to keeping
               | the software secure.
               | 
               | Its honestly terrible how many local businesses have
               | their own complex software built on some ancient version
               | of a frame work which is sitting on an ancient server box
               | in their office. Its a ticking time bomb no one wants to
               | think about. Prolonging the explosion is not the
               | solution.
        
               | gregjor wrote:
               | Agreed. I often tell customers to use an off-the-shelf
               | solution and get on with their real business. Custom
               | software development is expensive, risky, and incurs
               | long-term maintenance costs. I outright refuse to take on
               | custom e-commerce sites or accounting or CRM systems at
               | this point.
               | 
               | About half the time the customer will find someone else
               | who will happily bid on writing custom code despite my
               | suggestion. That's one reason the legacy code problem
               | just gets bigger every year, and a lot of it shouldn't
               | have been written in the first place.
        
               | SilverRed wrote:
               | Of course this is a lot of work but it means that unless
               | PHP takes security seriously, no one will take PHP
               | seriously and the language will die off / be relegated to
               | dirt cheap contractor work.
               | 
               | No serious org is going to use a product where you have
               | to remember that the sql escape function doesn't work and
               | you have to use the one that says real sql escape.
        
               | gregjor wrote:
               | This is a canard, really. The PDO library, which is a
               | core PHP module, has SQL injection mitigation built-in
               | (with escaped parameter substitution). It was introduced
               | with PHP 5 in 2004. The popular PHP frameworks such as
               | Laravel and CodeIgniter also protect against SQL
               | injection and XSS by default.
               | 
               | The MySQL escape functions are named the way they are
               | because that's what they are called in the MySQL API,
               | which PHP exposes pretty much verbatim. I don't see a lot
               | of people using that interface in new PHP code (because
               | Laravel and PDO), but it comes up on older code.
               | 
               | Again the problem is not obscure function names or that
               | PHP makes it possible to shoot yourself in the foot. The
               | problem is a whole lot of inexperienced programmers (and
               | quite a few who should know better) not understanding the
               | problem in the first place. If you don't know what SQL
               | injection is or how it happens or how code can make it
               | possible you aren't going to know how to protect against
               | it. PHP does do it for you if you use PDO (more than 15
               | years old at this point), or any of the numerous other
               | safe RDBMS libraries. This is like complaining that Honda
               | makes shitty cars because some people put glass packs and
               | spoilers on a Civic -- people use languages and tools
               | wrong out of ignorance and inexperience.
               | 
               | I think it's clear that PHP has been taken seriously for
               | some time, even if largely because of WordPress. It's not
               | going to die off or get relegated to the language ghetto
               | because it has some (obvious, well-known) flaws that
               | serious programmers have known how to live with for
               | literally decades. Regardless of what you think or see on
               | Upwork, PHP contractors are not cheap. No one who can and
               | will work on legacy code is cheap because most
               | programmers won't even do that work if they can help it.
               | Supporting legacy software, which includes improving and
               | securing and upgrading it, is maybe the most lucrative
               | and secure niche for programmers sitting there in plain
               | sight.
        
               | corobo wrote:
               | That command doesn't even exist anymore and hasn't since
               | 2013
        
               | hnick wrote:
               | PHP (and old languages in general) are full of ASCII-only
               | English-centric assumptions. I think both functions are
               | now considered deprecated since we have even more
               | variations like mysqli_real_escape_string (or just use
               | PDO with bound params).
        
         | cosmodisk wrote:
         | From my anecdotal data, a whole lot of tutorials are written by
         | 'learn Java in 21 day' stage developers. People are excited,
         | want to put their name out there and start churning out
         | tutorials on concepts only yesterday they had no clue about.
         | Similar situation with many online courses too.
        
         | marvinblum wrote:
         | Same here. PHP is also often picked by beginners (including me
         | 15 years ago) and you can see that. However, I have a lot of
         | fun fixing these kind of issues and improving the code. It
         | feels like archology/restauration sometimes and it makes me
         | happy to keep them running securely. Also, it pays really well
         | usually.
        
         | 908B64B197 wrote:
         | > Some of those are terrible, either very old or written by
         | amateurs excited to show how they got something to work.
         | 
         | And the current bootcamp trend will only amplify that. Lambda
         | has "instructors" that are students only 4 months ahead of the
         | students they are teaching...
        
       | lixtra wrote:
       | The clean code may still have other issues. For example [1] give
       | away if a certain email address is registered with the site or
       | not.
       | 
       | [1] https://phppot.com/php/user-registration-in-php-with-
       | login-f...
        
         | IshKebab wrote:
         | Everyone on HN is obsessed with that "vulnerability" without
         | considering that: a) almost all sites that try to avoid it fail
         | anyway when you try to sign up - "that email is already
         | registered" and b) it's really user-hostile for a tiny increase
         | in privacy so it's perfectly reasonable to not implement it on
         | _most_ sites.
        
           | jffry wrote:
           | If I did want to close that hole, is there anything more
           | clever than just having a username that isn't an email
           | address, and allow more than one account to use the same
           | email address?
        
             | ghusbands wrote:
             | I don't think people in general want to remember a username
             | for every site.
        
             | isbvhodnvemrwvn wrote:
             | Just return the usual "please confirm registration by
             | clicking a link in the email" - in the e-mail you just
             | notify the email owner that someone tried to create a new
             | account while another account was already registered for
             | this e-mail. This does not disclose anything to anyone
             | other than the owner of the e-mail.
        
           | hsbauauvhabzb wrote:
           | This. Risk assess whether user enumeration is actually bad,
           | the go fix it if you need to.
        
         | NavinF wrote:
         | IMO trying to stop user enumeration is a lost cause. People
         | with many email addresses and no password manager still need a
         | way to figure out which email/username they used on your site.
         | If they can't enumerate themselves, you end up with bad
         | retention or lots of support tickets.
        
           | thrwyoilarticle wrote:
           | Protecting PII is more important than your user retention.
        
             | NavinF wrote:
             | Too bad, roughly 0% of websites attempt to stop user
             | enumeration. The ones that try usually fail because they
             | don't do it consistently, but hey the ~0% of their user
             | base that is composed of HNers appreciate the effort. Also,
             | Santa Claus isn't real. When it rains, it pours.
        
       | robertwt7 wrote:
       | I still feel bad about the image of people towards PHP, but given
       | the amount of bad tutorials and packages that are outdated out
       | there I understand that most enterprise / startup wants to avoid
       | having to code in PHP again.
       | 
       | For the past couple of years I have been working with laravel in
       | a small company, and I really enjoyed it. The environment that it
       | provides honestly is amazing. Documentation is super easy to
       | read, laracast is amazing to bootstrap your knowledge in couple
       | of weeks, and community is huge that you can find almost anything
       | already built by them.
       | 
       | However its hard to find any big companies here that uses PHP,
       | jobs popping up is mostly python, java and c#, thus sadly I have
       | to leave php and learn java / python for the new big tech job
       | (also for my own future). Its not that java / python community is
       | bad, but I'll surely miss the laravel ecosystem.
        
         | charrondev wrote:
         | I'm a tech lead for Vanilla Forums (recently acquired by Higher
         | Logic). We have a few PHP positions open (remote or onsite).
         | The core product is open source
         | https://github.com/vanilla/vanilla If your looking to stick
         | with PHP you can check the open positions or reach out to my
         | contact info in my profile.
         | https://www.higherlogic.com/about/company/jobs/
        
         | paulddraper wrote:
         | > However its hard to find any big companies here that uses PHP
         | 
         | There's one pretty big one....Faceledgar? Peoplebook? Something
         | like that.
        
           | anaganisk wrote:
           | Dont rhey have their ownn PHP Frankenstein?
        
             | Sebb767 wrote:
             | It's literally called hack. Quite self-aware ;)
             | 
             | Though, recently PHP got quite a few features similar to
             | hack, like type annotations.
        
               | ransom1538 wrote:
               | Sure - fork something, call it something else, pretend it
               | is new. There are a ton of dollar signs in the FB source
               | code.
        
             | ransom1538 wrote:
             | Wordpress. I would google it. It is pretty big. Runs %60 of
             | the internet. (made that part up, but I bet I am close).
        
           | robertwt7 wrote:
           | Yeah, 1, and not many jobs opening here in AU lol
        
           | ummonk wrote:
           | It's nothing like vanilla PHP.
        
         | ransom1538 wrote:
         | If you are going from php to python just remove the dollar
         | signs $ and update how you treat strings. Those languages are
         | cousins. Honestly, within 2 weeks you wont look back. However,
         | Python2 vs Python3 makes php look like a bunch of geniuses and
         | you will miss php.net. The php8 team is really awesome and the
         | language is pushing forward. But if you need to be 'hip' yeah
         | learn python a 30 year old language from 1991 :)
        
         | [deleted]
        
       | treve wrote:
       | While the results are worrying, and not entirely surprising...
       | the search query made me wonder how many different queries the
       | author tried until getting a sufficiently bad result.
       | 
       | I wonder if the more obvious 'PHP MySQL Tutorial' would also
       | return this. I don't think that this changes the general point of
       | the article, there is a _ton_ of bad information out there. I did
       | the same with "Node.js JWT" and the results were even worse.
        
         | jamil7 wrote:
         | Node.js is more or less the new PHP so it makes sense.
        
       | jarym wrote:
       | I'm not surprised, plenty of tutorial writers (totally wrongly
       | imo) want to write the simplest example they can cobble together
       | under the guise of 'making it easy for people to understand'.
       | There's no excuse for avoiding SQL escaping and using
       | parameterised SQL and if it takes a bit longer for learners to
       | pick it up then that's just the cost of learning something new.
       | 
       | I really REALLY can't stand it.
        
       | Zababa wrote:
       | So what's the actual way of doing this in PHP?
        
         | tored wrote:
         | Using prepared statements, with the PDO database driver it
         | would be something like this                 $stmt =
         | $pdo->prepare('INSERT INTO user (email) VALUES(?)');
         | $stmt->execute([$email]);
         | 
         | For a full example you can look here, includes injection
         | example
         | 
         | https://3v4l.org/Fh2Pt
        
         | themodelplumber wrote:
         | That really depends on whether you are using raw PHP or a CMS,
         | CMF, or application framework. If it's any of the latter you
         | should check with the development team. In many cases there are
         | some great tools already provided for you by the frameworks, or
         | there are helpful conventions that make things more efficient.
         | 
         | If it's raw PHP I wouldn't want to compete with a lot of great
         | SO results out there, but you also have to take into account
         | circumstantial matters, like whether the given approach is
         | appropriate to the needed output or input you are dealing with.
         | 
         | For this reason I'd recommend arranging for some kind of code
         | review even if you ask online strangers for input.
        
         | acomjean wrote:
         | PDO. You write the query and insert the variables in a second
         | step. I've been doing php 10+ years and that's all we've been
         | using. Or if your framework has an orm you can use that.
         | 
         | There are pdo drivers for most popular databases
         | 
         | https://www.php.net/manual/en/book.pdo.php
         | 
         | Honestly it's my favorite way of accessing databases (compared
         | with Java Perl and python)
        
         | mr-ron wrote:
         | Last I looked, it was to leverage the
         | $mysqli->real_escape_string method.
        
         | hu3 wrote:
         | All top frameworks support parameter binding. Same for PHP
         | standard library like PDO or mysqli which also provide
         | parameter binding.
         | 
         | These eliminate SQL injection. But you have to use them and not
         | just concatenate user input to SQL queries.
        
       | [deleted]
        
       | technimad wrote:
       | I've fixed production bugs by removing code copied verbatim from
       | the PHP manual. It looked like the clueless previous developer
       | had copy pasted code from all over the place until the code sort
       | of did what it was supposed to do. The code snippets by itself
       | were ok, the composition created numerous bugs.
        
       | Cthulhu_ wrote:
       | This already was a problem ten, fifteen years ago, and I see it
       | hasn't changed. IIRC I wrote a blog post about it back when (I
       | get spurts of inspiration, then some time later I delete the
       | whole thing because I'm embarrassed about stuff I write,
       | including HN comments).
       | 
       | There was a big "grassroots" push some years ago about pusing
       | W3Schools docs out of the top Google results in favor of MDN; the
       | same should be done with bad PHP code / examples. Because in
       | practice, 90% of code is copy / pasted and adjusted.
       | 
       | There's just no big player behind PHP though, a party that wants
       | to professionalize the language and more importantly its
       | community. If there were, they would push for more authoritative
       | tutorials and documentation. As it stands, the PHP docs are fine
       | but are lacking information about SQL injection, and it's 10+
       | year old comments to that documentation that is often more
       | valuable than the docs itself.
       | 
       | PHP is still one of the top languages out there but it has so
       | much more potential.
        
       | gohbgl wrote:
       | Some time ago I found this video series on YouTube about how to
       | build a PHP application from scratch. Ten hours worth of XSS,
       | CSRF, SQL injection, badly coded authentication, you name it.
       | When confronted, the instructor said that he did not want to
       | confuse the beginners with all of that security stuff. I just
       | thought "ok" and moved on.
       | 
       | Now I went back to this guy's YouTube channel and saw that half a
       | year later he finally did upload a bonus episode on how to
       | mitigate SQL injections. One person in the comment section
       | actually thanked him for the much needed video because their site
       | was getting hacked. It is pretty hilarious to see this unfold but
       | I do feel bad for the ~10k people who watched his videos.
        
         | nyanpasu64 wrote:
         | XSS and SQL injection should be impossible by design, by using
         | proper libraries which treat HTML/SQL as structured formats,
         | and use this structure to properly embed text as text, rather
         | than allowing user input to be interpreted as surrounding
         | HTML/SQL constructs. (I suppose parameterized queries are "good
         | enough" even though they treat SQL as a string rather than an
         | AST, because the SQL engine _hopefully_ interpolates the text
         | /numbers/etc. _after_ parsing the query into an AST.)
        
           | NationalPark wrote:
           | This gets at the heart of why the problem is so widespread.
           | Beginners are the last people you can expect to figure out
           | how to install and use the "right" library. Watching someone
           | learn programming (from actual nothing) is very insightful -
           | they often don't stop and think because they have no
           | intuition. Rather they flail in the dark until they land on
           | something that almost works and use that as the kernel of
           | their solution. PHP used to have very poor flail-performance
           | and you still see it in things that are trickier to index and
           | refute like videos.
        
         | SilverRed wrote:
         | Maybe the solution here is to just have some kind of legal
         | penalty to losing user data due to incompetence. The problem
         | here is that self taught programmers are going out to the real
         | world and writing code that gets used to process sensitive info
         | without any senior developer guiding them or reviewing.
         | 
         | If there was a penalty to the business, they would stop getting
         | the bottom of the barrel programmer to work on their own. Yes
         | it would make it a little harder to enter the market but any
         | large business could still hire juniors and review their code
         | properly.
         | 
         | In most other industries, you are responsible for your work.
         | Usually you even need a formal certification first.
        
           | 908B64B197 wrote:
           | > In most other industries, you are responsible for your
           | work. Usually you even need a formal certification first.
           | 
           | That would go against the "Everyone can Code" trend and be
           | perceived as gatekeeping.
        
           | sk7 wrote:
           | It's handled by the GDPR. Companies are forced to report a
           | leak to the authorities and the max. penalties are very high.
        
           | toastal wrote:
           | Conceptually how is this different than someone building a
           | staircase it their house with tools, lumber, and no interest
           | in accessibility and building codes?
        
             | SilverRed wrote:
             | This analogy still works. The staircase is not public, its
             | in your house. Which would map to running on your local
             | computer or local network.
             | 
             | As soon as you turn your house in to a public venue (put
             | your code in use for the public) you now have to worry
             | about accessibility and safety. If that stair case
             | collapses because of your dodgy building, you are liable.
             | But you are free to fall off your own staircase in your own
             | house.
             | 
             | So people are free to run whatever they want on their
             | computer. But once you start taking user data, you now have
             | legal responsibility. User data is hazardous waste that
             | needs ultimate care.
        
       | ulzeraj wrote:
       | Not related to this specific case or coding but about bad
       | practices in documentation in general in my previous job I had
       | huge headaches with some bad practices described in Microsoft's
       | Active Directory training material. That company forest domain
       | ended in .local because the AD admin was a MS MVP through and
       | through.
       | 
       | https://en.wikipedia.org/wiki/.local#Microsoft_recommendatio...
       | 
       | However retail stores were almost entirely composed of Linux
       | machines except for the manager's desktop. The corporate software
       | used in these Linux machines would always pull samba which in
       | turn pulled avahi. As soon as the software was installed post
       | imaging because of licensing requirements connectivity with
       | central servers was interrupted and the person installing it
       | (which was always a different person because the stores were
       | spread through the country) will often scratch their head,
       | specially those who don't bother to read notes.
        
       | mkl95 wrote:
       | I'm not a fan of PHP, but I remember it having some lightweight,
       | built in API to secure SQL queries. On the other hand, using a
       | good ORM with a mature web framework removes most common
       | vulnerabilities, and you don't have to worry as much about your
       | junior peers creating security holes.
        
         | hannob wrote:
         | PDO is pretty straightforward:
         | 
         | $s = $dbc->prepare("SELECT * FROM table WHERE field = :foo");
         | $s->bindValue(':foo', $_GET['foo']); $r = $s->execute();
         | 
         | But all of that of course doesn't help if people don't use it.
        
       | hooby wrote:
       | > You can't just blindly copy paste code from the internet and
       | expect it to be perfectly safe and sound.
       | 
       | What a surprise!
        
       | lr4444lr wrote:
       | Wow! That low a ratio?
        
         | fencepost wrote:
         | Beat me to it. I'm astonished it's that low, and I suspect that
         | if you look at books on PHP programming that are currently or
         | recently "in print" you'll find a lot of examples in early
         | chapters that do exactly the same thing.
        
         | Cloudef wrote:
         | My surprise too. When swift (the language) was still young and
         | I had to use it. I looked for some ready made sql wrapper, and
         | oh boy it had the standard sql injection vulnerabilities
         | because it did not use prepared statements. I ended up writing
         | my own thing. Guess the memory safe language could not help you
         | here :)
        
       | spicyramen wrote:
       | I worked with different teams at Google that build tutorials. The
       | hard part of this is not creating them, but maintenance. Most of
       | the teams move to a new product and there is no incentive in
       | updating them, specially for security. Most of the updates have
       | to do with versioning and compatibility for multiple components
       | such as Db versions/GKE, SdK etc.
        
       | cletus wrote:
       | Should tutorials be expected to teach people sufficient security?
       | Should code snippets be production-ready to put on the Internet
       | for the general public? I tend to think not. Is this just me?
       | 
       | So here's a partial list of issues you'd need to deal with:
       | 
       | - sanitizing input
       | 
       | - Escaping output
       | 
       | - SQL injection
       | 
       | - HTML injection
       | 
       | - XSS
       | 
       | - CSRF
       | 
       | - CORS
       | 
       | - Clickjacking
       | 
       | - DDoS and other resource exhaustion attacks
       | 
       | - Various timing attacks (eg password hashing)
       | 
       | - How to store passwords
       | 
       | - Depending on language, buffer overflows
       | 
       | That's... a lot. You can take this even further: you should
       | assume you're going to get compromised at some point. What are
       | you going to do to detect a breach? Or an active attempt to find
       | a breach? What's your strategy for handling a breach?
       | 
       | Here's an analogy: we can tell you how to treat Poison Ivy
       | without having to add a disclaimer that you're not qualified to
       | be an attending dermatologist.
        
         | nextaccountic wrote:
         | Things should be secure by default. With a basic query builder
         | you can't ever have a SQL injection bug, not even by mistake,
         | not even if someone maliciously tell you to do something wrong.
         | This should be the default for tutorials.
         | 
         | The tutorials don't even need to talk about security: just tech
         | secure by default APIs. If the programmer later needs more
         | flexibility (which should be understood as an advanced topic),
         | they ought to learn that you must sanitize user input in raw
         | queries.
        
         | cerved wrote:
         | It shouldn't take anti pattern shortcuts that open up
         | vulnerabilities, especially without adding a disclaimer.
        
         | crazygringo wrote:
         | You're making the perfect into the enemy of the good.
         | 
         | Should every tutorial be an entire 200-page course on all web
         | security practices? Of course not.
         | 
         | But should every tutorial that inserts a user-provided value
         | into a SQL statement ensure it's escaped? _Of course_. There 's
         | essentially literally never a situation where you shouldn't do
         | that. It's not just to be "production-ready" -- it's so basic
         | as just to make sure the query will still even _parse_ if the
         | user includes a _quote character_ in their input.
         | 
         | So why on earth are you defending this mistake?
        
           | rlayton2 wrote:
           | I'd go further and say it's easier to teach prepared queries
           | than string building (or at least equally difficult).
           | 
           | That might not be true for other security issues but I think
           | tutorial writers should be fine saying "here is a bit of
           | magic that fixes a problem called csrf. We won't cover that
           | in this course but leave this in here"
        
         | tester34 wrote:
         | >- sanitizing input
         | 
         | Oh, that unicorn that everybody takes about, yet nobody does
         | anything with it
         | 
         | So, how do you sanitize input?
         | 
         | you save in database escaped strings?
         | 
         | allow only "english" letters?
         | 
         | >- HTML injection
         | 
         | >- XSS
         | 
         | those two belong to
         | 
         | >- Escaping output
         | 
         | don't they?
         | 
         | >- Various timing attacks (eg password hashing)
         | 
         | >- How to store passwords
         | 
         | just use state of art auth/login handling libs?
         | 
         | >- DDoS and other resource exhaustion attacks
         | 
         | I don't think I'd add it there, isn't it handled by firewall /
         | infrastructure than app directly?
        
           | giu wrote:
           | > I don't think I'd add it there, isn't it handled by
           | firewall / infrastructure than app directly?
           | 
           | Although most DDoS attacks happen on the layers 3, 4, and 6
           | of the OSI model, your application still has to be hardened
           | against resource exhaustion and other DDoS attacks.
           | 
           | For example, if you have a REST endpoint that starts a
           | complex query which might return a large result given some
           | specific query parameters (e.g. your limit parameter is not
           | bound, so I can set limit=1000000), running 10000 requests
           | against it from different hosts (malicious or not) may bring
           | down your database server.
        
             | tester34 wrote:
             | You're right, thanks for reminding
        
         | bogwog wrote:
         | I agree with you. Back when I was a little kid learning to code
         | on the internet by myself, tutorials that I could easily
         | understand and quickly use to build things were important.
         | Because without those, I would have probably given up.
         | 
         | Those stupidly bad PHP tutorials that show you how to
         | concatenate a URL parameter to an SQL string were easy to
         | understand, and taught me about everything from writing
         | PHP/SQL, setting up a MySQL server, networking/opening ports,
         | designing database tables, designing an application, and much
         | more. The motivation I got from learning so much in so little
         | time led me to keep learning new things, including learning and
         | understanding why all that code I wrote when I was younger was
         | so bad.
         | 
         | If those shitty tutorials get copy and pasted into production
         | codebases, that's the company's fault for hiring a lazy/bad
         | developer, and for not catching the vulnerability.
        
       | matei88 wrote:
       | this is the PHP bashing thread for this week, enoy ;-)
        
       | kevincox wrote:
       | Google has an internal "style guide" that forbids any new
       | projects in PHP because they consider it impossible to write
       | secure applications in this language.
       | 
       | Of course the end result is probably they they have less PHP
       | expertise than you might hope. But these are really sad failures.
        
       | closeparen wrote:
       | I work on a major mobile application. We have rigorous interviews
       | and pay well. We use a much trendier stack than PHP. Still, the
       | number of my colleagues who can fathom that a request to our
       | public API might come from elsewhere than our first-party client
       | is... maybe one in a hundred.
       | 
       | Don't think this is just a PHP problem. All across the industry,
       | people think of the OWASP Top 10 as some hyper-nerd shit that
       | they don't have to care about, and are indignant that you'd even
       | mention it in design review.
        
       | doomleika wrote:
       | In my work, when I raised the design/code will expose serious
       | security implications, Architects/seniors looked at me like I am
       | a freak.
       | 
       | Same person always bragged how important is security and how
       | he/she is good at it. The management ate it. It's only when real
       | money are lost and the C-Suit want heads to roll then maybe Mid-
       | Low management will start take my words seriously...for a few
       | months.
       | 
       | There's just no easy way to verify the security of an app. Being
       | security aware and try to make the code secure will cost extra
       | time and make you a diva.
       | 
       | Right now I simply refuse allow those madness infect my code and
       | create clear paper trails, so I can keep my code/job rather sane
       | in the asylum.
        
       | l0b0 wrote:
       | I googled for `php mysql email register`. This returns tutorials,
       | how-tos, code snippets. Most results include flawed DB
       | statements.
       | 
       | Nothing to do with Google itself, Google being vulnerable to SQL
       | injection, or completely arbitrary websites being vulnerable.
        
         | phil294 wrote:
         | Oh I see what you mean, I rephrased the title a bit. It is
         | pretty specific after all
        
       | haolez wrote:
       | Programming in PHP using GitHub's Copilot must be exciting :)
        
         | ineedasername wrote:
         | In a few years we might regard it the same way as MS Office's
         | Clippy:
         | 
         | "It looks like you're trying to create a web app front end! Do
         | you need assistance with A) Implementing a dark pattern or B)
         | Avoiding the use of dark patterns?"
        
           | hermitdev wrote:
           | It makes one wonder: was copilot development started before
           | or after MS's acquisition?
        
           | why_only_15 wrote:
           | so true
        
         | CR007 wrote:
         | I feel that it actually understand what I'm doing. Is very
         | wicked how sometimes copilot nails a line or an entire block
         | totally in my context and writing style.
         | 
         | Scary stuff.
        
       | 0x0nyandesu wrote:
       | Generally speaking lesson 1 on building queries skips over
       | injections and only after the basic premise is explained do you
       | go into the details on how to be secure in lesson 2.
        
         | nneonneo wrote:
         | And tons of people skip lesson 2 thinking they've got it, go on
         | to make websites which seem to work, and then get pwned by
         | script kiddies down the road.
         | 
         | SQL injections are incredibly easy to test for, and exploit
         | scripts like SQLmap make it trivial to dump an entire database
         | server's contents with a single point of entry (and, if you're
         | unlucky, tamper with or even delete your databases). There's
         | practically no excuse for not covering it in a tutorial, or at
         | least giving some forewarning about it.
        
       | kilodeca wrote:
       | What should I say? Why those people think they need to write a
       | tutorial? After all those "AI" GS can't figure out which one is
       | good content and which one is trying to sell. Web has become a
       | sad place. Where morons can have a voice and which are presented
       | to others as good "content". Much of this would not continue to
       | exist if there was no money to make.
        
       | jart wrote:
       | The worst thing about PHP is that the majority of people who
       | visit my website are script kiddies from the third world pen
       | testing for PHP vulnerabilities.
        
         | mcintyre1994 wrote:
         | I get this too. I doubt it's that active though at least in my
         | case - I think hosting provider IP ranges are well known and
         | bots just constantly throw known vulnerabilities in common web
         | software at them to see what they can break into and backdoor.
        
       | tored wrote:
       | Great article. How should the community fix this problem with bad
       | and dangerous tutorials?
       | 
       | I don't think fixing Google's index is enough and probably not
       | you something we can rely on.(there are other search engines)
       | 
       | One problem could be that official PHP documentation only
       | includes examples for using a specific function, not an entire
       | use case from start to end. That would mean that examples would
       | also include lots of HTML, CSS, SQL and JavaScript. But then of
       | course it will no longer be a PHP documentation.
       | 
       | Writing correct up to date examples is very time consuming. Sites
       | like w3schools tries to do this, w3schools was bad in the past
       | but has become better, but it is also a commercial site so
       | nothing you don't want to contribute to with your own examples.
       | At the same time it is understandable that w3schools wants
       | something in return.
       | 
       | Another idea could be to contact site owners of these tutorials,
       | but then they probably want the correct fix. This can also be
       | time consuming.
       | 
       | Maybe an index of approved tutorials voted by the community and
       | then make sure this index gets high on Google ranking.
        
         | CiPHPerCoder wrote:
         | > Great article. How should the community fix this problem with
         | bad and dangerous tutorials?
         | 
         | By updating all of the old, insecure tutorials to redirect
         | towards secure answers instead.
         | 
         | Details here: https://paragonie.com/blog/2018/01/our-ambitious-
         | plan-make-i...
        
       | thefr0g wrote:
       | I'm pretty sure that there is still quite some bad code out there
       | that I posted to code-snippet websites when I was ~13 :/
       | 
       | So here's some advice I wish someone had given me back then:
       | 
       | Please try to at least read and understand OWASP top ten security
       | risks1 before writing applications that anyone actually uses.
       | Also please be aware that you can write insecure code in any
       | general purpose language. Most of the bad PHP code is around
       | because it was a popular language with hobbyists, similiar to
       | Javascript and Python today. Languages might be better (or worse)
       | in certain aspects but they still can't protect you from bugs in
       | your programs logic. Only diligent planning, understanding of
       | best practises and proper communication can help prevent those.
       | 
       | 1 https://owasp.org/www-project-top-ten/
        
       | iratewizard wrote:
       | Amit Singhal's method for maintaining Google's search business
       | unit was its success. Hopefully they realize the ML pipe dream is
       | a failure sooner than later.
        
         | iamstupidsimple wrote:
         | Care to elaborate on how Amit ran things differently?
        
           | iratewizard wrote:
           | Search rules were written by hand and not left to an
           | automatic process
        
             | crummy wrote:
             | were there less SQL injection vulnerabilities in the search
             | results back then?
        
               | iratewizard wrote:
               | Yes. Search as a whole was a far superior level of
               | quality. Today's Google search is as bad as Yahoo's
               | search in the early 00s.
        
         | ma2rten wrote:
         | This doesn't seem like something that could be fixed by using a
         | rule based approach, because it would require actually
         | understanding the subject matter.
        
       | neycoda wrote:
       | Good job, you found how the real world works. I'm sure there's no
       | code from any other language with vulnerabilities in it posted
       | online.
        
       | villgax wrote:
       | CoPilot but for detecting horrible code & generating regexes.
        
       | dvh wrote:
       | People have been warning us about sql injection for more than 2
       | decades, it finally start to pay off and then someone in js
       | invents div.innerHTML=`template aka glued strings` and everybody
       | jumps on it like it's no big deal.
        
         | opheliate wrote:
         | I'm not sure what point you're making here? IMO, while JS is
         | certainly more bloated than ever as a result, the current
         | popularity of frameworks like React, Vue, etc. makes it much
         | less likely that a beginner will introduce XSS than 10 years
         | ago.
        
         | paulddraper wrote:
         | The existence of `innerHtml` or `eval()` or `exec()` etc isn't
         | the problem itself.
         | 
         | After all, you could implement the exact same thing in
         | userspace.
         | 
         | But yes, anytime you have one program writing instructions for
         | the other, you wind up with a risk for bad composition of those
         | instructions.
         | 
         | Fortunately, frameworks and libraries (for SQL and HTML) are
         | increasingly successful at adoption and removing the risk of
         | the programmer using low-level unsafe primitives.
        
       | ineedasername wrote:
       | I don't blame google for this. I blame crappy tutorials that
       | either gloss over important details or are written by people who
       | don't know them in the first place. If Google could develop a
       | search algorithm that selected results for quality code, they'd
       | have an entirely separate product they could sell, perhaps as
       | part of an "AI Cloud" assisted programming environment.
        
         | nwellnhof wrote:
         | I'm pretty sure all these crappy tutorials only appear in the
         | top results because of shady SEO tricks. Do you really think
         | these are "authority" sites which Google claims to rank
         | highest? It's a sad fact that Google is still unable to stop
         | black-hat SEO, so they are at least partly to blame.
        
       | techbio wrote:
       | > Several of these results were, simply put, SEO-optimized
       | baloney.
       | 
       | My experience in the past couple of years as well, and not just
       | for PHP. I wonder if anyone has looked into tutorial results with
       | and without privacy controls to see if the quality is
       | meaningfully different.
        
       | [deleted]
        
       | tester756 wrote:
       | People don't use ORMs there?
       | 
       | Those are great tools and you can always use raw sql in
       | exceptional cases
        
         | GuB-42 wrote:
         | Use an ORM if you want but parameterized queries work just as
         | well preventing SQL injections
         | 
         | ORMs are a heavyweight, something that is fundamental in your
         | design. Parameterized queries are just regular SQL queries, but
         | safer.
        
           | AtNightWeCode wrote:
           | All queries must in the end be parameterized I would say.
           | Both for security and performance reasons.
        
       | bobmaxup wrote:
       | Is it just me or does every post on HN about PHP associated with
       | some negative idea turn into an unmoderated flame war?
        
         | bogwog wrote:
         | > associated with some negative idea
         | 
         | I've never seen a post on this site about PHP that was
         | associated with a positive idea.
        
       | pshc wrote:
       | 25 years of plentiful SQL injections and XSS, and 25 years of
       | posters rushing to PHP's defense with variants of "you could do
       | this in any language. _All_ languages are potentially insecure."
       | 
       | At a certain point it turns from tragedy to farce.
        
         | cheeze wrote:
         | Amazon literally _banned_ php for a reason.
         | 
         | Don't get me wrong, PHP taught me a ton about programming and
         | was a very important language, but yeah...
        
       | dusted wrote:
       | This just in: "Search results are the result of searching"
        
       | tomohawk wrote:
       | It would seem that misinformation such as this would be much more
       | in the wheelhouse of companies such as Google as they consider
       | censoring content and twiddling search results. They don't employ
       | virologists, or other experts, but they regularly label
       | information that they have little inside technical expertise on
       | as misinformation.
       | 
       | With so much obvious misinformation on stack exchange, why is
       | Google so blase about directing searchers to the site?
        
         | bronzeage wrote:
         | Because Google doesn't label misinformation because Google
         | really wants to, but because it's pushed by the government
         | under the guise of "just a private company".
         | 
         | It's supposed to be unconstitutional to have your government
         | censoring things, but covid-19 is the catch all excuse for any
         | authoritarian violation these days.
        
         | yourenotsmart wrote:
         | Imagine seeing this in your search results:
         | 
         |  _In order to show you the most relevant results, we have
         | omitted some entries that contain shitty code and bad security
         | practices. If you like [repeat the search with the omitted
         | results included]._
         | 
         | I can't imagine this being controversial. No one would complain
         | at all about being affected.
        
       | 1vuio0pswjnm7 wrote:
       | How do other search engine results compare in this regard.
        
       | stabbles wrote:
       | Looking forward to statistics on vulnerabilities in Copilot
       | suggestions
        
       | oknowitsserious wrote:
       | The first "correct" example uses the deprecated function
       | mysql_real_escape_string. Are we still not considering every form
       | of escaping insecure?
       | 
       | https://www.php.net/manual/en/function.mysql-real-escape-str...
        
       | nazrulmum10 wrote:
       | We will create a signup system that allows users to create a new
       | account to the system. Our first step is to create a HTML
       | registration form. The form is pretty simple to create. It only
       | asks for a name, email, password, and confirm password. Email
       | addresses will be unique for every user. Multiple accounts for
       | the same email address are not allowed.
        
       | paul_f wrote:
       | I don't have a problem with this. If I am trying to figure out
       | how to do something, I'd rather the help be focused on the thing,
       | and not confuse my by adding the mysqli_real_escape_string stuff.
       | Yes, I know about little bobby tables and all that. Same with
       | trying to see an example of a php form. I don't need the
       | csrftoken, I already know to do that. Yes, it might help a
       | novice, but don't make everything more complicated just for
       | beginners benefit
        
         | TeMPOraL wrote:
         | > _If I am trying to figure out how to do something, I 'd
         | rather the help be focused on the thing, and not confuse my by
         | adding the mysqli_real_escape_string stuff._
         | 
         | In this case, the help is fundamentally _wrong_. Other than
         | "what is an example of a dumb programming mistake?", there
         | aren't really questions to which a valid answer involves
         | concatenating arbitrary strings and executing the result as an
         | SQL command.
         | 
         | If your question is, "how do I execute an SQL command?", there
         | are many better examples to use. If the question is, "how do I
         | store user-supplied data in the database?", or "how do I query
         | using user-supplied values", then the answer should not give
         | you what amounts to an accidentally working hack.
         | 
         | SQL is _a language of its own_. It has a syntax and a grammar.
         | When generating SQL from PHP (or any other language), you 're
         | switching languages - there must be a translation step
         | involved. Any answer that doesn't bring this up explicitly is
         | just _wrong_.
        
         | mgkimsal wrote:
         | > "... and not confuse my by adding the
         | mysqli_real_escape_string stuff... CSRF token ...I already know
         | to do that..."
         | 
         | If you're already that good, how does seeing a CSRF token in an
         | answer actually impact you? Does it prevent you from
         | copy/pasting someone's "example" code?
        
       | ChuckMcM wrote:
       | Pretty much. The best way to insert supply chain exploits is to
       | embed them in a stack exchange answer to a beginner's question.
       | 
       | This isn't new, we've always had programmers who programmed by
       | "recipe" rather than first principles, and DRY paints that as a
       | feature, but it underlies a lot of pain and cost over the years.
       | 
       | To give some context, I inherited some kernel code when I worked
       | in the Systems Group at Sun Microsystems in the 80's that was
       | written by a mathematician who had become a programmer because
       | the money was in programming, not applied math. They had cut and
       | pasted code they didn't understand in order to achieve the result
       | they wanted out of the code they were "writing." When I inherited
       | it I read through it and found a couple of dozen ways the code
       | would panic the kernel[1]. Once fixing those obvious issues, it
       | became clear that the original owner of the code didn't really
       | understand what computation did. They had an idea, and
       | mathematically they could show that it was correct, but literally
       | no ability to express that algorithmically.
       | 
       | This is not a "new" problem but it is an important one that
       | managers of software engineers need to watch for.
       | 
       | [1] At the time the only difference between "kernel" programmers
       | and "application" programmers was that kernel programmers
       | recognized that unsafe code crashed the whole system, not just
       | the application. So they tended to be cultivated from paranoid
       | programmers.
        
         | kadoban wrote:
         | In PHP's case, Stack Exchange is not necessary to get SQL
         | injected tutorials. The official docs for _years_, if not
         | decades, included them. The docs for how you were supposed to
         | do SQL were just full of the antipattern of building queries by
         | string formatting and concatenation. I wouldn't be surprised if
         | some dark corner of the docs still had those available.
        
           | sellyme wrote:
           | > The docs for how you were supposed to do SQL were just full
           | of the antipattern of building queries by string formatting
           | and concatenation
           | 
           | This is still to this day the recommended way to construct a
           | "WHERE foo IN (a,b,c,...)" query in PHP. It's insane that
           | there's no way to pass an array of values into a
           | parameterised query for that use case.
        
             | yourenotsmart wrote:
             | If there's anything more annoying than the lingering bad
             | examples of PHP code online, it's people lying about what
             | PHP "recommends", like you do.
             | 
             | Common database drivers like PGSQL, MySQL, SQLite etc.
             | don't accept arrays of values for parameterized queries.
             | This is at C level, in their own client libraries, and
             | their own communication protocols.
             | 
             | This means there's nothing specific to PHP about this
             | problem. Many higher level libraries, including for PHP,
             | abstract over this problem and _do_ offer arrays by binding
             | per query.
             | 
             | So where are statements like yours coming from? Probably
             | just being eager to say something bad about PHP without
             | checking your facts too much.
        
               | sellyme wrote:
               | > This means there's nothing specific to PHP about this
               | problem.
               | 
               | I don't particularly care if languages that I am not
               | using have the same problem. It's up to people who use
               | those languages to make those criticisms.
               | 
               | > Many higher level libraries, including for PHP,
               | abstract over this problem and _do_ offer arrays by
               | binding per query.
               | 
               | Feel free to link an in-built PHP library that supports
               | this feature, that would be far more useful than just
               | obliquely suggesting that one exists.
        
               | Sander_Marechal wrote:
               | Doctrine DBAL: https://www.doctrine-
               | project.org/projects/doctrine-dbal/en/l...
        
               | TrispusAttucks wrote:
               | PDO + Prepared Statements
               | 
               | https://www.php.net/manual/en/pdo.prepared-statements.php
        
               | sellyme wrote:
               | PDO explicitly does not support the functionality being
               | discussed [1]:
               | 
               | > For example, you cannot bind multiple values to a
               | single parameter in the IN() clause of an SQL statement.
               | 
               | You're required to roll your own implementation,
               | something that thankfully isn't particularly difficult,
               | but unfortunately also seems to be enough of a barrier
               | that a lot of programmers don't bother.
               | 
               | [1]: https://www.php.net/manual/en/pdo.prepare.php
        
               | TrispusAttucks wrote:
               | To be fair prepared statements happen at the RDBMS. PDO
               | is just a library to interface with that. It can't
               | compile a query execution plan without knowing the table
               | and columns involved. So dynamic tables or columns as
               | variables doesn't make sense so you need to handle that
               | outside the prepared statement as it doesn't belong
               | there.
        
               | noduerme wrote:
               | Just out of curiosity, do you have a preferred mysql
               | library in nodejs? I wrote my own based on node-mysql
               | that does server-side prepared statements, but it does
               | them by compiling PREPARE and SET calls, not through a
               | lower-level language. It works for my needs, but it's not
               | really high-performance.
        
               | noduerme wrote:
               | I'm pretty sure PDO doesn't support escaping
               | WHERE/IN(...) because MySQL prepared statements don't
               | support it. In theory, PDO could support it in emulation
               | mode, but supporting something like that _only_ in
               | emulation would be an antipattern.
               | 
               | Similarly, PDO doesn't support dynamic table names.
               | You're expected to roll your own precisely because it
               | demands more situationally specific escaping than regular
               | parameters would, e.g. testing a list of allowed tables.
        
               | yourenotsmart wrote:
               | > would be an antipattern
               | 
               | I just want to point out the above is identical to saying
               | "is bad" without explaining why it's bad.
               | 
               | We can say it doesn't align with PDO's goal of being
               | barebones library that doesn't add non-native features on
               | top. But that's not what it does. It both omits many
               | native features on the various databases it supports, and
               | has non-native features like hydrating objects, for some
               | reason.
               | 
               | I'd say if a PHP library is at the same level as the C
               | library that backs it, that's a failure of design goals.
               | C is intentionally low-level (by modern standards) and
               | PHP is supposed to be high-level and consumable by people
               | with much less clue than C programmers.
               | 
               | It's unfortunate that you pretty much need a DBAL (like
               | Doctrine DBAL) on top of a DBAL (PDO) to get some of the
               | missing features. Like, say, escaping identifiers.
        
               | tored wrote:
               | It is hard to design good API:s that can last for
               | decades. Just look at Java, language that is backed by
               | large international corporations but the Java standard
               | library still sucks. PHP core is a much smaller community
               | driven project.
               | 
               | Key to great APIs is battle tested APIs in real world
               | projects, finetuned over years of experience. PHP has
               | that in the much larger general PHP community and to
               | access it you use composer.
               | 
               | We, the PHP community, must use all resources to compete
               | with other languages, it is unrealistic that the core PHP
               | team can implement a great API, for example we can look
               | at the filter API, it works but it is not great. PHP core
               | also has longer release cycles.
               | 
               | We need to push PHP developers to use composer more,
               | maybe the PHP docs should state that.
        
               | geon wrote:
               | Are you just talking about prepared statements? Mysqli
               | was released in 2004.
               | 
               | https://www.php.net/manual/en/mysqli.quickstart.prepared-
               | sta...
        
               | Akronymus wrote:
               | > Common database drivers like PGSQL, MySQL, SQLite etc.
               | don't accept arrays of values for parameterized queries.
               | 
               | One workaround to that is passing the array as a string
               | with some separator, deconstructing it into a temp table
               | and then using that table as a array when it is part of a
               | stored procedure.
        
               | matharmin wrote:
               | Even better, you can pass it in a JSON array, and use the
               | built-in JSON functionality to iterate through it. I
               | started doing this in SQLite, and it made some queries a
               | lot cleaner.
        
               | x0x0 wrote:
               | postgres does. PQexecParams, which executes a sql
               | statement with parameters, accepts oids that are array
               | types.
        
               | nh2 wrote:
               | Maybe I'm misunderstanding you, but it looks like it _is_
               | a PHP specific problem. Python does not have it.
               | 
               | Of course at C level parameterised queries ("prepared
               | statements") do not accept arrays. It would not make
               | sense for them to do.
               | 
               | This is because the placeholders can be substituted by
               | values of different types.
               | 
               | In typed programming languages, arrays have elements of
               | the same type.
               | 
               | For example in SQLite, you are supposed to call
               | `sqlite3_bind_int()`, `sqlite3_bind_text()` [1], once for
               | each query parameter.
               | 
               | In languages like PHP and Python, where arrays can carry
               | values of different types, their wrappers around the
               | SQLite C functions can do this function calling for each
               | value in the array. In Python, that is easy, the default,
               | and explained in the very beginning of the official
               | standard library's sqlite documentation [2]:
               | 
               | It states at the very beginning that query construction
               | by string construction is unsafe and must be avoided. It
               | immediately provides an example of how to safely call a
               | parameterised query with an array of values, using
               | `execute()` and `executemany()`.
               | 
               | PHP's standard library simply does not seem to have such
               | an `execute()` function that accepts an array [3], nor do
               | the official docs seem to contain any prose that could
               | explain how to use the library safely [4]. The only way
               | you can find out is by reading user-contributed comments
               | on some specific functions in the function reference.
               | 
               | So Python's standard library provides safe functions, and
               | immediately instructs the user how to use them. PHP's
               | does not. Unclear to me how one can conclude that this
               | isn't a PHP specific problem.
               | 
               | [1]: https://www.sqlite.org/c3ref/bind_blob.html
               | 
               | [2]: https://docs.python.org/3/library/sqlite3.html
               | 
               | [3]: https://www.php.net/manual/en/sqlite3.prepare.php
               | 
               | [4]: https://www.php.net/manual/en/class.sqlite3.php
        
               | dreyfan wrote:
               | You're misunderstanding You cannot do something like the
               | following:                  "WHERE status in (...?)" and
               | then ->execute($status_array)
               | 
               | But you can pass an array of parameters just fine (to
               | individually bound input placeholders). It depends on
               | which API you're using but it's of the format:
               | ->bind_param($types, ...$params); or ->execute($params);
        
               | ransom1538 wrote:
               | "Maybe I'm misunderstanding you, but it looks like it is
               | a PHP specific problem. Python does not have it."
               | 
               | You can concatenate a sql query just fine in Python
               | anyway you want. Adding a sql injection is just as easy
               | in Python, PHP, or lisp. Thus this is a choice. Nothing
               | to do with a language. Language bashing is gross and
               | spreads lies. And yes, you can bind an array of params in
               | PHP.
        
               | jve wrote:
               | Actually if you use .NET EF Core 2 FromSql or
               | ExecuteSqlCommand, you get parametrized queries from
               | string interpolation for free:
               | https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-
               | core...
        
               | yourenotsmart wrote:
               | > Maybe I'm misunderstanding you, but it looks like it is
               | a PHP specific problem. Python does not have it.
               | 
               | I don't know how carefully you read what I said, if you
               | misunderstood that this is a native library limitation (C
               | level) of the actual database clients, and that most of
               | the popular PHP libraries can bind arrays.
        
               | pjungwir wrote:
               | I see what you're saying, but maybe "array" is the wrong
               | term. Indeed you can't say `WHERE foo IN (?)` and pass
               | more than one parameter (or an array parameter) for the
               | single `?`. That's a limitation of the databases, not the
               | programming languages. But Postgres does have arrays, and
               | you can pass them as parameters. In fact that's how you
               | solve this problem. An equivalent to `foo IN (...)` is
               | `foo = ANY (array[...])`. So parameterized that would be
               | `foo = ANY (?)`. Instead of a bunch of parameters, you
               | have one parameter of array type. The parens here signify
               | a subquery, not a list of single-attribute tuples. In
               | fact using ANY is _more_ expressive, since you can say
               | `ANY (array[])` (but you might need to add a cast), but
               | you can 't say IN ()` (which is a syntax error).
               | 
               | Anyway your point is true that lots of languages' client
               | libraries and ORMs implement sql "parameters" by string
               | substitution. That's still better than having the
               | programmer do it himself, but not as good as it could be.
        
             | chipotle_coyote wrote:
             | > It's insane that there's no way to pass an array of
             | values into a parameterised query for that use case.
             | 
             | Maybe I'm misunderstanding you, but assuming $params is an
             | array in the following code, isn't this passing an array
             | into a parameterized query for that use case? (Edited to
             | note this is literally an example from the PHP
             | documentation, and not one of the squiffy comments.)
             | $place_holders = implode(',', array_fill(0, count($params),
             | '?'));         $sth = $dbh->prepare("SELECT id, name FROM
             | contacts WHERE id IN ($place_holders)");
             | $sth->execute($params);
             | 
             | In Python, using MySQLdb, I believe this would be something
             | like                   place_holders = ','.join(['%s'] *
             | len(params))         cursor.execute("DELETE FROM foo.bar
             | WHERE baz IN (%s)" % place_holders,
             | tuple(params))
             | 
             | Which, while more succinct, seems to be functionally
             | exactly the same thing. I don't see what PHP is doing
             | that's "worse" here offhand.
             | 
             | One could argue, "Yes, but a Python programmer would use
             | SQLAlchemy," which is probably true, but then you need to
             | let the PHP programmer use Doctrine or Eloquent.
        
               | sellyme wrote:
               | > isn't this passing an array into a parameterized query
               | for that use case?
               | 
               | Yes, I definitely should have been more specific there -
               | what I'm referring to is passing it as _one_ parameter,
               | instead of potentially dozens or hundreds. There 's a lot
               | of ways to do this safely, but none of them are elegant.
               | In the example presented here I believe it's the case
               | that you can't do the ->execute($params) _and_ bind some
               | parameters explicitly, so if you had something like  "
               | AND status = ? AND due_date < ?" at the end of your query
               | you have to chuck those variables into the same
               | nondescript array.
               | 
               | I prefer the looped bindParam() method for this reason,
               | but that has its own challenges. Firstly, it requires
               | some boilerplate (not a big deal, but no-one likes
               | writing boilerplate), and more pressingly it still has
               | the issue where it actually _is_ each individual element
               | of the array being parameterised, and spams the ever-
               | loving crap out of any debug outputs.
               | 
               | Obviously all of these issues are way less concerning
               | than SQL injection vulnerabilities, but life would be so
               | much easier if you could just do $sth->bindParam(1,
               | $params); on a single question mark, and have that show
               | up logically in things like debugDumpParams(). Even if
               | you had to use special syntax to indicate when a
               | parameter is expected to be an array, that would be a
               | huge improvement.
               | 
               | I'm sure there's technical reasons why this is more
               | difficult to implement than it would initially seem, but
               | I've seen enough string-concatenated queries on
               | StackOverflow from people who just give up on getting the
               | parameterisation to play nicely that I believe it's worth
               | the effort to make doing things right as frictionless as
               | possible.
        
               | ipaddr wrote:
               | How often are you passing dozens or hundreds of
               | parameters to a single sql statement? Maybe there is a
               | better way to structure things.
        
               | sellyme wrote:
               | How often am _I_ doing it? Not very. But when there 's a
               | WHERE foo IN(a,b,c,...) query that has an arbitrary list
               | as input? Could be any number of parameters in there
               | (although I think most SQL drivers start complaining in
               | the early quadruple digits).
        
             | remram wrote:
             | Can't you at least build a "IN (?, ?, ?)" string, if you're
             | going to build a string dynamically?
        
               | sellyme wrote:
               | Not only is it the case that you _can_ do that, it 's the
               | case that you _should_ do that. Which leads to the
               | question of why it 's not in-built functionality. Making
               | secure code harder to write than insecure code is a great
               | way to ensure that lots of people write insecure code.
        
               | adzm wrote:
               | You end up writing code with 16 ? parameters and filling
               | the empty ones with -1 or something ;)
        
               | kijin wrote:
               | No, you use array_fill() and implode() to generate
               | exactly as many placeholders as you need.
        
             | path411 wrote:
             | What do you mean? You can Google php parameterize query and
             | get atleast 2 different methods of doing this. You
             | shouldn't ever touch string concat in any language when
             | doing queries
        
               | sellyme wrote:
               | > You can Google php parameterize query and get atleast 2
               | different methods of doing this
               | 
               | There's no way of doing this with a single parameter. You
               | need to parameterise every single individual item in the
               | IN clause to do it that way, which is a horrific solution
               | when it's of a completely unknown length.
               | 
               | Still better than string concatenation in many cases, but
               | that the language has no in-built way of doing it is one
               | of the many reasons PHP code is so often vulnerable to
               | injection attacks. There's so much friction to writing
               | secure code.
        
             | hattmall wrote:
             | That's what the docs should show because that's how it
             | works. The docs should give you the streamlined barebones
             | implementation. It's trivial to write your own function to
             | use parameterized queries and add in all the type checking
             | etc you need. It's only a few lines of code.
        
               | sellyme wrote:
               | > It's trivial to write your own function to use
               | parameterized queries and add in all the type checking
               | etc you need. It's only a few lines of code.
               | 
               | It's fairly trivial to do this, but now you're
               | potentially adding _thousands_ of parameters per query in
               | circumstances where the contents of the IN() are variable
               | in count. This is not ideal for a number of reasons.
               | 
               | Additionally, a language should be designed such that the
               | easiest possible way to do something is at least
               | _moderately_ secure. If you need to attach some
               | boilerplate code on top of the standard libraries every
               | single time you use them for it to be safe, then there is
               | no reason for that boilerplate to not be in the standard
               | libraries.
        
             | ec109685 wrote:
             | Better is to concatenate question marks and then pass the
             | params as an array.
        
               | tored wrote:
               | Yes, something like this                 $user_ids = [1,
               | 6, 46, 3, 17];       $count = count($user_ids);       $in
               | = '(' . implode(', ', array_fill(0, $count, '?')) . ')';
               | $sql = "SELECT user_id, email FROM user WHERE user_id IN
               | {$in}";       $stmt = $pdo->prepare($sql);
               | $stmt->execute($user_ids);
               | var_dump($stmt->fetchAll());
        
               | throwawayboise wrote:
               | I realize this is just an example but if you're in
               | control of all the values then there's nothing unsafe
               | about concatenating them into a query. The problem comes
               | with values that are submitted via a web form, API, or
               | some other external, untrusted source.
        
               | wk_end wrote:
               | This is true but it's still better to default to the Safe
               | Thing, as long as there isn't a good reason not to. How
               | long until those values you know you control carelessly
               | get turned into values you don't control somewhere along
               | the way?
        
               | sumtechguy wrote:
               | I used to mess with other devs by injecting bits of code
               | from other sources (when blink in html worked it was one
               | of my favorite ones). The correct way is to bind your
               | params and do not trust that the data you got from some
               | other system is 'OK'. What may be fine in one system
               | could be an escape code in another.
               | 
               | I speculate that the reason this is such an issue is
               | because the interface at the ODBC level is basically
               | security wise broken. It works 'OK' for getting/putting
               | the data but it has 2 modes of execution. One of those
               | paths is not great for security, the other has a usage
               | issue. 'Binding' can be a real pain as it takes at least
               | 1 call per variable parameter. Then managing the buffers
               | correctly. So just building up the strings is an easy way
               | to skip a lot of steps. So many take it. But that path
               | leads to security vulins.
        
               | sellyme wrote:
               | Yep. Fortunately a lot of the use cases of IN() _are_
               | with controlled values - often IDs obtained from a
               | previous query - so string concatenation is safe (and a
               | lot less hassle than the alternatives).
               | 
               |  _Un_ fortunately that gets people into the habit of
               | using string concatenation, which is not a great habit to
               | have.
        
               | tored wrote:
               | Not sure if I follow you completely, but in my example
               | $user_ids could come from an external source because I'm
               | only concatenating question marks (?), then bind
               | $user_ids with execute and that is safe. What I also
               | always do before passing the $user_ids to execute if it
               | comes from an external source is to validate that
               | everyone of them is an integer with filter_var.
        
             | fouc wrote:
             | Probably good idea to use a framework or a database library
             | in PHP. Laravel has Model::whereIn('foo', [a, b, c, ...])
        
               | billisonline wrote:
               | I'm shocked no one else gave this answer earlier in the
               | thread. If you're using PDO directly in 2021, you're
               | absolutely doing it wrong. You don't need to use all of
               | Laravel, or even all of Eloquent for that matter. If you
               | don't want to depend on a framework or use an ORM, you
               | can use "illuminate/database"
               | (https://packagist.org/packages/illuminate/database) for
               | a secure wrapper around PDO. No need to reinvent the
               | wheel.
        
               | sellyme wrote:
               | > If you're using PDO directly in 2021, you're absolutely
               | doing it wrong.
               | 
               | This is somewhat the point. If using the language's
               | standard libraries is "absolutely doing it wrong", that's
               | an indictment of the language.
        
               | BoxOfRain wrote:
               | >This is somewhat the point. If using the language's
               | standard libraries is "absolutely doing it wrong", that's
               | an indictment of the language.
               | 
               | Exactly, all languages have footguns but some have a lot
               | more than others. You don't hear for example Java
               | developers bitching about JDBC to anywhere close to the
               | extent PHP developers bitch about the various common
               | approaches to database connections.
        
               | billisonline wrote:
               | > If using the language's standard libraries is
               | "absolutely doing it wrong"
               | 
               | You are being deliberately obtuse. Other comments in this
               | thread offer correct examples of using PDO to avoid SQL
               | injection. I didn't mean it was _impossible_ to write
               | safe database code using the standard library--obviously,
               | PHP is a Turing-complete language, it can be done!--I
               | just meant it's awkward, and verbose, and developers are
               | unlikely to do it consistently throughout an application.
               | Hence this type of concern is best abstracted into a
               | library.
               | 
               | To your point about "indicting a language," most
               | languages have footguns like this. The worst you can say
               | about PHP is that the documentation should do more to
               | discourage new users from working with PDO directly. (And
               | I mean the official documentation--the language
               | maintainers can't be held responsible for the kind of
               | unofficial tutorials the article complains about.) But
               | regardless of what the official docs say, most PHP
               | development today is done using frameworks like Laravel,
               | Symfony, and Zend framework that do not suffer from SQL
               | injection issues.
        
           | nkozyra wrote:
           | > I wouldn't be surprised if some dark corner of the docs
           | still had those available.
           | 
           | It's not exactly a dark corner, but at least there's red
           | boxes all over the place.
           | 
           | Back in the 5.x early days it had disclaimers but clearly not
           | enough to discourage people from keeping unsafe code in
           | place.
        
           | [deleted]
        
           | tyingq wrote:
           | To be fair to PHP, a lot of other languages had bad examples
           | around as well. Pretty much every language has a way to do
           | string interpolation on untrusted input and pass it to to a
           | database .
        
             | flomo wrote:
             | Java and C# 1.0 examples (mostly) did not have anything
             | like this, because they shipped with a database layer
             | (JDBC/ADO.net) and not just a raw driver. PHP instead spent
             | many years fucking around with hacks like addslashes() and
             | etc before addressing the root issue.
        
               | tyingq wrote:
               | Java ones were pretty easy for me to find...
               | String insertQuery = "insert into student values('" +
               | studentNo + "','" + studentName +"','"+ studentAddress +
               | "','"+studentAge+"')";        int result =
               | statement.executeUpdate(insertQuery);
               | 
               | https://www.onlinetutorialspoint.com/jdbc/jdbc-insert-
               | progra...
               | 
               | Result #5 on Google for: jdbc insert program example
               | 
               | And this one, #1 for "jdbc example variable where" on
               | Google:                 String query = "select
               | LastModified from CacheTable where " + "
               | URL.equals(url)";
               | 
               | https://stackoverflow.com/questions/2608376/specifying-a-
               | var...
        
               | [deleted]
        
             | kaba0 wrote:
             | > Pretty much every language has a way to do string
             | interpolation on untrusted input and pass it to to a
             | database
             | 
             | Otherwise they would not be Turing complete.. but
             | defaults/easiest route does matter very much in this case.
        
               | tyingq wrote:
               | I don't mean going through hoops. String interpolation is
               | easy in most languages. See
               | https://news.ycombinator.com/item?id=27958651 for
               | example.
        
               | SilverRed wrote:
               | And the default docs and tutorials. If you look at Ruby
               | on Rails. The way every tutorial will show makes it
               | impossible to get an sql injection. Then as you gain more
               | skill you will eventually find the function that lets you
               | run a string query but no guide or tutorial shows you
               | this so it is less likely you will use it without
               | understanding.
        
               | codedokode wrote:
               | Ruby and Rails tutorial is not a Ruby tutorial. The
               | ancestor comment talked about language tutorials, not
               | framework tutorials.
        
               | kaba0 wrote:
               | JDBC does have an option to pass parameters without doing
               | string interpolation and I would not consider it a
               | framework.
        
           | nine_k wrote:
           | "Else you are not getting the authentic php4 experience!" /s
           | 
           | PHP has been in a poor shape for many, many years. It started
           | shaping up in last rather few years, and there is a large
           | backlog to tackle, colossal if you include all the numerous
           | tutorials and Q&As from getting copy-pasted since 2000.
        
             | mschuster91 wrote:
             | The language never was the problem, not since PHP 5.1 at
             | least (which introduced PDO) and that is 16 years ago.
             | 
             | The problem always was the ecosystem that took _decades_ to
             | update and the fact that Google 's search is algorithm-
             | ranked and not supposed to be curated by humans, which
             | would have kicked out at least the most horribly insecure
             | stuff.
        
               | kadoban wrote:
               | Long after PDO was a thing, the official docs still
               | included the old insecure jank.
               | 
               | Is your contention that Google is to blame for indexing
               | them?
        
               | jeltz wrote:
               | I disagree. As someone who has used PDO a lot it still
               | makes it unnecessarily hard to use parametrized queries
               | compared to the libraries available in most other
               | languages, even C (at least for PostgreSQL). The pgsql
               | library for PHP is also pretty good, better than PDO.
        
               | tored wrote:
               | You can do parametrized queries in two lines of code with
               | PDO. I wouldn't classify that as "unnecessarily hard",
               | sure you could split in half to one line of code, for
               | that you need to write your own wrapper function.
        
               | habibur wrote:
               | But, you need to write the hard thing once. In a 10 line
               | wrapper function and then call that function from
               | everywhere.
               | 
               | sql_query($db,$sql,$params);
               | 
               | Problem solved.
               | 
               | I guess every PHP developer writes a bunch of these
               | wrapper functions for common sql tasks before he starts
               | his work.
        
               | arp242 wrote:
               | This is the most PHP comment in this thread yet; "yeah, I
               | know this very basic API is inadequate and broken, but
               | you can just write a wrapper, everyone is writing the
               | same wrappers anyway!"
               | 
               | Is PHP supposed to be a high-level language or what?
               | Hell, I'd consider it a very flimsy excuse even in C (in
               | most contexts anyway).
        
               | tored wrote:
               | Already answered in this thread. There is nothing hard or
               | wrong about the API. It is just lots of misunderstandings
               | and commentators not looking things up before commenting.
               | $stmt = $pdo->prepare('INSERT INTO user (email)
               | VALUES(?)');       $stmt->execute([$email]);
               | 
               | https://news.ycombinator.com/item?id=27954454
        
               | porker wrote:
               | Or installs Doctrine DBAL which handles it all for you.
               | 
               | At the cost of some performance, but the ease-of-use with
               | a highly-tested and relied-upon library normally
               | outweighs that.
        
               | Cthulhu_ wrote:
               | Yup, make it work (securely!) before making it fast; you
               | can't diagnose performance if your code isn't working as
               | it should in the first place (and SQL injection safety is
               | a non-functional requirement; you can't consider code
               | working if there's that weakness). In practice, bad
               | database design or access (like the n+1 problem) will
               | weigh heavier than the overhead added by a library like
               | Doctrine. Or, it should, if Doctrine adds THAT much
               | overhead it's a problem.
        
               | acdha wrote:
               | PDO was slower, the interface - critically - tons of
               | examples still either made prepared statements a side
               | note or actively encouraged string concatenation, and it
               | preserved the flaws of the previous interfaces like
               | ignoring errors and warnings (silent is no longer the
               | default in PHP 8).
               | 
               | I no longer consider myself part of the PHP community
               | (started around 1999), in part due to the low priority
               | reliability and security had. It was exhausting having to
               | vet code so frequently because even experienced
               | developers forgot all of the rakes in the grass.
        
               | toast0 wrote:
               | I mean, PDO wasn't great (in contrast to perl's DBI which
               | was pretty good and offered parameterized queries even if
               | the underlying interface didn't), so it made sense to
               | prefer mysql_query. But mysql_query didn't do parameters,
               | and mysqli did, but only it you ran a new enough version
               | of MySQL.
               | 
               | I wouldn't call it a language failure per se, but a
               | problem with the libraries that shipped with the
               | language. That distinction may not make a difference.
               | 
               | Bad examples that stuck around don't help either, of
               | course.
        
           | mike_d wrote:
           | > The official docs for _years_, if not decades, included
           | them. The docs for how you were supposed to do SQL were just
           | full of the antipattern of building queries by string
           | formatting and concatenation.
           | 
           | PHP directly exposed the libmysqlclient C library. Any
           | language that provides the ability to send a raw SQL query
           | (hint: almost all of them) has documentation you can copy and
           | paste to introduce an injection vulnerability.
           | 
           | You'll find injection vulnerable examples in the MySQL docs
           | themselves: https://dev.mysql.com/doc/c-api/8.0/en/mysql-
           | real-query.html
        
             | nextaccountic wrote:
             | > You'll find injection vulnerable examples in the MySQL
             | docs themselves:
             | https://dev.mysql.com/doc/c-api/8.0/en/mysql-real-
             | query.html
             | 
             | I can't find those examples, is there something in the
             | mysql docs that I can copy and paste and be instantly
             | vulnerable?
        
             | iamgopal wrote:
             | MySQL docs shouldn't worry about injection.
        
               | mike_d wrote:
               | So why should Perl, Go, PHP, or Rust?
        
               | iamgopal wrote:
               | Because those language are usually used at application
               | level, and application does need to worry about wrong
               | input. Databases doesn't need to worry about if some
               | correct security level input ask to delete the database ,
               | it should delete it, not to question the input , but at
               | application level , that is not acceptable. How much
               | simpler can this get ?
        
               | cerved wrote:
               | because it's serious if it's a web server?
        
               | [deleted]
        
               | thallium205 wrote:
               | Because not everything that uses MySQL is a web server?
        
               | iamgopal wrote:
               | Why downvote ? Why database needs to worry about
               | executable wrong input ? That's input ( App ) level
               | problem. Database will do what it is asked to do.
        
               | anakaine wrote:
               | Because people learn from and refer to the documentation.
               | Examples therein should be presented in a manner that
               | demonstrates safe execution.
        
           | mlang23 wrote:
           | In defense of PHP, this is probably due to simplicity. PHP
           | got many people started with server side web development, and
           | docs were supposed to be "simple". The thinking back then
           | probably was "if we make the example more complicated, we
           | will loose people", which was probably even true for the
           | target audience.
        
             | prox wrote:
             | When I started like this, I always followed up with a
             | google query for securing what I did. Not the best way to
             | learn, but as you say, it got you started.
        
             | [deleted]
        
             | pdimitar wrote:
             | I don't see this as a defense, I am seeing it as a way to
             | reach to more programmers, and basic security practices be
             | damned in the process.
             | 
             | I have to wonder: what did these people have to gain if PHP
             | got popular (which it did)? That's an egotistical way of
             | popularizing your language.
        
               | tored wrote:
               | Now do C.
        
               | pdimitar wrote:
               | I know right. That's why I'm not doing C anymore, for 10+
               | years now.
        
               | tored wrote:
               | Was Dennis Ritchie egotistical for popularizing C? He
               | would have known all the security flaws in it, right?
        
               | NationalPark wrote:
               | Which MySQL library did Ritchie wrap back in 1972?
        
               | tored wrote:
               | https://news.ycombinator.com/item?id=27959145
        
               | NationalPark wrote:
               | My bad, which version of Linux should Ritchie have been
               | auditing in 1972?
        
               | pdimitar wrote:
               | Very disagreed with your analogy. By the time those PHP
               | tutorials were written, SQL injection attacks were
               | already known.
               | 
               | So not sure what you're trying to push here but I refuse
               | to participate.
        
               | tored wrote:
               | Still to this day you have free-after-use bugs in the
               | Linux kernel, about 20% of all known bugs in the kernel.
               | How is this not comparable?
        
               | pdimitar wrote:
               | It is comparable, that's why I'm moving to Rust. Hence I
               | said I don't want to participate simply because I am not
               | defending C either. It played its role and it's time for
               | it to be phased out.
        
             | Cthulhu_ wrote:
             | I see what you mean, but at the same time, back then just
             | getting a working PHP environment up and running was
             | complicated enough - PHP, Apache, MySQL, and you had to get
             | them all working together.
             | 
             | If it was about accessibility, they should have made an
             | easy installer and even offered cheap hosting themselves I
             | think.
             | 
             | As for SQL injection, were prepared statements even a thing
             | back then? Either way they should never have allowed and
             | normalized string concatenation to build up SQL queries.
        
               | zzzeek wrote:
               | > As for SQL injection, were prepared statements even a
               | thing back then?
               | 
               | wow.
               | 
               | yes, prepared statements have been a thing since there
               | were relational databases.
               | 
               | but also, (server side) prepared statements are not
               | required in order to use SQL with bound parameters. the
               | binding can occur just as easily on the client side, and
               | this is in fact quite common. the point is that the
               | programmer is not manually deciding whether or not to
               | escape a parameter on a query-by-query basis, the process
               | is automated.
        
               | piokoch wrote:
               | "just getting a working PHP environment up and running
               | was complicated enough"
               | 
               | Hah, that was one of the biggest strength of PHP stack -
               | it was not complicated; on you MS Windows machine it was
               | enough to install some wammp/xammp, etc. PHP/MySQL/Apache
               | bundle, open editor, put in the first line <? and start
               | coding.
               | 
               | On production, typically some shared hosting (cheap!
               | Another said stack advantage) this was already installed,
               | so it was sufficient to FTP files over there and be done
               | (one more advantage).
               | 
               | There was no other comparable stack in terms on
               | simplicity and being able to do something quickly. I
               | believe there is none today, only PHP stack matured, so
               | there are frameworks, etc.
               | 
               | Yes, there were security concerns, but still much less
               | comparing to its server-side predecessor CGI scripts
               | (better known today as AWS lambdas or "serverless").
        
               | jimmaswell wrote:
               | Configuring the "plugins" and everything to get PHP
               | working on Apache on Linux can be complicated and
               | annoying if you're not already familiar with the process.
        
               | kstrauser wrote:
               | > As for SQL injection, were prepared statements even a
               | thing back then?
               | 
               | Yes. I was writing prepared statements in Perl before
               | PHP3 was released.
        
               | tored wrote:
               | There have existed multiple installer projects for PHP,
               | Apache & MySQL on Windows for _two_ decades.
               | 
               | Mysqli driver was released with PHP 5.0 in 2004, it has
               | prepared statements.
        
             | chriswarbo wrote:
             | > In defense of PHP, this is probably due to simplicity
             | 
             | I don't consider this to be a good defence; in fact, I'd
             | argue that makes PHP _itself_ insecure.
             | 
             | I like to think of secure coding in terms of the 'path of
             | least resistance' for a lazy/busy/inexperienced developer.
             | If doing things securely makes life harder, things will be
             | done insecurely.
             | 
             | We don't need to make the secure approach easier in
             | absolute terms; we can just make the insecure approaches
             | more painful. In this case: have database functions require
             | arguments of an 'SQL' type, rather than strings; make it
             | easy to write literal SQL values; make it easy to
             | parameterise SQL values; make it as hard as possible to
             | convert a string value to an SQL value, e.g. bury it in
             | some deep namespace hierarchy, with a long and scary-
             | sounding name, require a config value to be enabled (or
             | even make it a compiler flag!), etc.
             | 
             | This way, the docs (plus stack overflow, blog posts, etc.)
             | don't have to choose between showing a secure approach or
             | showing the simplest approach; since they are the same!
        
               | guskel wrote:
               | >I don't consider this to be a good defence; in fact, I'd
               | argue that makes PHP itself insecure.
               | 
               | Agree with you completely on that. PHP, is in fact,
               | insecure by design.
        
               | michaelmior wrote:
               | > make it easy to parameterise SQL values
               | 
               | It usually is easy to parameterize things like values
               | used in WHERE clauses. It's often much harder to work
               | with dynamic query conditions (e.g. optional filters on a
               | particular column). I don't believe I've seen an approach
               | that does this in a way that can provably provide any
               | sort of safety guarantee.
        
               | chriswarbo wrote:
               | Do you have an example? I can only imagine three
               | scenarios:
               | 
               | - SQL logic. We should be able to write this as a literal
               | query, parameterised as needed, e.g. (made up syntax)
               | query(           addParam(             "MyParam",
               | $myParam,             SQL"SELECT foo FROM tbl WHERE
               | @MyParam IS NULL OR bar = @MyParam"           )         )
               | - PHP logic. This is just ordinary control flow, like
               | anything else, e.g.              query(
               | ($myParam === null)             ? SQL"SELECT foo FROM
               | tbl"             : addParam("MyParam", $myParam,
               | SQL"SELECT foo FROM tbl WHERE bar = @MyParam")         )
               | - A mixture of SQL logic and PHP logic. This seems
               | inherently unsafe to me, so it's not surprising that
               | safety guarantees can't be proven. My point is that such
               | things should be be made difficult ("artificially", if
               | needed), such that nobody would choose to go down that
               | route when another option is available.
        
               | michaelmior wrote:
               | I'm not quite sure what you're asking for an example of.
               | But suppose you have a table tbl(foo, bar, baz).
               | Depending on user input, you may want to query on any
               | combination of foo, bar, and baz. With this and larger
               | number of columns, it becomes impractical to have
               | conditions for every combination.
               | 
               | One approach would be to construct a list of conditions
               | as well as a list of parameters to be substituted. Shown
               | below without any particular language syntax, but
               | hopefully comprehensible.
               | 
               | conditions = ("foo=?", "bar>?") parameters = (fooValue,
               | barValue)
               | 
               | Then when building the SQL, you join the conditions
               | together with AND and substitute in the parameters. This
               | works in the sense that you are still prevented from
               | injection. But it's rather messy. I suppose perhaps you
               | can actually do what I'm discussing with some ORMs in a
               | reasonably clean way. But my point is that most SQL
               | interfaces make it easy to parameterize a single set of
               | fixed values, but hard to do so for table and column
               | names. Arguably this is a feature not a bug since you
               | probably want to avoid such parameterization anyway. But
               | having a safer way to do so would be nice.
        
             | mxd3 wrote:
             | The fact that it got newbies started doesn't mean it was
             | built for newbies. I think you're making too many
             | assumptions here.
        
           | ssully wrote:
           | My first job while in school was doing web development with a
           | LAMP stack. I had zero PHP experience, so it was 100%
           | learning on the job and my learning resources were basically
           | the official docs, a PHP book (can't remember which) I got at
           | a book store, and stackoverflow.
           | 
           | PHP has a very forgiving design; it makes it very easy to get
           | any trash code up and running. It really is great for newbies
           | to get their hands dirty. I look back fondly on that first
           | job, but boy did I have to unlearn a lot of bad lessons from
           | those days.
        
         | treeman79 wrote:
         | Thought the best way was to develop a basic and easy library.
         | Then upload a malicious binary that doesn't match the source.
         | 
         | There was a really good post on how to do it and evade
         | detection.
        
         | p1necone wrote:
         | > DRY paints that as a feature
         | 
         | That's not what DRY _should_ be. Good developers should
         | understand at least a couple of levels of abstraction
         | underneath what they 're writing in order to produce sensible
         | code.
         | 
         | The idea of abstraction is that you only have to spend the
         | afternoon/day/week (depending on the complexity that's being
         | abstracted over) learning how everything comes together _once_
         | , as opposed to spending that time to grok a slightly different
         | version of the same complex system every time you read/write
         | something new.
        
           | ahmedalsudani wrote:
           | Yeah; anyone who thinks DRY means copy the answer on SO is
           | completely missing the point.
           | 
           | DRY should not introduce vulnerabilities. It avoids them by
           | 
           | 1. reducing complexity and cognitive overhead
           | 
           | 2. allowing you to fix your code in one place and propagate
           | your fix throughout the codebase
        
         | ericye16 wrote:
         | "Programming from first principles" doesn't solve security
         | problems, in fact security problems in this case come from
         | being ignorant of best practices and industry experiences. You
         | would _want_ programmers to use established techniques to avoid
         | this problem. Of course developers should always understand
         | what their code is doing though.
        
         | tshaddox wrote:
         | > This isn't new, we've always had programmers who programmed
         | by "recipe" rather than first principles, and DRY paints that
         | as a feature, but it underlies a lot of pain and cost over the
         | years.
         | 
         | Something tells me that exploiters love the programmers who
         | attempt to build user authentication systems from first
         | principles.
        
         | p5a0u9l wrote:
         | Ironic how in today's market the applied math dude could easily
         | transition into some higher paying role like ML Engineer or
         | Data Scientist. Not knocking those roles by any means, but the
         | tech world seems ravenous for algorithms.
         | 
         | From my experience, algorithms are easy and the software
         | engineering is hard.
         | 
         | What's more, many, not all, but many of these algorithm
         | scientists look down on their programmer counterparts. It's
         | these folks who end up making the algorithm successful for the
         | company.
        
         | raxxorrax wrote:
         | I believe all programmers will resort to copying code without
         | too much of a review at some point. Strict first principles
         | would mean not to rely on mental work of predecessors, which is
         | entirely unrealistic today. Maybe that could work in the 80s,
         | but the amount of software layers today is astonishing.
         | 
         | I develop bare metal code for special uC, but I would never
         | imagine to build even a basic OS. This is work you spend your
         | lifetime in. Of course if I could just copy the things from
         | established OS things might look differently.
         | 
         | That said, I don't think the first steps in SQL should guard
         | against SQL injection. That is a topic for later and only hides
         | the main learning target. You can understand SQL perfectly by
         | first principles and still cause your first program to allow
         | for such injection. But that should be a different lesson at
         | first. Being able to identify it as a danger also relies on the
         | experience of others.
        
         | pvg wrote:
         | _The best way to insert supply chain exploits is to embed them
         | in a stack exchange answer to a beginner 's question._
         | 
         | None of these answers seem to come from SE so this might be
         | harder than you might assume.
        
           | Godel_unicode wrote:
           | It's not. Note that these threads are a few years old, but in
           | recent research (stay tuned!) it has if anything gotten
           | worse.
           | 
           | https://news.ycombinator.com/item?id=13099690
           | 
           | https://laurent22.github.io/so-injections/
        
             | pvg wrote:
             | It may have but this research doesn't show that. It appears
             | to be in questions, rather than answers, when I can find a
             | page that hasn't been removed. Beside most of these not
             | actually being there, the google result is for _answers_
             | which additionally have been ranked by Google. The thing
             | you link is not meaningfully comparable to the Google
             | result, nor is it representative of  'if you search for
             | something on SE, how often does it tell you to put SQLI in
             | your code'.
        
         | dragonwriter wrote:
         | > This isn't new, we've always had programmers who programmed
         | by "recipe" rather than first principles, and DRY paints that
         | as a feature
         | 
         | No, it doesn't. Programming by recipe rather than building the
         | recipe into a reusable abstraction is the exact opposite of
         | DRY.
        
         | simion314 wrote:
         | The problem seems to me to be if you hire newb developers and
         | don't have any mentor-ship or code review. Any non-newb dev
         | will know that you ALWAYS have to sanitize strings for SQL.
         | file names or whatever. Most SQL ORMs or libraries will let the
         | developer run raw SQL so you better have some competent person
         | writing teh code or at least review it.
        
           | bluedino wrote:
           | Certain people just aren't "real programmers". I worked with
           | a guy who would cut and paste some example and change a
           | couple things, and respond with "I got this working"
           | 
           | Meanwhile I would said okay, what does it actually do,
           | where's you copy it from, what did you change and why...
           | 
           | At this point he would just get mad at me. I'm sorry I don't
           | want people cutting and paste code they don't understand and
           | sticking it in our codebase.
        
             | simion314 wrote:
             | And the issue is the fucking search engine, I can't
             | understand why when you search for JS,html,css
             | documentation google sends me to outdated websites like w3c
             | schools. I always have to foce a search on MDN.
             | 
             | A newb can also copy paste bad Python code, mess up some
             | ORM clause and delete all your database.
             | 
             | But in this case oh PHP and MySQL even the worst dev shop
             | uses a framework or library, so this article is probably
             | affecting almost nobody that matters.
        
               | bluedino wrote:
               | >> I can't understand why when you search for JS,html,css
               | documentation google sends me to outdated websites like
               | w3c schools
               | 
               | Probably the same reason they still send people to sites
               | like Expert Exchange
        
           | acdha wrote:
           | > Any non-newb dev will know that you ALWAYS have to sanitize
           | strings for SQL. file names or whatever.
           | 
           | This is the "No true Scotsman" fallacy of programming. There
           | are many people with plenty of experience who haven't yet
           | learned that lesson memorably and at least an order of
           | magnitude more who know it but don't exhaustively trace every
           | data flow through the system and assume something already
           | handled validation or escaping, being correct all but a fatal
           | few times. With unsafe defaults an attacker only has to find
           | a mistake once -- you have to find them all.
        
             | simion314 wrote:
             | There is no unsafe defaults, all ORMs allow you to run raw
             | SQL so same "newb dev" can do same stupid thing if it finds
             | a SQL tutorial when googling "how to do X".
             | 
             | You need to teach developers to always escape strings, even
             | if we remove old and bad tutorials you still need to teach
             | the devs about this issues, otherwise they will do the
             | mistake with file names, or with parameters to shell
             | commands. It might mean having to read a book and not
             | reeling on Google and soon on AI to teach you to code or
             | SQL.
        
               | acdha wrote:
               | There's a difference between what you encourage and
               | what's technically possible. PHP code so commonly has
               | bugs of this class because there's a quarter century of
               | tradition, examples, and tutorials normalizing the idea
               | of taking request variables and passing them directly to
               | other code. Contrast with something like the Django
               | tutorials & docs where the examples pervasively use the
               | ORM's escaping & validation and the extension points
               | describing how to use custom SQL tell you to use
               | placeholders and emphasize why it's important.
               | 
               | That might not seem like a lot at first thought but it
               | lowers the bug frequency enormously in the code I've
               | looked at because you only need extreme caution in rare
               | cases rather than every view. That means that when
               | someone is busy, having a bad day, etc. they either have
               | no problem or it's a safe crash rather than an
               | exploitable hole.
        
               | simion314 wrote:
               | That is not the reality. Even the most stupid and lazy
               | person will find a framework to use.
               | 
               | This are just old pages that bad search engine surface.
               | IMO if you focus the actual lessons here are:
               | 
               | - developers are lazy, you need to fix that, there is no
               | magic language that solves the issue though some fanboys
               | will say that their favorite language is more idiot
               | friendly.
               | 
               | - search engine and soon the AIs are stupid, let's try to
               | encourage books or other quality materials. Recently I
               | found a collegue that did not know that in JS the
               | "addEventListener" function exists and you can use it to
               | add more then 1 listener at a time, this person probably
               | can put on his CV 5+ yearts JS experience and a few
               | frameworks. Mayb e if we stop focusing on the "my
               | language is cooler" we could find the actual problems.
               | 
               | Back in my starting years I was reading books to learn,
               | there when you get to the SQL chapter you were explained
               | all about SQL injection and related bugs and how to use
               | prepared statements. With PHP you can block this
               | dangerous functions (PHP is flexible and many stuff like
               | "exec" is blocked in most hosting places, but the problem
               | with newb developers remain, if we can agree about this
               | real problem(IMO_ we can maybe address it. Sure,
               | downranking bad tutorials would be a part of the
               | solution, also Google should probably stop their shit
               | where they put the solution directly on the search page
               | and not forces you to actualy visit SO and see comments,
               | limitations and alternatives, shame Google, you make
               | software industry worse with your greed...
        
         | gjs278 wrote:
         | nobody is intentionally inserting bad code on answers. they are
         | just bad programmers giving what they think is helpful advice.
        
         | crazygringo wrote:
         | > _The best way to insert supply chain exploits is to embed
         | them in a stack exchange answer to a beginner 's question._
         | 
         | Do you have any actual evidence for that?
         | 
         | As Hanlon says, "never ascribe to malice that which is
         | adequately explained by incompetence."
         | 
         | Incompetence explains this one fully for me.
        
           | eyelidlessness wrote:
           | It doesn't take a malicious actor to make a honeypot, only to
           | exploit it. If someone naively posts a widely used solution
           | on a help site, they've done the job for the exploiter, who
           | only needs to know what low hanging vulnerability fruit
           | awaits them.
        
         | dylan604 wrote:
         | In 1980s, where did one go to find code to copy&paste?
        
           | jimmygrapes wrote:
           | Mailing lists and USENET mostly, with FTP listing of open
           | source code here and there, followed by transcribing from
           | printed material
        
           | PeterisP wrote:
           | You would use a reference source, which may be paper
           | documentation provided by the tool vendor (e.g. API
           | documentation with usage samples), online documentation
           | provided by the tool vendor, sample source code provided by
           | the tool vendor (including illustrative sample applications
           | for reference was quite common), or third party reference
           | books. Since documentation was much more necessary than
           | nowadays, it was more thorough and generally of a higher
           | quality than now, though of course not always perfect.
        
           | fencepost wrote:
           | Dr. Dobb's Journal of Computer Calisthenics & Orthodontia
           | 
           | Running Light without Overbyte
        
           | dataviz1000 wrote:
           | copy & paste ... ha I wish. We had to type it bit by bit from
           | the back of a magazine back in my day. Do you remember this?
           | [0]
           | 
           | [0] https://arstechnica.com/staff/2018/11/first-encounter-
           | comput...
        
             | dylan604 wrote:
             | This is exactly how I got into coding. A friend had the
             | computer, and the 2 of us would hunt&peck the code in. We
             | were maybe 12 years old. The DATA lines were the tricky
             | spots. Everything else used words we could understand, and
             | it just made sense after doing it enough. The DATA was just
             | jibberish. We found it easiest if one typed while the other
             | called out the data. Faster and fewer mistakes.
        
               | jonwinstanley wrote:
               | Same. I used to buy Amiga Format magazine for the game
               | reviews then found the code for creating my own game was
               | way more fun
        
           | pjmlp wrote:
           | By using the brain as clipboard between book, eyes and
           | keyboard.
        
           | jussij wrote:
           | Back in the late 80s and early 90s many people learned to
           | code from a book.
           | 
           | You would just study the code samples found in those books.
        
             | hnick wrote:
             | Or the existing code on your machine or local
             | documentation. I learned quite a bit of QBASIC from reading
             | nibbles.bas and gorillas.bas and the editor's own help was
             | extensive.
        
         | latchkey wrote:
         | > _The best way to insert supply chain exploits is to embed
         | them in a stack exchange answer to a beginner 's question._
         | 
         | I'd love to see a concrete example of this happening in this
         | way!
         | 
         | The rest of your story just describes 'smart, but bad jr.
         | programmer' and doesn't really discuss the exploit issue.
        
       | laurent123456 wrote:
       | 50% is also what I had found on Stackoverflow (2018) -
       | https://laurent22.github.io/so-injections/
        
         | cmeacham98 wrote:
         | The top code snippet in the "latest vulnerabilities" section
         | (as of the time of writing) is:                    $query =
         | "SELECT * FROM wp_misure WHERE Id =
         | '".mysqli_real_escape_string($link, $_GET['id'])."'";
         | 
         | This is not vulnerable to SQLi unless I misremember how
         | real_escape_string works.
        
           | wruza wrote:
           | I always wondered if "real_" means "now this time we're
           | serious" or something less funny.
        
             | lillesvin wrote:
             | It seems to come from the MySQL C API:
             | https://dev.mysql.com/doc/c-api/8.0/en/mysql-real-escape-
             | str...
             | 
             | The 'real' supposedly alludes to the fact that
             | `mysql_real_escape_string()` accounts for character
             | encoding (if specified correctly) unlike its sibling
             | `mysql_escape_string()`.
             | 
             | So, yeah, I'm afraid 'less funny'. :-/
        
           | elktea wrote:
           | https://stackoverflow.com/questions/5741187/sql-injection-
           | th...
           | 
           | It's still not safe
        
           | laurent123456 wrote:
           | Yes it's not 100% accurate but still gives a good
           | approximation. See there for more info
           | https://github.com/laurent22/so-sql-injections/issues
        
           | acdha wrote:
           | I generally reject that in review because it perpetuates
           | thinking of the problem as needing to sprinkle escape calls
           | around rather than using a systemic fix. I've seen a number
           | of cases where this resulted in various errors because the
           | escaped value was later manipulated in some way - I don't
           | believe any of those were exploitable but they caused user
           | reports of broken formatting or crashes.
        
             | axiosgunnar wrote:
             | How would a systemkc fix look like, apart from using an
             | ORM?
        
               | piyh wrote:
               | Using bind parameters.                   https://docs.pyt
               | hon.org/3.8/library/sqlite3.html#sqlite3.Cursor
               | # Never do this -- insecure!      symbol = 'RHAT'
               | cur.execute("SELECT \* FROM stocks WHERE symbol = '%s'" %
               | symbol)      # Do this instead      t = ('RHAT',)
               | cur.execute('SELECT \* FROM stocks WHERE symbol=?', t)
               | print(cur.fetchone())      # Larger example that inserts
               | many records at a time      purchases = [('2006-03-28',
               | 'BUY', 'IBM', 1000, 45.00),          ('2006-04-05',
               | 'BUY', 'MSFT', 1000, 72.00),          ('2006-04-06',
               | 'SELL', 'IBM', 500, 53.00),         ]
               | cur.executemany('INSERT INTO stocks VALUES (?,?,?,?,?)',
               | purchases)
        
               | acdha wrote:
               | The lowest level improvement: make the default query
               | interface support placeholders, use that everywhere in
               | the documentation, and examples. Don't use string
               | concatenation anywhere except examples marked as high-
               | risk.
               | 
               | More advanced, 90s Perl style: setup something like a
               | taint bit on outside variables which has to be cleared
               | using an escape function to avoid an error.
               | 
               | OOP variant: A class system could be used to make
               | something like execute() only accept a SqlQuery instance
               | and that class throws a fatal error if you concatenate a
               | regular string. That still allows someone to run
               | arbitrary strings through whatever marks strings as safe
               | but that requires doing additional work rather than
               | forgetting and is easier to audit.
               | 
               | Nicer, possibly less safe variation: implement something
               | like Python's __add__ / __radd__ so query + string has
               | the string escaped automatically.
               | 
               | More advanced: make the query method only accept
               | constants defined at compile time with some escape hatch
               | function which is clearly marked as unsafe:
               | totally_insecure_query(). You need some way to combine
               | predefined fragments for conditionals but that should be
               | possible in most modern languages.
               | 
               | Rust example: https://polyfloyd.net/post/compile-time-
               | prevention-of-sql-in...
        
       ___________________________________________________________________
       (page generated 2021-07-26 23:02 UTC)