プロバイダーの汚点:blondemineプロジェクト

当社には、分散型販売ネットワークがあります。 店舗とのオフィス接続により、VPNがセンターに構成されているルーターが提供されます。 そして今、ある瞬間から、この接続は、53番目のDNSポートでのパケットの急増により、非常に低品質になりました。 ファイアウォールブロッキングルールの導入後に通信は改善されましたが、攻撃は止まりませんでした。



私は彼の側の問題を解決するためのリクエストでプロバイダーに頼りました。 彼は、「インターネットは汚い場所だ」という見出しに答えを受け取った。 そして、私は自分でこの現象に対処することにしました。



その結果、不正なネットワークパケットを収集および分析するためのシステムが収集されました。

そして、読者に技術的な詳細を退屈させないために、私は最も興味深いものをすぐに伝えます、そして、それを繰り返すか、それを改善したい人のために、私はそれを最後まで読むことをお勧めします。



ほぼ2か月間の運用の結果、システムでは約2億件のレコードが受信されました。 ほとんど(98%)はDNS増幅型の攻撃であり、ハブ[1][2]で複数回議論されています。 さらに、攻撃はすぐには開始されませんが、しばらく経った後、新しいパブリックアドレスがインターネットボットをスキャンするデータベースに入るのに十分です。 残りのイベントでは、ポート23に対する攻撃の大部分が強調表示されています。 私が見つけたように、これらは世界中に散らばっている中国のHikvision DVRシステムであり、Telnet接続のためにインターネット全体をスキャンします。 ちなみに、それらの3分の1は、工場のログインとパスワードだけです。 そして、他のすべてはすでにポートの人為的な検索、ログインの試行、SNMP経由の問い合わせなどです。







どうやって手に入れたの





まず、すべてのリモートルーターでファイアウォールを構成する必要がありました。 「モデル」ルールセットを導出し、チェックして設定を開始しました。 8番目のルーターで退屈し、デバイスのログを確認しました:「vk.comはマネージャーのコンピューターに接続できません」、「youtube.ruは興行所に接続できません」など。 しかし、興味深いエントリがありました:「src = 1.1.1.1:34567 dst = Zyxel:23ドロップ[4回]」、「src = 2.2.2.2:45678 dst = Zyxel:80ドロップ[12回]」。



これらのアドレスをNmapでスキャンすることにしました。ポート80と22は開いています。 ブラウザは、最初のアドレスはウクライナ企業の会議室のウェブカメラ(geoipとwhoisによる判断)であり、2番目のアドレスは特定のインドのユビキティルーターであると言いました。 工場出荷時のログインとパスワードはウェブカメラでのみ機能しましたが、ルーターでは工場出荷時の設定はsshで「のみ」のままでした。



さて、工場のログインとパスワードでインターネットデバイス全体を誇示するには、どのような種類の「ブロンド」である必要がありますか? そして、私はそのような「ブロンド」を一か所に集めて勉強することにしました。 将来的には、次のアルゴリズムを実装します。



攻撃者コレクション-パッシブ分析-アクティブ分析-応答



ステップ1:攻撃者を集める





セントラルマガジン





Zyxelルーターには、中央のsyslogサーバーにログを送信する機能があります。 これを行うために、Linux Debianとrsyslogをインストールしました:



sudo apt-get update sudo apt-get install rsyslog
      
      







ただし、単純なインストールでは十分ではありません。 syslogが外部からのメッセージを受け入れるようにする必要があります。



/etc/rsyslog.conf
 ... # provides UDP syslog reception $ModLoad imudp $UDPServerRun 514 ... # MAXA's rules - the local facilities local0.* /var/log/local0 local1.* /var/log/local1 local2.* /var/log/local2 local3.* /var/log/local3 local4.* /var/log/local4 local5.* /var/log/local5 local6.* /var/log/local6 local7.* /var/log/local7 # By the way - the above files should also be rotated by logrotate # And, of course, to work properly - there should be a static port translation on the border router ...
      
      









まあ、このポートがインターネットからデータをキャッチするためには、境界ルーターでブロードキャストする必要もあります。 シスコでの私の場合、私はこれを行いました:



 ip nat inside source static udp {syslog_IP} 514 {public_IP} 514 extendable
      
      







次に、メッセージを送信するようにリモートルーターを構成する必要があります。 私の場合、それはZyxel zywall 2PlusまたはUSG20です。



これらのルーターのモデルは、外部と内部の両方で大きく異なります。 ただし、チューニングの全体的なポイントは、ファイアウォールを除くすべてのログをオフにし、イベントをsyslogサーバーに送信することです。 Zyxel USG 20の外観は次のとおりです。

ファイアウォールのセットアップ:



画像



syslogログイベントのセットアップ:



画像



syslogサーバーのアドレスとタイプを設定します。



画像



デバイス設定でも、ソートの利便性のために、意味のあるホスト名を設定する必要があります。



最初の結果





すべてがこのように残されている場合、syslogサーバー上にlocal5テキストファイルが作成され、ファイアウォールの最後のルールに対応するすべてのイベントが含まれます。つまり、このルーターに対する攻撃です。



 Sep 27 17:34:54 2017 GW18PUB src="5.188.203.30:54193" dst="XXXX:8173" msg="invalid state detected, DROP" note="ACCESS BLOCK" user="unknown" devID="b0b2dcc63eec" cat="Firewall" class="Access Control" ob="0" ob_mac="000000000000" dir="ANY:ANY" protoID=6 proto="others" Sep 27 17:35:02 2017 GW36PUB src="212.83.176.116:51855" dst="YYYY:4287" msg="invalid state detected, DROP" note="ACCESS BLOCK" user="unknown" devID="b0b2dcc63eed" cat="Firewall" class="Access Control" ob="0" ob_mac="000000000000" dir="ANY:ANY" protoID=6 proto="others" Sep 27 17:35:17 2017 GW18PUB src="212.83.176.116:51855" dst="XXXX:3875" msg="invalid state detected, DROP" note="ACCESS BLOCK" user="unknown" devID="b0b2dcc63eec" cat="Firewall" class="Access Control" ob="0" ob_mac="000000000000" dir="ANY:ANY" protoID=6 proto="others"
      
      







ファイルは論理パーティション全体を使い果たすまで無限に大きくなるため、ログのローテーションを構成する必要があります。 これは、logrotateスクリプトを使用して実行できます。ログを数日間に分割し、古いアーカイブを毎日アーカイブして削除します。 しかし、より良いアイデアを思いつきました-必要なものだけをレコードから取り出し、フィールドに分割してデータベースに転送します。



データベースとログハンドラー





DBMSとしてpostgresqlをインストールしました-その時点でそれを操作することについて何も知らなかったので、本当に知りたいと思いました。



 sudo apt-get update sudo apt-get install postgresql-9.5
      
      







インストール後、postgresに接続します。



 sudo -u postgres psql
      
      







新しいユーザーを作成しました:



 CREATE USER pgmaxa WITH password 'strongpass';
      
      







ベース:



 CREATE DATABASE blondemine; GRANT ALL ON DATABASE blondemine TO pgmaxa;
      
      







最初の「wedro」テーブルには、イベントの時間、ルーターの名前、攻撃者のアドレス、および攻撃されたポートが含まれている必要があります。 そして、すべてはうまくいきますが、テキスト形式で保存するのは攻撃者の間違ったアドレスのように思えました。 その結果、IP4R拡張機能をインストールしました-最初の試行ではうまくいきませんでしたが、興味深い場合は教えてください。 その結果、テーブルは次のように作成されました。



 CREATE TABLE wedro ( rt timestamp without time zone, gw character varying(9), ad ip4, pt integer, dtst time without time zone NOT NULL DEFAULT now() )
      
      







ログハンドラー





ここで、データベースを埋めるlocal5ログハンドラーを作成します。 それは1日で書かれたものではなく、5つのエディションを経たので、最新の作業バージョンを提供します。



/usr/sbin/handmade/logtopostgres.sh
 #!/bin/bash # FILES SECTION # parsed file log=/var/log/local5 # prepared query file tmp=/var/log/local5.ptmp # final query file sql=/var/log/local5.psql # debug file err=/var/log/badform5.log # CONSTANTS yr=`date +%Y` # DATABASE SECTION # syntax: {var name}={corresponding field in DB} # local (gateway) time of atack lt=rt # hostname of atacked gateway gw=gw # ip address of blocked atacker ad=ad # blocked port number pt=pt echo "INSERT INTO wedro ($lt,$gw,$ad,$pt) VALUES " > $tmp cat $log | grep "Access Control" | grep default | \ sed 's/ [0-9]\{4\} / /g;s/\([0-9]\): /\1:/' | \ awk '{ \ gsub(/"/,"",$5) \ sub(/src=/, "", $5 ) \ split($5,HA,":"); \ gsub(/"/,"",$6) \ sub(/dst=/, "", $6 ) \ split($6,OP,":"); \ if (length($4) > 9) \ print \ "GWNAME too long: \x27" $4 "\x27 | whole line: \x27" $0 "\x27 |" \ >> "'$err'"; \ else \ if (OP[2]=="") \ print \ "PORT is empty: \x27 \x27 | whole line: \x27" $0 "\x27 |" \ >> "'$err'"; \ else \ print \ "(to_timestamp( \x27"'$yr'$2$1$3"\x27,\x27YYYYDDMonHH24:MI:SS\x27)," \ "\x27"$4"\x27," \ "\x27" HA[1] "\x27," \ "\x27" OP[2] "\x27)," >> "'$tmp'" \ }' truncate --size=-2 $tmp echo ";" >> $tmp mv $tmp $sql export PGPASSWORD=strongpass && psql -h localhost -U pgmaxa -d blondemine -f $sql rm $sql # # awk afterprint section for debug local output # #" Day: " $2 \ #" Month: " $1 \ #" Time: " $3 \ #" Host: " $4 \ #" AtackerIP: " HA[1] \ #" MyPort: " OP[2] \ #
      
      









この「スクリプト」の本質は次のとおりです。







別のコメントに感嘆符を付けました。 事実、雑誌Zywall2PlusとUSG20の形式は、1つは年を書いており、もう1つは何らかの理由で異なっているという点で異なります。 これらのレコードを一般的なビューにするには、すべてのレコードから年を削除し、システムから年の値を追加します。 これは実際にはあまり正しくなく、しばらくして、別の方法で行う必要があることに気付きました。 マガジンの各フォーマットについて、モジュールの形で特定の処理テンプレートを作成する必要があります。 しかし、時間がなくて、それがどうなるかを書きました。



/etc/logrotate.d/ログのローテーション設定でデータベースが自動的にいっぱいになるようにするには、ファイルサイズでローテーションを設定するlocal5のルールを作成する必要があります。



 /var/log/local5 { rotate 1 prerotate /usr/sbin/handmade/logtopostgres.sh endscript postrotate invoke-rc.d rsyslog rotate > /dev/null endscript size 2190000 missingok notifempty compress }
      
      







ただし、何らかの理由でローテーションが常に機能するとは限らず、cronスケジューラーで5分ごとに強制ローテーションを行いました。



 */5 * * * * root /usr/sbin/logrotate /etc/logrotate.d/loc5
      
      







結果





その結果、データベースは実際に自動的にいっぱいになります-2日間で複数のルーターからの約400万件のレコード。



ステップ2:受動分析





最初から、53番目のポートのレコードが多すぎて他のものを見ることができないことが明らかになりました。 結果として、それらを削除することほど良いものはありません、私はまだ思いついていません。 AFTER INSERTのトリガーがwedroテーブルでハングしました。



 CREATE OR REPLACE FUNCTION public.deldns() RETURNS trigger AS $BODY$ BEGIN DELETE FROM wedro WHERE pt=53 OR ad::text like '192.168%'; RETURN NEW; END; $BODY$ CREATE TRIGGER sweep AFTER INSERT ON public.wedro FOR EACH STATEMENT EXECUTE PROCEDURE public.deldns();
      
      







結果





このような定期的な清掃により、ベースは驚くべき速度で成長を停止し、その中に何かを見つけることが可能になりました。 確かに、一度占有されたリソースを解放するAUTOVACUUMの必要性もありました。



一意のアドレス





同じアドレスからの攻撃はしばしば繰り返されます。 したがって、それらを別のテーブルに収集することにしました。 データは5分ごとに更新されるため、トリガーの形でこれを行うことは意味がありません。その結果、pgagentスケジューラーのインストールと操作をマスターする必要がありました。



このために、さらに2つのipidおよびwedro_oldテーブルが作成されました。



 CREATE TABLE ipid ( id bigint NOT NULL DEFAULT nextval('ipid_id_seq'::regclass), ad ip4 NOT NULL, dtst timestamp without time zone NOT NULL DEFAULT now() ); CREATE TABLE wedro_old ( rt timestamp without time zone, gw character varying(9), ad ip4, pt integer, dtst time without time zone NOT NULL DEFAULT now() );
      
      







そして、pgagentでは、これらのテーブルに記入するために1時間ごとのタスクが開始されました。



 INSERT INTO ipid (ad) SELECT DISTINCT ad FROM wedro WHERE dtst > (select max(dtst) from ipid)::time AND ad NOT IN (select ad from ipid); INSERT INTO wedro_old SELECT * FROM wedro; TRUNCATE table wedro;
      
      







ステップ3:アクティブ分析





HikvisionカメラとDVR





残りのエントリは、23番目のtelnetポートに対する非常に多くの攻撃を示しました。 さらに、多くのアドレスがこれを繰り返し行い、他のポートをスキャンしませんでした。 このようなアドレスをブラウザーに入力すると、資格情報入力フォームが開きます。







場合によっては、工場管理者/ 12345がHikvisionデジタルテープレコーダーインターフェイスに許可されます。 また、一部のデバイスに文書化されていないオープンポート9527があることも興味深いです。アクティブ分析フェーズの例を次に示します。



23番目のポートのみを攻撃したアドレスを探しています。



 SELECT ad INTO telnetz FROM wedro_old WHERE ad IN ( SELECT a.ad FROM (SELECT ad,pt from wedro_old group by ad,pt) AS a GROUP BY a.ad HAVING count(*)=1 ) AND pt=23 GROUP BY ad,pt;
      
      







Nmapの結果リストを使用して、脆弱なDVRを検索します。



 #!/bin/bash nmap \ -n -Pn -p9527 --open `\ echo "select * from telnetz limit $1 offset $2;" | \ psql -U pgmaxa -d blondemine -t -h syslog_IP` | \ grep for | sed 's/^.*for //g'
      
      







ここでは、ターゲットの数に関するスキャナーの制限のために、制限およびオフセット式が使用されます。 無制限のリストでは、クラッシュします。



ステップ4:アクション





前の手順で見つかったノードについては、工場の資格情報を確認し、23番目のポートスキャナーを無効にすることを期待してスクリプトを作成しました。 ただし、ルーターへの不正アクセスを積極的に防止するという当初の目標からは十分に離れています。 そして、在庫を確保する時が来たと思います。



おわりに





インターネットは本当に汚い場所であり、私のシステムではこれを定量化できます。 私がここに持ってきたものから、システムが完璧からはほど遠く、改善が必要であることは明らかです。インターフェース、デバイステンプレート、すべてのモジュールを単一のインストールパッケージなどに結合する必要があります。 しかし、システムはすでに利用可能で、無料のコンポーネントから組み立てられています。 私のようなシステムが商業的実行に存在することを除外しません。 ただし、このようなシステムのすべてのモジュールが構成および変更に使用できるとは思えません。



All Articles