环境介绍
SQL 注入是一种注入攻击。当攻击者提交恶意制作的输入,导致应用程序执行意外操作时,就会发生注入攻击。由于SQL数据库无处不在,SQL 注入是 Internet 上最常见的攻击类型之一。
1、我们会通过这个例子来了解下sql注入,一个简单的登录窗口
2、通过日志观察与应用程序交互时会发生什么
进入正题
3、我们随便猜测下密码,看看日志会记录什么?
4、日志如下
5、再试下后面加一个单引号,会发生什么呢?
6、可以看到程序崩溃了。日志显示SQL语法错误,表示引号处以一些意想不到的方式崩溃了。
发生错误:PG::SyntaxError: 错误:未终止的带引号的字符串位于或接近 “‘1’’ limit 1” LINE 1: …ers where email = ‘user@email.com’ and password = ‘1’’ limit … ^ : select * from users where email = ‘user@email.com’ and password = ‘1’’ limit 1.
由于意外错误,无法登录此用户。
7、而对应后端代码就是个样子了,是不是感觉有哪里不对劲呢?
可以看到引号直接插入到sql字符串里,语法错误提前终止查询,这就是报语法错误的原因
SELECT * FROM users WHERE email = 'user@email.com' AND pass = '1'' LIMIT 1
所以判断这个地方是存在sql注入漏洞的!!!
搞定它
8、既然存在sql注入漏洞,那我们不妨构造一下payload搞定它
我们输入1’or’1’='1
对应后端代码
SELECT * FROM users WHERE email = 'user@email.com' AND pass = '1'or'1'='1' LIMIT 1
9、发现可以不用输入密码就能登录,是不是很神奇
危害!
· 提取敏感信息,例如社会安全号码或信用卡详细信息。
· 枚举在网站上注册的用户的身份验证详细信息,以便这些登录名可用于对其他站点的攻击。
· 删除数据或删除表,破坏数据库,并使网站无法使用。
· 注入更多恶意代码,当用户访问该站点时执行。
如何预防!
10、SQL注入的危害可想而知,一不留神就被偷家,那就谈一谈怎么预防sql注入
参数化语句
编程语言使用数据库驱动程序与 SQL 数据库对话。 驱动程序允许应用程序针对数据库构建和运行 SQL 语句,根据需要提取和操作数据。参数化语句 确保以安全的方式处理传递到 SQL 语句的参数(即输入)。
转义输入
如果您无法使用参数化语句或为您编写 SQL 的库,那么下一个最佳方法是确保正确转义输入参数中的特殊字符串字符。
注入攻击通常依赖于攻击者能够制作一个输入,该输入将过早关闭它们出现在 SQL 语句中的参数字符串。(这就是为什么您会经常在尝试 SQL 注入攻击中看到’或"字符的原因。)
编程语言有描述包含引号的字符串的标准方法——SQL 在这方面没有什么不同。通常,将引号字符加倍 - 替换’为’’- 意味着 “将此引号视为字符串的一部分,而不是字符串的结尾”。
转义符号字符是抵御大多数 SQL 注入攻击的一种简单方法,许多语言都有标准函数 来实现这一点。但是,这种方法有几个缺点:
在构建 SQL 语句的代码库中,您需要非常小心地转义字符。
并非所有注入攻击都依赖于引号字符的滥用。 例如,当 SQL 语句中需要数字 ID 时,不需要引号字符。无论您使用多少引号字符,以下代码仍然容易受到注入攻击:
def current_user(id)
User.where("id = " + id)
end
其他注意事项
最小特权原则
应用程序应该确保每个进程或软件组件只能访问和影响它需要的资源。酌情应用“许可级别”,就像只有某些银行员工才能访问金库一样。应用受限制的权限 可以帮助减轻很多围绕注入攻击的风险。
应用程序很少需要在运行时更改数据库的结构——通常在发布窗口期间创建、删除和修改表,并具有临时提升的权限。因此,在运行时减少应用程序的权限是一个很好的做法,这样它最多可以编辑数据,但不能更改表结构。在 SQL 数据库中,这意味着确保您的生产帐户只能执行DML语句,而不能执行DDL 语句。
对于复杂的数据库设计,将这些权限设置得更加细化是值得的。许多进程只能通过存储过程获得执行数据编辑的权限,或者以只读权限执行。
以这种方式明智地设计访问管理可以提供重要的第二道防线。无论攻击者如何访问您的系统,它都可以减轻他们可能造成的损害类型。
密码散列
我们的示例 hack依赖于密码以纯文本形式存储在数据库中的事实。事实上,存储未加密的密码本身就是一个主要的安全漏洞。应用程序应该将用户密码存储为 强大的单向哈希,最好是 salted。这降低了恶意用户窃取凭据或冒充其他用户的风险。
第三方认证
最后要注意的是,通常值得考虑将应用程序的身份验证工作流程完全外包。Facebook、Twitter 和 Google 都提供成熟的OAuth API,可用于让用户使用他们在这些系统上的现有帐户登录您的网站。这使您作为应用程序开发人员免于滚动您自己的身份验证,并确保您的用户他们的密码仅存储在一个位置。