アッhan!
セキュリティホール
道具箱 フリー素材集 ネチケット 書籍紹介 リンク集 お勧め情報 更新記録 FAQ  
Top Download Support Manual ご利用規定 改造計画 Security 関連知識  
セキュリティホールの報告と回避方法
  目次  
 1; 確認までの経緯
 2; 対象バージョン
 3; ご指摘の内容
 4; 修正処理の必要性
 5; 回避処理の主旨
 6; 修正スクリプト
 7; 回避処理の方法(Ver1,Ver2共)
    a) mibbs.cgi
    b) mainte.cgi
    c) search.cgi
    d) headline.cgi
 8; BBSを守る為のご提案
 9; 今後の展開
10; ページ作成日及び製作者
11; 当サイトトップページの報告記録(追加 06/Jun/2001 )
  1;確認までの経緯  
 2001年02月21に JAPUさんよりセキュリティホールについてご指摘いただき、私自身もその事実を確認いたしました。
 ご指摘、並びにご指導いただいたJAPUさんに心より感謝いたします。
 また、このスクリプトの検証については、http://www.japu.org/sa/の方でも詳しくJAPUさんにより報告されています。
 (JAPUさんに付いての情報は、http://www.japu.org/ and http://yasu.asuka.net/ で入手してください。)
  2;対象バージョン  
Ahhan! Ver.2.00βbまでの総てのスクリプト
  3;ご指摘の内容  
 パスワードが平文で記述されているファイルを含む、任意のファイルの読み取りが可能・任意のコマンドが実行可能。
  4;修正処理の必要性  
 これから2週間後に JAPUさん より参考コードが紹介されます。
 任意ファイルを読むことが出来るためパスワードや隠してるファイルを総て知ることが出来ます。
 この参考コードは、Perlを熟知している方なら容易に考える事の出来るもので、これまでに悪意のある利用者が現れなかった事を幸運に思います。
 悪意のある利用者は、その手法を使いあなたのサイトを容易に壊す事が出来るからです。
 必ず早急に修正を施すか新バージョンに更新して下さい。
  5;回避処理の主旨  
 mibbs.cgi及びsearch.cgiを利用した任意ファイルの読み取り可能状態を回避することによりパスワード入手を困難にし、そのことで、管理ボード(mainte.cgi)を利用したユーザ環境の操作や破壊を困難にする。
 また、合わせて、リモートホストデーターの漏れを防ぐ
  6;修正スクリプト  
 (Ver1,Ver2共) mibbs.cgi mainte.cgi search.cgi headline.cgi
  7;回避処理の方法  
 ※総て sub decode の中で下記部分のソースを追加いたします。(作業はそれほど難しく有りません。)

##//////////////////////////////////////////////////
  ここに書かれているソースをこの場所に追加する。
##//////////////////////////////////////////////////

  a)mibbs.cgi  
sub decode {
	if ($ENV{'REQUEST_METHOD'} eq "POST") {
		if ($ENV{'CONTENT_LENGTH'} > 5000) {
			&error("投稿量が大きすぎます。","no");
		}
		read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
	} else {
		$buffer = $ENV{'QUERY_STRING'};
	}
	@pairs = split(/&/,$buffer);
 	foreach $pair (@pairs) {
		($name, $value) = split(/=/, $pair);
		$value =~ tr/+/ /;
		$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
 		&jcode'convert(*value,'sjis');
 		if ($tagkey == 0) {
			$value =~ s/\&/&/g;
			$value =~ s//>/g;
		} else {
			$value =~ s/>>/>>/g;
			$value =~ s/<>/<>/g;
			$value =~ s///g;
		}
 		$FORM{$name} = $value;
 
		##セキュリティホールのパッチ(1)////////////////////////////
		if($name eq 'name' || $name eq 'com' || $name eq 'email'
			|| $name eq 'sub'){
		}else{
			$FORM{$name} =~ s/\W//g;# 任意のファイル読み込み回避
		}
		##//////////////////////////////////////////////////////////

	}
	$mode     = $FORM{mode};
	$pwd      = $FORM{pwd};
	$folder   = $FORM{fol};
	$folder_m = $FORM{fol_m};
	$name     = $FORM{name};
	$com      = $FORM{com};
	$email    = $FORM{email};
	$t_updn   = $FORM{sage};
	$sub      = $FORM{sub};
	$thre_st  = $FORM{ts};
	$thre_ed  = $FORM{te};
	$b_file   = $FORM{file};
	$thre_no  = $FORM{tn};
	$resnew   = $FORM{rn};
	$resstart = $FORM{rs};
	$resend   = $FORM{re};
	$readfirst= $FORM{rf};
	$all_p    = $FORM{al};
	$loc_scr  = $FORM{loc};

	##セキュリティホールのパッチ(2)//////////
	if($mode eq 'res'||$mode eq 'regist') {
	}else{
		$name     = "";
		$com      = "";
		$email    = "";
		$sub      = "";
	}
	##////////////////////////////////////////

	&decode_b
}
  b)mainte.cgi  
sub decode {
	if ($ENV{'REQUEST_METHOD'} eq "POST") {
		if ($ENV{'CONTENT_LENGTH'} > 5000) {
			&error("投稿量が大きすぎます。","no");
		}
		read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
	} else {
		$buffer = $ENV{'QUERY_STRING'};
	}
	@pairs = split(/&/,$buffer);
 
	foreach $pair (@pairs) {
		($name, $value) = split(/=/, $pair);
		$value =~ tr/+/ /;
		$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
 		&jcode'convert(*value,'sjis');
		$value =~ s/>>/>>/g;
		$value =~ s/<>/<>/g;
		$value =~ s///g;
		$FORM{$name} = $value;

		##セキュリティホールのパッチ/////////////////////////////////////////////////
		if($name eq 'name' || $name eq 'com' || $name eq 'email' || $name eq 'sub'
			||$name eq 'cla'||$name eq 'clb'||$name eq 'clc'||$name eq 'cld'
			||$name eq 'cle'||$name eq 'clf'||$name eq 'ca_l'||$name eq 'bo_c'
			||$name eq 'bnn'||$name eq 'bmes'){
		}else{
			$FORM{$name} =~ s/\W//g;# 任意のファイル読み込み回避
		}
		##/////////////////////////////////////////////////////////////////////////

	}
 
	$mode     = $FORM{mode};
	$pwd      = $FORM{pwd};
	$folder   = $FORM{fol};
	$folder_m = $FORM{fol_m};
	$name     = $FORM{name};
	$com      = $FORM{com};
	$email    = $FORM{email};
	$t_updn   = $FORM{sage};
	$sub      = $FORM{sub};
	$thre_st  = $FORM{ts};
	$thre_ed  = $FORM{te};
	$b_file   = $FORM{file};
	$thre_no  = $FORM{tn};
	$resnew   = $FORM{rn};
	$resstart = $FORM{rs};
	$resend   = $FORM{re};
	$readfirst= $FORM{rf};
	$all_p   = $FORM{al};
	$am_reto  = $FORM{rt};
	$am_sato  = $FORM{st};
	$am_close = $FORM{cl};
	$am_updn  = $FORM{ud};
	$am_no   = $FORM{no};
	$am_swa   = $FORM{sa};
	$am_swb   = $FORM{sb};
	$delname  = $FORM{delname};
	$delcom   = $FORM{delcom};
	$delemail = $FORM{delemail};
	$delsub   = $FORM{delsub};
	$line_no  = $FORM{lno};
	$cate_group = $FORM{gro};
	$rlo = $FORM{rlo};
	&decode_b
}
  c)search.cgi  
sub decode {
	if ($ENV{'REQUEST_METHOD'} eq "POST") {
		if ($ENV{'CONTENT_LENGTH'} > 5000) {
			&error("投稿量が大きすぎます。","no");
		}
		read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
	} else {
	$buffer = $ENV{'QUERY_STRING'};
	}
	@pairs = split(/&/,$buffer);
	foreach $pair (@pairs) {
		($name, $value) = split(/=/, $pair);
		$value =~ tr/+/ /;
		$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
		&jcode'convert(*value,'sjis');
		$value =~ s/\"/"/g;
		$value =~ s//>/g;
		$FORM{$name} = $value;

		##セキュリティホールのパッチ//////////////////////////////////
		if($name eq 'word'){
		}else{
			$FORM{$name} =~ s/\W//g;# 任意のファイル読み込み回避
		}
		##//////////////////////////////////////////////////////////

	}
	$mode  = $FORM{mode};
	$folder= $FORM{fol};
	$cond = $FORM{cond};
	$word = $FORM{word};
	$word =~ s/ / /g;
	$word =~ s/\t/ /g;
	@pairs_b = split(/ /,$word);
	$no_a=0;
	if (open(BN,"$boardname")){
		@boardname = ;
		close(BN);
		@select_board = 0;
$select_board [$no_a]=(<<"EOF");
<select name=fol>
EOF
		foreach (@boardname) {
			$boardname[$no_a] =~ s/\n//g;
			($nameshort,$namelong,$cola,$colb,$colc,$cold,$cole,$colf
			,$cate_link,$tag_act,$bo_act,$cate_gr,$b_nan,$b_mes)
			= split(/<>/, $boardname[$no_a]);
			$no_a++;
			$ser_on = "";
			if ($folder eq $nameshort) {
				$bbstitle=$namelong;
				$tbgc_a  =$cola;
				$bd_col  =$colb;
				$tp_col  =$colc;
				$tb_col  =$cold;
				$tb_colb =$cole;
				$tf_col  =$colf;
				$tf_col  =~ s/\n//g;
				$ser_on = " selected";
 
			}
			if($cate_link ne "off" ) {
$select_board [$no_a]=(<<"EOF");
  d)headline.cgi  
sub decode {
	if ($ENV{'REQUEST_METHOD'} eq "POST") {
		read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
	} else {
		$buffer = $ENV{'QUERY_STRING'};
	}
	@pairs = split(/&/,$buffer);
 
	foreach $pair (@pairs) {
		($name, $value) = split(/=/, $pair);
		$value =~ tr/+/ /;
		$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
		$value =~ s/\"/"/g;
		$value =~ s//>/g;
		$FORM{$name} = $value;

		##セキュリティホールのパッチ////////////////////////////
		$FORM{$name} =~ s/\W//g; # 任意のファイル読み込み回避
		##////////////////////////////////////////////////////

	}
	$mode  = $FORM{mode};
	$gorup = $FORM{gorup};
	$folder_c= $FORM{fol};
}

  8;BBSを守る為のご提案  
スクリプトを修正(更新)した後
1、pref.cgi 及び mainte.cgi の設置時のファイル名を変更してください。
2、mainte.cgiの呼び出しをメニューの中に組み込まないでください。
3、パスワードは、定期的に更新してください。

  9;今後の展開  
 ここに挙げた処理方法が JAPU さんにより不十分と判定される恐れもあります。
 その場合は、改めて回避の方法を検討いたします。
 当面の間、当サイトでお知らせいたしますので、定期的に確認してください。
 また、JAPUさんよりのご指導もあり、セキュリティを増すための策をスクリプトに随時反映させて行きます。

  10;ページ作成日及び製作者  
2001年 3月 6日

 bunbun@アッhan !

  11;当サイトトップページの報告記録  
 22/Mar/2001
今回のセキュリティホールについて、処理の安全が確認出来ましたので、ご報告いたします。
 06/Mar/2001
Ver 2.00βeで配布を再開しました。
 06/Mar/2001
アッhan! BBSに存在するセキュリティホールの報告と回避方法
 05/Mar/2001
アッhan! BBS御使用中の66のサイトへ
不具合についてのメールを配信いたしました。
 04/Mar/2001
3月6日に配布再開予定報告
 22/Feb/2001
(重要)不具合を確認いたしました。
 ・修正を完了するまで配布を停止いたします。
 ・修正完了後、修正個所は公開いたします。

Copyright© 2001, bunbun . All right reserved.