Skip to main content

SQL 和 OS 命令注入攻击

一、什么是注入攻击

注入攻击是 Web 安全领域中一种最为常见的攻击方式。

XSS 本质上也是一种针对 HTML 的注入攻击。

注入攻击的本质,是把用户输入的数据当做代码执行。

这里有两个关键条件,第一个是用户能够控制输入;第二个是原本程序要执行的代码,拼接了用户输入的数据。

二、SQL 注入

1、什么是 SQL 注入

SQL 注入,是将恶意的 SQL 查询或添加语句插入到应用的输入参数中,然后在后台 SQL 服务器上解析执行的攻击,是一种常见的 Web 安全漏洞,攻击者利用这个漏洞,可以访问或修改数据,或者利用潜在的数据库漏洞进行攻击。

2、SQL 注入攻击的原理

一次 SQL 注入的过程:

  • 获取用户请求参数;
  • 拼接到代码当中;
  • SQL 语句按照构造参数的语义执行成功。

SQL注入的必备条件:

  1. 可以控制输入的数据;
  2. 服务器要执行的代码拼接了控制的数据。

SQL 注入流程中与正常请求服务器类似,只是黑客控制了数据,构造了 SQL 查询,而正常的请求不会 SQL 查询这一步。

SQL 注入的本质:数据和代码未分离,即数据当做了代码来执行。

举个万能钥匙的例子:

<form action="/login" method="POST">
<p>Username: <input type="text" name="username" /></p>
<p>Password: <input type="password" name="password" /></p>
<p><input type="submit" value="登陆" /></p>
</form>

后端的 SQL 语句可能是如下这样的:

let querySQL = `
SELECT *
FROM user
WHERE username='${username}'
AND psw='${password}'
`;
// 接下来就是执行 sql 语句...

这是常见的登录页面,但如果有一个恶意攻击者输入的用户名是 admin' --,密码随意输入,就可以直接登入系统,这就是 SQL 注入。

原来预想的 SQL 语句是:

SELECT * FROM user WHERE username='admin' AND psw='password'

但攻击者用奇怪用户名将 SQL 语句变成了如下形式:

SELECT * FROM user WHERE username='admin' --' AND psw='xxxx'

在 SQL 中 ' -- 是闭合和注释的意思,-- 是注释后面的内容的意思,所以查询语句就变成了:

SELECT * FROM user WHERE username='admin'

所谓的万能钥匙密码本质上就是 SQL 注入的一种利用方式。

3、SQL 注入攻击的危害

  • 获取数据库信息
    • 管理员后台用户名和密码
    • 获取其他数据库敏感信息:用户名、密码、手机号码、身份证、银行卡信息...
    • 整个数据库:脱裤
  • 获取服务器权限
  • 植入 Webshell,获取服务器后门
  • 读取服务器敏感文件

4、如何防御 SQL 注入攻击

  • 严格限制 Web 应用的数据库的操作权限,给此用户提供仅仅能够满足其工作的最低权限,从而最大限度的减少注入攻击对数据库的危害;

  • 后端代码检查输入的数据是否符合预期,严格限制变量的类型,例如使用正则表达式进行一些匹配处理;

  • 对进入数据库的特殊字符(' " \ < > & * ; 等)进行转义处理或编码转换。基本上所有的后端语言都有对字符串进行转义处理的方法,比如 lodash 的 lodash._escapehtmlchar 库,或 mysql2 的 escape,点击查看转译实现代码

  • 所有的查询语句建议使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中,即不要直接拼接 SQL 语句。例如 Node.js 中的 mysqljs 库的 query 方法中的 ? 占位参数。

三、OS 命令注入

1、OS 命令注入的定义

OS 命令注入和 SQL 注入差不多,只不过 SQL 注入是针对数据库的,而 OS 命令注入是针对操作系统的。

OS 命令注入攻击指通过 Web 应用,执行非法的操作系统命令达到攻击的目的。只要在能调用 Shell 函数的地方就有存在被攻击的风险。倘若调用 Shell 时存在疏漏,就可以执行插入的非法命令。

命令注入攻击可以向 Shell 发送命令,让 Windows 或 Linux 操作系统的命令行启动程序。也就是说,通过命令注入攻击可执行操作系统上安装着的各种程序。

2、OS 命令注入的原理

黑客构造命令提交给 Web 应用程序, Web 应用程序提取黑客构造的命令,拼接到被执行的命令中,因黑客注入的命令打破了原有命令结构,导致 Web 应用执行了额外的命令,最后 Web 应用程序将执行的结果输出到响应页面中。

这里通过一个例子来说明其原理,假如需要实现一个需求:用户提交一些内容到服务器,然后在服务器执行一些系统命令去返回一个结果给用户。

// 以 Node.js 为例,假如在接口中需要从 github 下载用户指定的 repo
const exec = require('mz/child_process').exec;
let params = {/* 用户输入的参数 */ };
exec(`git clone ${params.repo} /some/path`);

如果 params.repo 传入的是 https://github.com/admin/admin.github.io.git 确实能从指定的 git repo 上下载到想要的代码。

但如果 params.repo 传入的是 https://github.com/xx/xx.git && rm -rf /* && 恰好你的服务是用 root 权限起的就糟糕了。

3、如何防御 OS 注入攻击

  • 后端对前端提交内容进行规则限制(比如正则表达式)
  • 在调用系统命令前对所有传入参数进行命令行参数转义过滤;
  • 不要直接拼接命令语句,借助一些工具做拼接、转义预处理,例如 Node.js 的 shell-escape npm 包。

更多 Web 安全知识参考《白帽子讲Web安全》