あなたのLinuxパスワードは安全ですか?

これは 2023/08/08 の MK 社内 LT で発表した内容です。

ユーザーアカウント情報の保存場所

  • /etc/passwd
  • /etc/shadow

/etc/passwd

root:x:0:0:root:/root:/bin/bash
...
cliff:x:1000:1000:cliff:/home/cliff:/bin/bash
...
  • ユーザーネーム:パスワード情報:UID:GID:GECOSフィールド:ホームパス:実行プログラム
  • パスワード情報
    • ”x”は実際のパスワードが/etc/shadowにあるという意味
  • GECOS フィールド
    • フルネーム
    • 電話番号
    • などなど
  • 実行プログラム
    • ログインするたびに起動するプログラム
    • 通常はシステムのコマンドラインインタープリター(シェル)

/etc/shadow

root:*:19405:0:99999:7:::
...
cliff:$6$iB6z.Wi1AdARgNKi$VyBMc4pjbFtTbLQluqxSNUJZ0TGbD6VJHN8GYXHs06TP/xzCXxWT19tBHvRxUcF4N4nZsZXgmyVkQSOEVlkqV.:19472:0:99999:7:::
...
  • ユーザーネーム:$ハッシュタイプID$ソルト$暗号化パスワード(パスワードのハッシュ値)...(下略)
  • 詳細説明:man shadow
  • ユーザーネーム:cliff
  • $ハッシュタイプ ID:6
    • 1:MD5
    • 5:SHA-256
    • 6:SHA-512
    • y: Blowfish
  • $ソルト:iB6z.Wi1AdARgNKi
  • $暗号化パスワード: VyBMc4pjbFtTbLQluqxSNUJZ0TGbD6VJHN8GYXHs06TP/xzCXxWT19tBHvRxUcF4N4nZsZXgmyVkQSOEVlkqV.
  • フル認証情報: $6$iB6z.Wi1AdARgNKi$VyBMc4pjbFtTbLQluqxSNUJZ0TGbD6VJHN8GYXHs06TP/xzCXxWT19tBHvRxUcF4N4nZsZXgmyVkQSOEVlkqV.

ログインプロセスをシミュレートする

#!/usr/bin/env python3

import crypt
import getpass

# Configuration
RETRY_LIMIT = 3

# Data in /etc/passwd and /etc/shadow
USER_NAME = "cliff"
HASH_TYPE_ID = "6"  # SHA-512
SALT = "iB6z.Wi1AdARgNKi"
ENCRYPTED_PASSWORD = "VyBMc4pjbFtTbLQluqxSNUJZ0TGbD6VJHN8GYXHs06TP/xzCXxWT19tBHvRxUcF4N4nZsZXgmyVkQSOEVlkqV."

# Input user name
user = input("login as: ")
salt = ""
auth = ""
if user == USER_NAME:
    # `salt` may be one of the `crypt.METHOD_*` values, or a string as returned by `crypt.mksalt()`
    salt = f"${HASH_TYPE_ID}${SALT}"
    auth = f"{salt}${ENCRYPTED_PASSWORD}"
print(f"[Debug] {auth}")

# Authentication
for i in range(RETRY_LIMIT):
    # Input password
    password = getpass.getpass(f"{user}'s password: ")
    result = crypt.crypt(password, salt)
    print(f"[Debug] {result}")
    if result == auth:
        print("Access granted")
        break
    else:
        print("Access denied")

パスワードが一致しない場合

$ python3 main.py
login as: cliff
[Debug] $6$iB6z.Wi1AdARgNKi$VyBMc4pjbFtTbLQluqxSNUJZ0TGbD6VJHN8GYXHs06TP/xzCXxWT19tBHvRxUcF4N4nZsZXgmyVkQSOEVlkqV.
cliff's password:
[Debug] $6$iB6z.Wi1AdARgNKi$WvxgfTbOQcyiAcxYjztYYNpirA06Q5Bb0bwNbxlHtk88yGdusaz6ndH9HuDnZMiboInJ4BLcLzQ4nOKwbK1Gb1
Access denied

パスワードが一致する場合

$ python3 main.py
login as: cliff
[Debug] $6$iB6z.Wi1AdARgNKi$VyBMc4pjbFtTbLQluqxSNUJZ0TGbD6VJHN8GYXHs06TP/xzCXxWT19tBHvRxUcF4N4nZsZXgmyVkQSOEVlkqV.
cliff's password:
[Debug] $6$iB6z.Wi1AdARgNKi$VyBMc4pjbFtTbLQluqxSNUJZ0TGbD6VJHN8GYXHs06TP/xzCXxWT19tBHvRxUcF4N4nZsZXgmyVkQSOEVlkqV.
Access granted

つまり

  • 計算を継続的に試みるだけで、パスワードを解読することができるじゃないか!
  • 実際のところ、有限の時間とリソース内では不可能だ

なのに

  • 計算を継続的に試みるためのツールが存在している

John the Ripper

build
  • wget https://www.openwall.com/john/k/john-1.9.0.tar.xz -O john-1.9.0.tar.xz
  • tar -xvf john-1.9.0.tar.xz
  • cd john-1.9.0/src
  • make clean linux-arm64le
unshadow
  • cd ../run
  • sudo ./unshadow /etc/passwd /etc/shadow >unshadowed.txt
  • cat unshadowed.txt
cliff:$6$iB6z.Wi1AdARgNKi$VyBMc4pjbFtTbLQluqxSNUJZ0TGbD6VJHN8GYXHs06TP/xzCXxWT19tBHvRxUcF4N4nZsZXgmyVkQSOEVlkqV.:1000:1000:cliff:/home/cliff:/bin/bash
john
  • ./john --incremental unshadowed.txt
  • なんと一瞬で解読できた!
result
  • cat john.pot
$6$iB6z.Wi1AdARgNKi$VyBMc4pjbFtTbLQluqxSNUJZ0TGbD6VJHN8GYXHs06TP/xzCXxWT19tBHvRxUcF4N4nZsZXgmyVkQSOEVlkqV.:cliff
  • なぜ一瞬で解読できたか?
  • 辞書攻撃(ズル)をしているからだ
  • 元々本来のパスワードは不安全だった
解読中の画面
$ ./john --incremental unshadowed.txt
Loaded 2 password hashes with 2 different salts (crypt, generic crypt(3) [?/64])
Remaining 1 password hash
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:03:20 0g/s 651.3p/s 651.3c/s 651.3C/s abasan..abusil
0g 0:00:03:23 0g/s 651.4p/s 651.4c/s 651.4C/s budy33..buta15
0g 0:00:03:24 0g/s 651.5p/s 651.5c/s 651.5C/s jamus1..jasien
0g 0:00:03:25 0g/s 651.6p/s 651.6c/s 651.6C/s jenjie..jetrid
0g 0:00:03:26 0g/s 651.7p/s 651.7c/s 651.7C/s jine08..jilshe
0g 0:00:03:27 0g/s 651.8p/s 651.8c/s 651.8C/s davya..darli
0g 0:00:03:28 0g/s 651.9p/s 651.9c/s 651.9C/s didie..dearl
0g 0:00:03:39 0g/s 652.5p/s 652.5c/s 652.5C/s memomo..mexy36
0g 0:00:03:40 0g/s 652.6p/s 652.6c/s 652.6C/s mufl21..mumomb
0g 0:00:04:13 0g/s 655.1p/s 655.1c/s 655.1C/s cattene..coralia
0g 0:00:04:14 0g/s 655.1p/s 655.1c/s 655.1C/s andyah3..aleshon
0g 0:00:04:15 0g/s 655.2p/s 655.2c/s 655.2C/s armale1..araggy2

結論

  • 不安全なパスワードを使用すると、簡単に解読される
  • 安全なパスワードを使用してください
この記事をシェア

弊社では、一緒に会社を面白くしてくれる仲間を募集しています。
お気軽にお問い合わせください!