注入攻击-SQL注入和代码注入

时间:2022-09-08 00:05:04

注入攻击

OWASP将注入攻击和跨站脚本攻击(XSS)列入网络应用程序十大常见安全风险。实际上,它们会一起出现,因为 XSS 攻击依赖于注入攻击的成功。虽然这是最明显的组合关系,但是注入攻击带来的不仅仅是 XSS。

注入攻击代指一类攻击,它们通过注入数据到一个网络应用程序以期获得执行,亦或是通过非预期的一个方式来执行恶意数据。这种类别的攻击包括跨站脚本攻击(XSS)、SQL 注入攻击、头部注入攻击、日志注入攻击和全路径暴露。当然限于篇幅,这里只是一个简单的介绍。

这类攻击是每个程序员的梦魇。它们数量庞大、攻击范围广,并且有时候防御措施很复杂,因此是最常见、成功率最高的网络攻击。所有的应用程序都需要从某个地方获取数据来运行。跨站脚本攻击和界面伪装漏洞最为常见,并且它们本身就已经非常重要,通常与注入攻击分开归类。接下来的一章我将单独介绍它们。

OWASP 对注入攻击的定义如下:

类似SQL、OS、LDAP注入攻击等注入攻击会在不可信数据作为命令或请求的一部分被发送到解释程序时发生。攻击者的恶意数据会迷惑解释程序去执行非计划的命令,或访问非授权的数据。

SQL 注入攻击

目前最常见的注入攻击形式是臭名昭著的 SQL 注入攻击。SQL 注入攻击不仅常见,而且致命。我要特别强调,了解这种攻击、实现攻击的条件以及防御攻击需要采取的措施极为重要。

SQL 注入攻击通过将数据注入网络应用程序,然后被用于 SQL 请求来操作。数据通常来自类似网页表单的不可信来源。不过,数据也可能来自包括数据库本身在内的其他来源。程序员通常会信任来自自己数据库的数据,以为它们是非常安全的,却没有意识到,在一种用法中安全,不代表它在所有其他用法中都是安全的。来自数据库在经过证明(比如说,通过验证流程)之前,应该被视为不可信。

如果攻击成功,SQL 注入攻击能够操纵受攻击的 SQL 请求,从而进行非程序员意愿的数据库操作。

看一下这条请求:

git·$db = new mysqli('localhost', 'username', 'password', 'storedb'); $result = $db->query( 'SELECT * FROM transactions WHERE user_id = ' . $_POST['user_id'] ); ·git

上面的请求中存在多处问题。首先,我们还没有验证 POST 数据来确保这是个有效的 user_id。其次,我们允许一个不可信来源告诉我们要使用哪个 user_id——攻击者可以任意设置一个有效 user_id。也许 user_id 包含在一个隐藏的表单字段,因为网络表单不允许编辑,我们就以为安全了(却不知道攻击者可以提交任何信息)。第三,我们并没有 escape 该 user_id,或将其作为一个绑定参数传给请求,由于我们一开始没有验证 SQL 请求,这就让攻击者有机会注入任意字符串来操纵该请求。

上述三点问题在网络应用程序中极其常见。

至于信任来自数据库的数据,想象一下我们使用 user_name 字段来搜索交易。用户名的范围相当广阔,可能还包含引用。可以想见,攻击者可以在一个用户名内储存一个 SQL 注入字符串。如果我们将数据库视为可信的数据来源,没能合理地 escape 或约束它,当我们在后续请求中再次使用该字符串时,它就可以操纵请求字符串。

另一个需要注意的 SQL 注入攻击因素是永久存储不需要总是在服务器上进行。HTML5 支持使用客户端数据库,可以借助 Javascript 使用 SQL 来查询。有两个支持这项操作的接口:WebSQL 和 IndexedDB。WebSQL 于2010年被 W3C 弃用,受到后台使用 SQLite 的 WebKit 浏览器支持。虽然这个接口不被推荐使用,但是 WebKit 处于后台兼容考虑,很有可能会继续支持它。正如它的名字所示,它接收 SQL 请求,因此容易遭受 SQL 注入攻击。IndexedDB 是一个新的备选,不过它是一种 NOSQL 数据库(不需要使用 SQL 查询)。

SQL 注入攻击范例

尝试操纵 SQL 命令的目标包含以下几种:

  1. 信息泄露
  2. 披露存储数据
  3. 操纵存储数据
  4. 避开权限管理
  5. 客户端 SQL 注入攻击

信息泄露

披露存储数据

操纵存储数据

避开权限管理

防御 SQL 注入攻击

防御 SQL 注入攻击可采用深度防御原则。在将数据用于 SQL 命令之前,应该进行验证,以确保它是我们期望的正确格式,并且在将数据包含在请求或绑定参数前,应该将其 escape。

验证

第二章讲述输入验证,而且正如我在其中提到的,我们应该假设不是由当前请求的 PHP 源代码直接生成的所有数据都不可信。对其严格验证,并且拒绝所有未通过验证的数据。不要尝试“修复”数据,除非只是简单修正数据格式。

常见的验证错误包括只验证数据当下用途(例如,展示或计算),却不考虑数据最终存储位置的数据库表字段的验证需求。

Escaping

通过使用mysqli 扩展,你可以利用 mysqli_real_escape_string() 函数来 escape包含在 SQL 查询中的所有数据。PostgresSQL 的 pgsql 扩展提供 pg_escape_bytea()、 pg_escape_identifier()、 pg_escape_literal() 和 pg_escape_string() 函数。Mssql(微软 SQL 服务器)不提供 escaping 功能,而经常被推荐的 addslashes() 方法并不够用——你实际上需要一个定制功能http://*.com/questions/574805/how-to-escape-strings-in-mssql-using-php

再告诉你一件头疼的事,你绝对绝对不能在 escape 进入 SQL 查询数据上出错。一旦失手,可能就会引发 SQL 注入攻击。

基于以上原因,并不推荐使用 escaping。它可以用来救急,如果你用来抽象的数据库程序库不强制参数绑定就能进行 SQL 查询,可能就需要使用它。否则你应该避免使用 escape。它很混乱,容易出错,而且因数据库扩展不同而存在差异。

参数化查询(预处理语句)

参数化或参数绑定是构建 SQL 查询的推荐方法,而且所有优秀的数据库程序库都默认使用这种方法。以下是使用 PHP 的 PDO 扩展的一个实例。

if(ctype_digit($_POST['id']) && is_int($_POST['id']))
{
$validatedId = $_POST['id'];
$pdo = new PDO('mysql:store.db');
$stmt = $pdo->prepare('SELECT * FROM transactions WHERE user_id = :id');
$stmt->bindParam(':id', $validatedId, PDO::PARAM_INT);
$stmt->execute();
} else {
// reject id value and report error to user
}

PDO 语句可用的bindParam() 方法让你可以给预处理语句中出现的占位符绑定参数,并且接受基本的数据类型参数,例如 PDO::PARAM_INT、 PDO::PARAM_BOOL、 PDO::PARAM_LOB 和 PDO::PARAM_STR。这种方法默认使用 PDO::PARAM_STR,因此记得对其他数值做相应调整!

不同于手动 escape,这种方式下的参数绑定(或者你的数据库使用的方法)会自动正确地 escape 绑定的数据,因此你不需要回忆之前用了哪种 escape 函数。持续使用参数绑定要比记着手动 escape 所有东西要可靠得多。

强制实施最小特权原则

制止已经发生的 SQL 注入攻击跟从一开始就防御同样重要。一旦攻击者获得执行 SQL 查询的能力,他们就会以一个数据库用户的身份进行查询。可以通过确保所有数据库用户只得到完成各自任务必需的权限,来执行最小特权原则。

如果一个数据库用户拥有很大的权限,攻击者就可能删除数据表,操纵其他用户的权限,从而发起其他 SQL 注入攻击。你绝对不能以超级用户、其他权限较高或管理员层级的用户身份访问网络应用程序的数据库,从而杜绝这种情况发生。

最小特权原则的另外一个变体是区别数据库的读数据和写数据权限。你可以设置一个拥有写数据权限的用户,和另一个只有读数据权限的用户。这种角色区分可以确保在 SQL 注入攻击目标为只读用户时,攻击者无法写数据或操纵表数据。这种生物隔离区划可以延伸到进一步限制访问权限,这样就可以将 SQL 注入攻击的影响最小化。

很多网络应用程序,尤其是开源应用程序,特别被设计成只有一个数据库用户,而且几乎从来不会有人检查该用户是不是高度特免的。记住以上观点,忍住诱惑,不要在一个管理员用户下运行这样的网络应用程序。

代码注入攻击(也叫Remote File Inclusion)

代码注入攻击指的是任何允许攻击者在网络应用程序中注入源代码,从而得到解读和执行的方法。这并不适用于对应用程序客户端的代码注入攻击,例如 Javascript,那属于跨站脚本攻击(XSS)。

源代码可以通过不可信的输入直接注入,或者网络应用程序在通过本地文件系统或类似 URL 这样的外部来源加载代码时被操纵。包含远程文件导致代码注入攻击的情况通常被称为远程文件包含漏洞,虽然远程文件包含攻击本身的目的就是为了注入代码。

造成代码注入攻击的初始原因包括输入验证失败,包含可能被当做 PHP 代码、任何语境下的不可信输入,未能保障源代码库的安全,在下载第三方程序库时不够谨慎,服务器配置不当导致非 PHP 文件通过网络服务器被传送到 PHP 解释程序。最后一点尤其要加以注意,因为它意味着不可信用户上传到服务器的所有文件都可能带来极大的风险。

代码注入攻击范例

众所周知,PHP 涉及无数代码注入攻击目标,因此任何一位程序员都要高度关注代码注入攻击问题。

文件包含攻击

代码注入攻击最明显的目标就是 include()、 include_once()、 require() 和 require_once() 函数。如果不可信输入被允许来决定传输给这些函数的路径参数,它就可能影响被包含的本地文件。应该注意的是,被包含的文件不一定是一个真正的 PHP 文件,任何能够携带文字数据(例如,几乎所有的)的被包含文件都有可能。

路径参数也可能遭受目录遍历攻击或远程文件包含攻击。在路径中使用 ../ 或 ..(dot-dot-slash) 字符串会让攻击者能够触及 PHP 流程能够访问的所有文件。除非 XXX 被禁用,否则以上函数还能接受 PHP 默认设置中的 URL。

评估

PHP 的 eval() 函数接收 PHP 代码字符串并执行。

正则表示式注入攻击

PHP 中 PCRE 的 preg_replace() 函数允许“e”(PREG_REPLACE_EVAL)修饰符,这就意味着替换字符串在替换后将被当成 PHP。用于替换字符串的不可信输入可能会注入即将执行的 PHP 代码。

缺陷文件包含逻辑攻击

按照定义,网络应用程序会包含满足各种需求所需的各类文件。通过操纵请求路径或请求参数,它可以利用服务器路由的缺陷逻辑、依赖管理、自动加载或其他流程,导致服务器包含非预期的本地文件。

这些超出网络应用程序设计初衷的操纵可能带来无法预料的影响。比如说,一个应用程序可能无意中暴露了只用于命令行用法的路径。该应用程序可能还暴露了构造函数用来执行任务的其他类(虽然并不推荐这种设计类的方法,不过还是有人这么做)。两种场景都有可能干扰应用程序的后台运行,导致本来不应该被直接访问的资源密集型运行活动遭受数据操纵或拒绝服务攻击(DOS)。

服务器配置不当

代码注入攻击的目标

由于代码注入攻击允许攻击者选择任意 PHP 代码来执行代码注入攻击的目标极其广泛。

防御代码注入攻击

命令注入攻击

命令注入攻击范例

防御命令注入攻击

原文地址:Injection Attacks

本文系 OneAPM 工程师编译整理。OneAPM 是应用性能管理领域的新兴领军企业,能帮助企业用户和开发者轻松实现:缓慢的程序代码和 SQL 语句的实时抓取。想阅读更多技术文章,请访问 OneAPM 官方博客

本文转自 OneAPM 官方博客

注入攻击-SQL注入和代码注入的更多相关文章

  1. 注入攻击(SQL注入防御)

    正确的防御SQL注入 sql注入的防御不是简单只做一些用户输入的escape处理,这样是不够的,只是提高了攻击者的门槛而已,还是不够安全. 例如 mysql_real_escape_string()函 ...

  2. 注入攻击(SQL注入)

    注入攻击是web安全领域中一种最为常见的攻击方式.注入攻击的本质,就是把用户输入的数据当做代码执行.这里有两个关键条件,第一是用户能够控制输入,第二个就是原本程序要执行的代码,将用户输入的数据进行了拼 ...

  3. SQL注入攻击和防御

    部分整理...   什么是SQL注入? 简单的例子, 对于一个购物网站,可以允许搜索,price小于某值的商品 这个值用户是可以输入的,比如,100 但是对于用户,如果输入,100' OR '1'=' ...

  4. ADO.NET笔记——带参数的查询防止SQL注入攻击

    相关知识: 把单引号替换成两个单引号,虽然能起到一定的防止SQL注入攻击的作用,但是更为有效的办法是把要拼接的内容做成“参数” SQLCommand支持带参数的查询,也就是说,可以在查询语句中指定参数 ...

  5. PHP漏洞全解(五)-SQL注入攻击

    本文主要介绍针对PHP网站的SQL注入攻击.所谓的SQL注入攻击,即一部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患.用户可以提交一段数据库查询代码,根据程序返 ...

  6. 带参数的查询防止SQL注入攻击

    把单引号替换成两个单引号,虽然能起到一定的防止SQL注入攻击的作用,但是更为有效的办法是把要拼接的内容做成“参数” SQLCommand支持带参数的查询,也就是说,可以在查询语句中指定参数: 参数的设 ...

  7. php安全编程—sql注入攻击

    php安全编程--sql注入攻击 定义 SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因 ...

  8. 【渗透攻防Web篇】SQL注入攻击高级

    前言 前面我们学习了如何寻找,确认,利用SQL注入漏洞的技术,本篇文章我将介绍一些更高级的技术,避开过滤,绕开防御.有攻必有防,当然还要来探讨一下SQL注入防御技巧. 目录 第五节 避开过滤方法总结 ...

  9. web攻击之三:SQL注入攻击的种类和防范手段

    观察近来的一些安全事件及其后果,安全专家们已经得到一个结论,这些威胁主要是通过SQL注入造成的.虽然前面有许多文章讨论了SQL注入,但今天所讨论的内容也许可帮助你检查自己的服务器,并采取相应防范措施. ...

随机推荐

  1. 高性能的JavaScript--数据访问(2)

    动态作用域 无论是with表达式还是try-catch表达式的catch子句,以及包含()的函数,都被认为是动态作用域.一个动态作用域只因为代码运行而存在.因此无法通过静态分析(查看代码机构)来确定( ...

  2. 关于C#操作数据库ExecuteNonQuery()的返回值问题

    ) { retValue = AccessCon.ExecuteSql(sql = "update salesData set sellingPrize='" + man.Sell ...

  3. C#中把Datatable转换为Json的5个代码实例

    一. /// <summary> /// Datatable转换为Json /// </summary> /// <param name="table&quot ...

  4. QT 字符串相等间距字符间增加字符

    /*************************************************Function: formatString()Description: 将十六进制字串每字节中间加 ...

  5. javascript原生方法实现extend

    var extend = (function () { for(var p in {toString:null}){ //检查当前浏览器是否支持forin循环去遍历出一个不可枚举的属性,比如toStr ...

  6. 2&period;1 re 模块

    正则表达式 简单的范围的字符组 字符 量词 字符集 分组 转义字符 flags 方法  .findall() .finditer() .search() .match()  .sub() .subn( ...

  7. 如何用kaldi做孤立词识别三

    这次wer由15%下降到0%了,后面跑更多的模型 LOG (apply-cmvn[5.2.124~1396-70748]:main():apply-cmvn.cc:162) Applied cepst ...

  8. angularjs学习第一天笔记

    您好,我是一名后端开发工程师,由于工作需要,现在系统的从0开始学习前端js框架之angular,每天把学习的一些心得分享出来,如果有什么说的不对的地方,请多多指正,多多包涵我这个前端菜鸟,欢迎大家的点 ...

  9. OC MRC之autorelease问题(代码分析)

    // // main.m // 08-autorelease // // Created by apple on 13-8-9. // Copyright (c) 2013年 itcast. All ...

  10. python 脚本运行时报错: AttributeError&colon; &&num;39&semi;module&&num;39&semi; object has no attribute &ast;&ast;&ast;

    最近在编写Python脚本过程中遇到一个问题比较奇怪:Python脚本完全正常没问题,但执行总报错"AttributeError: 'module' object has no attrib ...