ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Error Based SQLi / Blind SQLi [7주차]
    모의해킹스터디5기(feat.Normaltic) 2023. 12. 8. 23:57

     

    UNION SQLi와 비슷하지만 더 어려워졌다.

    오늘은 Error Based SQL Injection과 Blind SQL Injection에 대해 정리한다.


    Error Based SQLi

    이전 시간에 배운 UNION SQLi는 화면에 SQL문의 질의 결과가 출력될 때 사용할 수 있는 공격 기법이었다. 

    Error Based SQLi도 사용하기 위해 특정한 조건이 필요한데 바로 "화면에 에러메시지가 출력되는 경우" 이다.

    Error Based SQLi는 이 에러 메시지를 사용해 데이터를 추출한다.

     

     

     

     

    SQL 에러 / 로직 에러

    1. SQL 에러

    SQL 에러는 SQL 문법에 맞지 않아 나타나는 에러를 말한다. 예를 들어 ' 를 하나 빼먹었다던가 정해진 SELECT문의 형식을 따르지 않았다거나 해서 온전한 SQL문이 구성되지 않을 때의 에러를 뜻한다.

     

    이 SQL 에러를 사용할 수는 없다. 실행이 되지 않기 때문이다. 그 이유는 SQL문의 처리 과정에 있는데, DBMS는 SQL문을 입력받으면 먼저 SQL의 문법을 검사한다. 그리고 나서 문법적으로 통과가 되면 그 때 코드를 실행한다.

     

    애초에 코드가 실행되지 않은 상태에서 에러 메시지를 나타내는 것이기 때문에 SQL 에러로는 DB에서 어떤 데이터도 추출할 수 없다.

     

    2. 로직 에러

    반대로 로직 에러는 SQL 문법에는 맞지만 그 외의 논리적인 이유로 나타나는 에러를 말한다. 그 말은 일단 코드가 실행된다는 뜻이다. Error Based SQLi는 이 에러 메시지를 사용한다.

     

    로직 에러를 일으키는 방법은 DBMS의 종류마다 다르다. 우리는 MySQL에서 로직 에러를 일으키는

    extractvalue( 'xml글자', 'xml표현식' ) 함수를 사용한 방법을 알아보도록 하겠다.

     

     

     

     

    MySQL : extractvalue()

    여기서부터는 "아 이런 구문을 사용해서 에러를 일으키는 구나~" 하고 가볍게 넘어가는 편이 좋을 것 같다.

    중요한 것은 에러메시지로 데이터를 추출하는 것이니까.

     

    구문

    normaltic' and extractvalue('1', concat(0x3a, (select 'normaltic'))) and '1' = '1

     

    extractvalue()는 XML 파일에서 표현식에 맞는 데이터를 추출하는 함수이다. 표현식이 적절하지 않을 때 에러 메시지를 나타내는데 항상 에러 메시지를 나타내기 위해 콜론 : (아스키코드 0x3a)을 포함시킨다. 여기서 중요한 점은 표현식 안에 SQL 구문을 포함시킬 때, 에러메시지에 SQL 구문이 처리된 결과가 포함되어 나온다는 것이다. 

     

    결과

    XPATH syntax error ':normaltic'

     

    이제 위의 구문의 형식을 따르면서 원하는 SQL구문을 넣어 데이터를 추출하면 된다.

     

     

     

     

    Error Based SQLi의 과정

    UNION SQLi의 과정과 비슷하게 흘러가니 간단하게만 적어둔다.

     

    1. SQL Injection point 찾기

    • 로직 에러를 일으키는 곳

    2. 에러를 출력하는 함수 정하기

    • MySQL -> extractvalue()

    3. 공격 format 만들기

    • normaltic' and extractvalue('1', concat(0x3a, (___실행하고 싶은 SELECT문___))) and '1'='1

    4. DB 이름 출력

    • SELECT문 -> SELECT database()

    5. 테이블 이름 출력

    • SELECT문 -> SELECT table_name FROM information_schema.tables                                                                                                 WHERE table_schema='DB이름' LIMIT 0, 1
    • 에러메시지에는 SQL 결과 중 한 행만 보이니 LIMIT을 적절히 사용해야 한다.

    6. 컬럼 이름 출력

    • SELECT문 -> SELECT column_name FROM information_schema.columns                                                                                         WHERE table_name = '테이블이름' LIMIT 0, 1

    7. 원하는 정보 출력

    • SELECT문 -> SELECT 컬럼 FROM 테이블 LIMIT 0, 1

     

     

     


    Blind SQLi

    화면에 SQL문 결과가 출력되는 경우에는 UNION SQLi

    에러메시지가 출력되는 경우에는 Error Based SQLi

    그렇다면 아무것도 출력되지 않는 경우에는?

     

    이럴 때 Blind SQLi를 사용한다.

     

     

     

    원리

    Blind SQLi는 사실 어떤 곳에서든 사용할 수 있다. SQLi 계의 최후의 보루같은 느낌.

    대표적으로 로그인 페이지를 말할 수 있을 것 같다. 로그인 페이지에서 나오는 결과는 맞았거나 틀렸거나 둘 중 하나다.

    Blind SQLi는 이 참과 거짓의 응답 차이를 활용하는 기법이다.

     

    대충 원리를 말하자면

    "SELECT ~~ "의 결과의 첫번째 글자가 a 맞아? 하고 SQL문으로 물어보는 것이다.

     

    맞다고 하면 "존재하는 아이디입니다" 와 같이 참의 결과를 반환할 것이고,

    틀리면 "존재하지 않는 아이디입니다" 와 같이 거짓의 결과를 반환할 것이다.

    1. Blind SQLi 원리

     

    이런식으로 한 글자씩 정보를 추출하는 게 Blind SQLi 다.

     

     

     

    구문

    normaltic' and (ascii(substr((___SQL구문___), 1, 1)) > 0) and '1'='1

     

    모든 문자는 아스키코드의 숫자로 1대1 대응할 수 있는데 ascii() 함수가 문자를 아스키코드 숫자로 변환시키는 함수다. 이 함수로 그 글자를 판별할 수 있다.

     

    2. ascii 코드

     

    보통 글자를 찾을 때 ascii() > 90 으로 시작하는 이유가 대문자 A 65 이고, 소문자 z 122 라서 그 중간값부터 시작해

    점점 반씩 찾아가는 이진 탐색을 사용하는 게 가장 효율적이기 때문이다.

     

    substr(SQL구문, 시작 위치, 글자 개수) 함수를 사용해서 문자열을 한 글자씩 잘라낼 수 있다. SQL 구문에는 SQL의 처리 결과가 나오기 때문에 결과의 첫번째 글자부터 마지막 글자까지 하나씩 찾으면 된다.

    특이한 점은 substr()함수는 시작 위치가 0이 아닌 1부터 시작한다는 점이다. 1부터 시작해서 오류가 나기 전까지 번호를 올리면서 글자를 찾으면 된다. 오류가 난다는 것은 문자열의 길이를 벗어났다는 뜻이다. 

     

     

     

    Blind SQLi의 과정

    1. SQL Injection point 찾기

    • normaltic' and '1'='1 결과와 normaltic' and '1'='2 결과 확인
    • 무조건 참과 무조건 거짓의 결과가 다르게 나타나는 곳이어야 한다.

    2. SELECT문 사용이 가능한지 확인하기

    • normaltic' and ((select 'test')='test') and '1'='1

    3. 공격 format 만들기

    • normaltic' and (ascii(substr(___실행하고 싶은 SELECT문___), 1, 1)) > 90) and '1'='1
    • 1 ~ 오류 나기 전 숫자 -> SQL 결과의 길이
    • 아스키코드 숫자로 이진 탐색

    4. DB 이름 출력

    • SELECT문 -> SELECT database()

    5. 테이블 이름 출력

    • SELECT문 -> SELECT table_name FROM information_schema.tables                                                                                                 WHERE table_schema='DB이름' LIMIT 0, 1
    • substr()에도 SQL 결과 중 한 행만 들어가니 LIMIT을 적절히 사용해야 한다.

    6. 컬럼 이름 출력

    • SELECT문 -> SELECT column_name FROM information_schema.columns                                                                                         WHERE table_name = '테이블이름' LIMIT 0, 1

    7. 원하는 정보 출력

    • SELECT문 -> SELECT 컬럼 FROM 테이블 LIMIT 0, 1

    '모의해킹스터디5기(feat.Normaltic)' 카테고리의 다른 글

    XSS (Cross Site Scripting) [9주차]  (0) 2024.01.03
    SQL Injection 마무리 [8주차]  (0) 2023.12.19
    UNION SQL Injection [6주차]  (0) 2023.12.08
    SQL Injection [5주차]  (0) 2023.12.07
    Burp Suite [4주차]  (0) 2023.11.27
Designed by Tistory.