燈明日記 このページをアンテナに追加 RSSフィード

ごあいさつ

燈明日記へようこそ!!

燈明日記の主なテーマは、以下の通りです。

そして、燈明日記へ来られたのも『私』と『あなた』の何かのご縁です。なので、どうぞごゆっくりご覧下さい!


2016/6/16(木)

[][] 秀丸では9行以上の文字列をマッチすることが出来ない!

VB-TIPSのファイルが約550個ありまして、1ファイルで連続263行を「無」に置換したかったのですが・・・

秀丸エディッターの置換機能では、9行以上の文字列をマッチすることが、どうしてもできませんでした。


そこで、Perlプログラムを組んでやればいいと思いつきました。

しかし、今のPCにはPerlがインストールされていませんでした。


早速、Activeperlのサイトに行って、Perlをダウンロードしてインストールをしてみると・・・

なにかインストールプログラムが別に必要なみたいで、インストールが出来ませんでした。


そこで、古いPCを引っ張り出しコピーし、v5.10.0のperlをインストールしました。

まずは、ファイル約550個で、1ファイル毎に連続263行を「無」にする置換プログラムを作成しました。

(具体的には、ワイルドカード「*」を使ってファイル指定を「VBMemo*.htm」とし、

「<!-- BGN VBTIPS BOOK.*END VBTIPS BOOK -->」の間の263行を削除(無に)する)


$/ = undef; # ファイル全体を読み込むためにレコード区切り文字デリミタを未定義にする
while ($fileName = glob("VBMemo*.htm")) {
    open(FH, "<$fileName") or die "open error1 ($!)";
    $fileBody = <FH>; # ファイル全体を読み込む
    close(FH);

    $fileBody =~ s///ms;

    open(FH, ">$fileName") or die "open error2 ($!)";
    print FH $fileBody; # ファイル全体を書き込む
    close(FH);
}

正規表現オプションms」を使うことにより、上手く約550個ファイルの263行削除を一瞬ですることができました!888888

何かの参考になれば幸いです。(ファイル指定と正規表現の2箇所を変えれば汎用性あり)


しかし、約6年ぶりにプログラミングをしました。正直大変でした・・・

誰か、秀丸で置換文字列自体が9行以上場合のマッチの方法が分かる方、いたら教えてください!

2010/5/31(月)

[][] URLパラメータとGETパラメータの関係とは(バージョンアップ版)

URLパラメータは、ブラウザのアドレス欄に表示されるURLの「?」以降の文字列のことです(たぶん)。

GETパラメータは、form要素のmethod属性に"get"と指定してサブミットした時にアドレス欄に表示されるURLの「?」以降の文字列のことです(たぶん)。


通常、form要素のmethod属性に"post"を指定して、action属性にURLパラメータを指定すると、サーバー側では、postのデータは標準入力で、URLパラメータは環境変数で取得することができます。

また、form要素のmethod属性に"get"を指定すると、サーバー側では、環境変数で取得することができます。


では、form要素のmethod属性に"get"を指定して、action属性にURLパラメータを指定すると、サーバー側では、どのようになると思いますか?


そう、URLパラメータもGETパラメータも単独では環境変数にセットされるのですが、この2つが重なったときは、GETパラメータとなり、URLパラメータは無視されるのです。

これ、IE6,IE7,Opera10,Firefox3で同じ結果になりました。

以下は、そのサンプルソースです。


◆ サンプルソース テストフォーム(test_get.cgi

#!c:/perl/bin/perl.exe
use strict;

print <<"HERE1";
Content-type: text/html; charset=Shift_JIS

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>Test Form</title>
</head>
<body>
<h1>Test Form</h1>
<form method="get" action="test_get2.cgi?ID1=1&ID2=2" name="FM">
<p><input type="hidden" name="ID3" value="3"></p>
<p><input type="hidden" name="ID4" value="4"></p>
<p><input type="submit" value="実行"></p>
</form>
</body>
</html>
HERE1

◆ サンプルソース QUERY_STRING表示(test_get2.cgi)

#!c:/perl/bin/perl.exe
use strict;

# 画面出力
print <<"HERE1";
Content-type: text/html; charset=Shift_JIS

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>QUERY_STRING</title>
</head>
<body>
<h1>QUERY_STRING</h1>
<p>---------->$ENV{'QUERY_STRING'}<--------</p>
</body>
</html>
HERE1

また、GETパラメータだとhiddenにしてもアドレス欄に表示されてしまいますね(hiddenじゃない!)。

セキュリティ的には、form要素のmethod属性は"post"の方が安全ですね!

2010/5/16(日)

[] シーザー暗号を組んでみる!

先日ご紹介した『暗号化のお話 (1)』にシーザー暗号のことが書かれていました。

普通、暗号化は凄く数学的で難しいものですが、このレベルならまだ私でも理解ができたので、Perlで実装してみました。


◆シーザー暗号とは

古来から伝わる暗号化の方式としてシーザー暗号というのものがあります。

仕組みはとても簡単で、下の表のように文字列をアルファベット順に

数個ずらすだけです。この例では A〜Z を F〜Z・A〜E と、5つずらしています。

ABCDEFGHIJKLMNOPQRSTUVWXYZ
FGHIJKLMNOPQRSTUVWXYZABCDE

例えば「I LOVE YOU」というメッセージをこのシーザー暗号で

暗号化すると「N QTAJ DTZ」という暗号文になります。

暗号文を受信した側は、F〜Z・A〜E を 5つずらして A〜Z

に戻せば「I LOVE YOU」という平文が手に入ります。

http://x68000.q-e-d.net/~68user/net/crypt-1.html

◆実装仕様

仕様としては、アルファベット26文字のみ暗号化します。

暗号化(CaesarCipherEnc)としては、引数に平文とローテート数を指定します。

復号化(CaesarCipherDec)としては、引数に暗号文とローテート数を指定します。


サンプルソース(ango.pl)

use strict;
use warnings;

    # 暗号化
    my $ans = CaesarCipherEnc('I LOVE YOU', 5);
    print $ans, "\n";

    # 復号化
    $ans = CaesarCipherDec($ans, 5);
    print $ans, "\n";

sub CaesarCipherEnc {
# 第1引数は平文
# 第2引数はローテート数で0〜26
my ($intext, $rotate) = @_;
my  $wkABC1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ';
    return '引数エラー!' if (($rotate < 0) or ($rotate > length($wkABC1)/2));

my  $wkABC2 = substr($wkABC1, $rotate, length($wkABC1)/2);
    $_ = $intext;
    eval "tr/$wkABC1/$wkABC2/";
    return $_;
}

sub CaesarCipherDec {
# 第1引数は暗号文
# 第2引数はローテート数で0〜26
my ($intext, $rotate) = @_;
my  $wkABC1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ';
    return '引数エラー!' if (($rotate < 0) or ($rotate > length($wkABC1)/2));

my  $wkABC2 = substr($wkABC1, length($wkABC1)/2 - $rotate, length($wkABC1)/2);
    $_ = $intext;
    eval "tr/$wkABC1/$wkABC2/";
    return $_;
}

◆サンプルソースの実行結果

C:\Documents and Settings\hoge>perl ango.pl
N QTAJ DTZ
I LOVE YOU

◆サンプルソースのポイント

アルファベットの変換にtr///を使用してます。

tr///は、s///と違って、文字列単位の置換ではなく、1文字単位の変換です。

また、tr///は、普通、変数を指定することはできませんが、evalを使うことにより可能にしています。

これは、"tr/$wkABC1/$wkABC2/"の文字列展開をした後にevalで実行ができるためです。

また、『eval "tr/$wkABC1/$wkABC2/";』で変換されるべき変数は『$_』なので、先に$intextを$_に代入しています。

2010/5/5(水)

[][] WEB脆弱性のインジェクションとは?

前回の『WEB脆弱性のインジェクションとは?』に『対策』を追記してみました。

-------------------------------------------------------------------

インジェクション(injection)の意味は、内部に何かを注入することです。

そして、WEB脆弱性のインジェクションには、以下の3つがあります。

  1. SQLインジェクション
  2. OSコマンドインジェクション
  3. HTTPヘッダインジェクション

つまり、SQL、OSコマンド、HTTPヘッダの各々に、Webページから悪意のコマンドをインジェクションされることなのです。


◆SQLインジェクション

たとえば、$uidと$passhをWebページから入力(POST)される以下のSQLがあったとします。

$query = "SELECT * FROM usr WHERE uid = '$uid' AND pass = '$passh'";

$uidに「taro'--」と入力されたら、以下のように展開されます。

$query = "SELECT * FROM usr WHERE uid = 'taro'--' AND pass = ''";

すると、SQLで「--」はコメントになりますので、パスワードがなくても以下のSQLが発行されてしまうのです。

$query = "SELECT * FROM usr WHERE uid = 'taro'";

これ、Delete文もインジェクションされるケースもあり、私は実際にテストで体験しております。DBがクリアされました!


・対策1

バインド機構を利用します。

バインド機構とは、実際の値がまだ割り当てられていない記号文字(プレースホルダ)を使用して、あらかじめSQL文の雛形を用意し、後に実際の値(バインド値)を割り当ててSQL文を完成させるようにします。


・対策2

対策1のバインド機構が利用できない場合は、入力されるパラメータや、データベースに格納される情報や、SQL文を構成する全ての変数や演算結果に対し、エスケープ処理を行います。

エスケープ処理の対象は、SQL文にとって特別な意味を持つ記号文字(たとえば、「'」→「''」、「\」→「\\」等 )が対象です。

尚、特別な意味を持つ記号文字は、利用しているデータベースエンジンによって異なるので、それぞれに応じて対策を行います。


・対策3

たとえば、データ検索のみのケースでは、削除や更新系のSQLが使えないようにDBの権限設定を行います。


・対策4

あとは、SQLのエラーメッセージをWeb画面に表示しないとか、hiddenパラメータにSQL文をそのまま指定しないとか、があります。


◆OSコマンド・インジェクション

たとえば、$fromをWebページから入力(POST)される以下のopen文があったとします。

$from =~ s/"|;|'|<|>|\|| //ig;
open(MAIL, "|/usr/sbin/sendmail -t -i -f $from");

$from に「`touch[0x09]/tmp/foo`」と入力されたら、以下のように展開されます。

$from =~ s/"|;|'|<|>|\|| //ig;
open(MAIL, "|/usr/sbin/sendmail -t -i -f `touch[0x09]/tmp/foo`);

すると、touchコマンドが実行されてしまいます。


・対策1

OSコマンドを起動できる言語機能の利用を避けます。

たとえば、Perlでは、open関数でなくsysopen関数を使用すれば、OSコマンドを起動することができません。


・対策2

対策1が利用できない場合は、引数に埋め込む前にチェックをかけ、本来想定する動作のみが実行されるようします。


◆HTTPヘッダ・インジェクション

たとえば、$numをWebページから入力(POST)される以下のHTTPのLocationがあったとします。

$cgi = new CGI;
$num = $cgi->param('num');
print "Location: http://example.jp/index.cgi?num=$num\n\n";

$num に「3%0D%0ASet-Cookie:SID=evil」と入力されたら、以下のようなクッキーが発行されてしまうのです。

Set-Cookie: SID=evil

・対策1

ヘッダの出力を直接行わず、Webアプリケーションの実行環境や言語に用意されているヘッダ出力用APIを使用します。


・対策2

対策1が利用できない場合は、ヘッダの出力時に想定外の改行を許可しないようにします。

これは、HTTPヘッダは改行によって区切られる構造となっているため、これを許すと、任意のヘッダフィールドや任意のボディを注入される原因となるからです。


◆ 参考リンク

2010/5/4(火)

[][] WEB脆弱性のクロスサイト・スクリプティングとは

普通CGIなどWebアプリケーションは、Webページから検索のキーワード入力や個人情報の登録入力などを処理して、Webページとして出力します。

ここで、Webページへの出力処理に問題があると、そのWebページにスクリプトなどを埋め込まれてしまうことがあります。

このようなスクリプトのインジェクション(注入)を、特にクロスサイト・スクリプティング攻撃と言います。


対策としては、HTMLテキストの入力をエスケープ処理し、HTMLテキストを許可しない方法があります。

どうしても、HTMLテキストが必要な場合は、構文解析を行い、「ホワイトリスト方式」で許可する要素のみを抽出します。

また、共通の対策としては、HTTPレスポンスヘッダのContent-Typeフィールドに文字コード(charset)の指定を行います。


◆ 補足

・エスケープ処理

エスケープ処理には、Webページの表示に影響する特別な記号文字(「<」、「>」、「&」、「"」、「'」など)を、

HTMLエンティティ(「&lt;」、「&gt;」、「&amp;」、「&quot;」、「&#39;」など)に置換します。

また、URLを出力するときは、「http://」や 「https://」で始まるURLのみを許可するようにします。

これは、「javascript:」の形式で始まるURLがあるからです。


以下は、上記の置換をするPerlでのソースです(前に書いた記事の引用です)。

sub htmlf {
    my ($strhtml) = @_;
    $strhtml =~ s/&/&amp;/g;
    $strhtml =~ s/>/&gt;/g;
    $strhtml =~ s/</&lt;/g;
    $strhtml =~ s/"/&quot;/g;
    $strhtml =~ s/'/&#39;/g;
    return $strhtml;
}
http://d.hatena.ne.jp/chaichanPaPa/20080329/1206748795

・ホワイトリスト方式

リストに登録された内容に一致する文字列の通過を「許可」する方式です。

未知の攻撃パターンにも有効であり、漏れが生じにくい点で安全性は高いです。

ちなみに、ブラックリスト方式は、ホワイトリスト方式の逆で、リストに登録された内容に一致する文字列の通過を「禁止」する方式です。

これは、未知の攻撃パターンを検出できない可能性があり、漏れが生じやすいという性質あります。


・HTTPレスポンスヘッダの文字コード指定

HTTPレスポンスヘッダに文字コードを指定していないと、ブラウザは、文字コードを推定して画面表示を処理します。

たとえば、UTF-7に推測された場合、上記のような「エスケープ処理」を施してもエスケープをスルーしてしまうケースがあるとのことでした(参考リンク参照)。


◆ 参考リンク

2010/4/29(木)

[][] WEB脆弱性のディレクトリ・トラバーサル(Directory Traversal)とは?

「../../」のような相対パスを使用し、システム内の任意ファイルへアクセスする攻撃手法をディレクトリ・トラバーサルと言います。

システム内のディレクトリ間を自由に横断(トラバース)できることが攻撃名称の由来で、パス・トラバーサルとも呼ばれます。


対策は、CGIでは、GET(引数)とPOST(hidden)で、ファイル名のみで、ファイルパスを指定しないように設計します。

また、万が一、ファイル名にファイルパスを付加された場合を想定して、そのようなパスを削除するように設計します。


◆ ディレクトリ・トラバーサル対応のサンプルプログラム

#!c:/perl/bin/perl.exe
use strict;
use File::Basename;
use CGI;

my $form = new CGI;
my $file_name = $form->param('file_name');
local $/;

my $dir = 'c:/wk/';                # パス情報をプログラム内で持つ
$file_name = basename($file_name); # パスを指定されてもファイル名だけにする
                                   # openは、パス名とファイル名で連結する
open(my $fh, '<', $dir . $file_name) or die "$file_name, open err ($!)";

my $wk = <$fh>;
print <<"HERE1";
Content-type: text/plain; charset=Shift_JIS;

<html>
<body>
<h1>test</h1>
<p>$wk</p>
</body>
</html>
HERE1

尚、上記は、XSS対応にはなっていませんので、ご注意を!

XSSに関しては、後日まとめる予定です。


◆ 補足

『./』は自ディレクトリです。

『../』は、親ディレクトリです。

たとえば、bbbディレクトリにtest.txtがあったとします。

すると、

cat /aaa/bbb/test.txt

cat /aaa/bbb/ccc/ddd/../../test.txt

は、同じになるのです。


また、本記事は、以下のURL先を大変参考にさせて頂きました。問題があればコメント欄でご指摘ください。

2010/4/24(土)

[][] WEB脆弱性のインジェクションとは?

インジェクション(injection)の意味は、内部に何かを注入することです。

そして、WEB脆弱性のインジェクションには、以下の3つがあります。

  1. SQLインジェクション
  2. OSコマンドインジェクション
  3. HTTPヘッダインジェクション

つまり、SQL、OSコマンド、HTTPヘッダの各々に、Webページから悪意のコマンドをインジェクションされることなのです。


◆SQLインジェクション

たとえば、$uidと$passhをWebページから入力(POST)される以下のSQLがあったとします。

$query = "SELECT * FROM usr WHERE uid = '$uid' AND pass = '$passh'";

$uidに「taro'--」と入力されたら、以下のように展開されます。

$query = "SELECT * FROM usr WHERE uid = 'taro'--' AND pass = ''";

すると、SQLで「--」はコメントになりますので、パスワードがなくても以下のSQLが発行されてしまうのです。

$query = "SELECT * FROM usr WHERE uid = 'taro'";

これ、Delete文もインジェクションされるケースもあり、私は実際にテストで体験しております。DBがクリアされました!


◆OSコマンド・インジェクション

たとえば、$fromをWebページから入力(POST)される以下のopen文があったとします。

$from =~ s/"|;|'|<|>|\|| //ig;
open(MAIL, "|/usr/sbin/sendmail -t -i -f $from");

$from に「`touch[0x09]/tmp/foo`」と入力されたら、以下のように展開されます。

$from =~ s/"|;|'|<|>|\|| //ig;
open(MAIL, "|/usr/sbin/sendmail -t -i -f `touch[0x09]/tmp/foo`);

すると、touchコマンドが実行されてしまいます。


◆HTTPヘッダ・インジェクション

たとえば、$numをWebページから入力(POST)される以下のHTTPのLocationがあったとします。

$cgi = new CGI;
$num = $cgi->param('num');
print "Location: http://example.jp/index.cgi?num=$num\n\n";

$num に「3%0D%0ASet-Cookie:SID=evil」と入力されたら、以下のようなクッキーが発行されてしまうのです。

Set-Cookie: SID=evil

◆インジェクション対策

ということで、WEBアプリケーションは、上記3つの対策を打たないといけないわけです。

対策は、以下を参照してください。

尚、本記事のサンプルは、上記URLを大変参考にさせて頂きました。問題があればコメント欄でご指摘ください。


あと、他にも以下の対策も必要ですね。

  • ディレクトリ・トラバーサル
  • セッション管理の不備
  • クロスサイト・スクリプティング
  • クロスサイト・リクエスト・フォージェリ