“hirobykjj”为你分享10篇“确保PHP应用程序的安全[2]WEB安全”,经本站小编整理后发布,但愿对你的工作、学习、生活带来方便。
篇1:确保PHP应用程序的安全[4]WEB安全
浏览器内的数据操纵
有一类浏览器插件允许用户篡改页面上的头部元素和表单元素,使用 Tamper Data(一个 Mozilla 插件),可以很容易地操纵包含许多隐藏文本字段的简单表单,从而向 PHP 和 MySQL 发送指令。
用户在点击表单上的Submit之前,他可以启动 Tamper Data。在提交表单时,他会看到表单数据字段的列表。Tamper Data 允许用户篡改这些数据,然后浏览器完成表单提交。
让我们回到前面建立的示例。已经检查了字符串长度、清除了 HTML 标记并删除了十六进制字符。但是,添加了一些隐藏的文本字段,如下所示:
清单 17. 隐藏变量
if ($_POST['submit'] == “go”){
//strip_tags
$name = strip_tags($_POST['name']);
$name = substr($name,0,40);
//clean out any potential hexadecimal characters
$name = cleanHex($name);
//continue processing....
}
function cleanHex($input){
$clean =
preg_replace(“![][xX]([A-Fa-f0-9]{1,3})!”, “”,$input);
return $clean;
}
?>
“
”text“ name=”name“ id=”name“ size=”20“ maxlength=”40“/>
注意,隐藏变量之一暴露了表名:users。还会看到一个值为create的action字段。只要有基本的 SQL 经验,就能够看出这些命令可能控制着中间件中的一个 SQL 引擎。想搞大破坏的人只需改变表名或提供另一个选项,比如delete。
图 1 说明了 Tamper Data 能够提供的破坏范围。注意,Tamper Data 不但允许用户访问表单数据元素,还允许访问 HTTP 头和 cookie。
图 1. Tamper Data 窗口
要防御这种工具,最简单的方法是假设任何用户都可能使用 Tamper Data(或类似的工具)。只提供系统处理表单所需的最少量的信息,并把表单提交给一些专用的逻辑。例如,注册表单应该只提交给注册逻辑。
如果已经建立了一个通用表单处理函数,有许多页面都使用这个通用逻辑,那该怎么办?如果使用隐藏变量来控制流向,那该怎么办?例如,可能在隐藏表单变量中指定写哪个数据库表或使用哪个文件存储库。有 4 种选择:
不改变任何东西,暗自祈祷系统上没有任何恶意用户。 重写功能,使用更安全的专用表单处理函数,避免使用隐藏表单变量。 使用md5或其他加密机制对隐藏表单变量中的表名或其他敏感信息进行加密。在 PHP 端不要忘记对它们进行解密。 通过使用缩写或昵称让值的含义模糊,在 PHP 表单处理函数中再对这些值进行转换,
例如,如果要引用users表,可以用u或任意字符串(比如u8y90x0jkL)来引用它。
后两个选项并不完美,但是与让用户轻松地猜出中间件逻辑或数据模型相比,它们要好得多了。
现在还剩下什么问题呢?远程表单提交。
远程表单提交
Web 的好处是可以分享信息和服务。坏处也是可以分享信息和服务,因为有些人做事毫无顾忌。
以表单为例。任何人都能够访问一个 Web 站点,并使用浏览器上的File > Save As建立表单的本地副本。然后,他可以修改action参数来指向一个完全限定的 URL(不指向 formHandler.php,而是指向 http://www.yoursite.com/formHandler.php,因为表单在这个站点上),做他希望的任何修改,点击Submit,服务器会把这个表单数据作为合法通信流接收。
首先可能考虑检查$_SERVER['HTTP_REFERER'],从而判断请求是否来自自己的服务器,这种方法可以挡住大多数恶意用户,但是挡不住最高明的 。这些人足够聪明,能够篡改头部中的引用者信息,使表单的远程副本看起来像是从您的服务器提交的。
处理远程表单提交更好的方式是,根据一个惟一的字符串或时间戳生成一个令牌,并将这个令牌放在会话变量和表单中。提交表单之后,检查两个令牌是否匹配。如果不匹配,就知道有人试图从表单的远程副本发送数据。
要创建随机的令牌,可以使用 PHP 内置的md5()、uniqid()和rand()函数,如下所示:
清单 18. 防御远程表单提交
session_start();
if ($_POST['submit'] == ”go“){
//check token
if ($_POST['token'] == $_SESSION['token']){
//strip_tags
$name = strip_tags($_POST['name']);
$name = substr($name,0,40);
//clean out any potential hexadecimal characters
$name = cleanHex($name);
//continue processing....
}else{
//stop all processing! remote form. posting attempt!
}
}
$token = md5(uniqid(rand(), true));
$_SESSION['token']= $token;
function cleanHex($input){
$clean = preg_replace(”![][xX]([A-Fa-f0-9]{1,3})!“, ”“,$input);
return $clean;
}
?>
这种技术是有效的,这是因为在 PHP 中会话数据无法在服务器之间迁移。即使有人获得了您的 PHP 源代码,将它转移到自己的服务器上,并向您的服务器提交信息,您的服务器接收的也只是空的或畸形的会话令牌和原来提供的表单令牌。它们不匹配,远程表单提交就失败了。
篇2:确保PHP应用程序的安全[3]WEB安全
缓冲区溢出攻击
缓冲区溢出攻击试图使 PHP 应用程序中(或者更精确地说,在 Apache 或底层操作系统中)的内存分配缓冲区发生溢出,请记住,您可能是使用 PHP 这样的高级语言来编写 Web 应用程序,但是最终还是要调用 C(在 Apache 的情况下)。与大多数低级语言一样,C 对于内存分配有严格的规则。
缓冲区溢出攻击向缓冲区发送大量数据,使部分数据溢出到相邻的内存缓冲区,从而破坏缓冲区或者重写逻辑。这样就能够造成拒绝服务、破坏数据或者在远程服务器上执行恶意代码。
防止缓冲区溢出攻击的惟一方法是检查所有用户输入的长度。例如,如果有一个表单元素要求输入用户的名字,那么在这个域上添加值为 40 的maxlength属性,并在后端使用substr()进行检查。清单 13 给出表单和 PHP 代码的简短示例。
清单 13. 检查用户输入的长度
if ($_POST['submit'] == ”go“){
$name = substr($_POST['name'],0,40);
//continue processing....
}
?>
$_SERVER['PHP_SELF'];?>” method=“post”>
“name” id=“name” size=“20” maxlength=“40”/>
为什么既提供maxlength属性,又在后端进行substr()检查?因为纵深防御总是好的。浏览器防止用户输入 PHP 或 MySQL 不能安全地处理的超长字符串(想像一下有人试图输入长达 1,000 个字符的名称),而后端 PHP 检查会确保没有人远程地或者在浏览器中操纵表单数据。
正如您看到的,这种方式与前一节中使用strlen()检查GET变量pid的长度相似。在这个示例中,忽略长度超过 5 位的任何输入值,但是也可以很容易地将值截短到适当的长度,如下所示:
清单 14. 改变输入的 GET 变量的长度
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg(“^[0-9]+$”,$pid)){
//if non numeric $pid, send them back to home page
}
}else{
//empty $pid, so send them back to the home page
}
//we have a numeric pid, but it may be too long, so let's check
if (strlen($pid)>5){
$pid = substr($pid,0,5);
}
//we create an object of a fictional class Page, which is now
//even more protected from evil user input
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
//......
//......
?>
注意,缓冲区溢出攻击并不限于长的数字串或字母串。也可能会看到长的十六进制字符串(往往看起来像xA3或xFF)。记住,任何缓冲区溢出攻击的目的都是淹没特定的缓冲区,并将恶意代码或指令放到下一个缓冲区中,从而破坏数据或执行恶意代码。对付十六进制缓冲区溢出最简单的方法也是不允许输入超过特定的长度。
如果您处理的是允许在数据库中输入较长条目的表单文本区,那么无法在客户端轻松地限制数据的长度。在数据到达 PHP 之后,可以使用正则表达式清除任何像十六进制的字符串。
清单 15. 防止十六进制字符串
if ($_POST['submit'] == “go”){
$name = substr($_POST['name'],0,40);
//clean out any potential hexadecimal characters
$name = cleanHex($name);
//continue processing....
}
function cleanHex($input){
$clean = preg_replace(“![][xX]([A-Fa-f0-9]{1,3})!”, “”,$input);
return $clean;
}
?>
您可能会发现这一系列操作有点儿太严格了,
毕竟,十六进制串有合法的用途,比如输出外语中的字符。如何部署十六进制regex由您自己决定。比较好的策略是,只有在一行中包含过多十六进制串时,或者字符串的字符超过特定数量(比如 128 或 255)时,才删除十六进制串。
跨站点脚本攻击
在跨站点脚本(XSS) 攻击中,往往有一个恶意用户在表单中(或通过其他用户输入方式)输入信息,这些输入将恶意的客户端标记插入过程或数据库中。例如,假设站点上有一个简单的 来客登记簿程序,让访问者能够留下姓名、电子邮件地址和简短的消息。恶意用户可以利用这个机会插入简短消息之外的东西,比如对于其他用户不合适的图片或将 用户重定向到另一个站点的 JavaScript,或者窃取 cookie 信息。
幸运的是,PHP 提供了strip_tags()函数,这个函数可以清除任何包围在 HTML 标记中的内容。strip_tags()函数还允许提供允许标记的列表,比如或。
清单 16 给出一个示例,这个示例是在前一个示例的基础上构建的。
清单 16. 从用户输入中清除 HTML 标记
if ($_POST['submit'] == “go”){
//strip_tags
$name = strip_tags($_POST['name']);
$name = substr($name,0,40);
//clean out any potential hexadecimal characters
$name = cleanHex($name);
//continue processing....
}
function cleanHex($input){
$clean = preg_replace
(“![][xX]([A-Fa-f0-9]{1,3})!”, “”,$input);
return $clean;
}
?>
“
”text“ name=”name“ id=”name“ size=”20“ maxlength=”40“/>
从安全的角度来看,对公共用户输入使用strip_tags()是必要的。如果表单在受保护区域(比如内容管理系统)中,而且您相信用户会正确地执行他们的任务(比如为 Web 站点创建 HTML 内容),那么使用strip_tags()可能是不必要的,会影响工作效率。
还有一个问题:如果要接受用户输入,比如对贴子的评论或来客登记项,并需要将这个输入向其他用户显示,那么一定要将响应放在 PHP 的htmlspecialchars()函数中。这个函数将与符号、<和>符号转换为 HTML 实体。例如,与符号(&)变成&。这样的话,即使恶意内容躲开了前端strip_tags()的处理,也会在后端被htmlspecialchars()处理掉和>
篇3:确保PHP应用程序的安全[2]WEB安全
防止 SQL 注入攻击
在SQL 注入攻击中,用户通过操纵表单或GET查询字符串,将信息添加到数据库查询中,例如,假设有一个简单的登录数据库。这个数据库中的每个记录都有一个用户名字段和一个密码字段。构建一个登录表单,让用户能够登录。
清单 5. 简单的登录表单
Login
这个表单接受用户输入的用户名和密码,并将用户输入提交给名为 verify.php 的文件。在这个文件中,PHP 处理来自登录表单的数据,如下所示:
清单 6. 不安全的 PHP 表单处理代码
$okay = 0;
$username = $_POST['user'];
$pw = $_POST['pw'];
$sql = ”select count(*) as ctr from users where
username='“.$username.”' and password='“. $pw.”' limit 1“;
$result = mysql_query($sql);
while ($data = mysql_fetch_object($result)){
if ($data->ctr == 1){
//they're okay to enter the application!
$okay = 1;
}
}
if ($okay){
$_SESSION['loginokay'] = true;
header(”index.php“);
}else{
header(”login.php“);
}
?>
这段代码看起来没问题,对吗?世 界各地成百(甚至成千)的 PHP/MySQL 站点都在使用这样的代码。它错在哪里?好,记住 “不能信任用户输入”。这里没有对来自用户的任何信息进行转义,因此使应用程序容易受到攻击。具体来说,可能会出现任何类型的 SQL 注入攻击。
例如,如果用户输入foo作为用户名,输入' or '1'='1作为密码,那么实际上会将以下字符串传递给 PHP,然后将查询传递给 MySQL:
$sql = ”select count(*) as ctr from users where
username='foo' and password='' or '1'='1' limit 1“;
这个查询总是返回计数值 1,因此 PHP 会允许进行访问。通过在密码字符串的末尾注入某些恶意 SQL, 就能装扮成合法的用户。
解决这个问题的办法是,将 PHP 的内置mysql_real_escape_string函数用作任何用户输入的包装器。这个函数对字符串中的字符进行转义,使字符串不可能传递撇号等特殊字符并让 MySQL 根据特殊字符进行操作。清单 7 展示了带转义处理的代码。
清单 7. 安全的 PHP 表单处理代码
$okay = 0;
$username = $_POST['user'];
$pw = $_POST['pw'];
$sql = ”select count(*) as ctr from users where
username='“.mysql_real_escape_string($username).”'
and password='“. mysql_real_escape_string($pw).”' limit 1“;
$result = mysql_query($sql);
while ($data = mysql_fetch_object($result)){
if ($data->ctr == 1){
//they're okay to enter the application!
$okay = 1;
}
}
if ($okay){
$_SESSION['loginokay'] = true;
header(”index.php“);
}else{
header(”login.php“);
}
?>
使用mysql_real_escape_string()作为用户输入的包装器,就可以避免用户输入中的任何恶意 SQL 注入。如果用户尝试通过 SQL 注入传递畸形的密码,那么会将以下查询传递给数据库:
select count(*) as ctr from users where
username='foo' and password='' or '1'='1' limit 1”
数据库中没有任何东西与这样的密码匹配。仅仅采用一个简单的步骤,就堵住了 Web 应用程序中的一个大漏洞。这里得出的经验是,总是应该对 SQL 查询的用户输入进行转义。
但是,还有几个安全漏洞需要堵住。下一项是操纵GET变量。
防止用户操纵 GET 变量
在前一节中,防止了用户使用畸形的密码进行登录。如果您很聪明,应该应用您学到的方法,确保对 SQL 语句的所有用户输入进行转义。
但是,用户现在已经安全地登录了。用户拥有有效的密码,并不意味着他将按照规则行事 —— 他有很多机会能够造成损害。例如,应用程序可能允许用户查看特殊的内容。所有链接指向template.php?pid=33或template.php?pid=321这样的位置。URL 中问号后面的部分称为查询字符串。因为查询字符串直接放在 URL 中,所以也称为GET 查询字符串。
在 PHP 中,如果禁用了register_globals,那么可以用$_GET['pid']访问这个字符串。在 template.php 页面中,可能会执行与清单 8 相似的操作。
清单 8. 示例 template.php
$pid = $_GET['pid'];
//we create an object of a fictional class Page
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
//......
//......
?>
这里有什么错吗?首先,这里隐含地相信来自浏览器的GET变量pid是安全的,
这会怎么样呢?大多数用户没那么聪明,无法构造出语义攻击。但是,如果他们注意到浏览器的 URL 位置域中的 pid=33,就可能开始捣乱。如果他们输入另一个数字,那么可能没问题;但是如果输入别的东西,比如输入 SQL 命令或某个文件的名称(比如 /etc/passwd),或者搞别的恶作剧,比如输入长达 3,000 个字符的数值,那么会发生什么呢?
在这种情况下,要记住基本规则,不要信任用户输入。应用程序开发人员知道 template.php 接受的个人标识符(PID)应该是数字,所以可以使用 PHP 的is_numeric()函数确保不接受非数字的 PID,如下所示:
清单 9. 使用 is_numeric() 来限制 GET 变量
$pid = $_GET['pid'];
if (is_numeric($pid)){
//we create an object of a fictional class Page
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
//......
//......
}else{
//didn't pass the is_numeric() test, do something else!
}?>
这个方法似乎是有效的,但是以下这些输入都能够轻松地通过is_numeric()的检查:
100 (有效) 100.1 (不应该有小数位) +0123.45e6 (科学计数法 —— 不好) 0xff33669f (十六进制 —— 危险!危险!)
那么,有安全意识的 PHP 开发人员应该怎么做呢?多年的经验表明,最好的做法是使用正则表达式来确保整个GET变量由数字组成,如下所示:
清单 10. 使用正则表达式限制 GET 变量
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg(“^[0-9]+$”,$pid)){
//do something appropriate, like maybe logging
them out or sending them back to home page
}
}else{
//empty $pid, so send them back to the home page
}
//we create an object of a fictional class Page, which is now
//moderately protected from evil user input
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
//......
//......
?>
需要做的只是使用strlen()检查变量的长度是否非零;如果是,就使用一个全数字正则表达式来确保数据元素是有效的。如果 PID 包含字母、斜线、点号或任何与十六进制相似的内容,那么这个例程捕获它并将页面从用户活动中屏蔽。如果看一下Page类幕后的情况,就会看到有安全意识的 PHP 开发人员已经对用户输入$pid进行了转义,从而保护了fetchPage()方法,如下所示:
清单 11. 对 fetchPage() 方法进行转义
class Page{
function fetchPage($pid){
$sql = “select pid,title,desc,kw,content,
status from page where pid='
”.mysql_real_escape_string($pid).“'”;
//etc, etc....
}
}
?>
您可能会问,“既然已经确保 PID 是数字,那么为什么还要进行转义?” 因为不知道在多少不同的上下文和情况中会使用fetchPage()方法。必须在调用这个方法的所有地方进行保护,而方法中的转义体现了纵深防御的意义。
如果用户尝试输入非常长的数值,比如长达 1000 个字符,试图发起缓冲区溢出攻击,那么会发生什么呢?下一节更详细地讨论这个问题,但是目前可以添加另一个检查,确保输入的 PID 具有正确的长度。您知道数据库的pid字段的最大长度是 5 位,所以可以添加下面的检查。
清单 12. 使用正则表达式和长度检查来限制 GET 变量
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg(“^[0-9]+$”,$pid) && strlen($pid) > 5){
//do something appropriate, like maybe logging
them out or sending them back to home page
}
}else{
//empty $pid, so send them back to the home page
}
//we create an object of a fictional class Page, which is now
//even more protected from evil user input
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
//......
//......
?>
现在,任何人都无法在数据库应用程序中塞进一个 5,000 位的数值 —— 至少在涉及GET字符串的地方不会有这种情况。想像一下 在试图突破您的应用程序而遭到挫折时咬牙切齿的样子吧!而且因为关闭了错误报告, 更难进行侦察。
篇4:确保 PHP 应用程序的安全
目标
本教程讲解如何防御最常见的安全威胁:SQL 注入、操纵 GET 和 POST 变量、缓冲区溢出攻击、跨站点脚本攻击、浏览器内的数据操纵和远程表单提交,
前提条件
本教程是为至少有一年编程经验的 PHP 开发人员编写的。您应该了解 PHP 的语法和约定;这里不解释这些内容。有使用其他语言(比如 Ruby、Python 和 Perl)的经验的开发人员也能够从本教程中受益,因为这里讨论的许多规则也适用于其他语言和环境。
安全性快速简介
Web 应用程序最重要的部分是什么?根据回答问题的人不同,对这个问题的答案可能是五花八门。业务人员需要可靠性和可伸缩性。IT 支持团队需要健壮的可维护的代码。最终用户需要漂亮的用户界面和执行任务时的高性能。但是,如果回答 “安全性”,那么每个人都会同意这对 Web 应用程序很重要。
但是,大多数讨论到此就打住了。尽管安全性在项目的检查表中,但是往往到了项目交付之前才开始考虑解决安全性问题。采用这种方式的 Web 应用程序项目的数量多得惊人。开发人员工作几个月,只在最后才添加安全特性,从而让 Web 应用程序能够向公众开放。
结果往往是一片混乱,甚至需要返工,因为代码已经经过检验、单元测试并集成为更大的框架,之后才在其中添加安全特性。添加安全性之后,主要组件可能会停止工作。安全性的集成使得原本顺畅(但不安全)的过程增加额外负担或步骤。
本教程提供一种将安全性集成到 PHP Web 应用程序中的好方法。它讨论几个一般性安全主题,然后深入讨论主要的安全漏洞以及如何堵住它们。在学完本教程之后,您会对安全性有更好的理解。
主题包括:
SQL 注入攻击
操纵 GET 字符串
缓冲区溢出攻击
跨站点脚本攻击(XSS)
浏览器内的数据操纵
远程表单提交
Web 安全性 101
在讨论实现安全性的细节之前,最好从比较高的角度讨论 Web 应用程序安全性。本节介绍安全哲学的一些基本信条,无论正在创建何种 Web 应用程序,都应该牢记这些信条。这些思想的一部分来自 Chris Shiflett(他关于 PHP 安全性的书是无价的宝库),一些来自 Simson Garfinkel(参见 参考资料),还有一些来自多年积累的知识。
规则 1:绝不要信任外部数据或输入
关于 Web 应用程序安全性,必须认识到的第一件事是不应该信任外部数据。外部数据(outside data) 包括不是由程序员在 PHP 代码中直接输入的任何数据。在采取措施确保安全之前,来自任何其他来源(比如 GET 变量、表单 POST、数据库、配置文件、会话变量或 cookie)的任何数据都是不可信任的。
例如,下面的数据元素可以被认为是安全的,因为它们是在 PHP 中设置的。
清单 1. 安全无暇的代码
复制PHP内容到剪贴板
PHP代码:
$myUsername = ‘tmyer’;
$arrayUsers = array(’tmyer’, ‘tom’, ‘tommy’);
define(”GREETING”, ‘hello there’ . $myUsername);
但是,下面的数据元素都是有瑕疵的。
清单 2. 不安全、有瑕疵的代码 复制PHP内容到剪贴板
PHP代码:
$myUsername = $_POST['username']; //tainted!
$arrayUsers = array($myUsername, ‘tom’, ‘tommy’); //tainted!
define(”GREETING”, ‘hello there’ . $myUsername); //tainted!
为什么第一个变量 $myUsername 是有瑕疵的?因为它直接来自表单 POST。用户可以在这个输入域中输入任何字符串,包括用来清除文件或运行以前上传的文件的恶意命令。您可能会问,“难道不能使用只接受字母 A-Z 的客户端(JavaScript)表单检验脚本来避免这种危险吗?”是的,这总是一个有好处的步骤,但是正如在后面会看到的,任何人都可以将任何表单下载到自己的机器上,修改它,然后重新提交他们需要的任何内容。
解决方案很简单:必须对 $_POST['username'] 运行清理代码。如果不这么做,那么在使用 $myUsername 的任何其他时候(比如在数组或常量中),就可能污染这些对象。
对用户输入进行清理的一个简单方法是,使用正则表达式来处理它。在这个示例中,只希望接受字母。将字符串限制为特定数量的字符,或者要求所有字母都是小写的,这可能也是个好主意。
清单 3. 使用户输入变得安全 复制PHP内容到剪贴板
PHP代码:
$myUsername = cleanInput($_POST['username']); //clean!
$arrayUsers = array($myUsername, ‘tom’, ‘tommy’); //clean!
define(”GREETING”, ‘hello there’ . $myUsername); //clean!
function cleanInput($input){
$clean = strtolower($input);
$clean = preg_replace(”/[^a-z]/”, “”, $clean);
$clean = substr($clean,0,12);
return $clean;
}
规则 2:禁用那些使安全性难以实施的 PHP 设置
已经知道了不能信任用户输入,还应该知道不应该信任机器上配置 PHP 的方式。例如,要确保禁用 register_globals。如果启用了 register_globals,就可能做一些粗心的事情,比如使用 $variable 替换同名的 GET 或 POST 字符串。通过禁用这个设置,PHP 强迫您在正确的名称空间中引用正确的变量。要使用来自表单 POST 的变量,应该引用 $_POST['variable']。这样就不会将这个特定变量误会成 cookie、会话或 GET 变量。
要检查的第二个设置是错误报告级别。在开发期间,希望获得尽可能多的错误报告,但是在交付项目时,希望将错误记录到日志文件中,而不是显示在屏幕上。为什么呢?因为恶意的 会使用错误报告信息(比如 SQL 错误)来猜测应用程序正在做什么。这种侦察可以帮助 突破应用程序。为了堵住这个漏洞,需要编辑 php.ini 文件,为 error_log 条目提供合适的目的地,并将 display_errors 设置为 Off。
规则 3:如果不能理解它,就不能保护它
一些开发人员使用奇怪的语法,或者将语句组织得很紧凑,形成简短但是含义模糊的代码。这种方式可能效率高,但是如果您不理解代码正在做什么,那么就无法决定如何保护它。
例如,您喜欢下面两段代码中的哪一段?
清单 4. 使代码容易得到保护 复制PHP内容到剪贴板
PHP代码:
//obfuscated code
$input = (isset($_POST['username']) ? $_POST['username']:”);
//unobfuscated code
$input = ”;
if (isset($_POST['username'])){
$input = $_POST['username'];
}else{
$input = ”;
}
在第二个比较清晰的代码段中,很容易看出 $input 是有瑕疵的,需要进行清理,然后才能安全地处理。
规则 4:“纵深防御” 是新的法宝
本教程将用示例来说明如何保护在线表单,同时在处理表单的 PHP 代码中采用必要的措施。同样,即使使用 PHP regex 来确保 GET 变量完全是数字的,仍然可以采取措施确保 SQL 查询使用转义的用户输入。
纵深防御不只是一种好思想,它可以确保您不会陷入严重的麻烦。
既然已经讨论了基本规则,现在就来研究第一种威胁:SQL 注入攻击。
防止 SQL 注入攻击
在 SQL 注入攻击 中,用户通过操纵表单或 GET 查询字符串,将信息添加到数据库查询中。例如,假设有一个简单的登录数据库。这个数据库中的每个记录都有一个用户名字段和一个密码字段。构建一个登录表单,让用户能够登录。
清单 5. 简单的登录表单 复制PHP内容到剪贴板
PHP代码:
Login
这个表单接受用户输入的用户名和密码,并将用户输入提交给名为 verify.php 的文件。在这个文件中,PHP 处理来自登录表单的数据,如下所示:
清单 6. 不安全的 PHP 表单处理代码 复制PHP内容到剪贴板
PHP代码:
$okay = 0;
$username = $_POST['user'];
$pw = $_POST['pw'];
$sql = “select count(*) as ctr from users where
username=’”.$username.”‘ and password=’”. $pw.”‘ limit 1″;
$result = mysql_query($sql);
while ($data = mysql_fetch_object($result)){
if ($data->ctr == 1){
//they’re okay to enter the application!
$okay = 1;
}
}
if ($okay){
$_SESSION['loginokay'] = true;
header(”index.php”);
}else{
header(”login.php”);
}
?>
这段代码看起来没问题,对吗?世界各地成百(甚至成千)的 PHP/MySQL 站点都在使用这样的代码。它错在哪里?好,记住 “不能信任用户输入”。这里没有对来自用户的任何信息进行转义,因此使应用程序容易受到攻击。具体来说,可能会出现任何类型的 SQL 注入攻击。
例如,如果用户输入 foo 作为用户名,输入 ‘ or ‘1′=’1 作为密码,那么实际上会将以下字符串传递给 PHP,然后将查询传递给 MySQL:
$sql = “select count(*) as ctr from users where
username=’foo’ and password=” or ‘1′=’1′ limit 1″;
这个查询总是返回计数值 1,因此 PHP 会允许进行访问。通过在密码字符串的末尾注入某些恶意 SQL, 就能装扮成合法的用户。
解决这个问题的办法是,将 PHP 的内置 mysql_real_escape_string() 函数用作任何用户输入的包装器。这个函数对字符串中的字符进行转义,使字符串不可能传递撇号等特殊字符并让 MySQL 根据特殊字符进行操作。清单 7 展示了带转义处理的代码。
清单 7. 安全的 PHP 表单处理代码 复制PHP内容到剪贴板
PHP代码:
$okay = 0;
$username = $_POST['user'];
$pw = $_POST['pw'];
$sql = “select count(*) as ctr from users where
username=’”.mysql_real_escape_string($username).”‘
and password=’”. mysql_real_escape_string($pw).”‘ limit 1″;
$result = mysql_query($sql);
while ($data = mysql_fetch_object($result)){
if ($data->ctr == 1){
//they’re okay to enter the application!
$okay = 1;
}
}
if ($okay){
$_SESSION['loginokay'] = true;
header(”index.php”);
}else{
header(”login.php”);
}
?>
使用 mysql_real_escape_string() 作为用户输入的包装器,就可以避免用户输入中的任何恶意 SQL 注入。如果用户尝试通过 SQL 注入传递畸形的密码,那么会将以下查询传递给数据库:
select count(*) as ctr from users where
username=’foo’ and password=’’ or ’1’=’1′ limit 1″
数据库中没有任何东西与这样的密码匹配。仅仅采用一个简单的步骤,就堵住了 Web 应用程序中的一个大漏洞。这里得出的经验是,总是应该对 SQL 查询的用户输入进行转义。
但是,还有几个安全漏洞需要堵住。下一项是操纵 GET 变量。
防止用户操纵 变量
在前一节中,防止了用户使用畸形的密码进行登录。如果您很聪明,应该应用您学到的方法,确保对 SQL 语句的所有用户输入进行转义。
但是,用户现在已经安全地登录了。用户拥有有效的密码,并不意味着他将按照规则行事 ―― 他有很多机会能够造成损害。例如,应用程序可能允许用户查看特殊的内容。所有链接指向 template.php?pid=33 或 template.php?pid=321 这样的位置。URL 中问号后面的部分称为查询字符串。因为查询字符串直接放在 URL 中,所以也称为 GET 查询字符串。
在 PHP 中,如果禁用了 register_globals,那么可以用 $_GET['pid'] 访问这个字符串。在 template.php 页面中,可能会执行与清单 8 相似的操作。
清单 8. 示例 template.php 复制PHP内容到剪贴板
PHP代码:
$pid = $_GET['pid'];
//we create an object of a fictional class Page
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
//……
//……
?>
这里有什么错吗?首先,这里隐含地相信来自浏览器的 GET 变量 pid 是安全的。这会怎么样呢?大多数用户没那么聪明,无法构造出语义攻击。但是,如果他们注意到浏览器的 URL 位置域中的 pid=33,就可能开始捣乱。如果他们输入另一个数字,那么可能没问题;但是如果输入别的东西,比如输入 SQL 命令或某个文件的名称(比如 /etc/passwd),或者搞别的恶作剧,比如输入长达 3,000 个字符的数值,那么会发生什么呢?
在这种情况下,要记住基本规则,不要信任用户输入。应用程序开发人员知道 template.php 接受的个人标识符(PID)应该是数字,所以可以使用 PHP 的 is_numeric() 函数确保不接受非数字的 PID,如下所示:
清单 9. 使用 is_numeric() 来限制 GET 变量 复制PHP内容到剪贴板
PHP代码:
$pid = $_GET['pid'];
if (is_numeric($pid)){
//we create an object of a fictional class Page
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
//……
//……
}else{
//didn’t pass the is_numeric() test, do something else!
}?>
这个方法似乎是有效的,但是以下这些输入都能够轻松地通过 is_numeric() 的检查:
100 (有效)
100.1 (不应该有小数位)
+0123.45e6 (科学计数法 ―― 不好)
0xff33669f (十六进制 ―― 危险!危险!)
那么,有安全意识的 PHP 开发人员应该怎么做呢?多年的经验表明,最好的做法是使用正则表达式来确保整个 GET 变量由数字组成,如下所示:
清单 10. 使用正则表达式限制 GET 变量 复制PHP内容到剪贴板
PHP代码:
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg(”^[0-9]+$”,$pid)){
//do something appropriate, like maybe logging
them out or sending them back to home page
}
}else{
//empty $pid, so send them back to the home page
}
//we create an object of a fictional class Page, which is now
//moderately protected from evil user input
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
//……
//……
?>
需要做的只是使用 strlen() 检查变量的长度是否非零;如果是,就使用一个全数字正则表达式来确保数据元素是有效的,
如果 PID 包含字母、斜线、点号或任何与十六进制相似的内容,那么这个例程捕获它并将页面从用户活动中屏蔽。如果看一下 Page 类幕后的情况,就会看到有安全意识的 PHP 开发人员已经对用户输入 $pid 进行了转义,从而保护了 fetchPage() 方法,如下所示:
清单 11. 对 fetchPage() 方法进行转义 复制PHP内容到剪贴板
PHP代码:
class Page{
function fetchPage($pid){
$sql = “select pid,title,desc,kw,content,
status from page where pid=’
”.mysql_real_escape_string($pid).”‘”;
//etc, etc….
}
}
?>
您可能会问,“既然已经确保 PID 是数字,那么为什么还要进行转义?” 因为不知道在多少不同的上下文和情况中会使用 fetchPage() 方法。必须在调用这个方法的所有地方进行保护,而方法中的转义体现了纵深防御的意义。
如果用户尝试输入非常长的数值,比如长达 1000 个字符,试图发起缓冲区溢出攻击,那么会发生什么呢?下一节更详细地讨论这个问题,但是目前可以添加另一个检查,确保输入的 PID 具有正确的长度。您知道数据库的 pid 字段的最大长度是 5 位,所以可以添加下面的检查。
清单 12. 使用正则表达式和长度检查来限制 GET 变量 复制PHP内容到剪贴板
PHP代码:
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg(”^[0-9]+$”,$pid) && strlen($pid) > 5){
//do something appropriate, like maybe logging
them out or sending them back to home page
}
}else{
//empty $pid, so send them back to the home page
}
//we create an object of a fictional class Page, which is now
//even more protected from evil user input
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
//……
//……
?>
现在,任何人都无法在数据库应用程序中塞进一个 5,000 位的数值 ―― 至少在涉及 GET 字符串的地方不会有这种情况。想像一下 在试图突破您的应用程序而遭到挫折时咬牙切齿的样子吧!而且因为关闭了错误报告, 更难进行侦察。
缓冲区溢出攻击
缓冲区溢出攻击 试图使 PHP 应用程序中(或者更精确地说,在 Apache 或底层操作系统中)的内存分配缓冲区发生溢出。请记住,您可能是使用 PHP 这样的高级语言来编写 Web 应用程序,但是最终还是要调用 C(在 Apache 的情况下)。与大多数低级语言一样,C 对于内存分配有严格的规则。
缓冲区溢出攻击向缓冲区发送大量数据,使部分数据溢出到相邻的内存缓冲区,从而破坏缓冲区或者重写逻辑。这样就能够造成拒绝服务、破坏数据或者在远程服务器上执行恶意代码。
防止缓冲区溢出攻击的惟一方法是检查所有用户输入的长度。例如,如果有一个表单元素要求输入用户的名字,那么在这个域上添加值为 40 的 maxlength 属性,并在后端使用 substr() 进行检查。清单 13 给出表单和 PHP 代码的简短示例。
清单 13. 检查用户输入的长度 复制PHP内容到剪贴板
PHP代码:
if ($_POST['submit'] == “go”){
$name = substr($_POST['name'],0,40);
//continue processing….
}
?>
$_SERVER['PHP_SELF'];?>” method=”post”>
“name” id=”name” size=”20″ maxlength=”40″/>
为什么既提供 maxlength 属性,又在后端进行 substr() 检查?因为纵深防御总是好的。浏览器防止用户输入 PHP 或 MySQL 不能安全地处理的超长字符串(想像一下有人试图输入长达 1,000 个字符的名称),而后端 PHP 检查会确保没有人远程地或者在浏览器中操纵表单数据。
正如您看到的,这种方式与前一节中使用 strlen() 检查 GET 变量 pid 的长度相似。在这个示例中,忽略长度超过 5 位的任何输入值,但是也可以很容易地将值截短到适当的长度,如下所示:
清单 14. 改变输入的 GET 变量的长度 复制PHP内容到剪贴板
PHP代码:
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg(”^[0-9]+$”,$pid)){
//if non numeric $pid, send them back to home page
}
}else{
//empty $pid, so send them back to the home page
}
//we have a numeric pid, but it may be too long, so let’s check
if (strlen($pid)>5){
$pid = substr($pid,0,5);
}
//we create an object of a fictional class Page, which is now
//even more protected from evil user input
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
//……
//……
?>
注意,缓冲区溢出攻击并不限于长的数字串或字母串。也可能会看到长的十六进制字符串(往往看起来像 xA3 或 xFF)。记住,任何缓冲区溢出攻击的目的都是淹没特定的缓冲区,并将恶意代码或指令放到下一个缓冲区中,从而破坏数据或执行恶意代码。对付十六进制缓冲区溢出最简单的方法也是不允许输入超过特定的长度。
如果您处理的是允许在数据库中输入较长条目的表单文本区,那么无法在客户端轻松地限制数据的长度。在数据到达 PHP 之后,可以使用正则表达式清除任何像十六进制的字符串。
清单 15. 防止十六进制字符串 复制PHP内容到剪贴板
PHP代码:
if ($_POST['submit'] == “go”){
$name = substr($_POST['name'],0,40);
//clean out any potential hexadecimal characters
$name = cleanHex($name);
//continue processing….
}
function cleanHex($input){
$clean = preg_replace(”![][xX]([A-Fa-f0-9]{1,3})!”, “”,$input);
return $clean;
}
?>
您可能会发现这一系列操作有点儿太严格了。毕竟,十六进制串有合法的用途,比如输出外语中的字符。如何部署十六进制 regex 由您自己决定。比较好的策略是,只有在一行中包含过多十六进制串时,或者字符串的字符超过特定数量(比如 128 或 255)时,才删除十六进制串。
跨站点脚本攻击在跨站点脚本(XSS)攻击中,往往有一个恶意用户在表单中(或通过其他用户输入方式)输入信息,这些输入将恶意的客户端标记插入过程或数据库中。例如,假设站点上有一个简单的来客登记簿程序,让访问者能够留下姓名、电子邮件地址和简短的消息。恶意用户可以利用这个机会插入简短消息之外的东西,比如对于其他用户不合适的图片或将用户重定向到另一个站点的 JavaScript,或者窃取 cookie 信息。幸运的是,PHP 提供了 strip_tags() 函数,这个函数可以清除任何包围在 HTML 标记中的内容。strip_tags() 函数还允许提供允许标记的列表,比如或 。清单 16 给出一个示例,这个示例是在前一个示例的基础上构建的。清单 16. 从用户输入中清除 HTML 标记 从安全的角度来看,对公共用户输入使用 strip_tags() 是必要的。如果表单在受保护区域(比如内容管理系统)中,而且您相信用户会正确地执行他们的任务(比如为 Web 站点创建 HTML 内容),那么使用 strip_tags() 可能是不必要的,会影响工作效率。还有一个问题:如果要接受用户输入,比如对贴子的评论或来客登记项,并需要将这个输入向其他用户显示,那么一定要将响应放在 PHP 的 htmlspecialchars() 函数中。这个函数将与符号、< 和 > 符号转换为 HTML 实体。例如,与符号(&)变成 &。这样的话,即使恶意内容躲开了前端 strip_tags() 的处理,也会在后端被 htmlspecialchars() 处理掉。有一类浏览器插件允许用户篡改页面上的头部元素和表单元素。使用 Tamper Data(一个 Mozilla 插件),可以很容易地操纵包含许多隐藏文本字段的简单表单,从而向 PHP 和 MySQL 发送指令。用户在点击表单上的 Submit 之前,他可以启动 Tamper Data。在提交表单时,他会看到表单数据字段的列表。Tamper Data 允许用户篡改这些数据,然后浏览器完成表单提交。让我们回到前面建立的示例。已经检查了字符串长度、清除了 HTML 标记并删除了十六进制字符。但是,添加了一些隐藏的文本字段,如下所示:清单 17. 隐藏变量 注意,隐藏变量之一暴露了表名:users。还会看到一个值为 create 的 action 字段。只要有基本的 SQL 经验,就能够看出这些命令可能控制着中间件中的一个 SQL 引擎。想搞大破坏的人只需改变表名或提供另一个选项,比如 delete。图 1 说明了 Tamper Data 能够提供的破坏范围。注意,Tamper Data 不但允许用户访问表单数据元素,还允许访问 HTTP 头和 cookie。图 1. Tamper Data 窗口要防御这种,最简单的方法是假设任何用户都可能使用 Tamper Data(或类似的工具)。只提供系统处理表单所需的最少量的信息,并把表单提交给一些专用的逻辑。例如,注册表单应该只提交给注册逻辑。如果已经建立了一个通用表单处理函数,有许多页面都使用这个通用逻辑,那该怎么办?如果使用隐藏变量来控制流向,那该怎么办?例如,可能在隐藏表单变量中指定写哪个数据库表或使用哪个文件存储库。有 4 种选择:不改变任何东西,暗自祈祷系统上没有任何恶意用户。重写功能,使用更安全的专用表单处理函数,避免使用隐藏表单变量。使用 md5() 或其他加密机制对隐藏表单变量中的表名或其他敏感信息进行加密。在 PHP 端不要忘记对它们进行解密。通过使用缩写或昵称让值的含义模糊,在 PHP 表单处理函数中再对这些值进行转换。例如,如果要引用 users 表,可以用 u 或任意字符串(比如 u8y90×0jkL)来引用它。后两个选项并不完美,但是与让用户轻松地猜出中间件逻辑或数据模型相比,它们要好得多了。现在还剩下什么问题呢?远程表单提交。Web 的好处是可以分享信息和服务。坏处也是可以分享信息和服务,因为有些人做事毫无顾忌。以表单为例。任何人都能够访问一个 Web 站点,并使用浏览器上的 File > Save As 建立表单的本地副本。然后,他可以修改 action 参数来指向一个完全限定的 URL(不指向 formHandler.php,而是指向 ,因为表单在这个站点上),做他希望的任何修改,点击 Submit,服务器会把这个表单数据作为合法通信流接收。首先可能考虑检查 $_SERVER['HTTP_REFERER'],从而判断请求是否来自自己的服务器,这种方法可以挡住大多数恶意用户,但是挡不住最高明的 。这些人足够聪明,能够篡改头部中的引用者信息,使表单的远程副本看起来像是从您的服务器提交的。处理远程表单提交更好的方式是,根据一个惟一的字符串或时间戳生成一个令牌,并将这个令牌放在会话变量和表单中。提交表单之后,检查两个令牌是否匹配。如果不匹配,就知道有人试图从表单的远程副本发送数据。要创建随机的令牌,可以使用 PHP 内置的 md5()、uniqid() 和 rand() 函数,如下所示:清单 18. 防御远程表单提交 这种技术是有效的,这是因为在 PHP 中会话数据无法在服务器之间迁移。即使有人获得了您的 PHP 源代码,将它转移到自己的服务器上,并向您的服务器提交信息,您的服务器接收的也只是空的或畸形的会话令牌和原来提供的表单令牌。它们不匹配,远程表单提交就失败了。本教程讨论了许多问题:使用 mysql_real_escape_string() 防止 SQL 注入问题。使用正则表达式和 strlen() 来确保 GET 数据未被篡改。使用正则表达式和 strlen() 来确保用户提交的数据不会使内存缓冲区溢出。使用 strip_tags() 和 htmlspecialchars() 防止用户提交可能有害的 HTML 标记。避免系统被 Tamper Data 这样的工具突破。使用惟一的令牌防止用户向服务器远程提交表单。本教程没有涉及更高级的主题,比如文件注入、HTTP 头欺骗和其他漏洞。但是,您学到的知识可以帮助您马上增加足够的安全性,使当前项目更安全。
篇5:在PHP应用程序修复CSRF漏洞WEB安全
CSRF(跨站点请求伪造)是排名前10位的OWASP漏洞之一,它利用了网站在浏览器上的信任。这个漏洞危害用户的,通过使用用户的行动可以修改或删除用户数据。攻击的优势是,作为一个有效的用户执行操作,但用户从不知道他做了什么。如果目标为网站管理员帐户,攻击者可以执行的Web应用程序管理员的操作。不好的编码和错误是造成web应用程序存在安全漏洞的主要原因。
有时,它是被攻击者典型的利用这个漏洞。在这方面的详细的文章中,我们将了解跨站点请求伪造漏洞。我们还将创建一个表单,具有很强的保护从这个漏洞。我们还将看到流行的框架,可以用来修补此漏洞的脚本和方法。
什么是跨站请求伪造攻击?
CSRF(跨站请求伪造攻击)是一个恶意的行为,最终从用户(有效用户)的一个无辜的网站的浏览器,他/她是运行网站的一个有效的会话。。如果用户在网站上进行身份验证,从他的浏览器中执行的每一个动作将是属于他的。该网站还认为该请求是来自用户。
这种攻击是最常见的影响是改变密码,从银行账户的资金转移,一个项目的采购。
这种攻击是产生假的请求在原网站执行。当这些请求被发送到用户浏览器已验证的网站,该网站认为该请求是由用户发出的。在下一节中,我们将看到CSRF是如何工作的。
CSRF是如何工作的:
大部分的时候,攻击者使用一个第三方可信网站完成这种攻击。假链接张贴在论坛和社交网站,可能会导致CSER。这次攻击是一个序列的请求和响应。假设一个受害者是登录在目标网站上。他发现了论坛上的一个链接。执行一个恶意链接的链接在目标网站。他点击了链接和链接发送给目标网站恶意请求。
现在,例如:
1、您登录在一个网站http://targetwebsite.com上。
2、这个网站有一个删除账号的按钮在页面上。这个按钮通过表单提交一个删除请求。
3、当单击该按钮时,网站将删除的帐户登录的用户。所以,它依赖于活动的会话来识别用户。
4、攻击者伪造了一个页面,提交该表单载入页面。他已经在论坛发出了这个链接。
5、你发现的有趣的链接点击。
6、一旦你点击了链接,页面提交表单。表单的操作将删除您的帐户,因为你有一个活跃的会话。
7、这样,您的帐户已被删除的攻击者没有你的知识。但是请求都是从你的浏览器。
我相信:这个简单的例子已经明确漏洞如何影响网站的用户。同样,如果您的银行应用程序存在漏洞,我们可以显示它如何影响你的银行帐户。
如果动作是通过一个GET请求,攻击者还可以请求一个图像标记。图像的SRC属性将表单上的操作链接。当页面上的图像加载,它将执行操作。
CSRF攻击的误解
跨站请求伪造是最危险的Web应用程序的漏洞之一。因此,必须仔细检查和修补。但是有几个误区的修补。一般来说,开发人员使用一些方法来修补漏洞。但这些方法都不足以预防这个漏洞。修补CSRF有一些错误的方法:
使用的关键任务POST请求。
1、开发者认为很容易创建一个假的GET请求。但是,创建一个假的POST请求是不容易的。如果你是为web开发安全,您可以轻松地创建一个页面,可以通过JavaScript在页面加载的形式提交。这样永远不会阻止CSRF。所以,如果你要套用这个逻辑,你应该三思而后行。任何隐藏的表单可以通过JavaScript触发。
2、另一个CSRF修补错误的例子是URL重写。开发人员创建URL重写方法具有独特会话ID的URL。这使得的URL不可预知的。但是这种方法也暴露在URL中的用户的凭据。可能防止CSRF,但它是对用户同样有害。
3、有时网站使用多步交易过程,如果我们在以前的帐户中删除的列子,假设要求删除帐户后,网站会对要求进行确认。如果两个请求没有阻止CSRF,攻击者可以预测和执行所有步骤或减少步骤通过某些方面的交易请求。
很少有其他无用预防方法并不重要,讨论在这里。
有效预防CSRF漏洞方法
检查 Referral Header
检查Referral Header可以帮助预防CSRF。如果请求是来自其他域,它一定是假的请求即阻止它。总是允许来自同一个域。如果网站具有已经开放重定向漏洞,这种方法失败。击者可以通过使用开放的重定向执行GET CSRF
如今,大多数应用程序使用HTTPS连接。在这里的引用将被省略。如果网站使用HTTPS,所以这种方法不会的帮助。因此,我们将不得不寻找另一种方式。
在forms验证验证码
这是另一个不错的方式来阻止CSRF攻击方法。验证码验证过程最初是发达国家以防止机器人在forms的垃圾邮件。但它也可以有助于阻止CSRF。为验证码是在客户端生成随机,攻击者无法猜测模式。所以,他将永远无法发送正确的验证码和一个假的请求。所有虚假请求将被一个验证码验证功能受阻。
这个方法不是很人性化。大多数用户不希望在网站上填写的验证码。我们应该试图找到防止CSRF漏洞的方式对用户无需增加任何额外负担。
不可预知的同步令牌模式
这是最安全的方法预防CSRF。与验证码验证,该方法具有与用户无关。因此,用户不知道的东西已经被添加到保护他们。在该方法中,网站在每个表单中生成一个随机的令牌作为一个隐藏的值。这个标记是与用户当前的会话关联的。一旦表单被提交后,网站验证是否随机令牌通过请求。如果是的话,那么验证否是正确的。通过使用这种方法,开发人员可以很容易地确定请求用户是否被攻击。
…
这种方法的强度取决于令牌生成方法,
所以,总是试图生成令牌的方式,它始终是不可预知的。
所以,如果你正在考虑实现这项,尽量使用随机。
您可以使用
$randomtoken = md5(uniqid(rand, true));
或尝试这个
$randomtoken = base64_encode( openssl_random_pseudo_bytes(32));
用base64_encode,它可确保生成的值不会打破你的HTML布局与HTML字符。
生成这randomgtoken,一旦会话后启动登录,并添加到您的会话变量。
$ _SESSION [:'csrfToken'] = $ randomtoken。
将任何用户添加到form表单
每个会话的csrftoken是独特的,在每一个新会话,它将再次生成和然后varified表单请求。
您可以使用一个单一的CSRF令牌在单个会话中的所有形式。但使用不同的所有形式可能会更安全。但是,使用这种方法可以创建为产生不同的csrfToken的不同形式的麻烦,当用户打开多个标签,并提交逐一多种形式。
有几个开源的PHP类和库也可。你可以使用这些开源类实现一个强大的抵御CSRF漏洞。
很少有开源的库:
1、Clfsrpm
Clfsrpm是一种流行的PHP类,给人以强烈的措施防止CSRF。它给出了一些公共的功能,你可以使用CSRF令牌生成和验证。复杂的部分已经被开发商完成。
你可以阅读更多链接下载类:http://www.clfsrpm.net/csrf/
2、NoCSRF
NoCSRF是另一种简单的防御CSRF令牌生成和检查类写在PHP5。它还配备了易于理解的例子来学习如何正确地实现这个类在Web应用程序。
可以从这里下载NoCSRF:https://github.com/BKcore/NoCSRF
3. csrf by Skookum
这是另一个PHP实现保护的CSRF PHP。代码是免费。所以你可以复制和在应用程序中使用。
从这里获取代码: https://github.com/Skookum/csrf/blob/master/classes/csrf.php
4. anticsurf
anticsurf是另一个小型PHP库,可用于阻止CSRF在PHP中的web应用程序。
这个图书馆声称给暴力攻击有很强的entropy 。它还实现了一次性使用令牌提供超时限制。阅读更多关于这个PHP库,并从这里下载:https://code.google.com/p/anticsurf/
5. CSRF-Magic
CSRF-Magic是另一中强大的实现方法,可以防止CSRF攻击的网站。库是免费在线演示。你可以只包含在你的PHP文件的顶部。该库将完成剩下的工作。它重新写脚本在您的网站上,然后拦截POST请求的形式来检查令牌注入,但这意味着它自动添加所有你的传统不安全的形式。你不需要添加额外的代码。只包括库文件的顶部。
其中一个最简单的CSRF保护库可用于PHP应用程序…
下载库,在这里看到的演示:http://csrf.htmlpurifier.org/
6.CSRF Protection
CSRF Protection 也是一个不错的和简单的类。虽然,它没有附带的教程。但它有完整的代码注释,让你理解如何使用这个库。它给你一些函数来生成,然后验证CSRF令牌。在下载页面,它给了几个示例代码显示了如何使用这个类来生成您自己的Web应用程序,然后验证CSRF令牌。
下载从github CSRF保护库,通过此链接:https://github.com/XCMer/csrfprotect
根据您的选择,您可以使用任何上述类或库。但不要忘了通过评论与我们分享。
用户方面防御
CSRF是一种有害的漏洞,因此,用户还应该按照几个步骤,以确保其安全性。这些都是几个重要的点:
始终在不使用时登出重要的Web帐户。
不要使用重要的网络账号(如在线银行)免费上网
不要使用脚本浏览器插件来保护自己免受恶意脚本
结论
在这篇文章中,我们已经看到,跨站请求伪造是一种有害的脆弱性和影响用户的帐户。我们也看到了各种方法来防止这种攻击,并保护用户的帐户。如果网站有一个跨站脚本漏洞,表演CSRF攻击变得更加容易。攻击者可以创建一个的自动蠕虫击败CSRF防御。
在这篇文章中,我们已经讨论了各种开源库和类。这些类可以直接使用基于PHP的Web应用程序内,以防止CSRF漏洞。Web开发人员应该照顾网站的安全,并按照给定的提示。有各种工具和手动的方法可用来测试CSRF。最常用的工具是OWASP CSRF Tester。你可以从这里下载:https://www.owasp.org/index.php/Category:OWASP_CSRFTester_Project
如果你想手动启动,您可以查看代码和看到的形式。如果随机令牌不可用,你应该添加可用的开源类。我敢肯定,现在你知道足够的有关CSRF的修补。如果你有什么话要说,你可以与我们分享它通过评论。
作者简介
Pavitra Shandkhdhar是一个工学毕业的研究生和安全研究员。他感兴趣的领域是网络渗透测试。他喜欢找漏洞在网站和玩电脑游戏在空闲时间。他是目前信息安全研究所研究员。
原文地址:http://resources.infosecinstitute.com/fixing-csrf-vulnerability-in-php-application/
篇6:关于如何防止PHP漏洞?WEB安全
踏入编程圈一年不到,之前写的文章一直放在个人博客上,以后我写的或整理的好的教程一定到园子里分享,只是园子里PHPer好像不怎么活跃,希望同行多多交流,这是我之前整理的一篇PHP漏洞文章!
漏洞无非这么几类,XSS、sql注入、命令执行、上传漏洞、本地包含、远程包含、权限绕过、信息泄露、cookie伪造、CSRF(跨站请求)等。这些漏洞不仅仅是针对PHP语言的,本文只是简单介绍PHP如何有效防止这些漏洞。
1.xss + sql注入(关于xss攻击详细介绍)
其中占大头的自然是XSS与SQL注入,对于框架类型或者有公共文件的,建议在公共文件中统一做一次XSS和SQL注入的过滤。用PHP写个过滤函数,可由如下所示:
$_REQUEST = filter_xss($_REQUEST);
$_GET = filter_xss($_GET);
$_POST = filter_xss($_POST);
$_COOKIE = filter_xss($_COOKIE);
$_POST = filter_sql($_POST);
$_GET = filter_sql($_GET);
$_COOKIE = filter_sql($_COOKIE);
$_REQUEST = filter_sql($_REQUEST);
最简单的filter_xss函数是htmlspecialchars()
最简单的filter_sql函数是mysql_real_escape_string()
当然,谁都知道这种过滤filter_sql(详细防止sql注入)只能过滤字符型和搜索型的注入,对于数字型是没有办法的,但也说明做了这层过滤后,只需在后面注意数字型的SQL语句就可以了,遇到了加intval过滤就可以了,这就变得容易多了。
2. 命令执行
对于命令执行,可以从关键字入手,总共可分为3类
(1) php代码执行 :eval等
(2)shell命令执行:exec、passthru、system、shell_exec等
(3) 文件处理:fwrite、fopen、mkdir等
对于这几类需要注意其参数是否用户可控,
3.上传漏洞
对于上传漏洞,也是重点关注的地方,要仔细分析它的处理流程,针对上传的绕过方式是很多的,最保险的方式:在保存文件是采用文件名随机命名和后缀白名单方式。其次要注意的一点是上传文件的地方可能不止一处,不要有遗漏,可能会碰到这样的情况,突然在某个目录里面包含了一个第三方的编辑器在里面。
文件包含漏洞涉及的函数如include() 、include_once()、require()、require_once()、file_get_contents()等
最常见的还是出在下载文件功能函数,例如download.php?file=../../../etc/passwd 这种类型中。
4. 权限绕过
权限绕过可分为两类吧
(1)后台文件的未授权访问。后台的文件没有包含对session的验证,就容易出现这样的问题
(2)未作用户隔离,例如mail.php?id=23显示了你的信件,那么换个ID, mail.php?id=24就查看到了别人的信件,编写代码是方便,把信件都存在一个数据表里,id统一编号,前端展现时只需按id取出即可,但未作用户隔离,判定归属,容易造成越权访问。
这样的例子是很常见的,给某银行做评估是就经常发现这种漏洞。
5. 信息泄露
信息泄露算是比较低危的漏洞了,比如列目录这种就属于部署问题,而与代码审计无关了,而像暴路径、暴源码这种是需要防止的。曾经遇到这样的代码
表面上似乎没问题,可是当请求变为 xx.php?a[]=1时,即参数变为数组的时候,就会发生错误以致路径泄露,而用isset判断则不会,当然一个个防太麻烦,建议在配置文件中关闭错误提示,或者在公共文件中加入如下代码以关闭错误显示功能:
之前PHP点点通(phpddt.com)就有一篇文章:关于PHP防止漏洞策略 ,介绍了register_globals 的危害以及魔术引用Magic Quotes使用说明。
注明:本文部分内容摘自PHPCHINA
篇7:浅谈变形PHP WEBSHELL检测WEB安全
一、变形webshell
webshell比如eval($_POST[])大家都耳熟能详,近几年在常见的webshell基础上衍生了很多变种,加大了检测难度,下面先看几个从网上摘取的样本:
1、无ascii码和数字的webshell
2、隐藏关键字
3、编码 + 隐藏关键字
从目前已经公开的样本来看,变形的php webshell都是采取了隐藏关键字(eval、system等)的方法来躲避查杀,有一位monyer同学写过一篇webshell的检测文章,他把webshell拆分为下面的结构,执行数据和数据传递,检测思路是:以小括号为界限,匹配执行数据部分是否命中收集的样本的关键字。这种思路很好,个人觉得有两处不足:
1、需要人工维护收集新样本。
2、误报量不可预估。
再看这个结构,变形的webshell无非是隐藏了执行数据部分或者数据传递部分,不过无论怎么变形本质上还是去调用eval、调用system、exec等命令执行函数,杀毒软件通过异常行为来检测木马病毒,比如开机自启动,这种思想同样也可以用在webshell的检测中。获取行为数据是第一步。
二、PHP HOOK
这里我们只需要一些敏感的行为数据,比如eval、system的调用。实现方法很简单,hook这些php函数或语法结构,这里通过php扩展来实现hook。下面以eval和system来简要概述下hook的方法。
Eval是一个语法结构,调用eval最终会调用php内核的zend_compile_string函数,hook eval的只需要重写zend_complie_string函数即可,流程如下:
System是php的一个内部函数,php代码是转化为opcode(指令)来执行,函数调用的指令是ZEND_DO_FCALL,风雪之隅大牛在taint扩展(详见参考二)就是通过重载ZEND_DO_FCALL的方法实现了。因为我们并不需要hook每个内部函数,所以这里介绍另外一种方法,流程如下:
上报的数据写在一个日志文件中,包括文件名、调用函数名、代码在文件的行数,
日志结构和内容如下:
附件中有eval、system函数hook实现的demo,具体细节可以查看代码。demo只在php-5.3.6上测试过,不兼容之处忘见谅。
三、检测
变形webshell分为两大类,下面依次说明一下检测逻辑。
1、执行数据隐藏
一个正常的程序员如果使用eval、system是不会刻意的转换隐藏的,如果发现某个函数执行了,代码中却找不到这个函数名,我们认为这是一个异常行为。以下面这个变形为例
比如 传入参数nonalpha.php?_=system&__=whoami执行了一条命令,日志会记录
我们在后端取nonalpha.php文件的第7行内容匹配system(字符串,如果没找到,则认为是一个变形webshell。
2、数据传递隐藏
先看下面这个例子
这个webshell通过编码的referer来传递攻击载荷,利用日志文件记录到的文件名和行数把代码上报到后端,和后端svn中的代码做对比,如果不一致,则认为是一个webshell。
四、不足
web承受着大量的访问请求,增加的php扩展的性能和稳定性是一个严峻的考验,另外在服务器比较多的公司还存在一个推广和部署成本。
五、参考:
[1] http://hi.baidu.com/monyer/item/a218dbadf2afc7a828ce9d63
[2] http://www.laruence.com//02/18/2560.html
[3]http://www.80vul.com/webzine_0x05/0x07%20%E6%B5%85%E8%B0%88%E4%BB%8EPHP%E5%86%85%E6%A0%B8%E5%B1%82%E9%9D%A2%E9%98%B2%E8%8C%83PHP%20WebShell.html
附件:check_webshell_demo.7z
篇8:PHP开发web应用安全总结
XSS跨站脚本
概念:恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的,
危害:
盗取用户COOKIE信息。
跳转到钓鱼网站。
操作受害者的浏览器,查看受害者网页浏览信息等。
蠕虫攻击。
描述:反射型跨站。GET或POST内容未过滤,可以提交JS以及HTML等恶意代码。
代码:
//正常URL
user.php?msg=henhao
//带JS的URL
user.php?msg=
//恶意跳转URL
user.php?msg=
解决方法:
输出过滤,php端输出到view的模板页面上的数据都需要经过过滤:
//输出过滤HTML JS标签
$var = str_replace(array('
$var = addslashes($var);
CSRF跨站攻击
概念:CSRF跨站请求伪造,也被称成为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
危害:强迫受害者的浏览器向一个易受攻击的Web应用程序发送请求,最后达到攻击者所需要的操作行为。
例子:
1. 上面是一个图片的html标签,但是src中是一个添加id为123好友的新增好友链接。
2. 恶意用户可以将这段代码植入其它网站网页上面,甚至可以img设置为0,0,让用户不知不觉中点击这个链接,达到用户并不像加这个人好友,但是添加的目的。
3. 当很多人都无意加了id为123这个人为好友的时候,id为123的恶意用户就有权限来查看这些人的信息,甚至可以发送很多恶意的信息,达到恶意用户的目的。
解决方法:
1. http:// /addfriend.php?id=123 使用POST方法会相对安全一点。
2. 采用类似随即码或者令牌的形式,让用户操作唯一性。 (每次用户登录网站随机生成一个token,存放在cookie中,用户的所有操作中都需要经过token验证)
flash安全问题
例子:
http://images.sohu.com/bill/s/liulin/nokia/1602600902.swf?clickthru=javascript.:alert(1)
解决方法:
在网站根目录中,添加crossdomain.xml文件,这个文件主要是控制flash的域访问。
淘宝的:http://www.taobao.com/crossdomain.xml
sql注入安全问题
概念:所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
危害:
1. 查询数据库中敏感信息。
2. 绕过认证。
3. 添加、删除、修改服务器数据。
4. 拒绝服务。?id=(BENCHMARK(100000000, MD5(RAND));
例子:
$sql = “SELECT name FROM users WHERE id = '”. $_GET['id'] . “'”;
当ID值为:1’or 1=’1 SQL语句(已测试可以注入):
SELECT name FROM users WHERE id = ‘1’ or 1=’1 ‘
说明:1=1的时候,条件语句WHEREOR之前的不起作用。 ‘的作用是组装SQL语句。
解决方法:
SQL组装的时候,对外部变量以及所有变量都进行过滤:
PHPWIND中,可以用sqlEscape、sqlImplode、sqlSingle、sqlMulti等函数过滤组装。过滤主要是一些’单引号这些可以破坏SQL组装的数据。
/**
* SQL组装-私有SQL过滤
* @param string $val 过滤的值
* @param int $iskey 0-过滤value值,1-过滤字段
* @return string
*/
private function build_escape_single($val, $iskey = 0) {
if ($iskey === 0) {
if (is_numeric($val)) {
return “ '” . $val . “' ”;
} else {
return “ '” . addslashes(stripslashes($val)) . “' ”;
}
} else {
$val = str_replace(array('`', ' '), '', $val);
return ' `'.addslashes(stripslashes($val)).'` ';
}
}
XML注入安全问题
概念:和SQL注入原理一样,XML是存储数据的地方,如果在查询或修改时,如果没有做转义,直接输入或输出数据,都将导致XML注入漏洞,
攻击者可以修改XML数据格式,增加新的XML节点,对数据处理流程产生影响。
危害:
1. 攻击者可以新增XML节点
2. 破坏原来的XML结构,影响业务流程,甚至产生严重的错误。
例子:
$xml = “
需要得到的XML结构:
恶意代码:
user1@a.com
意外的XML文档:
解决方法:
1. 对php处理XML文档的时候,进行标签过滤
2. 尽量减少直接被外部访问到xml文档,可以采用文件名用散列方法等。
url跳转漏洞
概念:Web应用程序接收到用户提交的URL参数后,没有对参数做”可信任URL”的验证,就向用户浏览器返回跳转到该URL的指令。
危害:钓鱼网站
例子:
http://m.yahoo.cn/log.php?c=web&u=http://www.163.com
解决方法:
对跳转的php函数进行进一步优化,使页面跳转可以在可信任的范围内。 例如可以有跳转域名白名单方法,这个访问各大公司使用比较多
文件系统跨越漏洞
概念:对文件目录参数没有进行过滤,导致恶意用户可以通过在参数中输入一些执行命令,或者跨越访问的行为,来超出用户的访问权限。
例子:通过一个或多个../跨越目录限制
$fp = fopen(“image/{$_GET['filename']}”, 'r');
Getfile?filename=../../../../etc/passwd
解决方法:
1. 对文本操作的时候一定要谨慎,不可信任
2. 严格使用phpwind中安全类库escapePath函数
系统命令漏洞
概念:用户提交的参数用于执行系统命令的参数。
解决:
1. 谨慎使用系统命令,对使用系统命令的地方需要进行安全评审
2. 对命令语句进行严格过滤
文件上传漏洞
概念:Web应用程序在处理用户上传的文件时,没有判断文件的扩展名是否在允许的范围内,或者没检测文件内容的合法性,就把文件保存在服务器上,甚至上传脚本木马到web服务器上,直接控制web服务器。
情况:
1. 未限制扩展名
2. 未检查文件内容
3. 病毒文件
解决方法:
1. 使用安全的,可信任的上传组件。
2. 检查文件扩展名,保证文件的类型正确。
3. 检查文件内容,保证用户不伪造文件类型。
任意文件下载漏洞
解决方法:
1.Apache虚拟目录指向
2.Java/PHP读取文件
权限控制漏洞
概念:属于业务逻辑上的安全管理。
访问控制:
1. 水平访问:Web应用程序接收到用户请求,修改某条数据时,没有判断数据的所属人,或判断数据所属人时,从用户提交的request参数(用户可控数据)中,获取了数据所属人id,导致恶意攻击者可以通过变换数据ID,或变换所属人id,修改不属于自己的数据。
2. 垂直访问:由于web应用程序没有做权限控制,或仅仅在菜单上做了权限控制,导致的恶意用户只要猜测其他管理页面的URL,就可以访问或控制其他角色拥有的数据或页面,达到权限提升目的。
存在情况:
1.URL级别的。(例如论坛需要操作评分的时候,有一个提交的URL地址,该地址提交过去,如果不做权限判断,那么恶意用户就可以随意的拿这个URL地址来进行恶意行为)
2. 菜单级别。(会员中心或者后台管理中心,会有菜单,管理员可以看到多个功能,普通管理员只能看到一部分功能。但是如果你对管理员操作的功能区不做权限判断,那么普通管理员只要猜测或者获取管理区的URL,就可以进行管理员操作了)
危害:
1. 属于业务逻辑的漏洞,这些危害性是巨大的,可以让普通用户就可能获取管理员的权限,对网站进行恶意破坏或者做非法行为。
解决方案:
1. 项目先期,做一份详细的权限规划文档。
2. 在开发中严格按照权限文档的要求去做权限。
3. 后期测试需要覆盖权限这一块功能区。
4. 程序员需要经常注意这些方面的要求。
cookie安全设置
解决:
cookie httponly flag : 在用到用户名登陆密码之类的安全性比较高的cookie的时候,可以在cookie中设置httponly属性,该属性只允许php等访问cookie,而不允许js访问。
cookie secure flag : 在涉及到https这样的情况,需要对cookie加密传输,那么可以设置这个属性
session安全
1. SESSION是保存在服务器端的,具有比COOKIE一定的安全性。
2. 使用COOKIE的时候,如果长时间没有动作,可以设置一个时间值,来对COOKIE进行过期。
3. 尽量让用户每次的cookie值都是不同的,这样可以保证cookie被盗取也不能长期使用的问题
作者 initphp的LAMP开源世界
篇9:PHP安全防护web攻击实例介绍
网络安全是目前互联网的热门话题之一,作为个人用户的我们同样需要关注,做好防护。常见的Web攻击分为两类:一是利用Web服务器的漏洞进行攻击,如CGI缓冲区溢出,目录遍历漏洞利用等攻击;二是利用网页自身的安全漏洞进行攻击,如SQL注入,跨站脚本攻击等。下面这篇文章主要介绍了PHP安全防护之Web攻击,需要的朋友可以参考,下面来一起看看吧。
SQL注入攻击(SQL Injection)
攻击者把SQL命令插入到Web表单的输入域或页面请求的字符串,欺骗服务器执行恶意的SQL命令。在某些表单中,用户输入的内容直接用来构造(或者影响)动态SQL命令,或作为存储过程的输入参数,这类表单特别容易受到SQL注入式攻击。
常见的SQL注入式攻击过程类如:
1.某个Web应用有一个登录页面,这个登录页面控制着用户是否有权访问应用,它要求用户输入一个名称和密码;
2.登录页面中输入的内容将直接用来构造动态的SQL命令,或者直接用作存储过程的参数;
例如:
$query = 'SELECT * from Users WHERE login = ' . $username . ' AND password = ' . $password;
3.攻击者在用户名字和密码输入框中输入'或'1'='1之类的内容;
4.用户输入的内容提交给服务器之后,服务器运行上面的代码构造出查询用户的SQL命令,但由于攻击者输入的内容非常特殊,所以最后得到的SQL命令变成:
SELECT * from Users WHERE login = '' or '1'='1' AND password = '' or '1'='1';
5.服务器执行查询或存储过程,将用户输入的身份信息和服务器中保存的身份信息进行对比;
6.由于SQL命令实际上已被注入式攻击修改,已经不能真正验证用户身份,所以系统会错误地授权给攻击者。
如果攻击者知道应用会将表单中输入的内容直接用于验证身份的查询,他就会尝试输入某些特殊的SQL字符串篡改查询改变其原来的功能,欺骗系统授予访问权限。
系统环境不同,攻击者可能造成的损害也不同,这主要由应用访问数据库的安全权限决定。如果用户的帐户具有管理员或其他比较高级的权限,攻击者就可能对数据库的表执行各种他想要做的操作,包括添加、删除或更新数据,甚至可能直接删除表
防范方法:
1.检查变量数据类型和格式
2.过滤特殊符号
3.绑定变量,使用预编译语句
跨网站脚本攻击(Cross Site Scripting, XSS)
攻击者将恶意代码注入到网页上,其他用户在加载网页时就会执行代码,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。这些恶意代码通常是JavaScript、HTML以及其他客户端脚本语言。
例如:
echo “欢迎您,”.$_GET['name'];
如果传入一段脚本 ,那么脚本也会执行。用这样的URL将会执行JavaScript的alert函数弹出一个对话框:常用的攻击手段有:
盗用cookie,获取敏感信息;
利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击)用户的身份执行一些管理动作,或执行一些一般的如发微博、加好友、发私信等操作;
利用可被攻击的域受到其他域信任的特点,以受信任来源的身份请求一些平时不允许的操作,如进行不当的投票活动;
在访问量极大的一些页面上的XSS可以攻击一些小型网站,实现DDoS攻击的效果。
防范方法:使用htmlspecialchars函数将特殊字符转换成HTML编码,过滤输出的变量
跨网站请求伪造攻击(Cross Site Request Forgeries, CSRF)
攻击者伪造目标用户的HTTP请求,然后此请求发送到有CSRF漏洞的网站,网站执行此请求后,引发跨站请求伪造攻击。攻击者利用隐蔽的HTTP连接,让目标用户在不注意的情况下单击这个链接,由于是用户自己点击的,而他又是合法用户拥有合法权限,所以目标用户能够在网站内执行特定的HTTP链接,从而达到攻击者的目的。
它与XSS的攻击方法不同,XSS利用漏洞影响站点内的用户,攻击目标是同一站点内的用户者,而CSRF 通过伪装成受害用户发送恶意请求来影响Web系统中受害用户的利益。
例如:
某个购物网站购买商品时,item参数确定要购买什么物品,num参数确定要购买数量,如果攻击者以隐藏的方式发送给目标用户链接
,那么如果目标用户不小心访问以后,购买的数量就成了100个
防范方法:
1、检查网页的来源
2、检查内置的隐藏变量
3、使用POST,不要使用GET,处理变量也不要直接使用$_REQUEST
相关阅读:网络安全事件:
一、英特尔处理器曝“Meltdown”和“Spectre漏洞”
1月,英特尔处理器中曝“Meltdown”(熔断)和“Spectre” (幽灵)两大新型漏洞,包括AMD、ARM、英特尔系统和处理器在内,几乎近发售的所有设备都受到影响,受影响的设备包括手机、电脑、服务器以及云计算产品。这些漏洞允许恶意程序从其它程序的内存空间中窃取信息,这意味着包括密码、帐户信息、加密密钥乃至其它一切在理论上可存储于内存中的信息均可能因此外泄。
二、GitHub 遭遇大规模 Memcached DDoS 攻击
202月,知名代码托管网站 GitHub 遭遇史上大规模 Memcached DDoS 攻击,流量峰值高达1.35 Tbps。然而,事情才过去五天,DDoS攻击再次刷新纪录,美国一家服务提供商遭遇DDoS 攻击的峰值创新高,达到1.7 Tbps!攻击者利用暴露在网上的 Memcached 服务器进行攻击。网络安全公司 Cloudflare 的研究人员发现,截止2018年2月底,中国有2.5万 Memcached 服务器暴露在网上 。
三、苹果 iOS iBoot源码泄露
2018年2月,开源代码分享网站 GitHub(软件项目托管平台)上有人共享了 iPhone 操作系统的核心组件源码,泄露的代码属于 iOS 安全系统的重要组成部分——iBoot。iBoot 相当于是 Windows 电脑的 BIOS 系统。此次 iBoot 源码泄露可能让数以亿计的 iOS 设备面临安全威胁。iOS 与 MacOS 系统开发者 Jonathan Levin 表示,这是 iOS 历史上最严重的一次泄漏事件。
四、韩国平昌冬季奥运会遭遇黑客攻击
2018年2月,韩国平昌冬季奥运会开幕式当天遭遇黑客攻击,此次攻击造成网络中断,广播系统(观众不能正常观看直播)和奥运会官网均无法正常运作,许多观众无法打印开幕式门票,最终未能正常入场。
五、加密货币采矿软件攻击致欧洲废水处理设施瘫痪
2018年2月中旬,工业网络安全企业 Radiflow 公司表示,发现四台接入欧洲废水处理设施运营技术网络的服务器遭遇加密货币采矿恶意软件的入侵。该恶意软件直接拖垮了废水处理设备中的 HMI 服务器 CPU,致欧洲废水处理服务器瘫痪 。
Radiflow 公司称,此次事故是加密货币恶意软件首次对关键基础设施运营商的运营技术网络展开攻击。由于受感染的服务器为人机交互(简称HMI)设备,之所以导致废水处理系统瘫痪,是因为这种恶意软件会严重降低 HMI 的运行速度。
web攻击
篇10:DedeCMS 安全设置 禁止PHP执行权限WEB安全
使用.htaccess禁止php执行
RewriteEngineonRewriteCond%!^$RewriteRuleuploads/(.*).(php)$–[F]RewriteRuledata/(.*).(php)$–[F]RewriteRuletemplets/(.*).(php)$–[F]RewriteRulezkzy/(.*).(php)$–[F]RewriteRulezktk/(.*).(php)$–[F]RewriteRulexxff/(.*).(php)$–[F]RewriteRulexlogo/(.*).(php)$–[F]RewriteRulestyle/(.*).(php)$–[F]RewriteRulenews/(.*).(php)$–[F]RewriteRuleimgcss/(.*).(php)$–[F]RewriteRuleimages/(.*).(php)$–[F]RewriteRuledyimg/(.*).(php)$–[F]RewriteRulebkbd/(.*).(php)$–[F]RewriteRulea/(.*).(php)$–[F]RewriteRuleinclude/(.*).(php)$–[F]RewriteRuledede/(.*).(php)$–[F]
【确保PHP应用程序的安全[2]WEB安全(精选10篇)】相关文章:
securytas.ro sql 注入2022-05-07
一个web蠕虫的简单实现2022-08-30
初学摄影心得体会感想2023-12-19
GTK+2.6安装笔记Unix系统2023-08-21
由于Nginx漏洞导致的入侵事件WEB安全2023-08-17
《互联网软件应用于开发》教案11-12章2022-10-27
软件在网站设计和维护中的作用论文2022-04-30
PHP笔试题目及答案2023-09-04
Windows 配置POP3服务服务器教程2022-12-04
PHP中级开发工程师的具体职责范围2023-03-25