安全|错误
PHP对于飞速发展的动态网站来说是一门恐怖的语言。它对于新手来说也有很多友好的性质,比如变量不需要定义就可以直接使用。但是,一些类似的这种性质使程序员不会注意到在网站应用方面的一些安全问题。一个非常著名的邮件列表就充满很多条了对PHP应用有漏洞的例子,但一旦你理解了PHP应用中这些基本的漏洞,PHP将变得比其他任何语言都安全。
在这篇文章中,我会详细的说说明在一般PHP程序中常见的导致安全问题的错误。而且会展示给你什么是不能做的,还有这些特殊的漏洞是怎么被发现的,我希望你不但可以懂得怎么来避免这些特殊的错误,而且可以知道它们为什么会导致安全问题。了解每种可能出现的漏洞能帮助你避免在编写PHP程序时发生同样的错误。安全是一个过程,而不是一个产品,通过在开发应用程序的过程中了解安全问题可以让你编出更高效更健壮的代码。
Unvalidated Input Errors 不受重视的输入错误
最常见的PHP安全问题之一就是对用户输入过滤的漏洞。一般用户提交数据都是不可信任的。你应该假设所有所有访问你网站的用户都是恶意的。非正常输入是很多PHP应用程序漏洞的最根本的原因,我们将在后面进行讨论。
现在给大家一个例子,你可以写下面这段代码来允许用户看到可以一个通过执行UNIX中的cal命令来显示特殊月份。
$month = $_GET[month];
$year = $_GET[year];
exec("cal $month $year", $result);
print "
"; <br>foreach ($result as $r) { print "$r<BR>"; } <br>print "";
这段代码有很多安全问题。比如$_GET[month]和$_GET[year]没有过滤就直接赋给了$month和$year,如果用户输入的月份是1到12之间,而且年份是4位数字当然是没有问题。不过,恶意的用户会在年份后面加上一个";ls -la",这样他就可以以列表的方式看到你网站的所有目录。更加极端的用户会在年份后面加上";rm -rf",这样就能删掉你的整个网站!
改正这个安全问题的最好的方法是在接收用户输入的数据时进行检测,使他成为你所希望的格式。不要使用JS来验证,这种验证很容易就能绕过,比如建立一个自己的表单来提交数据,或者用浏览器禁用JS。你应该用PHP代码来确保输入的年份和月份是数字,而且必须是数字。就象下面的代码这样:
$month = $_GET[month];
$year = $_GET[year];
if (!preg_match("/^[0-9]$/", $month)) die("Bad month, please re-enter.");
if (!preg_match("/^[0-9]$/", $year)) die("Bad year, please re-enter.");
exec("cal $month $year", $result);
print "
"; <br>foreach ($result as $r) { print "$r<BR>"; } <br>print "";
这样的代码就能安全的使用,而不用考虑用户提交的数据会使你的应用程序产生错误,或导致服务器运行用户提交的非法代码。正则表达式是验证数据的一个非常有效的工具。虽然他很难完全掌握,但在这种情况下还是非常实用的。
你应该验证用户提交的数据,来拒绝所有非法的数据。一定不要在没有验证之前接收任何数据,除非你可以确定它一定是安全的数据。这是一个常见的安全问题。但有时,恶意的用户会通过一些方法来提交一些特定的数据,这样可以绕过你的验证,而且会起到有害的作用。
所以你应该严格的验证提交的数据,如果一些字符是不需要的,那么你应该过滤掉这些字符或者直接拒绝接收这些的数据。
アクセス制御の欠陥 不正制御の脆弱性
これはPHPアプリケーションにとって必須ではない検証ですが、非常に重要な、つまり不正制御です。たとえば、Web サイトの構成を変更したり、機密情報を表示したりできる管理ページがあります。
すべての PHP アプリケーション ページを実行するときは、ユーザーの権限を確認する必要があります。ホームページ上でユーザーの権限を確認するだけの場合、悪意のあるユーザーがアドレス バーにアドレスを直接入力して、権限が確認されない後続のページにアクセスする可能性があります。
厳密な検査をお勧めします。可能であれば、IP に基づいてユーザーの権限を決定できます。もう 1 つの良い方法は、他の人にアクセスさせたくないページを特別なディレクトリに置き、このディレクトリを Apache の .htaccess で保護することです。
Web サイトの設定ファイルは、Web サイトが直接アクセスできるディレクトリの外に配置します。この構成ファイルには、悪意のあるユーザーがサイトを攻撃するために使用できるデータベース パスワードとその他の情報が含まれています。これらのファイルをインクルードするには、PHP の include 関数を使用します。これらのことを行うのは少し冗長に感じるかもしれませんが、それでも Web サイトのセキュリティにプラスの効果があります。
たとえば、私が書いた PHP アプリケーション。すべてのカスタム関数ライブラリは、includes フォルダーに配置されます。通常、これらのインクルード ファイルには .php 接尾辞が付いたファイル名が付けられます。このように、たとえすべての保護手段がバイパスされたとしても、サーバーはこれらのファイルを PHP ファイルとして解析し、これらのファイルを表示しません。 URL 経由で直接アクセスできるフォルダーは、www フォルダーと admin フォルダーだけです。 admin フォルダーは .htaccess で保護されており、.htpasswd に保存されているユーザー名とパスワードを知っているユーザーのみにアクセスが許可されます。
/home
/httpd
/www.example.com
.htpasswd
/includes
cart.class.php
config.php
/logs
access_log
error_log
/www
index.php
/admin
.htaccess
index.php
Apacheのデフォルトのホームページ名をindex.phpに設定し、すべてのディレクトリにindex.phpファイルがあることを確認する必要があります。他の人にアクセスさせたくないディレクトリに誰かがアクセスした場合は、画像などが保存されているディレクトリなど、Web サイトのホームページにリダイレクトします。
バックアップ ファイルにファイル名拡張子 .bak を付けたり、URL から直接アクセスできるディレクトリに保存したりしないでください。これを行うと、これらのファイル内の PHP コードは解析されず、ユーザーが URL を通じて直接ダウンロードする可能性もあります。これらのファイルにパスワードやその他の機密情報が含まれている場合、他人に知られる可能性があり、GOOGLE などの検索エンジンで直接検索されてページに表示される可能性もあります。これらのファイルの名前は必ず .bak.php 接尾辞が付いたファイルに変更してください。これにより安全になりますが、最善の解決策は CVS などのコントロールを使用することです。 CVS は学習するのが少し複雑ですが、学習に費やした時間は後で報われます。このようなシステムを使用すると、プログラムの各バージョンを別のフォルダーに保存できます。後でプログラムに問題が発生した場合、以前に保存したバージョンが貴重なリソースになる可能性があります。 .
[1] [2] [3] 次のページ