Base64作为清理Mysql用户输入的方法

时间:2014-06-12 03:05:45

标签: mysql input

我认为保证用户输入是mysql安全的唯一方法是使用白名单,只允许mysql安全输入,或者将输入编码为始终返回mysql安全的东西。 Base64接缝对我来说就像这样一个编码的候选者,以及mysql_escape_string ...除了用户可读性之外还有什么理由不应该使用Base64进行输入卫生吗?这被认为是不好的做法吗?我还有一种感觉,如果问题是由mysql处理而不是依靠单个程序员来确保数据是安全的,那么用户数据的所有过滤以确保正确的安全性可能更容易实现...例如通过使用单个函数而不是基于查询的字符串,以便命令和用户输入在整个调用过程中保持独立...

Like: mysql_query("SELECT * FROM Users WHERE username=","$userinput");

或者可以使用编码:

$input = encode($_POST['UserInput']);
mysql_query("SELECT * FROM Users WHERE username='$input'");

4 个答案:

答案 0 :(得分:4)

不要"清理" 输入,以此作为始终阻止SQL注入(1) - use placeholders (or proper escaping)的方法。始终如一。注意安全。问题已经解决了。

这个案例将是"安全" due to the limited domain 函数的base64_encode然而..

  

除了用户可读性之外,是否有任何理由不应该使用Base64进行输入卫生?这被认为是不好的做法吗?

不良做法并存储base64编码的值(这样显示的查询可能起作用 2 )会带来几个否定含义更改存储的信息:销毁值的排序,使信息不是简单的可搜索的,需要额外的 >"编码/解码"步骤,甚至消耗更多空间 - 哎哟!

因此,虽然可能存在基本64位编码数据的特定情况,但这种方法非常适合作为缓解SQL Injection的方法。

  

..如果问题是由mysql处理而不是依靠单个程序员来确保数据是安全的,那么可以更容易实现正确的安全性。

问题是由于通过文本协议访问SQL,其中查询命令/形状和混合在一起。使用正确的转义技术(例如mysql_real_escape_string)通过确保转义信息以便按预期解析 来解决此问题,从而解决了这个问题。一个base64编码步骤它实际上改变了提供的信息!

  

例如,通过使用单个函数而不是基于查询的字符串,以便命令和用户输入在整个调用过程中保持独立...

is exactly what placeholders provide!占位符是 普遍正确的方法,应该受到鼓励。占位符allow the query and values to be sent to the database separately受库/数据库支持;并通过逃避来模仿。正确的占位符使用消除了 SQL注入以及用户代码将值混合到SQL命令文本中的需要,这也可以使查询更容易编写和维护。

防止"个别程序员"通过编写可怕的查询,解决方案是阻止 ad-hoc查询分散在代码中:将数据访问操作收集到Data Access Layer (DAL)(可能与ORM结合)和仅暴露相关操作,确保在DAL中正确使用SQL。在更简单的项目中,DAL也是集中管理卫生 1 和其他验证逻辑的业务规则的合适位置。


1 更准确:

  • 清理业务规则的值;这应该可以防止错误的信息,例如用户名太短,包含受限制的字符,或者无法满足业务要求。

  • 使用占位符来阻止SQL Injection严格与将数据传输到SQL有关,并且与其中的信息无关。


2 虽然MySQL 5.6.1添加了FROM_BASE64,因此编码可能只是在SQL命令文本中使用,这仍然会增加一个明确的解码步骤并在使用这种编码方案时使查询复杂化。这种base64方法只是必要,因为已经有成熟的技术可以防止SQL注入,并且在初始问题中没有提出。

答案 1 :(得分:2)

如果您不想使用预准备语句,则使用real_escape_string

的简单方法

这是一种保护mysql免受用户输入影响的标准方法。没有必要重新发明轮子。

答案 2 :(得分:2)

不,不要使用base64编码来关闭SQL注入漏洞。首先,SQL注入不是一个需要解决的问题;它已经解决了。

早期版本的商业关系数据库(例如DB2,Oracle,Sybase)已经解决了这一问题。所有这些都提供了支持 预处理语句 的接口,使用占位符< strong> 绑定值

自从十五年前至少版本3.x(早在2000年)以来,MySQL就提供了“真正的转义字符串”功能。

真正的问题是开发人员忽略了他们编写的代码中的SQL注入漏洞。当指出这些漏洞时,最常见的反应似乎是“哦,这段代码只是为了学习。我现在不需要关注它。”他们通过制作易受攻击的代码来学习,并采用这些糟糕的编码实践。他们分享他们新获得的专有技术,不良编码实践的例子激增,新程序员从这些不好的例子中学习,并采用相同的错误编码实践。

避免SQL注入漏洞的最佳做法是将 预备语句 绑定值 一起使用。这完全符合您在问题中的建议,将已知为“安全”的静态SQL文本与提供的可能“不安全”值分开。这是编写代码的正确方法。

(这个讨论没有解决将可能不安全的值插入数据库的问题,以及坏代码如何检索这些值并将其处理为“安全”,而不是将它们视为可能“不安全” ”。)

你应该指出早期版本的MySQL不支持真正的“服务器端”预处理语句;客户端库模拟了对预准备语句的支持。客户端库接受了预准备语句和绑定值,并将它们捆绑到它发送到服务器的SQL文本中,但至少框架在接口中。 MySQL客户端库负责“转义”绑定值以使它们安全地包含在SQL文本中,但是该责任由客户端库处理,而不是由调用者处理。)

某些MySQL接口(特别是不推荐使用且常用的PHP mysql接口)不支持预准备语句和绑定变量。但它提供了下一个最好的东西,访问mysql_real_escape_string功能。文档解释说应该使用这个函数,但根据大量不使用它的代码示例,你根本不知道它的使用是非常重要的。

如果必须使用PHP mysql_接口,那么请正确使用 mysql_real_escape_string 函数,包括SQL文本中可能不安全的字符串。

$sqltext = "SELECT * FROM Users WHERE username= '" . mysql_real_escape_string($userinput) . "'"; 
mysql_query($sqltext);

如果您不必使用已弃用的mysql界面,请使用 mysqli PDO 。这两个接口都支持预处理语句和绑定变量。 (并不是说你会知道这些实际上提供了对这些功能的支持,基于完全忽略这些功能的大量代码示例,并且轻率地继续存在困扰mysql接口示例的相同错误编码实践。(一些开发人员似乎认为mysqli和PDO“修复”SQL注入漏洞,而不了解它们编写的具有SQL注入漏洞的代码,而不是他们使用的接口。

将PHP和MySQL单独列为SQL注入漏洞的唯一来源是不公平的。在使用Microsoft Visual Basic,Visual C ++,C#等编写的易受攻击代码的众多示例中,这些相同的漏洞很普遍。


底线,base64编码是 NOT SQL注入漏洞的解决方案。 (使用base64编码可能有一些很好的理由,但显然,避免SQL注入是 NOT 其中一个原因。)

答案 3 :(得分:0)

是的,它将完成工作

从技术上讲,您可以这样做:

    $name = "Joe Smith";
    $b64_name = base64_encode($name);
    $sql = "select * from users where username=from_base64('$b64_name');";

...它将起作用。实际上,这很正确:您阻止了字符串脱离其位置。您将其转换,然后mysql将其转换回去。这是在不更改整个数据库访问基础结构的情况下保护内容的一种简约方法。老套?当然。派上用场吗?好吧,是的,有时候确实如此。我在遗留代码上做了很多工作,在某些情况下,这种方法可以节省很多工作。

但是您有更好的选择

我们不再是过去。 PDO 可以绑定实际值,它的速度很快,它使您的代码更整洁,方便且易于使用。 (只记得始终关闭ATTR_EMULATE_PREPARES。愚蠢的是它不是默认设置。)

连接查询从来都不是真正的方法,我们之所以这样做,是因为周围没有别的东西了。因此,只要使用PDO,就可以在没有其他东西的情况下保持这个肮脏的把戏。