PHPの脆弱性への攻撃名称と対策メモ

自分用メモ。ごちゃごちゃすると忘れるので、なるべくシンプルにまとめたい。
誤り、不備などあれば、随時追加修正します（ご指摘ありがとうございます）。


---

## クロスサイトスクリプティング（cross site scripting、XSS）

### 概要

訪問者に目的のサイトとは別の罠サイトを踏ませて不正な処理を実行させる行為。

### 原因

フォームから受け取った値を、エスケープせずに画面に出力するために発生
（偽のフォームを作成する手法も有るので、JavaScriptの対策だけでは不足）

### 対策

* HTMLの実体参照を用い、& を &amp;amp; に、< を &amp;lt; に、> を &amp;gt; に、" を &amp;quot; に、それぞれ置換する。
PHPではhtmlspecialchars関数を用いれば、一括で対策できる
（ただしENT_QUOTESを設定しないとシングルクォーテーションはエスケープされない）

```php
<?php
echo htmlspecialchars($val, ENT_QUOTES); 
?>
```


* タグの属性値は必ず "～" （ダブルクオート）で括る。また属性値中のエスケープを忘れない。
かつ、「`style` `href` `src` `onclick` `onload` などの危険な属性に対してユーザー入力を用いない」



* cookieを使う際の、HttpOnlyを指定(JavaScriptからクッキーを読み込まれないようにする）

``` php
<?php
ini_set('session.cookie_httponly', true);
?>
```

## SQLインジェクション（SQL Injection）

### 概要

アプリケーションの意図しないSQLを実行させる。

### 原因

外部から受け取った値を、エスケープせずにSQLを実行するために発生。

###対策

*  プレースホルダを使用する(推奨）。


## ディレクトリトラバーサル（Directory Traversal）
### 概要

意図しないファイルにアクセスされる。

### 原因

外部から受け取った値を、エスケープせずにファイル名を取得するために発生。

### 対策
* 外部からファイル名を要求する仕様を避ける
*  要求する場合はファイル名からディレクトリ情報を取り除く
 * PHPではbasename関数を用いれば、対策できる

```php
<?php
/*ファイルを開く場合は、固定ディレクトリ＋ファイル名にする
参考URL//http://www.websec-room.com/2013/03/21/694
*/

  $DIRECTRY_PATH = "/var/files/";
 
  //ファイル名取得
  $fileName = basename("../../../etc/passwd");

  //パス結合($pathの中身　/var/files/passwd）
  $path = $DIRECTRY_PATH . $fileName;
?>
```

* 備考……
$_FILES 変数に関しては、 PHP5.3.7 以降はディレクトリトラバーサル対策済み。


## セッションハイジャック

### 概要

本利用者のセッションを攻撃者に乗っ取られる

### 原因

セッションIDの推測、強要、盗み出し　etc...

### 対策

* 推測されにくセッションIDを生成する
* 認証後にセッションIDを変更する

```php
// PHP5.1.0以降
<?php
session_start();
session_regenerate_id(TRUE);
?>
```

PHP5.1.0までは、古いセッション情報が削除されずにそのまま残っているため書き方が変わる

```php 
// PHP5.1.0以前
<?php
session_start();
$old_id = session_id();
session_regenerate_id();
unlink(session_save_path() . 'sess_' . $old_id);
?>
```

* パスワードの再入力（保険的対策）

## OSコマンドインジェクション(OS command injection )

### 概要

アプリケーションの意図しないシェルを実行させる
（system(), passthru(), proc_open(), shell_exec(), ）。

### 原因

外部から受け取った値を、エスケープせずにシェルコマンドを実行させるために発生。

### 対策

* 外部から受け取った値をコマンドラインのパラメータに渡さない（推奨）。
* 使用する場合は以下の文字列をサニタイジングする
（想定されているパラメータの指定が英数字限定であれば、受け取る値をそれのみにしてやれば漏れが発生しづらい）

## クロスサイトリクエストフォージェリ（Cross Site Request Forgeries）

### 概要

正規の利用者に意図せず何らかの操作(書き込み、パスワードの変更etc..)を行わせる。

### 原因

以下のWebの性質から起因する
form要素のaction属性にはどのドメインのURLも使用できるため。
クッキーに保管されたセッションIDは、対象サイトに自動的に送信されるため。

### 対策

決済実行など、必要な処理の画面の直前に、以下の対策をとる

* トークンを埋め込む

```html:html側
//HTML側のhiddenにトークンを埋め込む
<input type="hidden" name="token" value="<?php echo htmlspecialchars(session_id(),ENT_COMPAT, 'UTF-8'); ?>"
```

```php:php側
//送られるトークンが想定されているものか検証する
if(session_id() !== @$_POST['token']){
    //不正な処理
}
```

* Refererのチェック
* パスワードの再入力

### 備考

####XSSとの違い

* CSRFはサーバ側の処理を悪用する。
* XSSはブラウザ上の処理を悪用する（JavaScriptの使ってサーバ側の機能の悪用も可能）







＊参考にされて、脆弱性が発生しても、責任は取れません



## 参考文献

書籍

* 『体系的に学ぶ 安全なWebアプリケーションの作り方』著 徳丸 浩

ネット

* ウィキペディア
* 『体系的に学ぶ 安全なWebアプリケーションの作り方』著 徳丸 浩
* 覇王色を求めて
 * http://d.hatena.ne.jp/ryster/20080229/1204304780
* Webセキュリテリの小部屋
 * http://www.websec-room.com/2013/03/21/694
* yohgaki's blog
 * http://blog.ohgaki.net/session_regenerate_id_wo
* KIAI＠PG
 * http://d.hatena.ne.jp/owa-tayo/20100129/1264727922
* to-R
 * http://blog.webcreativepark.net/2007/02/03-013141.html
* Shoulder.jp
 * http://canalize.jp/archives/009281.php