动态SQL查询命名发布密钥

时间:2010-07-02 17:43:54

标签: security post

将表单字段命名为与列名相同是不好的?我的意思是人们真的这么做:

 <?php
 $id = intval($_POST['user_unique_key']);
 $name = mysql_real_escape_string($_POST['name_of_user']);
 $email = mysql_real_escape_string($_POST['user_mail_thing']);
 $address = mysql_real_escape_string($_POST['user_place_of_living']);
 //....
 $sql = "INSERT INTO `users`('id','name','email','address') VALUES($id,$name,$email,$address)"
 ?>

另请注意,上述数据验证非常糟糕!我永远不会用它。

<a href="http://forums.devnetwork.net/viewtopic.php?f=50&t=118175">My Data Validation</a>

我应该使用表格前缀,例如:'secret_prefix _'?

我不太喜欢的最终解决方案是我可以使用双向哈希来散列字段名称。所以输入名称是

 <?php echo $field_name = base64_encode(mcrypt_encrypt( MCRYPT_RIJNDAEL_128, $key, $key, MCRYPT_MODE_ECB, $iv ));?>

然后在发布字段名称后对其进行解码

 <?php
  foreach($_POST as $name=> $value)
  {
  $input[base64_decode(mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $key, $name, MCRYPT_MODE_ECB, $iv ))] = $value;
  }?>

3 个答案:

答案 0 :(得分:1)

  

将表单字段命名为   与我的专栏名称相同?

简短的回答是并不总是,如果数据库配置正确,更改列/数据库/表的名称可以使应用程序更能抵御攻击。默认情况下,攻击者可以获得这些数据,如果他有sql注入,那么如果你把它交给他并不重要。

如果您确实想要隐藏这些名称,那么您还必须撤消对INFORMATION_SCHEMA数据库的访问权限:

REVOKE SELECT ON INFORMATION_SCHEMA.* TO mysql_app_user

这就是为什么:

常见的SQL注入攻击是从另一个表中选择多汁数据。在MySQL中,你不能像在(插入...; select * from ...; grant ...)中那样“堆叠quires”。所以你必须使用“联合选择”。

例如:

mysql_query("select path,type from images where id=".$_GET[id]);

相应的漏洞利用如下:

http://localhost/sql_inj.php?id=0 union select username,password from users where id=1

在这种情况下,第一个select语句将为空,没有主键为零。第二个select语句将从同一数据库中的username表中选择passworduser,这将获取1的主键,其中99%的时间是管理员即可。为了解决此问题,您需要知道表格的 EXACT 名称以及所需的列。

好吧,在mysql中有information_schema数据库绞盘提供这些数据。因此,如果列和数据库名称被遮挡,那么它们仍然可以通过以下方式获得:

http://localhost/sql_inj.php?id=0 union select COLUMN_NAME,"junk" from FROM INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME like "%user"

此查询将破坏任何安全性前缀。但是,同样的攻击可用于获取MySQL数据库中的 ALL 列,数据库和表。如果撤消对Web应用程序的mysql用户帐户的选择权限,则他无法执行此操作。您还应该撤消FILE权限,因为这些权限可用于上传后门或读取配置文件。

答案 1 :(得分:0)

如果服务器端的清理/验证代码很强,那么表单字段与表名相同/接近并不重要。

不要浪费时间试图对其进行模糊处理,如果您对自己的干净方法有信心,请使用常规字段名称。

答案 2 :(得分:0)

首先,我不会依赖混淆表单字段名称作为Web安全性的解决方案。使用多种方法来保证安全性要好得多:

  1. 过滤(就像您使用intval()
  2. 验证
  3. 转义(如果将内容插入到SQL字符串中)
  4. 使用参数准备查询(需要使用ext / mysqli或ext / pdo_mysql)
  5. 那就是说,混淆字段名称不会受到伤害。我不会去你所展示的散列列名的极端例子。这是不必要的开支。是否要在每次生成表单时调用散列函数对列名进行编码,并在每次处理表单时解码POST字段名称?

    您甚至不必对每个表单字段名称进行模糊处理,以使模糊处理达到其效果。如果表单字段的某些与数据库列名称不匹配,则攻击者不知道哪些匹配,哪些不匹配! : - )