Forum
J! JAPAN TOP
ようこそ, ゲスト
ユーザ名: パスワード: 自動ログイン

トピック: Joomla!が不正アクセスを受けた場合の対応

Joomla!が不正アクセスを受けた場合の対応 3 年 8 ヶ月 ago #4590

  • michizo
  • michizo さんのアバター
  • Offline
  • Fresh Boarder
  • 投稿数: 8
  • カルマ: 0
Joomla!バージョン:1.5.26
PHPバージョン:
MySQLバージョン:
サーバ情報:Linux
URL(公開可能であれば):http://example.jp

michizoと申します。

Joomla!1.5.26を利用していますが、JCE1.5.7.4のぜい弱性を突いたと思われるアクセスを受けました。その際のログには下記のように記録されていました。

"POST /index.php?option=com_jce&task=plugin&plugin=imgmanager&file=imgmanager&method=form&cid=20&6bc427c8a7981f4fe1f5ac65c1246b5f=9d09f693c63c1988a9f8a564e0da7743 HTTP/1.1" 200 72 "-" "BOT/0.1 (BOT for JCE)"
"POST /index.php?option=com_jce&task=plugin&plugin=imgmanager&file=imgmanager&version=1576&cid=20 HTTP/1.1" 200 36 "-" "BOT/0.1 (BOT for JCE)"
"GET / HTTP/1.1" 200 17580 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)"
"POST /xxxxx.php HTTP/1.1" 200 17 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)"

サーバ上には上記ログに記録されている「xxxxx.php」がいつの間にかアップロードされており、タイムスタンプはログの日時と一致してました。その後も複数回にわたって同様なアクセスログが記録されており、やはりそのログの日時と同じタイムスタンプでファイルがアップロードされていました。

ネットで調べたところ、どうやらJCE1.5.7.4のバージョンが古いためにJCEのぜい弱性を突かれたことによる不正アクセスだと推測されます。でも、本当にJCE1.5.7.4のぜい弱性を突かれたことによる不正アクセスなのかどうか、確証がありません。

この場合、どういった対応をすればよいものでしょうか?
これは間違いなくJCE1.5.7.4のぜい弱性を突いてファイルをアップロードした不正アクセスだ、という確証が得られればよいのですが・・・。
最終編集: 3 年 8 ヶ月 ago : michizo.
ゲストの書き込みは許可されていません。

Joomla!が不正アクセスを受けた場合の対応 3 年 8 ヶ月 ago #4591

  • hanji009
  • hanji009 さんのアバター
  • Offline
  • Platinum Boarder
  • 投稿数: 466
  • 感謝を受け取りました 18
  • カルマ: 10
吉田 Goyat LLCです。

www.facebook.com/Joomla.Goyat

JCE ver.1576を使っているサイトは、ハッキング攻撃があればやれれますよ。

先ほど、私のサイトにLocal Inclusion攻撃があった。JCE ver.1576を指定したURLでJCEの穴を攻撃していた。Joomla 1.5が対象だが、この攻撃は、サイトのヴァージョンを見ていない。

SecurityCheck Proを使っていたのでそれが見えた。

JCE ver.1576のセキュリティ脆弱でハッキングされたJoomla1.5が今、増えていると思う。

対応策もFacebookに書いてありますので参考にして下さい。
ゲストの書き込みは許可されていません。

Joomla!が不正アクセスを受けた場合の対応 3 年 8 ヶ月 ago #4592

  • toshiki
  • toshiki さんのアバター
  • Offline
  • Senior Boarder
  • 投稿数: 76
  • 感謝を受け取りました 2
  • カルマ: 8
ログのURLはJCEのコンポーネントへのアクセスです("option=com_jce" の部分でわかる)。作られたファイルのタイムスタンプが一致とのこともあわせて考えるとJCEの脆弱性を突いたものと判断してほぼ間違いないでしょう。

対策としてはJCEをアンインストールする(TinyMCEなど他のエディタに乗り換える)、JCEをバージョンアップする、がよいと思います。

私は過去にJCEのアンインストールでエラーになった経験があるので、作業前にバックアップをとることをおすすめします。
ゲストの書き込みは許可されていません。

Joomla!が不正アクセスを受けた場合の対応 3 年 8 ヶ月 ago #4595

  • michizo
  • michizo さんのアバター
  • Offline
  • Fresh Boarder
  • 投稿数: 8
  • カルマ: 0
hanji009さん、toshikiさん、回答ありがとうございます。

やはりJCEのぜい弱性を突かれたことによる不正アクセスに間違いなさそうですね。

対策として、最新バージョンのJCEをインストールしました。

最初、現行バージョンをアンインストールしてから最新バージョンのインストールを実行したのですが、正常にインストールが完了できませんでした。そこで、DBにあったJCE関連と思われるテーブル2つ(jos_jce_groups、jos_jce_plugin)を削除した上で最新バージョンのインストールを実行したところ、正常にインストールを完了することができました。

今後はコンポーネントのぜい弱性にも気を配って運用していきたいと思います。

ありがとうございました。
ゲストの書き込みは許可されていません。

Joomla!が不正アクセスを受けた場合の対応 2 年 10 ヶ月 ago #4845

  • Azul
  • Azul さんのアバター
  • Offline
  • Fresh Boarder
  • 投稿数: 2
  • カルマ: 0
この問題について、情報集積および攻撃を遮断するようなスクリプトを作ってみました。
添付のファイルを${document_root}/xxxx.php 等の適当な名前にして設置し、index.phpの<?phpの冒頭付近で require_once xxxx.php; を追記すれば使えると思います。
com_jceを使ったクラッキングのパターンとして、wawalo.gifという名前のphpスクリプトをポストし、/images/stories/wawalo.gif にアクセスする事で、追加のバックドア用スクリプトを設置できるようにしたり、ディレクトリ等の情報を取ってきたりする仕組みのようです。

また、index.phpが存在していると決めつけて攻撃を仕掛けて来ているようにも見えますね…。
そうしますと、以下のようにするのもいくらか効果があるかもしれません。

index.phpをyyyy.php等の別名に変更し、そのスクリプトに繋がるように.htaccessの設定を切り替え、httpd.confの<Directory ${document_root}>内にある
DirectoryIndex index.html index.php
等の設定を以下のように変更
DirectoryIndex index.html yyyy.php
※気休め程度にしかならないかもしれませんが…。

<?php
class AttackRecorder {
	// 情報集積用のpath (書き込み権限が必要になります)
	// ウィンドウズ環境では、'C:\tmp\attacked_jce'等とするのが良いかもしれません
	const	logDir	= '/tmp/attacked_jce';
	final public static function check() {
		// option=com_jce, com_jnews のアクセスを遮断 (実際に活用されている場合は、検出方法をもう少し厳密にする必要があるかもしれません)
		if(array_key_exists('option', $_GET) && preg_match('"\bcom_(?:jce|jnews)\b"i',$_GET['option'])) {
		// option=com_jnewsのアクセスを遮断 (こちらも実際に活用されている場合は、検出方法をもう少し厳密にする必要があるかもしれません)
		} elseif(array_key_exists('REQUEST_URI', $_SERVER) && preg_match('"/components/com_jnews/"',$_SERVER['REQUEST_URI'])) {
		} elseif(!empty($_FILES)) {	// check eval php file
			foreach($_FILES as $fSet) {
				$data	= file_get_contents($fSet['tmp_name']);
				// 悪意のあるソースはevalを使っているようです
				if(false === strpos($data,'<?') || !preg_match('"\beval\b(?=\s*\()"i', $data)) return;
			}
		} else {
			return;
		}
		self::record();
		exit;
	}
	final public static function record() {
		if(!file_exists(self::logDir)) mkdir(self::logDir);
		$tim	= new DateTime();
		$pBase	= sprintf('%s/%s', self::logDir, $tim->format('Ymd-His'));
		if(!empty($_FILES)) {
			$idx	= 0;
			if(!empty($_FILES)) {
				foreach($_FILES as $fSet) {
					$path	= sprintf('%s_%d.txt', $pBase, $idx++);
					move_uploaded_file($fSet['tmp_name'], $path);
					// eval無効化
					$data	= preg_replace('"\beval\b(?=\s*\()"i', '/*$0*/print', file_get_contents($path));
					$fh	= fopen($path, 'w');
					fwrite($fh, $data);
					fclose($fh);
				}
			}
		}
		if(isSet($_SERVER)) {
			$ps	= !empty($_POST);
			$nm	= sprintf('%s_%s', $pBase, $ps ? 'post' : 'get');
			if(array_key_exists('REQUEST_URI', $_SERVER) && preg_match('"(?<=/components/com_)\w+(?=/)"', $_SERVER['REQUEST_URI'], $mt)) {
				$nm	.= sprintf('-%s', $mt[0]);
			} elseif(array_key_exists('option', $_GET) && preg_match('"(?<=\bcom_)\w+\b"i',$_GET['option'], $mt)) {
				$nm	.= sprintf('-%s', $mt[0]);
			}
			$fh	= fopen(sprintf('%s.txt', $nm), 'a');
			flock($fh, LOCK_EX);
			fwrite($fh, "########## _SERVER ##########\n");
			foreach($_SERVER as $h => $v) {
				// ログ取りする情報を調整
				if(preg_match('"^(?:DOCUMENT_ROOT|GATEWAY_INTERFACE|HTTP_(?:HOST|ACCEPT)|PATH|SERVER_\w+|SCRIPT_(?:FILE)?NAME|PHP_SELF)$"i',$h)) continue;
				fwrite($fh, sprintf("%s	: %s\n", $h, $v));
			}
			if(!empty($_POST)) {
				fwrite($fh, "########## _POST ##########\n");
				foreach($_POST as $h => $v) {
					fwrite($fh, sprintf("%s	: %s\n", $h, $v));
				}
			}
			if(!empty($_FILES)) {
				fwrite($fh, "########## _FILE ##########\n");
				foreach($_FILES as $fSet) {
					fwrite($fh, sprintf("Name	: %s\n", $fSet['name']));
				}
			}
			fclose($fh);
		}
	}
}
AttackRecorder::check(); // ここでチェック!
?>

なお、php.iniを編集し、以下の記述の箇所を見つけ、disable_functionsを登録する事でかなりの攻撃が防げるのではないかと思われます。
disable_functions	=
disable_functions	= eval, phpinfo, system, shell_exec, exec, passthru, popen
最終編集: 2 年 10 ヶ月 ago : Azul. 理由: 関数の無効化で防ぐのが良いかもしれません
ゲストの書き込みは許可されていません。

Joomla!が不正アクセスを受けた場合の対応 2 年 10 ヶ月 ago #4849

  • michizo
  • michizo さんのアバター
  • Offline
  • Fresh Boarder
  • 投稿数: 8
  • カルマ: 0
Azulさん、ありがとうございます。

Joomla!に限らず、ぜい弱性や不正アクセスとの戦いは果てしなく続きますので、今後もいろいろ考えていかねばならないですね。

こういった積み重ねが大事なのだと思います。

#残念ながら私は全くお役にたてませんが・・・。
ゲストの書き込みは許可されていません。

Joomla!が不正アクセスを受けた場合の対応 2 年 10 ヶ月 ago #4858

  • Azul
  • Azul さんのアバター
  • Offline
  • Fresh Boarder
  • 投稿数: 2
  • カルマ: 0
phpそのものの脆弱性の把握は、色々と活用できそうですが、難しいですね…。
なお、先日紹介したdisable_functions を使った防御法ですが、どうやら調べてみるとPHP 5.5.11現在、php.iniでdisable_functionsにevalを設定しても有効ではないようです。
evalやechoは実際には関数ではなく、language constructであるためとの事…。
なぜこれほど危険なコードがphpで無防備で使用できてしまうのか不思議です。

gzinflate, str_rot13, base64_decodeをdisable_functionsに登録するのも効果があると思われますが、決定打となるevalが防げないのが痛いです…。
ゲストの書き込みは許可されていません。