php – Joomla! 連接資料庫的 JDatabase 不安全

該篇版本 Joomla! 3.8.7 Stable [ Amani ] 18-April-2018 14:00 GMT

PHP PDO 建議使用佔位符來取代 Quote(在條件的值左右加上 ” 包圍),參考 PDO::quote() http://php.net/manual/en/pdo.quote.php

If you are using this function to build SQL statements, you are strongly recommended to use PDO::prepare() to prepare SQL statements with bound parameters instead of using PDO::quote() to interpolate user input into an SQL statement.

 

Joomla 的範例

最後輸出 SELECT id, greeting FROM #__helloworld WHERE id = ‘1’

Joomla 使用在 where 子句中添加 $db->quote() 的方式,也就是在參數的左右添加 ” 並消毒,這個在現在的 PHP 官方認為是不安全的。這種做法是在 mysqli 的年代,後來 PHP 發展出 PDO,使用佔位符來解決第三方 libraries 自行編撰消毒 SQL Inject。

 

驗證

我依序回推查看原始 Joomla 的原始碼,了解 Joomla 的 Quote() 是用什麼實作

  1. jjoomla\database\driver.php: 1848 在 1861 行使用 escape()
  2. 來到 libraries/joomla/database/driver/pdomysql.php:457 在 466 行使用 $this->connection->quote($text)
  3. 來到 C:\www\joomla\libraries\fof\database\driver\pdo.php: 119 查找 220 行,在 function 返回連線 PDO 物件
  4. 所以得知 Joomla 使用的 Quote 正好是 PHP 不建議使用的  PDO::quote() 。PHP 官方建議使用 PDO::prepare() 佔位符來綁定。

 

PDO 改寫上方

PDO 若直接查看 Query 字串,會看到 id = ? 而不是 id = 1

PDO 的概念是將 ‘?’ 丟到 MySQL 核心引擎依序替換掉 ‘?’,所以我們無法在 PHP 中看到 id = 1。這在 PHP 手冊中提到這是目前最安全的作法。消毒這件事情不要透過 PHP 執行而是 Database。參考 http://php.net/manual/en/pdo.prepare.php

If the database server successfully prepares the statement, PDO::prepare() returns a PDOStatement object. If the database server cannot successfully prepare the statement, PDO::prepare() returns FALSE or emits PDOException (depending on error handling).

發表迴響