针对PHP 的网站主要存在下面几种***方式:
1、命令注入(CommandInjection)
2、eval 注入(Eval Injection)
3、客户端脚本***(Script Insertion)
4、跨网站脚本***(Cross Site Scripting, XSS)
5、SQL 注入***(SQLinjection)
6、跨网站请求伪造***(Cross Site Request Forgeries, CSRF)
7、Session 会话劫持(Session Hijacking)
8、Session 固定***(Session Fixation)
9、HTTP 响应拆分***(HTTP ResponseSplitting)
10、文件上传漏洞(File Upload Attack)
11、目录穿越漏洞(DirectoryTraversal)
12、远程文件包含***(Remote Inclusion)
13、动态函数注入***(Dynamic Variable Evaluation)
14、URL ***(URL attack)
15、表单提交欺骗***(Spoofed FormSubmissions)
16、HTTP 请求欺骗***(Spoofed HTTP Requests)
以后的每期连载,会逐个介绍这些漏洞的原理和防御方法。
几个重要的php.ini 选项
Register Globals
php>=4.2.0,php.ini 的register_globals 选项的默认值预设为Off ,当register_globals 的设定
为On 时,程序可以接收来自服务器的各种环境变量,包括表单提交的变量,而且由于PHP
不必事先初始化变量的值,从而导致很大的安全隐患。
例1:
//check_admin() 用于检查当前用户权限,如果是admin 设置$is_admin 变量为true ,然后下面
判断此变量是否为true ,然后执行管理的一些操作
//ex1.php
if (check_admin())
{
$is_admin =true; } if ($is_admin) {
do_something(); } ?> 这一段代码没有将$is_admin 事先初始化为Flase ,如果register_globals 为On ,那么我们直接提交http://www.sectop.com/ex1.php?is_admin=true, 就可以绕过check_admin() 的验证
例2: //ex2.php
do_something(); } else {
echo "您尚未登录!"; } ?> 当register_globals=On 时,我们提交http://www.sectop.com/ex2.php?_SESSION[username]=dodo ,就具有了此用户的权限所以不管register_globals 为什么,我们都要记住,对于任何传输的数据要经过仔细验证,变量要初始化
safe_mode 安全模式,PHP 用来限制文档的存取、限制环境变量的存取,控制外部程序的执行。启用安全模式必须设置php.ini 中的safe_mode =On 1、限制文件存取safe_mode_include_dir ="/path1:/path2:/path3"
不同的文件夹用冒号隔开2、限制环境变量的存取safe_mode_allowed_env_vars =string 指定PHP 程序可以改变的环境变量的前缀,如:safe_mode_allowed_env_vars = PHP_,当这个选项的值为空时,那么php可以改变任何环境变量safe_mode_protected_env_vars =string 用来指定php程序不可改变的环境变量的前缀3、限制外部程序的执行safe_mode_exec_dir = string 此选项指定的文件夹路径影响system 、exec 、popen 、passthru ,不影响shell_exec 和“` `” 。disable_functions = string
不同的函数名称用逗号隔开,此选项不受安全模式影响
magic quotes 用来让php程序的输入信息自动转义,所有的单引号(“'”) ,双引号(“"”) ,反斜杠(“\”) 和空字符(NULL) ,都自动被加上反斜杠进行转义magic_quotes_gpc =On 用来设置magic quotes 为On ,它会影响HTTP 请求的数据(GET 、POST 、Cookies) 程序员也可以使用addslashes 来转义提交的HTTP 请求数据,或者用stripslashes 来删除转义
PHP 漏洞全解(二)-命令注入***命令注入***PHP 中可以使用下列5个函数来执行外部的应用程序或函数
system 、exec 、passthru 、shell_exec 、``( 与shell_exec 功能相同)
函数原型
string system(string command, int &return_var) command 要执行的命令return_var 存放执行命令的执行后的状态值string exec (string command, array&output, int &return_var) command 要执行的命令output 获得执行命令输出的每一行字符串return_var 存放执行命令后的状态值void passthru (string command, int &return_var) command 要执行的命令return_var 存放执行命令后的状态值string shell_exec (string command) command 要执行的命令
漏洞实例
例1:
//ex1.php
$dir =$_GET["dir"];
if (isset($dir))
{ echo "
"; system("ls -al".$dir); echo "
";
}
?>
我们提交http://www.sectop.com/ex1.php?dir=| cat /etc/passwd
提交以后,命令变成了system("ls -al| cat /etc/passwd");
eval 注入***
eval 函数将输入的字符串参数当作PHP 程序代码来执行
函数原型:
mixed eval(string code_str)//eval 注入一般发生在***者能控制输入的字符串的时候
//ex2.php
$var = "var";
if (isset($_GET["arg"]))
{ $arg= $_GET["arg"]; eval("\$var =$arg;"); echo "\$var =".$var;
} ?> 当我们提交http://www.sectop.com/ex2.php?arg=phpinfo(); 漏洞就产生了动态函数
dosomething(); } funcB() {
dosomething(); } if (isset($_GET["func"])) {
$myfunc= $_GET["func"];
echo $myfunc(); } ?> 程序员原意是想动态调用A 和B 函数,那我们提交http://www.sectop.com/ex.php?func=phpinfo 漏洞产生
防范方法1、尽量不要执行外部命令2、使用自定义函数或函数库来替代外部命令的功能3、使用escapeshellarg 函数来处理命令参数4、使用safe_mode_exec_dir 指定可执行文件的路径esacpeshellarg 函数会将任何引起参数或命令结束的字符转义,单引号“'”,替换成“\'”,双引号“"” ,替换成“\"” ,分号“;” 替换成“\;” 用safe_mode_exec_dir 指定可执行文件的路径,可以把会使用的命令提前放入此路径内safe_mode =On safe_mode_exec_di r= /usr/local/php/bin/
PHP 漏洞全解(三)-客户端脚本植入客户端脚本植入(Script Insertion) ,是指将可以执行的脚本插入到表单、图片、动画或超链接文字等对象内。当用户打开这些对象后,***者所植入的脚本就会被执行,进而开始***。可以被用作脚本植入的HTML 标签一般包括以下几种: 1、 无限弹框插入 跳转钓鱼页面或者使用其他自行构造的js 代码进行***
防范的方法一般使用htmlspecialchars 函数来将特殊字符转换成HTML 编码函数原型
string htmlspecialchars (string string, int quote_style, string charset) string 是要编码的字符串quote_style 可选,值可为ENT_COMPAT 、ENT_QUOTES 、ENT_NOQUOTES ,默认值ENT_COMPAT ,表示只转换双引号不转换单引号。ENT_QUOTES ,表示双引号和单引号都要转换。ENT_NOQUOTES ,表示双引号和单引号都不转换
charset 可选,表示使用的字符集
函数会将下列特殊字符转换成html 编码:
&---->&;
"---->";
'---->';
<----><;
>---->>;
把show.php 的第98行改成
然后再查看插入js 的漏洞页面
PHP 漏洞全解(四)-xss 跨站脚本***XSS(Cross Site Scripting) ,意为跨网站脚本***,为了和样式表css(Cascading Style Sheet) 区别,缩写为XSS 跨站脚本主要被***者利用来读取网站用户的cookies 或者其他个人数据,一旦***者得到这些数据,那么他就可以伪装成此用户来登录网站,获得此用户的权限。跨站脚本***的一般步骤: 1、***者以某种方式发送xss 的http 链接给目标用户2、目标用户登录此网站,在登陆期间打开了***者发送的xss 链接3、网站执行了此xss ***脚本4、目标用户页面跳转到***者的网站,***者取得了目标用户的信息5、***者使用目标用户的信息登录网站,完成***
当有存在跨站漏洞的程序出现的时候,***者可以构造类似
http://www.sectop.com/search.php?key= ,诱骗用户点击后,可以获取用户cookies 值
防范方法:
利用htmlspecialchars 函数将特殊字符转换成HTML 编码
函数原型
string htmlspecialchars (string string, int quote_style, string charset)
string 是要编码的字符串
quote_style 可选,值可为ENT_COMPAT 、ENT_QUOTES 、ENT_NOQUOTES ,默认值
ENT_COMPAT ,表示只转换双引号不转换单引号。ENT_QUOTES ,表示双引号和单引号都
要转换。ENT_NOQUOTES ,表示双引号和单引号都不转换
charset 可选,表示使用的字符集
函数会将下列特殊字符转换成html 编码:
&---->&;
"---->";
'---->';
<----><;
>---->>;
$_SERVER["PHP_SELF"] 变量的跨站
在某个表单中,如果提交参数给自己,会用这样的语句
" method="POST">
......
$_SERVER["PHP_SELF"] 变量的值为当前页面名称
例:
http://www.sectop.com/get.php
get.php 中上述的表单
那么我们提交
http://www.sectop.com/get.php/">
那么表单变成
" method="POST">
跨站脚本被插进去了防御方法还是使用htmlspecialchars 过滤输出的变量,或者提交给自身文件的表单使用 这样直接避免了$_SERVER["PHP_SELF"] 变量被跨站
PHP 漏洞全解(五)-SQL 注入***SQL 注入***(SQLInjection) ,是***者在表单中提交精心构造的sql 语句,改变原来的sql 语句,如果web 程序没有对提交的数据经过检查,那么就会造成sql 注入***。SQL 注入***的一般步骤: 1、***者访问有SQL 注入漏洞的网站,寻找注入点2、***者构造注入语句,注入语句和程序中的SQL 语句结合生成新的sql 语句3、新的sql 语句被提交到数据库中进行处理4、数据库执行了新的SQL 语句,引发SQL 注入***
实例数据库
CREATE TABLE `postmessage` ( `id` int(11)NOTNULLauto_increment, `subject` varchar(60)NOT NULL default '', `name` varchar(40)NOTNULL default '', `email` varchar(25)NOT NULL default '', `question` mediumtext NOTNULL, `postdate` datetime NOTNULL default '0000-00-00 00:00:00', PRIMARYKEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=gb2312 COMMENT=' 使用者的留言'
AUTO_INCREMENT=69;
grantall privileges on ch3.*to 'sectop'@localhostidentified by'123456';
//add.php 插入留言//list.php 留言列表//show.php 显示留言程序和数据库打包下载地址点我下载页面http://www.netsos.com.cn/show.php?id=71 可能存在注入点,我们来测试http://www.netsos.com.cn/show.php?id=71 and 1=1
返回页面
提交http://www.netsos.com.cn/show.php?id=71 and 1=2 返回页面
一次查询到记录,一次没有,我们来看看源码//show.php12-15 行// 执行mysql 查询语句$query= "select *from postmessage whereid =".$_GET["id"]; $result =mysql_query($query)
ordie(" 执行ySQL 查询语句失败:". mysql_error()); 参数id 传递进来后,和前面的字符串结合的sql 语句放入数据库进行查询提交and 1=1 ,语句变成select * frompostmessage whereid =71 and 1=1 这语句前值后值都为真,and 以后也为真,返回查询到的数据提交and 1=2 ,语句变成select * from postmessagewhereid = 71 and 1=2 这语句前值为真,后值为假,and 以后为假,查询不到任何数据正常的SQL 查询,经过我们构造的语句之后,形成了SQL 注入***。通过这个注入点,我们还可以进一步拿到权限,比如说利用union 读取管理密码,读取数据库信息,或者用mysql 的load_file,into outfile 等函数进一步***。防范方法整型参数: 使用intval 函数将数据转换成整数函数原型
int intval(mixed var,int base)
var 是要转换成×××的变量
base ,可选,是基础数,默认是10
浮点型参数:
使用floatval 或doubleval 函数分别转换单精度和双精度浮点型参数
函数原型
int floatval(mixed var)
var 是要转换的变量
int doubleval(mixed var)
var 是要转换的变量
字符型参数:
使用addslashes 函数来将单引号“'”转换成“\'”,双引号“"” 转换成“\"” ,反斜杠“\” 转换成“\\”,
NULL 字符加上反斜杠“\”
函数原型
string addslashes (string str)
str 是要检查的字符串
那么刚才出现的代码漏洞,我们可以这样修补
// 执行mysql 查询语句
$query= "select *from postmessage whereid =".intval($_GET["id"]);
$result =mysql_query($query)
ordie(" 执行ySQL 查询语句失败:". mysql_error());
如果是字符型,先判断magic_quotes_gpc 是否为On, 当不为On 的时候使用addslashes 转义
特殊字符
if(get_magic_quotes_gpc())
{
$var = $_GET["var"]; } else {
$var = addslashes($_GET["var"]); }
再次测试,漏洞已经修补