AIDEMOIRE

【アイデモワール】

オートコンプリートに使うURLのハッシュ値を計算する方法

Internet Exploreのパスワードのオートコンプリート機能を使っていて、うっかり“いいえ”を押してしまい、そのページに関してパスワードを記憶できなくなった場合の対処方法です。

追記(2013/10/22):以下の方法はWindows 8では正しいHash値を計算できませんでした。どうもWindows 8から計算方法が変わったのかと思われます。とりあえず、Windows 7での方法ということで。

そのURL(ページ)を記憶対象とするかどうか、またそのユーザ名とパスワードの情報はWindows 7ではレジストリの次の場所に格納されています。

HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\IntelliForms\Storage1
または
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\IntelliForms\Storage2

(Strage1は“フィールド”のオートコンプリートで値を保持するため、Strage2は“パスワード”のオートコンプリートで値を保持するために使われていると思われます。)

この“キー(Storage1/2)”にURLをハッシュ(数値化)したものが“値”として保存されます。またその”値”の“データ”には、オートコンプリートの対象とするかどうか、また暗号化されたユーザ名やパスワードが格納されているようです。つまり、ここにはオートコンプリートの対象、非対象に関わらず、IEの問合せに対して“はい”または“いいえ”に答えたすべてのURLが暗号化されていますので、オートコンプリートを使っている場合には結構な数の“値”が並んでいます。間違って消してしまうと、他のURLのユーザ名/パスワードを消去してしまうことになるので、目的のURLの値を識別して、それだけを削除しなければなりません。

問題はその識別の方法です。ネットで探してもすと、①怪しいツールを使う、②一旦レジストリを保存してから消去して、対象URLを再登録して識別し、保存してあるデータを元に戻してから削除する、③プログラムをコンパイルして使う、などでした。①は余りやりたくありませんし、②ば面倒です。③は開発環境を持っていないとできません。

一番うれしいのはコマンドラインでURLのハッシュ値を計算できることなのですが、その方法は見つかりませんでした。そこで、その方法を作っちゃいました。

Power Shellを起動して次のコマンドを実行してください。(コピペするときは最初行のURLの部分を適宜、変更してください。)
PowerShell

$url = "https://www.hatena.ne.jp/login"
$url16 = [System.Text.Encoding]::GetEncoding("UTF-16").GetBytes($url + "`0")
$sha1 = [System.Security.Cryptography.SHA1]::Create()
$hash = $sha1.ComputeHash($url16)
$hs = "" ; $cs = 0
$hash | %{ $hs += $_.ToString("x2") ; $cs += $_ }
($hs + ($cs % 256).ToString("x2")).ToUpper()

URLのハッシュ値を求めるミソはURLをUTF-16で表現し、さらに文字列の最後にNULLコードを入れることです。これを実行すると、“はてな”のログインページのURLは次のハッシュ値であることが判ります。

07105037DDFCEBEE689E29F99C0C76696B23F75FE3

ここで、求めた文字列と同じ“値”の項目を削除すればOKです。指定するURLは全て英小文字でパラメータ(“?”以降)を削除した形で入力します。なお、項目を削除するとそのURLで以前覚えていたパスワードも無くなります、念のため。

ちなみにですが、私は余りPowerShellは使わないので、上の短いプログラムを作るまでに色々と調べながら3時間位かかってしまいました。Linuxbashであれば15分位で出来たのですが。
Bourne-Again Shell版

#!/bin/bash

URL="https://www.hatena.ne.jp/login"

if [ X"$1" != "X" ] ; then URL="$1" ; fi
URL_HASH=`echo -n "$URL" | ( nkf -w16L0 ; echo -n -e '\x00\x00' ) | openssl SHA1 -r | cut -d ' ' -f1`
SUM=`echo -n "$URL" | ( nkf -w16L0 ; echo -n -e '\x00\x00' ) | openssl SHA1 -binary |  sum -s | cut -d ' ' -f1`
SUM=`expr $SUM \% 256`
HEX="0123456789abcdef"
CS=${HEX:`expr $SUM / 16`:1}${HEX:`expr $SUM \% 16`:1}
echo ${URL_HASH}${CS} | tr "a-f" "A-F"

(ASCIIとUnicodeの変換にnkfというオプション パッケージを使っています。)
何でWindowsのハッシュを調べるのにLinuxのコマンド作るの?と思われる方もいるかと思いますが、実は最初はbash版を作りました。私はUNIX系の方が得なので。個人的にはbashのプログラムを作って終了!だったのですが、WebにメモるのであればやっぱりCMDかPowerShellで作らないと申し訳ないかなと思ってPowerShell版を作った次第です。折角、参考にしてもらってもLinuxの環境がないと計算できないのでは「使えねぇ~」ってことになってしまいますから。:-p

■ 改めてオートコンプリートは使うべきではありませんね

今回、オートコンプリートの復活方法を調べていて分かったのですが、パスワードのオートコンプリートって≫本当に≪危険な機能なのですね。

ユーザ名/パスワードの本体もURLを暗号キーとして暗号化されています。従って、URLが分かってしまうとユーザ名/パスワードも解けてしまいます。URLはSHA1でハッシュされていますが、次の理由で大変解読しやすいです。

  1. IEにはURLの履歴がのこるので、アクセスするURLを容易に推測できる
  2. ハッシュ値がどのPCでも全く同じになってしまう。

オートコンプリートを使う場合は、ほぼURLの履歴も使っている筈です。履歴に残っているURLを上のようなプログラムに入力すればハッシュ値が求めることができ、それをレジストリと比較すれば登録しているURLが分かってしまいます。あとは、そのURLを使ってパスワードを復元するだけです。

2については、例えば“はてなのログインページ”のURLはどのPCでも 07105037DDFCEBEE689E29F99C0C76696B23F75FE3 として保存されています。だから、有名なサイトのログインページであれば、たとえIEで履歴を残していなくても使っているかどうかは直ぐ分ってしまいます。予め一覧を作っておけば計算する必要もないわけです。

例えば、次の様なプログラムがあります。

これらは“パスワードと忘れてた場合にパスワードを復元する”便利なツールなのですが、つまりはパスワード解読ツールなので正義の味方か悪の手先になるかは使う人次第でしょう。二つ目のページは単にツールを提供するだけでなく、パスワードの解読方法のプログラムも解説しています。(なお、これらのツールを使う場合は、もちろん自己責任で。どんな危険性があるかは各自で判断してください。)

と、なんやかんや書きましたが、やっぱりパスワードのオートコンプリートは便利なので私も使っています。でも、次のように限定しています。

  • 安全を確保した特定のPCだけでつかう
  • 漏えいしてしまうことを前提として、影響の少ないサイトに限って使う。(例えば銀行などには絶対に使わない。)
  • 盗難の可能性があるノートPCでは絶対に使わない。(URLの履歴やクッキーも禁止。)

明日、はてなブログが乗っ取られていたらどうしよう!?

■ 参考ページ

PowerShellで改行コードのない文字列データを生成する方法
How to output text without newline in Powershell? - Stack Overflow

PowerShellSHA1を算出する方法
PowerShell でファイルのハッシュ値を計算する | Operations Lab.

WindowsのコマンドでASCIIをUnicodeに変換する方法
Batch files - The TYPE command

WindowsのコマンドでSHA1を算出する方法
Availability and description of the File Checksum Integrity Verifier utility