不正アクセスへの対策

トップ > PHP入門 > 不正アクセスへの対策

目次

広告

不正アクセス対策について

PHPでプログラムを制作したら、レンタルサーバーなどにアップロードして利用することになります。そして不特定多数の訪問者が、そのプログラムにアクセスすることになります。

つまりWebアプリケーションはその性質上、常に不特定多数からの攻撃にさらされることになります。

PHPは文法が比較的容易に覚えられるので、「動作する」Webアプリケーションを作成するのは難しくはありません。ですが「安全な」Webアプリケーションを作成するのは簡単なことではありません。

Webアプリケーションへの攻撃を防ぐには、具体的な攻撃方法を知っておく必要があります。攻撃方法を知って初めて、攻撃を防ぐためのプログラムを書くことができるようになります。

これまでの解説の中でも何度か不正アクセスについて触れていますが、ここで再度、Webアプリケーションへの代表的な攻撃方法と、その防御方法を紹介します。

XSS(クロス・サイト・スクリプティング)

概要

XSS(クロス・サイト・スクリプティング)とは、特定のURLを送りつけて悪意のあるプログラムを強制的に実行させる攻撃のことです。

以下に、XSSへの対策がされていないプログラムを掲載します。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>サンプル</title>
</head>
<body>
<p><?php

echo 'ID ' . $_GET['id'] . ' の記事を表示します。';

//以下、IDに応じた記事を表示する処理が続く

?></p>
</body>
</html>

これはニュース管理プログラムなどで、記事を個別に表示する際の処理を想定しています。このプログラムのファイル名は view.php とします。つまり、このファイルには http://www.example.com/view.php?id=2 のようにアクセスされることを想定しています。

このプログラムを利用して攻撃する場合、以下のような文面をターゲット(サイトの管理者など)にメールで送りつけるなどします。

こんなページを見つけたよ!
http://www.example.com/view.php?id=%3Cscript%3Edocument.location%3D'http://www.google.co.jp/'%3C/script%3E

掲載されているURLが普段利用するサイトのURLなので安心してしまいますが、プログラムが埋め込まれることによって別のサイトに強制的に移動させることができます。

%3Cscript%3Edocument.location%3D'http://www.google.co.jp/'%3C/script%3E

この部分がJavaScript(ブラウザ上で実行できるプログラム)による攻撃コードです。これが $_GET['id'] に代入されて画面に表示されると、

<script>document.location='http://www.google.co.jp/'</script>

と解釈され、これは「http://www.google.co.jp/ に強制的に移動させるプログラム」となります。突然Googleに移動してもビックリするだけで害は無いですが、移動先をウイルスが仕掛けられたページにすれば悪質な攻撃になります。

対策

XSSへの対策は、これまで何度か紹介しているように htmlspecialchars 関数を使うことです。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>サンプル</title>
</head>
<body>
<p><?php

echo 'ID ' . htmlspecialchars($_GET['id'], ENT_QUOTES) . ' の記事を表示します。';

//以下、IDに応じた記事を表示する処理が続く

?></p>
</body>
</html>

このようにしておけば、

<script>document.location='http://www.google.co.jp/'</script>

という文字が画面に表示されるだけでJavaScriptは実行されません。$_GET$_POST など、訪問者からの入力を受け付けるときは、必ずこの対策を行ってください。

Script Insertion(スクリプト埋め込み)

概要

Script Insertion(スクリプト埋め込み)とは、JavaScriptなどを埋め込んだメッセージを投稿し、第三者に表示・実行させる攻撃のことです。

以下に、Script Insertion への対策がされていないプログラムを掲載します。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>サンプル</title>
</head>
<body>
<?php

$fp = fopen('message.txt', 'r');
while ($line = fgets($fp)) {
  echo "<p>$line</p>\n";
}
fclose($fp);

?>
</body>
</html>

これは掲示板プログラムなどで、記事を一覧表示する際の処理を想定しています。message.txt には投稿されたメッセージが格納されているものとします。

このプログラムを利用して攻撃する場合、掲示板の本文に以下のような文面を投稿します。

<script>document.location='http://www.google.co.jp/'</script>

XSSの際も紹介しましたが、「http://www.google.co.jp/ に強制的に移動させるプログラム」です。移動先をウイルスが仕掛けられたページにすれば、やはり悪質な攻撃になります。

対策

Script Insertion への対策は、XSSのときと同じく htmlspecialchars 関数を使うことです。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>サンプル</title>
</head>
<body>
<?php

$fp = fopen('message.txt', 'r');
while ($line = fgets($fp)) {
  echo '<p>' . htmlspecialchars($line, ENT_QUOTES) . "</p>\n";
}
fclose($fp);

?>
</body>
</html>

このようにしておけば、

<script>document.location='http://www.google.co.jp/'</script>

という文字が画面に表示されるだけでJavaScriptは実行されません。訪問者からの投稿を受け付けるときは、必ずこの対策を行ってください。

SQL Injection

概要

SQL Injection とは、データベースに送る命令を改竄し、データを盗んだり破壊したりする攻撃のことです。

以下に、Script Insertion への対策がされていないプログラムを掲載します。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>サンプル</title>
</head>
<body>
<?php

try {
  $pdo = new PDO('mysql:dbname=phpdb;host=127.0.0.1', 'root', '1234', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
  $pdo->query('SET NAMES utf8');

  $stmt = $pdo->query('SELECT * FROM articles WHERE id = ' . $_GET['id']);
  if ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
    echo '<p>' . $data['no'] . ':' . $data['name'] . "</p>\n";
  } else {
    echo "<p>指定された記事が見つかりません。</p>\n";
  }
} catch (PDOException $e) {
  exit($e->getMessage());
}

$pdo = null;

?>
</body>
</html>

これはニュース管理プログラムなどで、記事を個別に表示する際の処理を想定しています。このプログラムのファイル名は view.php とします。つまり、このファイルには http://www.example.com/view.php?id=2 のようにアクセスされることを想定しています。

このプログラムを利用して攻撃する場合、以下のようなURLでプログラムにアクセスします。

http://www.example.com/view.php?id=2;DELETE FROM articles;

これにより、$_GET['id'] には 2;DELETE FROM articles; が格納されますので、

SELECT * FROM articles WHERE id = 2;DELETE FROM articles;

というSQLが実行されてしまいます。つまり、テーブル内のデータがすべて削除されてしまいます。

対策

Script Insertion への対策は、これまで何度か紹介しているようにプレースホルダを使うことです。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>サンプル</title>
</head>
<body>
<?php

try {
  $pdo = new PDO('mysql:dbname=phpdb;host=127.0.0.1', 'root', '1234', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
  $pdo->query('SET NAMES utf8');

  $stmt = $pdo->prepare('SELECT * FROM articles WHERE id = :id');
  $stmt->bindValue(':id', $_GET['id'], PDO::PARAM_INT);
  $stmt->execute();
  if ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
    echo '<p>' . $data['no'] . ':' . $data['name'] . "</p>\n";
  } else {
    echo "<p>指定された記事が見つかりません。</p>\n";
  }
} catch (PDOException $e) {
  exit($e->getMessage());
}

$pdo = null;

?>
</body>
</html>

このようにしておけば、PDOが適切なエスケープ処理を自動で行ってくれます。プレースホルダを使わずに、addslashes 関数で '" をエスケープしたり、intval 関数で強制的に数値に変換しても大丈夫ですが、常にプレースホルダを使うクセをつけておくといいでしょう。

Script Insertion は、プログラムの具体的な内容を知っていないと攻撃は成功しづらいですが、成功したときの破壊力は大きいので注意してください。

データファイルへの直接アクセス

概要

掲示板の投稿データやショッピングカートの顧客情報などをファイルに保存している場合、そのファイルに直接アクセスされる可能性があります。

例えば、掲示板の投稿データを

http://www.example.com/message/message.txt

というファイルに記録したり、ショッピングカートの顧客情報を

http://www.example.com/shopping/customer.log

というファイルに記録したり…とすると、ブラウザから message.txtcustomer.log などに直接アクセスされる可能性があります。つまり、個人情報が流出することになります。

重要なデータを保存するファイルには、ブラウザからアクセスできないようにしましょう。いくつか対策を紹介します。

対策1

.htaccess でのアクセス制限ができるサーバーの場合、.htaccess

<Files ~ "\.log$">
  Deny from all
</Files>

と書いておくと、拡張子が log のファイルにはブラウザから直接アクセスできなくなります。(PHPプログラムからは読み込めます。)この制限は、.htaccess が存在するディレクトリ内で有効です。ディレクトリ内にさらにディレクトリがあれば、そのディレクトリ内も有効です。

対策2

FTPソフトでファイルをアップロードする場合、「ホームページとして公開したいデータは public_html 内にアップロードしてください」のようにアップロード場所が指定されていることが多いですが、このディレクトリの外にファイルを配置すれば、ブラウザからはアクセスできなくなります。(PHPプログラムからは読み込めます。)これを利用して、直接アクセスしてほしくないファイルは公開用ディレクトリの外に設置するのも有効です。

www /
 |
 +-- public_html / index.html
 |                 cart.php … PHPプログラムは公開ディレクトリ内
 |
 +-- data / customer.log … データファイルは公開ディレクトリ外

ただし、公開ディレクトリ外にファイルを配置できないレンタルサーバーがありますので、その場合はこの方法は利用できません。

対策3

フリーソフトとして配布されているPHPプログラムを設置すると、どこに何のファイルがあるのか訪問者も把握することができます。

ですので、重要なデータが保存されるファイルは、初期設定とは異なる保存場所にしたりファイル名を変更したりしておくと有効です。(ファイル名の変更方法などは利用するプログラムによって異なりますので、そのプログラムのサポートページなどを参照してください。)

これは、どんなサーバーを利用している場合でも有効です。可能なら、対策1~3をすべて施しておくとセキュリティが向上します。