Ubuntu上でJohn the Ripperを使ってPDFのパスワードを解析する
背景とツールの概要
知人から連絡をもらった。
自身が過去にかけたパスワードがわからず、PDFファイルの中身を見れなくなってしまっている。もしなにか技術的な対処方法で開けられるなら開けてもらえないか、と。
そこで少し対応方法を検討し、今回はセキュリティ界隈でもCTF(Capture The Flag)などで度々使われるツールである、John the Ripper(以下JtR)を使って解析することにした。
JtRは、有名なBrute-force(総当たり)だけでなく、比較的一般的なパスワードを使っている場合に効率的に解析できる辞書型(ワードリスト)を使った方法での解析を容易に実現してくれるツール。
今回使う仕組みは、パスワードがかけられている対象に合わせてツール(JtR)がハッシュ値を生成して、それに対して平文で用意したパスワードリスト等を渡し、同じくツールが平文からハッシュ値を生成して突合、ハッシュ値が一致するものがあればパスワードがわかる、というもの。
その中でも今回は、"jumbo" と呼ばれる、より多様なハッシュや暗号化の方式などに対応している拡張版のものを使う。(PDFは"jumbo"で対応している)
実行環境と周辺準備
今回の実行環境としては、Docker上にUbuntuのコンテナをベースに構築することとした。
バージョンとしては次のとおり。
- Docker:
Docker version 26.1.0
- (ベースイメージの)Ubuntu:
24.04
- John:
John the Ripper 1.9.0-jumbo-1+bleeding-ffd18e6b5d
今回使用しているJtRはjumbo版だが、これも前述の通りPDFについてはjumbo版でないと対応していなかったため。
また、前述の通り、CTFで使われることも多いためか、検索結果としては、Kali Linuxを使用している場合が多い。個人的に、Ubuntuの使用経験が長く、早々に確認をしたい事情があったため、今回はコンテナ上のUbuntuで試している。
JtRにほぼ初めて触れる人はこの勘違いを起こす可能性が高そうには思うが、Ubuntuで試す場合の注意点としては、Ubuntuでは apt install john
で簡単に入手できるもののこれはjumbo版ではないため、後述するような形のインストールをする必要がある。
自分の場合は、検索の仕方が曖昧だったせいか、jumbo版が最初から入っているKali Linuxを使用している例[1]か、UbuntuにおいてAptでパッケージをインストールしているものの自ら何らかの方法でハッシュ化した暗号ないし/etc/passwdと/etc/shadowに対しての解析などjumbo版を使わなくてもサポートされているもの[2]だった。(参考までに、jumbo版ではないものを動かした場合のメッセージを末尾に記載する[3])
それから、ツールの概要の中で "平文で用意したパスワードリスト等を渡し" という話を出したが、このリストも用意が必要となる。JtR内にも簡易的なリストは用意されている(デフォルトでは指定しないとそれが使われる)が、もう少しボリュームのあるものを、ということで探すと、RockYouという有名なサイトでの漏洩パスワードのリストが出てくる。
リークがあった年は2009年なので、rockyou2009という名称であちこちに出回っていて、130MB程度(ダウンロードサイズは50MB程度)、のもの。前述のKali Linuxならファイル(rockyou.txt.gz)が同梱されている。
ダウンロードできるものとしては、どこにあるものを信頼するか、という話にはなるが、例えばGitHub上で公開されているものだと次のあたりなど。
また、これでも小さいということであればrockyou2021、rockyou2024というものも出てきている。
ただし、これは、次のリンク先が詳しいが、rockyou2009と違って実際に漏洩したパスワードのリストではなく、rockyou2009のような漏洩パスワードリストと典型的な言葉や数字などとの組み合わせ、と理解しておくと良さそう。rockyou2021が欲しい場合は、記事の著者がTorrentとマグネットリンクを公開してくれている。
ちなみにデータサイズはダウンロードで13GB程度、ファイルとしては90GBの巨大なもので、およそ84億行に及ぶらしい。今回のPDFファイルの解析に自分はこのrockyou2021を使用している。
同じ環境を再現したい場合には次のDockerfileを参考にしてもらうとよさそう。(使いやすさ重視なのでレイヤーリングなど意識しきれていないがご容赦いただきたい、また、状況により試行錯誤したいニーズがありaptのclearnやlistsの削除はしていません)
FROM ubuntu:24.04
# johnのインストールガイド内記載
# --> git, build-essential, libssl-dev, zlib1g-dev
# Zipファイルのパスワード検証に使う
# --> unzip
# ファイル編集に使う(別エディターでもOK)
# --> vim
# rockyou2021の展開に使う
# --> p7zip-full, p7zip-rar
RUN apt-get update && apt-get install -y \
git \
build-essential \
libssl-dev \
zlib1g-dev \
unzip \
vim \
p7zip-full \
p7zip-rar
# johnのインストールガイド内、必須確認内容のみ
RUN mkdir -p ~/src && cd ~/src && git clone https://github.com/openwall/john -b bleeding-jumbo john
RUN cd ~/src/john/src && ./configure && make -s clean && make -sj4
docker build -t john-bleeding-jumbo .
# 終了後に自動削除したいので "--rm"
docker run --rm --name=jtrwork -it john-bleeding-jumbo /bin/bash
別ターミナル・コンテナ外にて
# zipファイル準備, コンテナ内で準備する場合にはapt install zipが必要
touch plain.txt
vi plain.txt # 空のファイルだとうまくいかないので何か値を入れる
zip -e --password=hogehoge enc.zip plain.txt
docker cp enc.zip jtrwork:/
# PDFファイル準備
docker cp enc.pdf jtrwork:/
(Optional)rockyou2021を使う場合は次の通り。
同じく別ターミナル・コンテナ外にて
# 事前にダウンロードが済んだ状態での対応
docker cp RockYou2021/ jtrwork:/
コンテナに入っているターミナルに戻って
cd RockYou2021
7z x RockYou2021.7z.001
なお、インストールガイドはこちら。
実行と結果
結論から言って、残念ながらPDFファイルの方は解析をかけてもパスワードとしてマッチするものはなかった。
(言い換えると、典型的なパスワードとは違うものをセットしていたということなので良かったとも言える、かも)
rockyou2021の84億件のデータとは整合せず、結果的にパスワードはわからなかった。
コンテナ上でシングルプロセスで15hほどかかった。ざっと計算すると、15.6万件/s (5.6億件/h)の処理ができていたということになるかな。
cd ~/src/john/run
./pdf2john.pl /enc.pdf > pdf.hash
cat pdf.hash
/enc.pdf:$pdf$2*3*128*-1852*1*16*08ebaecfb0955f22{OMITTED}092ed5bf19c9b426
./john --wordlist=/RockYou2021/rockyou2021.txt --format=pdf pdf.hash
Using default input encoding: UTF-8
Loaded 1 password hash (PDF [MD5 SHA2 RC4/AES 32/64])
Cost 1 (revision) is 3 for all loaded hashes
Will run 2 OpenMP threads
Note: Passwords longer than 10 [worst case UTF-8] to 32 [ASCII] rejected
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
0g 0:00:18:20 1.97% (ETA: 12:53:22) 0g/s 150224p/s 150224c/s 150224C/s 0613712425..0613712655
:
:
:
:
0g 0:14:50:06 DONE (2024-10-02 12:18) 0g/s 149679p/s 149679c/s 149679C/s ~~~~~~niyara..~~~~~~~~~~~~~~~~~~~~
Session completed.
なので今回は単に、典型的なパスワード等の場合にはこうやってパスワードクラックができる、という経験が積めた、という感じ。
ちなみに、zipファイルの場合はこんな感じ。
cd /
unzip enc.zip
Archive: enc.zip
[enc.zip] plain.txt password:
skipping: plain.txt incorrect password
cd ~/src/john/run
./zip2john /enc.zip > zip.hash
cat zip.hash
enc.zip/plain.txt:$pkzip$1*2*2*0*18*c*b095e5e3*0*43*0*18*b3e9*6d2a689497f806f29b336588f95a60df3a17eac78670e6a5*$/pkzip$:plain.txt:enc.zip::/enc.zip
./john zip.hash
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Note: Passwords longer than 21 [worst case UTF-8] to 63 [ASCII] rejected
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
Almost done: Processing the remaining buffered candidate passwords, if any.
0g 0:00:00:00 DONE 1/3 (2024-10-03 13:33) 0g/s 3320Kp/s 3320Kc/s 3320KC/s Txtzip1900..Tplain1900
Proceeding with wordlist:./password.lst
Enabling duplicate candidate password suppressor
hogehoge (enc.zip/plain.txt)
1g 0:00:00:00 DONE 2/3 (2024-10-03 13:33) 6.250g/s 824693p/s 824693c/s 824693C/s iloveyou!!..281985
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
最後から数行前のあたりを見ると "hogehoge" が出ていることがわかる。当然ながら、ここで出てきた値を入れると展開できる。
unzip /enc.zip
Archive: /enc.zip
[/enc.zip] plain.txt password:
extracting: plain.txt
ということで、元々の目的は果たせなかったものの、面白い経験をできた。
また、ここから体感できたこととして、自身としては次のようにまとめたい。
- 典型的なパスワードや一度リークしたパスワードは、このJohnで今回取った方式を使うと比較的早く解析されてしまうので危険
- また、短いパスワードはそもそもBrute Forceで比較的短期に解析されてしまうのでやはり危険
- 長くて典型的ではないパスワードにすることは大事
余談
Dockerに割り当てていたディスクサイズが小さく、rockyou2021を使うには不足があった。
そこで、単にボリュームマウントさせて対応しようとしたが、使用している環境(colima)の制約でできなかった。
具体的には、 -v
が動かないというもの。2022年12月時点に起票されて解決はしていない。
しかし、解決策として、colimaの起動設定でディスクサイズを与えるという方法の記載があったため、次のようにした。
colima stop
colima start --disk 128
-
著者は全く悪くないが、例えば John the RipperのJumboルールを使ったパスワード解析 https://zenn.dev/fire_fire_2/articles/7d1f5ecfdd1e85 や パスワード保護されたPDF文書を総当たり攻撃で復号する https://qiita.com/v_avenger/items/443358029c333a4a6d13 など ↩︎
-
同様に著者は全く悪くないが、例えば John the Ripperを使ってパスワードを解析する https://qiita.com/phase-d/items/61e45740bde489bbbb85 など ↩︎
-
例えば
pdf.hash
がPDFから生成したハッシュの値を入れたファイルだとして、john pdf.hash
とすると次のように表示される。-->No password hashes loaded (see FAQ)
また、--format
オプションをつけて、対象がPDFであることを明示した場合には次のようになる。 -->Unknown ciphertext format name requested
いずれの場合も、ハッシュの値を入れたファイルが正しく作られている場合には、jumbo版では発生しない。 ↩︎
Discussion