.htaccessでTor経由のアクセスを遮断する
Tor使っててなんとなくTorからのアクセス遮断したくなったので書いてみた(特に意味は無い) Torの出口ノードを.htaccessで遮断するだけなので
出口ノード一覧はここにあります
http://torstatus.blutmagie.de/ip_list_exit.php/Tor_ip_list_EXIT.csv
一覧更新が定期的に行われるっぽいので.htaccessをその都度更新します
# -*- coding: utf-8 -*- import time import datetime from subprocess import call, PIPE, DEVNULL while True: # download Tor list cmd = "wget -nc http://torstatus.blutmagie.de/ip_list_exit.php/Tor_ip_list_EXIT.csv" ret = call(cmd.split(), stdout=DEVNULL, stdin=DEVNULL, stderr=DEVNULL) if ret != 0: print("download error") else: with open('/var/www/.htaccess', 'w') as fp: fp.write('Order allow,deny\n') fp.write('Allow from all\n') fp.write('<IfModule mod_rewrite.c>\n') fp.write(' RewriteEngine on\n') with open('Tor_ip_list_EXIT.csv', 'r') as torfp: list = torfp.readlines() for l in list: ip = l.replace('.', '\\.').replace('\n', '') + '$' fp.write(' RewriteCond %{REMOTE_ADDR} ^' + ip) tail = '\n' if l == list[-1] else ' [OR]\n' fp.write(tail) fp.write(' RewriteRule ^(.*) torpage.html [L]\n') fp.write('</IfModule>\n') print(datetime.datetime.now().isoformat(' '), "done") time.sleep(60 * 60 * 12) # 12じかんおき
python3で書いてます。
12時間おきにTorの出口ノード一覧をチェックし、/var/www/.htaccessを上書きします。内容はTorからのアクセスをtorpage.htmlに書き換えて返すだけです(以前のhtaccessは失われるので注意)
実行&常駐
$ screen $ python3 torlimit_htaccess.py [Ctrl + A + D]でデタッチ
出力
Order allow,deny Allow from all <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{REMOTE_ADDR} ^2\.98\.200\.182$ [OR] RewriteCond %{REMOTE_ADDR} ^2\.111\.64\.26$ [OR] (略) RewriteCond %{REMOTE_ADDR} ^217\.172\.190\.19$ [OR] RewriteCond %{REMOTE_ADDR} ^217\.210\.165\.43$ RewriteRule ^(.*) torpage.html [L] </IfModule>
http://zipsan.pw/ にTorでアクセスしてみるとしっかり遮断してくれるので一応動いてるっぽい。
他にうまい方法あるかも?
Python+Selenium+Phantom.js+Beautifulsoupでスクレイピングする
※【2018/04/17追記】
Phantom.jsはメンテナンスが終了したようです。今後はGoogle Chromeを使用してJavascriptの処理を行っていくことになります。以下の記事で解説していますので合わせてご覧ください。 zipsan.hatenablog.jp
【追記終わり】
最近スクレイピングのスクリプト書いて遊んでいるのでそれについてのメモがてらに。
Pythonでスクレイピングする方法は多々あるみたいなんですが,個人的に一番使いやすかった(慣れ?)のがこの組み合わせでした。
以前Pythonのurllib.request+Beautifulsoupでレスポンスhtmlの解析をして次々とたどっていくようなスクリプトを書いていたんですが、これだとJavascriptで追加されたエレメントは受け取れなかったり、リダイレクト処理がめっちゃ大変だったり色々と面倒でしたが今回SeleniumとPhantomjsを使用することでその辺りの面倒な処理を一括でできるようになりました。
簡単に流れを説明すると、PythonでSeleniumを操作し、SeleniumがPhantom.jsでJSを実行し、結果のHTMLをBeautifulSoupでパースし、解析していきます。
Selenium
Seleniumはブラウザの自動化を行うツールです。複数のブラウザでWebのテストを実行したりすることができたり、Android/iOSでテスト出来たりいろいろと便利(Seleniumサーバー建てて集中管理したりもできるみたいだし)。今回はFirefoxやChromeの代わりにPhantom.jsを使います。
Selenium - Web Browser Automation
Phantom.js
Phantom.jsは本来はブラウザがないと実行できないJavascriptを、ブラウザ画面なしで実行できるすごいやつ。API形式で叩けるっぽい? PhantomJS | PhantomJS
Beautiful soup
Beautiful soupはHTML/XMLのパーサーで、HTMLを解析して使いやすくしてくれるものです。HTMLをDOMに倣って列挙したり検索したり選択したりできます。
Beautiful Soup: We called him Tortoise because he taught us.
環境設定とか
特にそんなにすることないけど・・・
使用した言語はPython3.4です。Linux, Mac, Windowsで動くのを確認
Python3は入ってること前提で。まずはpythonのseleniumモジュールのインストール
pip3 install selenium
次にPhantom.jsを入れます。これは特に説明しないので適当に入れてください。
http://phantomjs.org/
ちゃんとパスを通しておくこと。
最後にBeautifulSoupを入れます。bsはpython3の場合は2to3
コマンドでpython3用に変換する必要があります(公式でそう書いてある)。
http://www.crummy.com/software/BeautifulSoup/#DownloadここからBeautiful Soup 4を落としてきて2to3で変換。
wget http://www.crummy.com/software/BeautifulSoup/bs4/download/4.3/beautifulsoup4-4.3.2.tar.gz # 現時点(2015/04/12)での最新版 tar zxf beautifulsoup4-4.3.2.tar.gz cd ./beautifulsoup4-4.3.2 2to3 -w bs4 python3 setup.py
うまく行かなければ2to3した後に直接ライブラリディレクトリの中に突っ込んでもOK
使ってみる
from selenium import webdriver from bs4 import BeautifulSoup driver = webdriver.PhantomJS() driver.get("http://sukumizu.moe/") data = driver.page_source.encode('utf-8') print(data) driver.save_screenshot("ss.png") driver.quit()
結果
b'<!DOCTYPE html><html><head>\n\t<title>sukumizu.moe</title>\n\t<link rel="st(略
こんなかんじで扱えます。
スクリーンショットも撮れます。
from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities des_cap = dict(DesiredCapabilities.PHANTOMJS) des_cap["phantomjs.page.settings.userAgent"] = ( 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/28.0.1500.52 Safari/537.36' ) driver = webdriver.PhantomJS(desired_capabilities=des_cap) driver.get("http://sukumizu.moe/") data = driver.page_source.encode('utf-8')
取得したhtmlの解析 (Beautiful soup)
from bs4 import BeautifulSoup # ----- 略 ----- html = BeautifulSoup(data) print(html) # htmlソースを表示する print(html.title) # タイトルタグ print(html.title.string) # タイトルタグ内の文字 print(html.find('h1')) # h1タグ print(html.find_all('link')) # 全てのlinkタグのリスト print(html.find_all('link', attrs={'href': 'style.css'})) # linkタグかつhrefがstyle.cssのもののリスト
結果
<!DOCTYPE html> <html><head> <title>sukumizu.moe</title> ---(略)--- </body></html> <title>sukumizu.moe</title> sukumizu.moe <h1>What is your favorite "sukumizu"...? </h1> [<link ...., <link ...., <link ....] [<link href="style.css" rel="stylesheet"></link>]
これくらい使えれば困らないかも。他にもいろいろあるのでbsのドキュメントを参照。
タグの要素の選択やチェックはブラウザ標準の「要素を検証」「開発ツール」が便利。 Chromeなら左上の虫眼鏡、Firefoxなら右上の矢印で要素の選択ができます
pythonは簡単でいいなあ
セキュリティ・キャンプ九州 in 福岡 2014 Writeup
セキュリティ・キャンプ九州 in 福岡 2014 (SecurityCamp Kyushu 2014)に参加してきました。
セキュキャンと言えば、選抜されたメンバーが情報セキュリティに特化した様々な技術を学んぶ合宿です。近年の日本の情報セキュリティの需要増加や技術者不足を解消するために、様々なセキュリティ系の企業やIT系の企業、また独立行政法人や官公庁などの支援により毎年開催されています。
セキュキャン全国大会の方は22歳以下の学部生以下が対象で、院生は参加不可能なのですが、今回はなんと九州大会に限り院生参加可能!ということですぐに応募用紙を書き、運良く選考に受かることが出来ました。
セキュキャン九州の日程は2014年8月29日~31日。夏休み最後の日に開催でした。
実はその周辺、大学のコース授業で1週間ほど大阪で合宿→その後研究室合宿で3日ほど大分へ合宿→1日休みの後セキュリティ・キャンプ→セキュキャン終了翌日神戸で合宿という、普段家から出ない学生にはかなりしんどい日程でした。(これ書いてる途中も神戸合宿の間只中です)
しかし、そんなハードスケジュールでも参加してよかった。とても充実したキャンプでした。
日程
8月29日 金曜日(1日目)
9:30 受付開始
10:00 オープニング
11:00 『情報セキュリティ技術の使い方~技術を学んで怪物となる前に』 吉井講師
12:00 『CTF、バグハント、コンテストの現在。~セキュリティ・キャンプの紹介も兼ねて~』園田講師
13:00 お昼休み
14:00 『怪しいアプリ、怪しくないアプリ』 宮本講師、園田講師
16:00 『CTFを通じて学ぶセキュリティ技術基礎』続き 花田講師
17:00 ホテル移動、夕食
19:00 『セキュリティ技術者の職種ガイド ~セキュリティ対応ケーススタディ と絡めて~』 堂領講師
21:00 終了
8月30日 土曜日(2日目)合宿講習
9:00 『プログラミングとセキュリティ』 小出講師
12:00 お昼休み
13:00 『Webセキュリティ基礎&実践』 服部講師
17:00 ホテル移動、夕食
19:00 『情報セキュリティ技術の使い方をケースで考えよう』 吉井講師
21:00 終了
8月31日 日曜日(3日目)合宿講習
9:00 『ハニーポット+簡易セキュリティ診断講座+マルウェア解析講座(前編)』 濱本講師
12:00 お昼休み
13:00 『ハニーポット+簡易セキュリティ診断講座+マルウェア解析講座(後編)』 濱本講師
15:00 クロージング
16:00 案内
16:30 終了
一日目
一日目は9:30~10:00集合。福岡に住んでるお陰でそんなに早い時間に出発しなくても大丈夫でした。他の県の方々は夜行バスだったり新幹線だったりなかなか大変だったみたい。
@mrtc0氏も参加するということで、非常に楽しみ。
場所はエルガーラホール。会場に到着するともうすでに結構な人数が到着していました。
小出先生(@hirosk)や、県警の方などと少しお話をし、適当に開いてる席に座り、MBAを開いて適当にツイッターしていると
ん??となりいにいるのもりたこ氏?
— 16000000000GB (@dskzip) 2014, 8月 29
隣が@mrtc0氏でした。すごい偶然。ということで名刺交換をしました。
zipさんの名刺いただいた
— もりたこ (@mrtc0) 2014, 8月 29
@mrtc0氏・・・怖い人だ
講演の内容は三輪会長による技術者の人材に関することであったり、吉井先生による法律の問題であったり、園田さんによるCTFに関するお話であったり、情報セキュリティの表面に現れる問題に関する内容でした。特記はしませんが、非常に楽しめる内容でした。
昼食後、15:00(16:00?)くらいから別の館に移動。西日本新聞社さんの会議室の模様。
その後、花田さん(@decoy_service)による簡易CTF大会が行われました。練習問題を5問ほど解き、すぐにCTF大会の方に移行。
合宿講習の1日目午後は、花田さんより「CTFを通じて学ぶセキュリティ技術基礎」です。手を動かしながら、学ぶセキュリティ技術です。 #spcamp #seccamp pic.twitter.com/MaMZDEc0iD
— security_camp (@security_camp) 2014, 8月 29
問題的にはFor(+NW)とCry系が大半でした。200点までの問題は基本的なこと(fileやstiringsコマンド、基本ツールの使用)が殆どで、それ以上の点数の問題は海外のCTF(CSAW, backdoorなど)の300,400点問題となっていて、難易度が非常に高かったように感じました。また、独自問題も有り、そのほとんどが発想力を問われるものが多く、非常につらかったです。
最終的には3位と同点の4位でした。エスパー系の問題が全然解けなかった。
CTF終了後、夕食タイム。夕食はホテルの食事でした。席につき食事を待っていたのですが・・・
なんで こんな 無言 なの
— えすらん@進捗 (@nrsdogs) 2014, 8月 29
皆無言でお通夜状態でした w
せっかくのキャンプで無言は嫌なので、ちょこちょこ話を振っていたのですがなかなか会話が弾まず。。(でもご飯美味しかった)
夜はホテルの会議室で堂領さんより、「セキュリティ技術者の職種ガイド」をお話しいただきました。セキュリティ技術の使い方、そして地元でセキュリティな仕事を見つける方法を、事例を交えながらお聞きしました。 #spcamp #seccamp pic.twitter.com/3jy5FjbvJU
— security_camp (@security_camp) 2014, 8月 29
無言の夕食を経て、堂領講師による情報セキュリティの職種に関するお話がありました。ここでは情報セキュリティの職種にはどのようなものがあるのか具体的に十数個例を挙げて解説をしていただきました。分類や就労場所など細かな要素までおしえていただいたので非常に参考になりました。
ここで一日目が終了。
2日目
朝7時に朝食だったのでめちゃくちゃつらかったです。前日の無言感は皆もやばいと思ってたようで
えすらん氏(@nrsdogs)が話題を作ってくれてました(よかった)
えすらん氏いなければ無言の食事になるとこだった(もうなった後だったけど)
— 16000000000GB (@dskzip) 2014, 8月 29
2日目午前は、小出先生からプログラミングとセキュリティ。 実際に開発しながら、セキュリティを考えます。 #spcamp #seccamp pic.twitter.com/7iSzA3pPWa
— security_camp (@security_camp) 2014, 8月 30
朝食後、2日目のはじめの講義。うちのボスの小出先生(@hirosk)の「プログラミングとセキュリティ」でした。JavaとGlassFishでWebアプリを作成し、プログラミング上でどのようなセキュリティの考え方やコーディングがあるのかの解説でしたが、不慮の事故でセキュリティまで届かず。終了後にサイボウズLive上でアフターケアを行ってくれました。ハンズオンは環境が違うとプロでも難しいみたい
前日、班員の皆さんとワイワイCTFをやっていたので若干寝不足だったのですが、エンジニアの主食のお陰で生きることが出来ました。↓
セキュキャン九州2日目開始です #seccamp http://t.co/wP0tcfsqDP
— 16000000000GB (@dskzip) 2014, 8月 29
午後は「Webセキュリティ基礎&実践」と題して服部先生からのCTF大会Webアプリケーションのセキュリティについてでした。
2日目午後は、服部さんより、「Webセキュリティ入門」なのに、いきなりのXSS実習! #spcamp #seccamp pic.twitter.com/3ADYnyCRH4
— security_camp (@security_camp) 2014, 8月 30
Webセキュリティとは何だったのか。(いやセキュリティだけど)
いきなりXSSの実習を行いました。level1~5までのステージにフォームがおいてあり、それぞれに超基本的なXSSが可能なので、アラートを出してねという問題。簡単に書くと
- level1:<script>alert(1)</script>
- level2:<script>が消されるので<s<script>cript>alert(1)</script> or <scirpt >(スペース)
- level3: hiddenタグがエスケープされていないので埋め込む
- level4: iが1に変えられるので<scrIpt>alert(1)</scrIpt>
- level5: <scriptが消されるので<scri<scriptpt>alert(1)</script>
こんな感じでした。簡単ですね
練習問題終了後は脆弱性を作りこんだ本番のような環境で演習を行いました。
掲示板を模したWebサービスを使用して書き込み回数が多かったほうが勝ちというものでした。(知っている人は知っているアレ)掲示板にXSSができるので色々やってねと言うもの。アラート出たり飛ばされたり色々と面白かった。
最後の演習は普通のWebサイトを模したもので演習を行いました。XSSを複数個とphpの脆弱性、ディレクトリトラバーサルなど見つけました。最終的にphpスクリプトを注入して探索して、user情報とadminアカウントのハッシュをゲットしたので、レインボーテーブルでホイホイしてadminになり、トップページを乗っ取って終了。楽しかった。
Webアプリケーションでもヘタすればサーバーごと乗っ取られちゃうよということで、対策をしっかり行わなければならないなと思いました。
2日目夜は、吉井先生の「情報セキュリティ技術の使い方」です。ディスカッションで問いかけながら、みんなに考えて欲しいという吉井先生の思いが伝わってくる講義です。 #spcamp #seccamp pic.twitter.com/d2NutFDysz
— security_camp (@security_camp) 2014, 8月 30
夜は会議室で吉井先生からの法と情報セキュリティ技術の使い方の講義でした。レッドブル効力が切れていたので結構眠気が襲ってきましたが、ディスカッションを合間に入れてくださっていたので眠気が吹っ飛びました。ディスカッション楽しかった。
もうすでにこの状況 pic.twitter.com/XJjxYCfJHO
— 16000000000GB (@dskzip) 2014, 8月 30
これはいいよねって状態 pic.twitter.com/mjehdvW1XI
— もりたこ (@mrtc0) 2014, 8月 30
3日目
3日目は一日濱本さんより、「ハニーポット&マルウエア解析」 #spcamp #seccamp pic.twitter.com/mrdaUO7SSE
— security_camp (@security_camp) 2014, 8月 31
最終日は一番楽しみにしていた濱本さんによるハニーポットの解析演習でした。
はじめはネットワーク探索の基礎などを学びました。pingやnmapなど基本的なツールを使用して調査を行う手法を学びました。
攻撃者によってめちゃくちゃにされたあとのハニーポットの中身を探索し、どんなコマンドが使われているのか、何のマルウェアがどこに入っているのか。何をされたあとなのかを調査しました。/var/log/を漁ったり、コマンドのログを漁ったりしてなにか変な通信がないか、なにか変なコマンド実行してないかを一つ一つ見ていくのは大変でした。途中でftpで謎のファイルを落としていることを班員の方が見つけてくれたので、その周辺を調査するとルートキットを見つけました。見慣れないディレクトリやファイルが一緒に設置してあったので、調査を続けていたところでタイムアップ。とても楽しかった。
難しかったことは、/var/log/やhistoryなどを漁る場合、通常のコマンドや正常なトラフィックが入り交じっていて、どこが危険なのかどの部分が怪しいのかを判断することでした。また、濱本先生から「lsコマンドは汚染されています」と言われるまでlsコマンドが改ざんれていることに気づきませんでした。findなどは改ざんされていないとの事だったので、$ find . -maxdepth 1にエイリアスを貼って使用。こんなこともあるんだなと非常に勉強になりました。
After
今回記事にしたのはほんの一部で、その他にも沢山の技術や法的な解釈、モラル、現状などを学ぶことが出来ました。九州でのセキュリティ・キャンプは今回が第1回ということで、記念すべき第1回目の卒業生になれてとても嬉しいです。今後セキュリティ・キャンプ九州は続いていく(よね!?)と思うので、非常に期待しています。
実行委員や講師の方々、また支援して頂いた方々、参加者の方々ありがとうございました。
おまけ
新聞に掲載されました。
LINE乗っ取り詐欺が来たのでアクセス元を特定してみた
2014年08月04日18:30頃、次の日の試験勉強をしていると一通のDMが花田さん(@decoy_service)より届きました。
!?
ということで、やってみました。
先日SECCON Onlineでソーシャルハックという問題がありましたが、まさかこんな形で実践することになるとは。
続きを読むSECCON 2014 quals Online あみだくじ Writeup
先日のSECCON 2014 quals OnlineのProgramming 300 あみだくじを試合終了後にときましたので、置いておきます。
二時間程度かかりました。もうちょっと早く綺麗に解けるようにならないとな・・・。
Prog300 あみだくじ
問題ファイル:amida
実行ファイルが渡されるので、解いてねと言う問題。
書いたプログラムが以下。(python3)
# -*- coding: utf-8 -*- import sys from subprocess import Popen, PIPE # 元の文章を渡すとhead(数字行), mondai(あみだ本体), tail(*行) のリストを返す def transform(original): # 最初のNo~と最後の空白行を削除 # top => 最初の行, bottom => 最後の行 original = original[1:-1] top = list(original[0]) bottom = list(original[-1]) # あみだが横に倒れている場合 if "".join(top).find('--') != -1: trans = [] for m in original: t = m.replace('-', '#') t = t.replace('|', '-') t = t.replace('#', '|') trans.append(t) trans = list(map(list, zip(*trans))) # 転置 original = ["".join(tr) for tr in trans] top = list(original[0]) bottom = list(original[-1]) # 最終行が数字で始まっていたら上下を反転 if bottom[0] == '1' or bottom[0] == '8': trans = [] for m in original: trans.insert(0, m) original = trans top = list(original[0]) bottom = list(original[-1]) # 1 2 3 4 5 6 7 8 のように空白が開いている場合は、各行から冗長部分を削除 if (top[0] == '1' or top[0] == '8') and "".join(top).find(' ') != -1: i = 0 j = 0 while i < len(top) - 1: while top[j:j + 2] == [' ', ' ']: for k in range(len(original)): tmp = list(original[k]) del tmp[j + 1] original[k] = "".join(tmp) del top[j + 1] i += 1 j += 1 head = list(original[0]) body = original[1:-1] # headとtailを除いた部分 tail = list(original[-1]) return (head, body, tail) def main(): p = Popen(["./amida"], stdout=PIPE, stdin=PIPE, shell=True) while True: print('=' * 50) # 標準出力から問題を取得する msg = "" while True: c = p.stdout.read(1) if not c or c == b'?': break msg += c.decode('utf-8') print(msg) original = ["".join(list(m.replace('\x00', ''))) for m in msg.split('\n')] # 整形処理 head, body, tail = transform(original) print("#" * 30) print("".join(head)) print("\n".join(body)) print("".join(tail)) print("#" * 30) # solve for i in range(len(body)): for j in range(len(body[0])): if body[i][j] == '-': # swap tmp = head[j - 1] head[j - 1] = head[j + 1] head[j + 1] = tmp answer = head[tail.index('*')] print("Answer:", answer) # 答えを投げる p.stdin.write((answer + '\n').encode()) p.stdin.flush() if __name__ == '__main__': sys.exit(main())
渡された問題を標準出力から読み取り、整形して、解いて、標準入力から渡しています。
結局あみだくじは橋が出てきたら数字を入れ替えて行って、入れ替え終わったら*の位置と照合するだけでいいので、整形のほうがメインになってきます。
この問題、問題が進んでいくたびに上下が逆になったり、橋の間隔が大きくなったり、横になったりするので、それぞれに応じて整形してあげなければいけませんでした(ここが一番つらかった)
問題の出現順序が変わらなかったので、「一問あたりの制限時間あるけどどうせ100くらいなら手作業でいけるっしょ〜w」と思い、競技中は順番に入力して解いてたんですが、100問超えくらいから徐々に怪しくなって、160問くらいでつらくなったのでやめました。
その後、やっぱスクリプト書こう!!ってことで書き始めたんですが、もう考える気力と集中力は残ってなかった。結局解けず・・・(あたがわさんに任せとけばよかったなぁ・・・)
実はPythonのsubprocess.Popen使って標準入出力を制御する方法がわからず、ぐぐっても見つけきれなかったので始めは
$ netcat -l -p 40000 -e ./amida
して、それに対してTelnetlibから入出力を受け取って解いてました w
メンバーさんに聞いたらやっぱりPopenでできるみたいだよ!とURL付きで教えてくれたので、それを参考に組みました。勉強が足りないな・・・・。