ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

超初心者向けCGI講座コミュのsendmailとスパムメール

  • mixiチェック
  • このエントリーをはてなブックマークに追加
 自作のsendmail.cgiが踏み台にされ、某プロバイダーへ大量にスパムメールが発信されていた、と契約レンタルサーバーサポートからお叱りの連絡がありまして「へへーっ、大変失礼をば致しました!」
 「スキルのないヤツがそんなの設置するな!」というお叱りも覚悟し、どうやって踏み台にされてしまったなどの今後の対策スキルが上がれば良いなと思ってトピを立てさせて頂きました。

------------------------------------------------------------------------------------
 formタグのhtmlから、&tl;form action="sendmailへのパス" method=post> としますが、このsendmailへのパスは、何も同じサーバーじゃなくても、他のサーバーからでも可能なので、

if($ENV{'REQUEST_METHOD'} eq "POST"){
  read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
 }else{
  &error("エラー");
 }

としましたが、ダメだったようです。

------------------------------------------------------------------------------------
$mymail = 'nakajima@siron.net';

とし、

 print MAIL &mimeencode("Reply-To: $email")."?n";
 print MAIL "To: $mymail?n";
 print MAIL &mimeencode("From: $email")."?n";
 print MAIL &mimeencode("Subject: $subject")."?n";

のところで、先の外部からのformタグに、name="maymail" value="任意のメルアド" としてやれば入れ替わってしまうのでしょうか。

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

print MAIL &mimeencode("Reply-To: $email")."?n";

 スパムで送りたいメルアドをこの$emailに入れてしまう。
 同様に、$mymailにはあり得ないメルアドに入れ替えて、自動返信で・・・。

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

この3つかな、と予想を立てたところで今日は力尽きてしまいました。明日以降試してみようと思っていますが、その前にいろいろアドバイスを頂けたら心強い限りです。

コメント(11)

$server_name = $ENV{'SERVER_NAME'};
if($ENV{'HTTP_REFERER'} =~ /^http:\/\/$server_name/){

#リクエスト元が同サーバーだった場合に処理を実行
 #https://アドレスも必要かな?

print MAIL &mimeencode("Reply-To: $email")."?n";
print ・・・
print ・・・
}

で、だめなのかな?私も未熟なのでなんとも・・・誤りがあった場合は修正お願いします。
Toのアドレスを自由に入力できるのであれば、大抵のCGIは踏み台に出来ると思います。

また、Toが書けなくてもSubjectやFromなどのヘッダーを完全自由に書ければ同じように送信できてしまう恐れがあります。改行だけは消すようにした方がいいと思います。

1.メールアドレスにカンマ、改行、空白等は使えないようにする
2.メールヘッダーで使用するものはすべて改行を削除する
3.連続したIP,送信内容,FROM,TO等の送信を一定回数で制限する

こんな感じで入力文字をチェックしてあげるのがいいかと思います。
詳しくは「メール サニタイズ」とかで検索してみてください。

1でシバ兄さんが書いているREFERERによる制限でも十分かもしれませんが、REFERERは偽装が出来てしまうので、あまり過信はしない方がいいかも知れません。
その時点で踏み台としては選ばれないかもですが。
貴重なアドバイスありがとうございます。
まず referer でチェックし、みずのさんの1〜3で改造してみようと思っています。

ところで、2の「全ての改行を削除」ですが、例えば、
print MAIL &mimeencode("Reply-To: $email")."?n";

の ."?n" などもこの場合の「改行」として削除するのでしょうか。
RFC2822的には
reply-to = "Reply-To:" address-list CRLF

などのようになっているので、そこにはCRLFが必要です。

みずのさんのおっしゃっているのは、「入力値に対して」サイニタイジングを行いましょう、というイミです。

たとえばこのケースであれば
print MAIL &mimeencode("Reply-To: $email")."?n";

$emailの値が
\nTo: hogehoge@somedomain
となればToが入れ替わりますよね。
なるほど、引き続きKIDD@病弱さん、アドバイスありがとうございます。
「サニタイズ」も検索してみて、ふむふむ。
ちょっと今夜にでも作り直してみます。

>>1.メールアドレスにカンマ、改行、空白等は使えないようにする
 とすれば、
>>?nTo: hogehoge@somedomain
 のように、; も使えないようにした方が良いように思えましたが。
 
というか「メールアドレスに使うことのできない文字」をすべて排除すればいいだけの話。
サニタイジングはやりすぎも結構問題が出たりします。
:はたぶん大丈夫だと思いますが。

世の中には:もアカウントに使えるようなシステムがあったりするかも知れません。

深く考えればRFCに則ったサニタイジングをすればいいってことになるかも知れませんが、私的にはルーズな設定にすることが多いです。

実際に自分のサーバーや専用サーバー等で設置してきちんとmail_logを確認できるとこで使った方が良いかもですね。
プログラムに限ったことではありませんが、サニタイズや入力制限は

×全部通過でNGそうな文字を禁止する。
○全部禁止でOKな文字を通過させる。

です。
慣れてくれば前者でもいいのですが、基本は後者で入力制限を行った方が間違いは(検査ミス)は起き難いです。

メアドの入力検査において注意する事といえば最近は"."(ピリオド)の取り扱いでしょうか。
一部携帯のキャリアではRFCで許されていないピリオドの連続や先頭、行末のピリオドも許してたりするので。

あとREFERERも出ていますが、クライアントが任意に設定できる値を信じるのは止めた方がいいでしょう。
やらないよりはマシですが、あくまでCSRF対策程度に思ってしまった方がいいです。REFERERチェックは正当性検査未満の問題かと。
#踏み台探してたりする場合は、取り合えずREFERERとUAは偽装するでしょうね。
踏み台というのは手動ではなく、プログラムとかで自動的にだと思います。

拙スクリプトでは、完全ではないですが、
$email のチェックで、

if($email !~ /^[a-zA-Z0-9][-?.?w]+?@[a-zA-Z0-9][-?.?w]+?.[a-zA-Z]{2,4}$/){
&error("エラー ");
}

としていたので、あるとすれば、$mymail か、$subject で、そこに改行等を入れられてとかではないかと予想しました。

 改めて、$email と $mymail に改行等の禁止チェックを入る。
if($email =~ /(,|?n|?s|;|:)/ || $mymail =~ /(,|?n|?s|;|:)/){
&error("エラー ");
}

 プロント(< や >)、や全角スペースも入れておいた方が良いかな、と思うも、一体どうやって踏み台にするのか、その詳細を知った方がより解決も早いと感じます。
 しかし、それを読んで悪用というのもあるから、なかなかアドバイスする方も難しいかも、なんて感じたりしています。どのようにしてrefererを偽造するかとかetc。

===================
と、仮にここまでをOKだとすると、自動的に不正アクセス?しようとしても、エラー表示で止まってくれます。
 取り敢えず、#2 のみずのさんからのアドバイスに沿っていますでしょうか。
#2のみずのさんの

> Toのアドレスを自由に入力できるのであれば、大抵のCGIは踏み台に出来ると思います。

まずはこれを根本的に解決しない限りは・・・と思うのですが・・・
「Toのアドレス」は、設置者のアドレス、つまりこの場合は私のアドレスですよね。
これは記述ミスで失礼しました。
ご丁寧にもhtmlに補足説明として、toへのメルアドが入っている変数が $mymail であることを<!-- で記してしまっていました。

よって、スクリプト内だけで、$my_e-mial = "abc@defg.net"; とかにしとけば、メルアドの入っている変数名は分からないと思ったのですが、どうでしょうか。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

超初心者向けCGI講座 更新情報

超初心者向けCGI講座のメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング