また連続で膨大なアクセスを行うため、DoS攻撃として威力業務妨害となる可能性もある。
絶対に行わないようにしてください。
セキュリティを学ぶ上で、防御側の立場しかしらないと適切な判断ができない思い、攻撃側の立場にたち、総当たり攻撃(Brute-Force Attack)のアルゴリズムを考えてみた。
総当たり攻撃(Brute-Force Attack)とは
総当たり攻撃とは、暗号の解読やパスワードの割り出しなどに用いられる手法の一つで、割り出したい秘密の情報について、考えられるすべてのパターンをリストアップし、片っ端から検証する方式。
総当たり攻撃 : IT用語辞典
もっとも原始的な暗号解読方法のひとつで、考えられるパターンをすべて試行する攻撃。
たとえば3桁のダイアルロックがあれば、000、001、002〜998、999のようにすべてのパターン(3桁の数字であれば1000通り)を試行して、パスワードを解読する。
ただ、これではあまりにも時間がかかりすぎてしまうため、よく使われるパスワード(passwordやadminなど)をあらかじめ用意しておいて、その辞書をもとに攻撃する手法もある。
重複組合せでパスワードを生成し、総当たり攻撃を行う
今回は簡単に実装できたPythonと、ちょっと苦労したJavaScritpでの実装方法を紹介する
前提条件
クラックするパスワードの条件は以下のとおりとする。
- 英字(小文字)のみ
- 4桁
ちなみにこの条件で、次に紹介するプログラミングを使うと1秒以内にクラックできる。
実行環境やアルゴリズムにもよるが、秒殺、いやミリ秒殺だ。
Pythonの場合
import time
from itertools import product
target = 'pass'
chars = 'abcdefghijklmnopqrstuvwxyz'
def check(chars, repeat):
pws = product(chars, repeat=repeat)
for pw in pws:
if ''.join(pw) == target:
return ''.join(pw)
start = time.time()
pw = check(chars, 4)
if (pw is None):
print('failure')
else:
print('got it! -->', pw)
finish = time.time() - start
print(finish, ' sec');
Pythonの場合は、itertoolsのproductを使うことで簡単に重複組合せの文字列を生成することができる。
JavaScriptの場合
const gen = (chars, repeat) => {
var result = [];
for (let i = 0; i < repeat; i++) {
for (let j = 0; j < Math.pow(chars.length, repeat); j++) {
result[j] = result[j] || [];
result[j].push(chars.charAt((j / Math.pow(chars.length, i) ) % chars.length));
}
}
return result;
};
const target = 'pass';
const chars = 'abcdefghijklmnopqrstuvwxyz';
const start = new Date().getTime();
const list = gen(chars, 4);
for (let pw of list) {
if (pw.join('') === target) {
console.log('success', pw);
}
}
const finish = new Date().getTime();
console.log(finish - start, 'msec');
JavaScritpにはPythonのitertools.productみたいな便利な機能がないので、地道に重複組合せの文字列を作成する。genメソッドがそれに該当する。
このようにBrute-Force(力ずく)でクラックする。力こそパワーだ。
総当たり攻撃は、こんな原始的なのに有効だったりする。
パスワードがハッシュ化されていたって、暗号化されていたってお構いなし。
CPUを思いっきり使ってやてば、英字8桁くらいなら数秒〜数分でクラックされてしまう。
総当たり攻撃への対策
こんな単純な攻撃でも、単純なパスワードを利用しているとすぐにクラックされてしまう。そこで開発者視点と利用者視点の双方に立って、対策をまとめていく。
なぜ双方の視点が必要かというと、開発者がセキュリティ対策しても、利用者が単純なパスワードを使っていればすぐにクラックされる。
反対に、利用者が複雑で長いパスワードを使っていたとしても、開発者が十分なセキュリティ対策をしていなければ、これまたすぐにクラックされてしまうからだ。
開発者としての対策
- 一定時間の試行回数を制限する
- 一定速度以上の試行を禁止する
- アクセス元を制限する
- 不正ログイン試行が検知されたらアカウントをロックする
- ワンタイムパスワードやセキュリティトークンを利用する
- 二段階認証をする
- パスワード強度チェッカーを提供する
利用者としての対策
- パスワードの桁数を増やす
- 英数字に加え、記号も使う
- 想定されにくいパスワードを利用する
「パスワードの定期変更」は無意味?
組織に所属していると、3ヶ月ごとにパスワードを変えろと言われることがある。
この「パスワードの定期変更」はむしろ有害な場合もあるので、注意しなければならない。
まず、無害な場合は、利用者が個人の意志で変更する場合。
逆に有害な場合は、強制的に変更させる場合。
強制されると利用者は「覚えやすいパスワードを使おう」と思うようになり、安易なパスワードを利用することがある。
私は前職で同じような環境にあり「1qaz2wsx」「2wsx3edc」「3edc4rfv」……を延々と変え続けていた。このあたりは英数字混在8桁で古いパスワードチェッカーでは「強力」とでていたが、おそらく辞書攻撃(Dictionary Attack)されたら一発だろう。
この他にも心理的な理由から、セキュリティ的な理由などで「パスワードの定期変更」は必ずしも有効な手段ではないといえる。
もちろん「定期的に変更してはいけない」というわけではない。
参考文献
セキュリティについては、徳丸本(体系的に学ぶ 安全なWebアプリケーションの作り方)を読んでいただければ、だいたいのことが理解できると思う。
PHPのプログラムが付属しているので、実際に手を動かしながら読める良本だ。
以上
written by @bc_rikko
0 件のコメント :
コメントを投稿