【问题标题】:Sanitisation of input for a stored MySQL database procedure对存储的 MySQL 数据库过程的输入进行清理
【发布时间】:2012-12-04 12:30:06
【问题描述】:

我正在使用其他人制作的数据库(我并没有真正的更改它的授权)。但是,当我查看数据库中的存储过程时,我注意到了以下过程:

DELIMITER $$

CREATE PROCEDURE `logIn`(userName varChar(50), userPass varChar(50))
BEGIN
  declare userID int;

  SELECT 
    u.userID INTO userID 
  FROM
    users u
  WHERE
    u.userName=userName 
    AND u.userPassword=MD5(userPass);

  IF (IFNULL(uID,-1) > 0) THEN
    select 1 as outMsg;
  ELSE
    select 0 as outMsg;
  END IF;
END$$

对应的表users有三列:userID INTuserName VARCHAR(50)userPassword VARCHAR(50)

由于我对此不太擅长,有人可以告诉我是否需要对此类函数的输入进行清理以不允许任何 SQL 注入,如果不需要 - 为什么?非常感谢一般的经验法则。

附:此函数将在表单提交时从 JS 脚本调用。

【问题讨论】:

  • 过程本身不易受到攻击,因为参数uNameuPass 将由RDBMS 正确处理,并且您没有执行动态SQL 字符串。但是,您如何在代码中调用该过程可能会受到攻击......我们需要看到这一点。
  • 使用一些服务器端语言过滤器
  • 用 javascript 清理输入永远不会安全。这必须在服务器上完成。

标签: mysql sanitization


【解决方案1】:

这里有一些经验法则取决于基础数据类型及其插入数据库的方式。

首先,参数化查询总是最适合 SQL 注入保护.. 但是.. 如果你不能改变它..

字符串类型:

  1. 删除所有单引号 将任何单引号替换为单引号两次。

  2. 将以下任何字符替换为其编码的替代字符;

    • >
    • "
    • ;
    • (第 34 章)
    • )
    • (
    • 例如.. ) 替换为 & #x29;

      -(上例中的空格是为了让你看到代码,去掉它得到")")

对于字符串以外的数据类型,请检查数据类型是否正常,并删除任何不应出现在数据类型中的字符。如果是整数,请确保您传入的字符串是整数。这通常可以通过转换为代码中的类型来完成。演员要么工作..要么导致错误。检查数据类型 min 和 maxes 是否没有被超过也是很好的。例如.. 如果我正在检查一个整数,我可能会使用类似这样的代码:

var myInt = parseInt(param);

然后我可能会检查它的界限以确保它小于最大整数值并且大于最小整数值。

这应该足以防止 SQL 注入攻击......

而且.. 由于您没有发布实际与数据库接口的代码... 作为额外的预防措施.. 您可能还想删除 --,`,%,",", ""。

你只希望'sane'值进入数据库调用..所以像 $309 这样的整数没有意义,你想删除 $..。可能通过对任何非数字字符使用正则表达式替换逗号和句点。 [^[0-9,.]]

要格外小心。

【讨论】:

  • 据我所知,上述 php 使用 mysqli 的简单事实应该足以确保查询是安全的。我的结论正确吗?
  • 没有。为此,您必须绑定参数。 $stmt = $mysqli->prepare("INSERT INTO table (column) VALUES (?)"); // TODO 检查 $stmt 创建是否成功 // "s" 表示数据库需要一个字符串 $stmt->bind_param("s", $unsafe_variable);
  • 是的,我知道prepare 语句实际上使代码安全。但是,sprintf 不确保我提供的那个也是安全的吗?如果可能,请提供一个简短的例子,如果不是这样的话。
  • 你需要做的是 $stmt = $mysqli->prepare("call logIn(?,?)"); $stmt->bind_param('ss',$uName, $uPSW); $stmt->执行(); $stmt->bind_result($result); $stmt->fetch();回显$结果; $stmt->关闭(); $mysqli-close();
【解决方案2】:

是的,在尝试运行程序之前必须对输入进行清理。

您可能希望在此处共享该过程的实际调用点以获得更多帮助,因为无法在表单提交时直接从 JS 调用该过程。你可能有一个 Servlet、PHP 页面或一些 HTTP 友好的中介来以某种方式调用数据库。

【讨论】:

  • 我已经包含了调用的 PHP 页面,之前我没有注意到它实际上是从 PHP 代码中调用的。很抱歉造成混乱,正如我所说的,我不太擅长这个。
猜你喜欢
  • 2016-04-23
  • 1970-01-01
  • 1970-01-01
  • 2017-04-07
  • 1970-01-01
  • 1970-01-01
  • 2021-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多