Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:108906 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 71364 invoked from network); 9 Mar 2020 15:26:40 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 9 Mar 2020 15:26:40 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id EA4211804D0 for ; Mon, 9 Mar 2020 06:47:18 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-wm1-f44.google.com (mail-wm1-f44.google.com [209.85.128.44]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Mon, 9 Mar 2020 06:47:18 -0700 (PDT) Received: by mail-wm1-f44.google.com with SMTP id e26so9633268wme.5 for ; Mon, 09 Mar 2020 06:47:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=craigfrancis.co.uk; s=default; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=J828zxVUWxC5zfJTPCzYglZ+fJ8eT6u9puVD6PJ8Hnw=; b=aTDIeyPK0Keg89PWbr1dAvZEIor0rSPe5+nZX6CYrKYHkJiSIL2MWVN/hSICzFE5XY L4mAj2swwstfoGm7e1ArUkCwoGwfJnkuIekETUYgth7r0wgMAZhl+o44hljiYMc1d2d4 1VTse0hluhTb/9ktCgQ/usOmXysnxpQdBwm9I= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=J828zxVUWxC5zfJTPCzYglZ+fJ8eT6u9puVD6PJ8Hnw=; b=nUibI0Mq00VHoLL8R7CRqqIwmxdZINE+Maqxv198G5AQhHMGDuR9wLlLAXAcPb4Ck6 0h/8iM7tosEhLkAox+krGrYJrFvdmZgPKBLIdpDhIlwlhY0Bn3UfRbAeNvmq1n2flQ75 VTFWGtzcfVOPFjOOis9SLmToD6QB5j7wUPEl/hb2zp1qF4Zo423zhRwnRVptTuTNmHsb QuEfPtJR9o/N9ACSKV36CDG/GDJ6zyv3WIiw3UwBJM0UIf896pdM9xXybK8fibh7Kzzw O8c+Bc0WPYkYnBrbp7vu1ZNMTKdbhTQgB9NqFWf52WkH5wrreYcdyXdyxG2j3QdA+I8B 07Lw== X-Gm-Message-State: ANhLgQ0HtNVgJziinjBud/4rDYzCN0oQLh24gtXtc4nCgTmciNBA7Wsq TBPOcObJ5iTLi6jpuEGeU/YTH8D3lACJkqi7teBAX0AD7y8= X-Google-Smtp-Source: ADFU+vvAj8BUKv358dGQyJRyN59ZVbCFA1qPKrfvPY1gvITs+uf0AWsUXPGZuY5dFueRHLG67yTw49+8AvFnzLJeAzs= X-Received: by 2002:a1c:2701:: with SMTP id n1mr20361787wmn.180.1583761633483; Mon, 09 Mar 2020 06:47:13 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Mon, 9 Mar 2020 13:47:02 +0000 Message-ID: To: PHP internals Content-Type: multipart/alternative; boundary="00000000000092b66205a06c3de1" Subject: Re: Literal / Taint checking From: craig@craigfrancis.co.uk (Craig Francis) --00000000000092b66205a06c3de1 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi, As I'm not sure how to make any more process on this, I've added added a Feature Request: https://bugs.php.net/bug.php?id=3D79359 It shows how this change in PHP could stop SQL injection, and proposes a way it could be used against HTML injection as well. Craig On Thu, 13 Feb 2020 at 12:31, Craig Francis wrote: > Hi, > > While there was a brief discussion about an *is_literal*() method in > August, I'm wondering where I can go next? > > Just as a reminder, the main objection seemed to be that Taint checking i= s > the current solution. For example, those created by Laruence[1], > MediaWiki[2], and Matthew[3]. But this can never be as good at the PHP > engine explicitly stating a variable *only* contains literal values, wher= e > it can be checked at runtime, and be a key part of the development proces= s. > > And while I'm using SQL injection in my examples (because it's easy to > show how it can enforce the use of parameterised queries); it would also = be > useful to protect against command line injection, and HTML/XSS as well > (e.g. a templating system can only accept HTML as literal strings, and > the user supplied values be provided separately). > > I'm assuming this would change the zval structure (to include an > "is_literal" flag?), and it would be more of a PHP 8.0 change, rather tha= n > 8.1. > > Craig > > > --- > > Broken taint check, due to missing quote marks: > > $sql =3D =E2=80=98... WHERE id =3D =E2=80=99 . mysqli_real_escape_string(= $db, $_GET[=E2=80=98id=E2=80=99]); > > --- > > Support for "WHERE ... IN", ideally done via an abstraction, so you don't > need to write this every time: > > $sql =3D '... WHERE id IN (' . substr(str_repeat('?,', count($ids)), 0, -= 1) > . ')'; > > --- > > [1] https://github.com/laruence/taint > [2] https://www.mediawiki.org/wiki/Phan-taint-check-plugin > [3] https://psalm.dev/r/ebb9522fea > > --- > > > > > On Thu, 15 Aug 2019 at 19:02, Craig Francis > wrote: > >> Hi, >> >> How likely would it be for PHP to do Literal tracking of variables? >> >> This is something that's being discussed JavaScript TC39 at the moment >> [1], and I think it would be even more useful in PHP. >> >> We already know we should use parameterized/prepared SQL, but there is n= o >> way to prove the SQL string hasn't been tainted by external data in larg= e >> projects, or even in an ORM. >> >> This could also work for templating systems (blocking HTML injection) an= d >> commands. >> >> Internally it would need to introduce a flag on every variable, and a >> single function to check if a given variable has only been created by >> Literal(s). >> >> Unlike the taint extension, there should be no way to override this (e.g= . >> no taint/untaint functions); and if it was part of the core language, it >> will continue to work after every update. >> >> One day certain functions (e.g. mysqli_query) might use this information >> to generate a error/warning/notice; but for now, having it available for >> checking would be more than enough. >> >> Craig >> >> >> >> public function exec($sql, $parameters =3D []) { >> if (!*is_literal*($sql)) { >> throw new Exception('SQL must be a literal.'); >> } >> $statement =3D $this->pdo->prepare($sql); >> $statement->execute($parameters); >> return $statement->fetchAll(); >> } >> >> ... >> >> $sql =3D 'SELECT * FROM table WHERE id =3D ?'; >> >> $result =3D $db->exec($sql, [$id]); >> >> >> >> [1] https://github.com/tc39/proposal-array-is-template-object >> https://github.com/mikewest/tc39-proposal-literals >> > --00000000000092b66205a06c3de1--