16-09-05

Write-upを読んだ

InternetWache CTF 2016 : Mess of Hash

require "digest/md5"

ans = "0e408306536730731920197920342119"

for i in 0..999999999 do
  s = Digest::MD5.hexdigest(
    Digest::MD5.hexdigest(i.to_s) + "SALT"
  )
  if s === ans
    puts "#{i} ---> #{s}"
    break
  end
end

と、結構時間がかかった。ちなみに、

<?php
$a = "0e408306536730731920197920342119";
$b = "0e123";    /* 0e~であれば何でもよい */
var_dump($a == $b);    /* bool(true) */
var_dump($a === $b);    /* bool(false) */
?>

となることが問題の趣旨。
ちなみに、アルファベット4文字以下の文字列で"0e"から始まるもの
を探してみた。

require "digest/md5"

astr = "abcdefghijklmnopqrstuvwxyz" +
  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
chars = astr.split ""
chars << " "

magic_hashes = []
chars.each do |a|
  chars.each do |b|
    chars.each do |c|
      chars.each do |d|
        candidate = [a, b, c, d].join
        if candidate.include? " "    # 3文字以下の候補を作るため
          candidate.gsub! " ", ""    # (4 - 半角空白の個数)文字の候補
        end
        if Digest::MD5.hexdigest(candidate).start_with?("0e")
          magic_hashes.push candidate
        end
      end
    end
  end
end
puts magic_hashes.inspect    # ["aapb", "aaqn", "aaPS", ...]
puts magic_hashes.length    # 30950

puts Digest::MD5.hexdigest("aapb")    # 0e5aec1844b1~
puts Digest::MD5.hexdigest("aaqn")    # 0e0768b0b14c~
puts Digest::MD5.hexdigest("aaPS")    # 0eba89dcae2fb~

PHP上での対策としては、まず"==="を使って比較すべき、ということになる。