暗号文
No.2 Base64 Encoding
符号化は本当の意味での暗号ではないが、暗号機能を中心としたあらゆる規格で多く使われている。特にBase64エンコーディング。
Base64エンコーディングは、あらゆる種類のバイトを特定の範囲のバイトに変換するために使われる。この特定範囲とは、ASCIIで読めるバイトのこと*1。こうすることで、秘密鍵などのバイナリデータをより簡単に転送することができる。また、エンコードは可逆的である。エンコードされたバージョンからオリジナルのバージョンを作成することができる。(デコード)
元データを6ビットずつに分割。(6ビットに満たない分は0を追加して6ビットにする)
各6ビットの値を変換表を使って4文字ずつ変換。(4文字に満たない分は = 記号を追加して4文字にする)
その結果、符号化されたバイトのサイズは 4/3に(約33%)増加する。
Hello ==> SGVsbG8=
Basic Authentication : ベーシック認証
Webアプリケーションではベーシック認証が使われることがある。これはBase64エンコーディングを使用する。そのため、サーバに送信されるユーザー名やパスワードを他人に読まれないようにするために、少なくともTLS・HTTPで暗号化する必要がある。(Base64エンコーディングは簡単にデコードできるから)
$echo -n "myuser:mypassword" | base64 bXl1c2VyOm15cGFzc3dvcmQ=
このとき HTTP header は次のようになる
Authorization: Basic bXl1c2VyOm15cGFzc3dvcmQ=
問題. 次のヘッダを傍受したとする。
Authorization: Basic c2hp***************taW4=
このときのユーザーネームとパスワードは?
「Base64 デコード」で検索しても良いが、今回は BurpSuite のデコーダーを使う。
No.3 その他のエンコーディング
HTML エンコーディング
HTML エンコーディングは、フォームデータやリクエストパラメータをサーバに送信する際に多く使用される。URLではスペースは許可されていないので、これは%20に置き換えられる。 UUEncode
Unix-2-Unix
Unix-2-Unix エンコーディングは、メールの添付ファイルを送信するために使用されている。
XOR エンコーディング
パスワードを格納するための最初でシンプルな難読化技術として、エンコーディングが使用されることもある。IBM WebSphere Application Server などでは、XOR エンコーディングの特定の実装を使用して、構成ファイルにパスワードを格納している。IBM では、これらのファイルへのアクセスを保護し、既定の XOR エンコーディングを独自のカスタム暗号化に置き換えることを推奨している。しかし、これらの推奨事項が守られていない場合、このデフォルト設定が脆弱性になる可能性がある。
問題. XORエンコードされたデーターベースパスワード Oz4rPj0+LDovPiwsKDAtOw== を見つけた場合、実際のパスワードは何か。
WebSphere {xor} password decoder and encoder に入れてみる。
No.4 Plain Hashing
プレーンハッシュ ハッシュ化は暗号の一種であり、主に元のデータが変更されたかどうかを検出するために使用されます。ハッシュは元のデータから生成されます。これは不可逆的な暗号技術に基づいています。元のデータが1バイトでも変更された場合、結果のハッシュも異なるものになります。 そのため、ある意味では安全な技術のように見えます。しかし、パスワードに使用する場合は、決して良い解決策ではありませんし、決してそうではありません。ここでの問題は、辞書からパスワードを生成し、そのパスワードからあらゆる種類のバリエーションを計算することができるということです。各パスワードに対してハッシュ値を計算することができます。これはすべて大規模なデータベースに保存することができます。ですから、パスワードになりそうなハッシュを見つけたときはいつでも、データベースの中のハッシュを調べてパスワードを見つけることができます。 いくつかのハッシュアルゴリズムは、もう使わない方がいいでしょう。MD5、SHA-1 これらのハッシュでは、ペイロードを変更しても同じハッシュが得られるようにすることができます。これには多くの計算能力が必要になりますが、それでも実現可能なオプションです。
ソルトハッシュ プレーンパスワードは、明らかにデータベースに保存されるべきではありません。そして、プレーンなハッシュについても同じことが言えます。OWASP Password Storage Cheat Sheet は、パスワードに関連する情報を安全に保存する必要がある場合に、何を使用すべきかを説明しています。 www.DeepL.com/Translator(無料版)で翻訳しました。
問題. 次の各ハッシュ値から導き出せるパスワードは何か。
E10ADC3949BA59ABBE56E057F20F883E
8F0E2F76E22B43E2855189877E7DC1E1E7D98C226C95DB247CD1D547928334A9
ヒント:ハッシュの長さからハッシュ関数の種類を推測する。
E10ADC3949BA59ABBE56E057F20F883E(32文字)→MD5
8F0E2F76E22B43E2855189877E7DC1E1E7D98C226C95DB247CD1D547928334A9(64文字)→sha256
MD5 Online | Free MD5 Decryption, MD5 Hash Decoder
→123456
https://sha256.web-max.ca/
→passw0rd
検索すると他にも多々デコードページはあるが、解析可否はそのサイトのレインボーテーブルに登録されているかどうかによる。
No.6 署名
署名とは、あるデータの妥当性を確認するために使用できるハッシュのことである。署名は、それが検証するデータとは別に提供することもできますし、CMSやSOAPの場合は同じファイルに含めることもできます。(ファイルの一部がデータを含み、一部が署名を含む場合)。
署名は、整合性が重要な場合に使用されます。これは、AからBに送信されたデータが変更されていないことを保証するためのものです。したがって、Aはデータのハッシュ値を計算し、そのハッシュ値を非対称秘密鍵を使って暗号化することでデータに署名します。次にBは、データのハッシュを計算し、署名を復号化することで、両方のハッシュが同じかどうかを比較することで、データを検証することができます。
RAW署名
生の署名は通常、以下のように計算されます。
データのハッシュを作成する (例:SHA-256 ハッシュ)
非対称秘密鍵を使ってハッシュを暗号化する (RSA 2048ビット鍵など)
(オプションで) base64 エンコーディングを使用して暗号化されたバイナリハッシュをエンコードします。
Bは公開鍵付きの証明書も取得しなければなりません。これは以前にも交換されているかもしれません。つまり、データ、署名、証明書の少なくとも3つのファイルが関係しているということです。
www.DeepL.com/Translator(無料版)で翻訳しました。
問題. ここで簡単な課題です。秘密のRSA鍵が送られてきます。RSA鍵のモジュラスを16進数の文字列として決定し、その鍵を使ってその16進数の署名を計算します。
以下の秘密鍵を持っているとします。
-----BEGIN PRIVATE KEY----- MIIEvAIBADANBgk(中略)Sc3LEI2xfo+x56VutL -----END PRIVATE KEY-----
公開鍵のモジュラスは何ですか?そして、そのモジュラスに基づいて署名を提供してください。
とりあえず何も入力せずに "post the answer" をクリックしてみる。
ヒント. opensslを使って、秘密鍵から公開鍵を取得します。どうやら秘密鍵と公開鍵の両方の情報が保存されているようです。
秘密鍵をコピペして private-key.pem という鍵ファイルを作成する。(鍵名は適当に) hoge@fuga:~$ cat private-key.pem -----BEGIN PRIVATE KEY----- MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCIITOeNuzsafFU/4u+KJR (中略) BZSe1N4icwGwtpzHg+UWYvXzyCapSCoDDmImbTR/aH5Q7VSpyM/uStK4XxyklDSabZcA== -----END PRIVATE KEY----- hoge@fuga:~$ openssl rsa -in private-key.pem -pubout -out public-key.pem writing RSA key hoge@fuga:~$ ls private-key.pem public-key.pem hoge@fuga:~$ cat public-key.pem -----BEGIN PUBLIC KEY----- MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAiCEznjbs7GnxVP+LviiU (中略) lQIBEQ== -----END PUBLIC KEY-----
- 次に公開鍵からモジュラスを取得する。
hoge@fuga:~$ openssl rsa -in public-key.pem -pubin -modulus -noout Modulus=8821339E36ECEC69F154FF8BBE2894758C067805D05CD4225EF26584C5891433331994792EC9D6DE8535981EED2CC68A978 (中略) 6A5DEA9C4530CD8FEBFB0BA0F172A3DF8083E8F9C68C52A80BA92ADC0D43B530769F15298D89B7E37F2C0053C295
表示されたモジュラスを回答欄にコピペする。
モジュラスは正解。次は署名欄。
先ほどのモジュラスをコピーして次のコマンドに入力する。
hoge@fuga:~$ echo -n "88C189B0626BD7C4CFEDB594F9E472E1ADD4EDE59468A70ED15C66B6F74FE0A3F9BDAF1601C0EBB7AB1057C6719EB4BB206E9A8EDAA6F3210FB7602F5CFF4E17A2CF5BFBEC9DDF813533F4DB3531DC9801E2C2CC104867E29AB0F7E4C520AAFB0332F54587FBFF28D9E708BB81BF22754E97165ED45710A17F6969EC99983C1BC5488E83C153581BC35FBF4E9BB0C7169604639114DA1D8CD64F8892D9FD890ACECB7A8E3DE341D3EE05568469B380630A71D80BB53D4C0410DB02A17CA7FF1E50CE43E2038D6E797A48044C99E0E528A552FB4B6DD23549B08944EE1E108834BDD2D4B71C1B61D11398B674D8C35A88F611B2EE11FFCBAF71BB7C966CC2823D" | openssl dgst -sign private-key.pem -sha256 -out sign.s ha256 hoge@fuga:~$ ls private-key.pem public-key.pem sign.sha256
sign.sha256 ができたがまだ答えではない。このままだと暗号化されているので読めない。
fuga@hoge:~$ cat sign.sha256 UFgҼ-Uo" (中略) +RM6$nD|jj8ru:eU5Ez J-f-|-v'7ss< 7Z{uĞ\%bǏi%&'H[5l
Base64エンコーディングを使用して暗号化されたバイナリハッシュをエンコードする必要がある。
hoge@fuga:~$ openssl enc -base64 -in sign.sha256 -out sign.sha256.base64 hoge@fuga:~$ ls private-key.pem public-key.pem sign.sha256 sign.sha256.base64 hoge@fuga:~$ cat sign.sha256.base64 VUZn1NK8LZCwtVVv2ejAItcKpI2k3HjpqpJ+PYcpEe71bRpgT9K1unz7BtLwZKGy (中略) jwDsaSUmJ0iBW881+mwTuw==
上記を回答欄にコピペする。
正解。
No.8
この演習では、docker コンテナイメージの中に誤って残された秘密を取得する必要があります。この秘密を使って、以下のメッセージを解読することができます。>U2Fsd(中略)D7as=. 実行中のコンテナ (docker exec ...) にログインし、/root にあるパスワードファイルにアクセスすることでメッセージを解読できます。その後、コンテナ内のopensslコマンドを使用します(Windows/Mac/Linux上でのopensslの移植性の問題のため)。 以下のdockerイメージの中に秘密を見つけることができます。
ヒント:dockerコンテナを起動した後、docker exec -ti dockerid /bin/bash を使ってコンテナに入ります。
PS D:\hoge> docker run -d webgoat/assignments:findthesecret
PS D:\hoge> docker exec -ti 8cd3XXX(CONTAINER ID) /bin/bash webgoat@8cd39XXXXXXX:/$ ls bin boot dev docker-java-home etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var webgoat@8cd39XXXXXXX:/$ cd /root/ bash: cd: /root/: Permission denied
root 権限がない。
WebGoat之路-1-Introduction & General | riChar
ファイルの名前はまだわかっていません。明らかにroot権限がsu必要ですが、パスワードは直接必要です。したがって、rootパスワードを変更する必要があります。
最初にdockerのbashを終了し sudo docker container cp [CONTAINER ID]:/etc/shadow ./ で shadowファイルをコピーします。
Linuxパスワードストレージのルールに従って、$id$salt$encrypted 私たちは自分でパスワードを生成することができます。そこで、Pythonでコードを書きました。
import crypto,random passwd=input("Please input your password: ") salt="$6$"+"".join(random.sample('1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM',16)) print(crypt.crypt(str(passwd),salt))ルート行の最初の2つのコロンの間に出力文字列を書き込み(元の * を置き換えます)、保存します。sudo docker container cp ./shadow [CONTAINER ID]:/etc/shadow 変更した shadow ファイルを書き込みます。
もう一度 sudo docker exec -ti [CONTAINER ID] /bin/bash 接続を使用し、su 設定したパスワードを入力すると、root 権限が付与されます。ls /root default_secret というファイルがあります。docker の bash から抜けます。
sudo docker container cp [CONTAINER]:/root/default_secret ./ でコピーします。- タイトルの要件に従って入力した後、
echo "U2Fsd(中略)pD7as=" | openssl enc -aes-256-cbc -d -a -kfile default_secret
復号化は成功します。- 最終的な答えは Leaving passwords in docker images is not so secure と default_secret です。
PS D:\hoge> docker container cp 8cd3925cd393:/etc/shadow ./ PS D:\hoge> ls ディレクトリ: D:\hoge Mode LastWriteTime Length Name ---- ------------- ------ ---- (前略) -a---- 2019/11/21 16:32 530 shadow (後略) PS D:\hoge> python.exe .\hoge.py Traceback (most recent call last): File "C:\Users\XXXXX\AppData\Local\Programs\Python\Python38\lib\crypt.py", line 6, inimport _crypt ModuleNotFoundError: No module named '_crypt' During handling of the above exception, another exception occurred: Traceback (most recent call last): File ".\hoge.py", line 1, in import crypt,random File "C:\Users\XXXXX\AppData\Local\Programs\Python\Python38\lib\crypt.py", line 9, in raise ImportError("The crypt module is not supported on Windows") ImportError: The crypt module is not supported on Windows
ということで、WSL Ubuntu で。
shinkanaoka@FRGRH:~$ python hoge.py Command 'python' not found, did you mean: command 'python3' from deb python3 command 'python' from deb python-is-python3
はい。
shinkanaoka@FRGRH:~$ python3 hoge.py Please input your password: (ここで新しいパスワードを設定する) $6$6K(中略)Ww1O0.
Windowsに戻って
PS D:\hoge> docker container cp ./shadow 8cd3XXXXXXXX:/etc/shadow PS D:\hoge> docker exec -ti 8cd3925cd393 /bin/bash webgoat@8cd3925cd393:/$ su - Password: (さっきPythonで設定したパスワード) root@8cd3925cd393:~# ls /root/ default_secret root@8cd3925cd393:~# cat root/default_secret ThisIsMySecretPassw0rdF0rY0u root@8cd3925cd393:~# echo "U2Fsd(中略)pD7as=" | openssl enc -aes-256-cbc -d -a -kfile default_secret Leaving passwords in docker images is not so secure
答え:
default_secret
Leaving passwords in docker images is not so securer
最後に、dockerをオフにすることを忘れないでください。
sudo docker kill [名称]
スペースを節約するために、ミラーを削除してください。
sudo docker image rm webgoat/assignments:findthesecret --force
この質問は少し感じ始めます。要約すると、最終的な答えが言ったように、dockerにパスワードを残す必要はありません。外部ユーザーがdockerコンテナを操作するために使用できるコマンドは、root権限を持つことと同じです。中に保管されているものはそうではありませんそれは安全でなければなりません。