今回はブルートフォースアタックに挑戦です。

解説動画はこちら



ブルートフォースアタックを知らない方のために
手口を紹介すると
総当たりでパスワードの文字列を生成して
突破を試みる方法です。

この手のプログラムは
慣れれば小学生でも行けちゃうやつです。

早速コードを作ってみましょう。

まずはパスワード用の文字列を
用意するところからです。

stringライブラリを用いると
沢山文字を入力しなくても
文字列を用意する事ができます。
import string

chars = string.ascii_letters + string.digits

print(chars)
print(len(chars))
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
62


続いて記号も組み合わせてみます。
import string

chars = string.ascii_letters + string.digits
chars += '/*-+.,!#$%&()~|_'

print(chars)
print(len(chars))
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/*-+.,!#$%&()~|_
78

記号まで入れると結構な文字種になりますね。

この文字列を使ってランダムでパスワードを
生成してみましょう。

randomライブラリを用いる方法と
secretsライブラリを用いる方法があります。

import string,random

size = 10
chars = string.ascii_letters + string.digits
chars += '/*-+.,!#$%&()~|_'
password = ''.join(random.choices(chars,k=size))

print(password)
DSyzlv.ec3
import string,secrets

size = 10
chars = string.ascii_letters + string.digits
chars += '/*-+.,!#$%&()~|_'
password = ''.join(secrets.choice(chars) for i in range(size))

print(password)

Axu_#,OXf!


ランダムではなく総当たり式で
パスワードを生成するには
itertoolsのproductでデカルト積を作ります。

ここでは文字種が多いので
数字だけでやっていますが
記号含めの文字列でやることもできます。

文字種が多いほど莫大な
組み合わせになります。

import string,random,itertools

size = 3
chars = string.digits

for ch in itertools.product(chars,repeat=size):
    password = ''.join(ch)
    print(password)
・・・
399
400
401
402
・・・


さて、パスワードが用意できたところで
ZIPファイルのパスワードを
総当たりで破ってみましょう。

あらかじめZIPファイルは生成しておくこととして
パスワードは「otupy」にしておきました。

文字種が多いと組み合わせが多すぎて
実験は大変すぎるので
文字は8種類、文字数5文字の
パスワード破りを試します。

import zipfile

file_path = 'data/otupy.txt.zip'
size = 5
chars = 'abcotupy'
count = 0

with zipfile.ZipFile(file_path , 'r') as zf:
    for i in range(100000):
        # パスワードはバイト型で有る必要がある
        pwd = bytes(''.join(random.choices(chars,k=size)),'UTF-8')
        try:
            zf.extractall(path='.', pwd=pwd)
            print('success : password  : {}'.format(pwd))
            break
        except Exception as e:
            count +=1

print('tried passwords : ' , count)
success : password  : b'otupy'
tried passwords :  36993

だいたい、数万回の試行で
パスワードが破れるようです。

この文字種と文字数なので
これだけの時間で終わりますが


78種類
10文字のパスワードだと
8335775831236199424通りも
パスワード候補が有るので
滅多に破られることはありません。

あらかじめ辞書を用意して置いたり
文字種を限定しておくことで
ロック解除する側は探索時間を
短くする事ができます。

逆に対処する側は
パスワードの文字数は最低でも8文字
文字種の組み合わせも70種類以上にしておけば
候補は576480100000000通りになるので
破られにくくなります。

ただし、攻撃する側も
サーバーを複数台用意したり
マルチコアに対応するコードを書く事で
1秒あたりのアタック回数を増やす事が
できてしまいます。

そこで対処する側では
短時間でのパスワード突破失敗を検知したり
何回か失敗したらロックをかけるような
機構を組み込んでおく必要があります。

日頃からこういった攻撃に対する
防衛策は講じておく必要がありますね。

ZIPのパスワードくらいであれば
忘れてしまっても
総当たりで何日か放置しておけば
破れると思いますので
気になる方は試してみてください。

本日はここまでです
それでは。