WebGaot 5 Crypto Basics

暗号文

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 のデコーダーを使う。

f:id:hirose-test:20210216224900j:plain

f:id:hirose-test:20210216225628j:plain

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 に入れてみる。

f:id:hirose-test:20210217232716j:plain

f:id:hirose-test:20210217232826j:plain

No.4 Plain Hashing

プレーンハッシュ ハッシュ化は暗号の一種であり、主に元のデータが変更されたかどうかを検出するために使用されます。ハッシュは元のデータから生成されます。これは不可逆的な暗号技術に基づいています。元のデータが1バイトでも変更された場合、結果のハッシュも異なるものになります。 そのため、ある意味では安全な技術のように見えます。しかし、パスワードに使用する場合は、決して良い解決策ではありませんし、決してそうではありません。ここでの問題は、辞書からパスワードを生成し、そのパスワードからあらゆる種類のバリエーションを計算することができるということです。各パスワードに対してハッシュ値を計算することができます。これはすべて大規模なデータベースに保存することができます。ですから、パスワードになりそうなハッシュを見つけたときはいつでも、データベースの中のハッシュを調べてパスワードを見つけることができます。 いくつかのハッシュアルゴリズムは、もう使わない方がいいでしょう。MD5SHA-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

検索すると他にも多々デコードページはあるが、解析可否はそのサイトのレインボーテーブルに登録されているかどうかによる。

f:id:hirose-test:20210217234849j:plain

No.6 署名

署名とは、あるデータの妥当性を確認するために使用できるハッシュのことである。署名は、それが検証するデータとは別に提供することもできますし、CMSSOAPの場合は同じファイルに含めることもできます。(ファイルの一部がデータを含み、一部が署名を含む場合)。

署名は、整合性が重要な場合に使用されます。これは、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" をクリックしてみる。

f:id:hirose-test:20210227124235j:plain

ヒント. opensslを使って、秘密鍵から公開鍵を取得します。どうやら秘密鍵と公開鍵の両方の情報が保存されているようです。

  1. 公開鍵のモジュラスを問われているが、秘密鍵しかないため、まずは秘密鍵から公開鍵を作成する。
秘密鍵をコピペして 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-----
  1. 次に公開鍵からモジュラスを取得する。
hoge@fuga:~$ openssl rsa -in public-key.pem -pubin -modulus -noout
Modulus=8821339E36ECEC69F154FF8BBE2894758C067805D05CD4225EF26584C5891433331994792EC9D6DE8535981EED2CC68A978
(中略)
6A5DEA9C4530CD8FEBFB0BA0F172A3DF8083E8F9C68C52A80BA92ADC0D43B530769F15298D89B7E37F2C0053C295

表示されたモジュラスを回答欄にコピペする。

f:id:hirose-test:20210227124643j:plain

モジュラスは正解。次は署名欄。
先ほどのモジュラスをコピーして次のコマンドに入力する。

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==

上記を回答欄にコピペする。 f:id:hirose-test:20210227154942j:plain 正解。

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パスワードを変更する必要があります。

  1. 最初にdockerのbashを終了し sudo docker container cp [CONTAINER ID]:/etc/shadow ./ で shadowファイルをコピーします。

  2. 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つのコロンの間に出力文字列を書き込み(元の * を置き換えます)、保存します。

  3. sudo docker container cp ./shadow [CONTAINER ID]:/etc/shadow 変更した shadow ファイルを書き込みます。
    もう一度 sudo docker exec -ti [CONTAINER ID] /bin/bash 接続を使用し、su 設定したパスワードを入力すると、root 権限が付与されます。

  4. ls /root default_secret というファイルがあります。docker の bash から抜けます。
    sudo docker container cp [CONTAINER]:/root/default_secret ./ でコピーします。

  5. タイトルの要件に従って入力した後、
    echo "U2Fsd(中略)pD7as=" | openssl enc -aes-256-cbc -d -a -kfile default_secret
    復号化は成功します。
  6. 最終的な答えは 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, in 
    import _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

f:id:hirose-test:20210227205246j:plain

最後に、dockerをオフにすることを忘れないでください。
sudo docker kill [名称]
スペースを節約するために、ミラーを削除してください。
sudo docker image rm webgoat/assignments:findthesecret --force
この質問は少し感じ始めます。要約すると、最終的な答えが言ったように、dockerにパスワードを残す必要はありません。外部ユーザーがdockerコンテナを操作するために使用できるコマンドは、root権限を持つことと同じです。中に保管されているものはそうではありませんそれは安全でなければなりません。

*1:データを64種類の印字可能な英数字のみを用いて、それ以外の文字を扱うことの出来ない通信環境にてマルチバイト文字やバイナリデータを扱うためのエンコード --WikiPedia

/* -----codeの行番号----- */