1

最近、私のサーバーで悪意のある攻撃を試みている攻撃者が何人かいたので、それほど遠くまで到達しないことはわかっていますが、ある程度「追跡」することにしました。

現在、サーバー ログを含むディレクトリ全体があり、ディレクトリ内のすべてのファイルを検索し、文字列が見つかった場合はファイル名を返す方法が必要です。そこで私は、テキストとファイルの操作に使用する言語で、Perl より優れた言語はあるだろうかと考えました。そのため、私の友人は、特定の IP のすべてのファイルをスキャンし、その IP を含むファイル名を返すスクリプトを手伝ってくれているので、すべてのログから攻撃者を手動で検索する必要はありません。(私は何百も持っています)

#!/usr/bin/perl

$dir = ".";

opendir(DIR, "$dir");
@files = grep(/\.*$/,readdir(DIR));
closedir(DIR);

foreach $file(@files) {
    open FILE, "$file" or die "Unable to open files";

    while(<FILE>) {
        print if /12.211.23.200/;
    }

}

ディレクトリの読み取りエラーが発生していますが。どんな援助も大歓迎です。

編集: コードが編集されましたが、10 行目で権限が拒否されたため、ディレクトリを開くことができません。

マイク。

4

14 に答える 14

14

代わりにgrepを使用できますか?

于 2009-01-12T00:23:22.347 に答える
3

で見つかったファイルを使用する場合 は、 と連結$dirnameする必要があります。これらのファイルが存在するディレクトリに移動していないことに注意してください。$filnamereaddirchdir

open FH, "<", "$dirname/$filname" or die "Cannot open $filname:$!";

ちなみに、grep -rログディレクトリの下のすべてのサブディレクトリで文字列を再帰的に検索するだけではどうですか?

編集:あなたの編集と2つのことがわかります。まず、この行:

@files = grep(/\.*$/,readdir(DIR));

.文字列の末尾にある0 個以上の文字を検索しているため、効果的ではありません。ゼロ以上なので、ディレクトリ内のすべてに一致します。で終わるファイルを除外しようとしている場合は.、これを試してください。

@files = grep(!/\.$/,readdir(DIR));

!これらのファイルを除外しようとしている場合は、否定記号に注意してください。それ以外の場合 (これらのファイルのみが必要で、意図を誤解している場合) は省略してください!

いずれにせよ、dieメッセージが 10 行目で表示されている場合は、ファイルを読み取れないようなアクセス許可が設定されている可能性があります。ファイル名をダイ出力に入れてみて、失敗しているファイルを確認できるようにします。

open FILE, "$file" or die "Unable to open file: $file";

しかし、他の回答と同様に、繰り返しますが、grepを使用しないのはなぜですか? Perl 関数ではなく、unix コマンドです。

于 2009-01-12T00:25:07.057 に答える
2

これにより、perl で探しているファイル名が取得され、perl 正規表現を実行して実行するよりもはるかに高速になります。

@files = `find ~/ServerLogs -name "*.log" | xargs grep -l "<ip address>"`'

ただし、これには *nix 準拠のシステム、または Windows 上の Cygwin が必要です。

于 2009-01-12T00:22:39.103 に答える
1

ところで、私は File::Next について言及するつもりでした。ディレクトリ内のすべてのファイルを (再帰的に) 反復処理するには:

use Path::Class; # always useful.
use File::Next;

my $files = File::Next::files( dir(qw/path to files/) ); # look in path/to/files
while( defined ( my $file = $files->() ) ){
    $file = file( $file );
    say "Examining $file";
    say "found foo" if $file->slurp =~ /foo/;
}

File::Next は汚染に対して安全です。

于 2009-01-12T12:47:40.910 に答える
1

まず、ソース ディレクトリ内のファイルのリストを取得します。

opendir(DIR, "$dir");
@files = grep(/\.log$/,readdir(DIR));
closedir(DIR);

そして、それらのファイルをループします

foreach $file(@files)
{
  // file processing code
}
于 2009-01-12T00:22:58.027 に答える
1

私の最初の提案は、代わりに grep を使用することです。仕事に最適なツール、と彼らは言います...

しかし、あなたの質問に答えるには:

readdir は、ディレクトリからファイル名を返すだけです。ディレクトリ名とファイル名を連結する必要があります。

$path = "$dirname/$filname";
open FH, $path or die ...

次に、「.」など、実際にはディレクトリであるファイルを無視する必要があります。と ".."。$path を取得したら、それがファイルかどうかを確認します。

if (-f $path) {
    open FH, $path or die ...
    while (<FH>)
于 2009-01-12T00:28:06.830 に答える
0

私はこの議論にかなり遅れていることを知っています(grep関連の投稿を検索しているときに遭遇しました)が、とにかく答えるつもりです:

これらが Web サーバー ログ (Apache、IIS、W3SVC など) であるかどうかは明確に指定されていませんが、これらのデータをマイニングするための最適なツールは、Microsoft の LogParser ツールです。詳細については、logparser.com を参照してください。

LogParser を使用すると、ログ ファイルに対して SQL に似たステートメントを記述できます。非常に柔軟で非常に高速です。

于 2009-03-20T19:41:52.307 に答える
0

~ は Perl では自動展開されません。

opendir my $fh,  '~/' or die("Doin It Wrong");  # Doing It Wrong. 

opendir my $fh, glob('~/') and die( "Thats right!" );
于 2009-01-12T00:33:33.107 に答える
0

また、 を使用する必要がreaddir()ある場合は、次のように式を保護してください。

while (defined(my $filename = readdir(DH))) {
    ...
}

テストを行わないと、defined()「0」というファイルが見つかった場合にループが終了します。

于 2009-01-12T00:42:31.123 に答える
0

優れた grep のように、コマンド ラインから perl を使用する

perl -wnl -e '/12.211.23.200/ and print;' *.log > output.txt

ここでの利点は、ロジックをはるかに簡単に連鎖できることです

perl -wnl -e '(/12.211.23.20[1-11]/ または /denied/i ) and print;' *。ログ

気分が悪い場合は、より高度なコマンド ライン オプションを使用して、perl ワン ライナーの結果を他の perl ワン ライナーにフィードすることもできます。

「Minimal Perl: For UNIX and Linux People」を読む必要があります。これはまさにこの種のことに関する素晴らしい本です。

于 2013-02-13T15:22:07.570 に答える
0

ログ パーサーについてCPANを調べましたか? 「log parse」で検索したところ、200 件以上ヒットしました。一部 (おそらく多く) は関係ありませんが、一部は関係がある可能性があります。一部、使用している Web サーバーによって異なります。

于 2009-01-12T01:07:59.980 に答える
0

私はこれを正しく読んでいますか?エラーが発生する10行目は

open FILE, "$file" or die "Unable to open files";

6 行目によると、読み込もうとしている $file は、

@files = grep(/\.*$/,readdir(DIR));

0 個以上のドットで終わるファイルです。これはあなたが本当に欲しかったものですか?これは基本的に、「.」を含むディレクトリ内のすべてのファイルと一致します。と ".."。読み取り用に親ディレクトリを開くための十分な権限がない可能性がありますか?

編集: すべてのファイル (隠しファイルを含む) のみを読み取りたい場合は、次のようなものを使用することをお勧めします。

opendir(DIR, ".");
@files = readdir(DIR);
closedir(DIR);

foreach $file (@files) {
  if ($file ne "." and $file ne "..") {
    open FILE, "$file" or die "cannot open $file\n";
    # do stuff with FILE
  }
}

これはサブディレクトリを処理しないことに注意してください。

于 2009-01-12T01:17:47.840 に答える
-1

まず、を使用しますgrep

しかし、あなたが望まないのであれば、ここに私がまだ言及していないことをあなたがすることができる2つの小さな改善があります:

1)変更:

@files = grep(/\.*$/,readdir(DIR));

@files = grep({ !-d "$dir/$_" } readdir(DIR));

このようにして、「。」だけでなく除外します。および「..」だけでなく、サーバーログディレクトリに存在する可能性のあるその他のサブディレクトリ(openダウンストリームがチョークする)。

2)変更:

print if /12.211.23.200/;

print if /12\.211\.23\.200/;

.」は「任意の文字」を意味する正規表現のワイルドカードです。これを「\.」に変更すると、誤検知の数が減ります(実際には結果が変わる可能性は低いですが、とにかく正確です)。

于 2009-01-12T08:58:56.050 に答える