#注入攻击php
OWASP将注入攻击和跨站脚本攻击(XSS)列入网络应用程序十大常见安全风险。实际上,它们会一块儿出现,由于 XSS 攻击依赖于注入攻击的成功。虽然这是最明显的组合关系,可是注入攻击带来的不只仅是 XSS。html
注入攻击代指一类攻击,它们经过注入数据到一个网络应用程序以期得到执行,亦或是经过非预期的一个方式来执行恶意数据。这种类别的攻击包括跨站脚本攻击(XSS)、SQL 注入攻击、头部注入攻击、日志注入攻击和全路径暴露。固然限于篇幅,这里只是一个简单的介绍。mysql
这类攻击是每一个程序员的梦魇。它们数量庞大、攻击范围广,而且有时候防护措施很复杂,所以是最多见、成功率最高的网络攻击。全部的应用程序都须要从某个地方获取数据来运行。跨站脚本攻击和界面假装漏洞最为常见,而且它们自己就已经很是重要,一般与注入攻击分开归类。接下来的一章我将单独介绍它们。git
OWASP 对注入攻击的定义以下:程序员
相似SQL、OS、LDAP注入攻击等注入攻击会在不可信数据做为命令或请求的一部分被发送到解释程序时发生。攻击者的恶意数据会迷惑解释程序去执行非计划的命令,或访问非受权的数据。sql
##SQL 注入攻击数据库
目前最多见的注入攻击形式是臭名昭著的 SQL 注入攻击。SQL 注入攻击不只常见,并且致命。我要特别强调,了解这种攻击、实现攻击的条件以及防护攻击须要采起的措施极为重要。api
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 命令的目标包含如下几种:
####信息泄露
####披露存储数据
####操纵存储数据
####避开权限管理
###防护 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://stackoverflow.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 官方博客