Re: Literal / Taint checking

This is only part of a thread. view whole thread
  108537
February 13, 2020 12:31 craig@craigfrancis.co.uk (Craig Francis)
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 is
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, where
it can be checked at runtime, and be a key part of the development process.

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 than
8.1.

Craig


---

Broken taint check, due to missing quote marks:

$sql = ‘... WHERE id = ’ . mysqli_real_escape_string($db, $_GET[‘id’]);

---

Support for "WHERE ... IN", ideally done via an abstraction, so you don't
need to write this every time:

$sql = '... 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 <craig@craigfrancis.co.uk>
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 no > way to prove the SQL string hasn't been tainted by external data in large > projects, or even in an ORM. > > This could also work for templating systems (blocking HTML injection) and > 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 = []) { > if (!*is_literal*($sql)) { > throw new Exception('SQL must be a literal.'); > } > $statement = $this->pdo->prepare($sql); > $statement->execute($parameters); > return $statement->fetchAll(); > } > > ... > > $sql = 'SELECT * FROM table WHERE id = ?'; > > $result = $db->exec($sql, [$id]); > > > > [1] https://github.com/tc39/proposal-array-is-template-object > https://github.com/mikewest/tc39-proposal-literals >