Write Rule security check for missing db_rewrite_sql on SELECT FROM {node}

douggreen - August 29, 2008 - 14:13
Project:Coder
Version:6.x-2.x-dev
Component:Review/Rules
Category:task
Priority:normal
Assigned:douggreen
Status:reviewed & tested by the community
Description

LIVE FROM DRUPALCON SZEGED. This idea came out of a session that Ken Rickards gave on node_access.

When you do a "SELECT FROM {node}", you should typically also wrap this in db_rewrite_sql. Since this is a security issue, but not a hard and fast rule, the rule should say something like "you are probably doing something wrong."

#1

douggreen - September 21, 2008 - 17:22
Status:active» needs review

Please try the attached rule.

AttachmentSize
301552.patch 1.97 KB

#2

stella - September 22, 2008 - 12:11

That patch doesn't work as it also alerts on queries which do use db_rewrite_sql(). I've re-rolled it with this change, please review.

Cheers,
Stella

p.s. looks like this will all be changing in D7, see http://drupal.org/node/310077

AttachmentSize
coder_301552.patch 2.06 KB

#3

douggreen - September 29, 2008 - 13:09
Version:6.x-1.x-dev» 6.x-2.x-dev

Updated patch to use the new test structure, and moved it from the sql review to the security review.

#4

douggreen - September 29, 2008 - 13:10

... and the patch !

AttachmentSize
301552.patch 4.15 KB

#5

stella - September 29, 2008 - 13:41
Status:needs review» reviewed & tested by the community

Looks good to me!

#6

John Morahan - October 1, 2008 - 20:53

The rule looks like it would miss queries that join the node table:

<?php
  $results
= db_query("SELECT * FROM {mytable} t INNER JOIN {node} n ON t.nid = n.nid");
?>

Also, there is this:

+    $this->assertCoderPass('  $results = db_query(db_rewrite_sql("SELECT * FROM {node}"));');

Ideally, that test should actually fail - since db_rewrite_sql also needs to know the correct alias for the node table, which it assumes to be 'n' unless you tell it otherwise. So:

<?php
  $results
= db_query(db_rewrite_sql("SELECT * FROM {node} n")); // right
 
$results = db_query(db_rewrite_sql("SELECT * FROM {node} foo", 'foo')); // also right
 
$results = db_query(db_rewrite_sql("SELECT * FROM {node}", '{node}')); // also right, but rare
 
$results = db_query(db_rewrite_sql("SELECT * FROM {node}")); // wrong
?>

That would probably be a separate rule though; I just wanted to point out the bad test here.

#7

John Morahan - October 23, 2008 - 14:15

Hmm, and apparently SELECT * is wrong too, as the primary field has to actually exist in the query or db_distinct_field() will fail.

 
 

Drupal is a registered trademark of Dries Buytaert.