さとーC++ぶろぐ

アクセスカウンタ

zoom RSS PHPとかでHIDDENとかのセキュリティ対策かTEXTAREAの複数行をHIDDENへ入れる

<<   作成日時 : 2007/06/14 19:04   >>

なるほど(納得、参考になった、ヘー) ブログ気持玉 2 / トラックバック 1 / コメント 0

PHPとかでFORMの値のHIDDENとかのセキュリティ対策かTEXTAREAの複数行を入れた時に,HTMLとして壊れてしまう。


しかし,普通に良く使うセッション風にINPUTとかTEXTAREAの値を次のページではHIDDENに入れたとき,そのまま入れると,"とか < とか改行文字を組み合わせて,ページの内容を書き換えられてしまう。

たとえば入力された値が "> <Script> とかだと,JavaScriptを組み込めたりしていろんな動作ができる。他にもこの値を内部のPHPで取り込んで処理するときにも,問題が発生する。

htmlspecialchars( ) とか使えば,HTMLを取り除くことができるが,まだやばい。入力する値を工夫すれば,セキュリティホールがあるかもしれない。

これじゃ,セキュリティ的にやばい。

さらに,改行がある文字は,<input type="hidden" value="TEXTAREAの内容は
改行できるので,
良くない">
という風なHTMLが出力されたりする。valueが複数行になってしまう。

改行文字を書き換えればよいが,オリジナルデータを変更してしまうことになる。


で,根本的な解決策の1つを思いつく。

それは・・・FORMの値をBase64にしてしまうことだ。

Base64を使うメリットとしては,PHPならば,標準の関数1発でエンコードとデコードができること。暗号化よりも負荷が少ないし,使い方が簡単。それでいていて,エンコード後の出力結果の文字に使われるのは以下の通り。

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789+/=?

HTMLのクラックに必須の <や >や "や'  がない! つまり value=""の中に使うものでは,とっても安全かつお手軽なエンコードだ。"" の中に書かれたBase64ならば,いかなる組み合わせでも,問題ない。もちろんBase64の実装そのものにセキュリティホール(バッファオーバーフローなど)がある場合を除くが。。。
もちろん改行文字もエンコードされるので,改行が含まれていても改行無しでエンコード結果を得ることが出来る!textareaの値をinput type="hidden" value="ここ"にそのままの値で入れることが出来る。

他にも適したエンコードがあるかもしれないが,標準の関数1発でエンコードとデコードが出来るし,マニアックなエンコードより他の人(上長とか)に説明しやすい。標準ならセキュリティ対策も結構進んでいる(はず)などなど,利点が多い。


しかし,送信途中から,BASE64になったらややこしいのでは?ということだが,
<input type="hidden" name="b64" value="1" />
とか,識別子をつけて使えば,何とかなる。

以下の関数を作れば,その辺も自動化してくれる。
<input type="text" name="name" />
を受け取ったものは,
$name = get_val("name");
で取得。これは,base64デコードを識別する。
さらに,input type="hidden" で別のページに送る時は以下の関数を使うと,hiddenの出力をしてくれる。
print_h_val( "name");
改行文字やセキュリティに対応している。
<input type="hidden" name="b64" value="1" />
をつけて送れば,その次の受信も
$name = get_val("name");
で取れる。
表示したければ,
print get_disp_val("name");
で,改行は<br /> で,タグなどは,無効にしてそのまま出力する。

これなら,不正な文字を使ったXSS攻撃やクロスサイトスクリプティング対策に完全対応できます。

ただし,Base64のエンコードやデコードを狙ったアタックには弱いかも(笑い)


※あまりテストしていないので,動作は保障しません。。。。使うなら,デバッグや検証をしてね。


<?php
// フォームから送信された値を取得する関数
// POSTの値をチェックし,なければGETの値をチェック
// ただし,BASE64エンコードされているときは,デコードする
function get_val( $key )
{
    if($_GET["b64"] == "1" || $_POST["b64"] == "1") {
        if(!empty( $_POST[ $key ] ) ) {
            return base64_decode( $_POST[ $key ] );
        } else {
            return base64_decode( $_GET[ $key ] );
        }
    } else {
        if(!empty( $_POST[ $key ] ) ) {
            return $_POST[ $key ];
        } else {
            return $_GET[ $key ];
        }
    }
}

// 上のBASE64を無視して取得する版。転送とか
function get_raw_val( $key )
{
    if(!empty( $_POST[ $key ] ) ) {
        return $_POST[ $key ];
    } else {
        return $_GET[ $key ];
    }
}

// Base64の値で取得する。次のフォームに転送するときとか
function get_b64_val( $key )
{
    if($_GET["b64"] == "1" || $_POST["b64"] == "1") {
        if(!empty( $_POST[ $key ] ) ) {
            return $_POST[ $key ];
        } else {
            return $_GET[ $key ];
        }
    } else {
        if(!empty( $_POST[ $key ] ) ) {
            return base64_encode( $_POST[ $key ] );
        } else {
            return base64_encode( $_GET[ $key ] );
        }
    }
}

// データを転送するためのもの
function print_h_val( $key )
{
    print "<input type=\"hidden\" name=\"" . $key . "\" value=\"" . get_b64_val($key) ."\" />\n";
}

// $strをHTMLタグをそのまま表示できる形式に変換
function cnv_disp( $str )
{
    return nl2br( htmlspecialchars( $str , ENT_NOQUOTES, "UTF-8") );
}

// フォームの値を表示できる形式に(Base64も自動認識)
function get_disp_val( $key )
{
    return cnv_disp( get_val ( $key ) );
}

// フォームの値を表示できる形式に(Base64は処理しない)
function get_disp_raw_val( $key )
{
    return cnv_disp( get_raw_val ( $key ) );
}


?>


参考文献:

テーマ

関連テーマ 一覧


月別リンク

ブログ気持玉

クリックして気持ちを伝えよう!
ログインしてクリックすれば、自分のブログへのリンクが付きます。
→ログインへ
気持玉数 : 2
なるほど(納得、参考になった、ヘー)
ナイス

トラックバック(1件)

タイトル (本文) ブログ名/日時
PHPで送信前の確認画面で入力内容を表示するためのタグ変換
PHPで送信前の確認画面で入力内容を表示するためのタグ変換 ...続きを見る
さとーC++ぶろぐ
2007/12/15 13:21

トラックバック用URL help


自分のブログにトラックバック記事作成(会員用) help

タイトル
本 文

コメント(0件)

内 容 ニックネーム/日時

コメントする help

ニックネーム
URL(任意)
本 文
PHPとかでHIDDENとかのセキュリティ対策かTEXTAREAの複数行をHIDDENへ入れる さとーC++ぶろぐ/BIGLOBEウェブリブログ
文字サイズ:       閉じる