본문 바로가기

웹해킹/개념

SQL Injection 심화(Blind, Error based ...)

Blind SQL Injection

Blind SQL Injection은 일반적인 SQL Injection과 달리, 결과값을 정확히 확인할 수 없을 때 사용하는 기법입니다.

예를 들어서 다음 코드가 있다고 가정하겠습니다.

@app.route('/', methods=['GET'])
def index():
    uid = request.args.get('uid', '')
    nrows = 0

    if uid:
        cur = mysql.connection.cursor()
        nrows = cur.execute(f"SELECT * FROM users WHERE uid='{uid}';")

    return render_template_string(template, uid=uid, nrows=nrows)

 

위의 코드는 SQL 검사가 미흡해서 SQL Injection이 일어날 수 있는 코드입니다. 그러나, 결과 값을 보면, 다음과 같이 출력됩니다.

삽입된 구문을 실행했을 때 , 이 구문이 올바르게 수행된다는 것만 알려주고, 원래 진행했던 SQL Injection과는 달리 완전한 결과값을 출력하지 않습니다. 이처럼 완전한 결과값을 알려주지 않는 경우에 사용할 수 있는 기법이 Blind SQL Injection입니다.

 

위의 코드를 기준으로 설명하면, uid는 알고 있고 upw를 모르는 상황이기 때문에, 다음과 같이 하나하나 대조해가면서 확인해야 합니다.

만약 exists가 뜬다면, 이 구문이 정상적으로 실행이 완료되었다는 뜻이므로 upw의 2번째 글자의 아스키코드는 72가 됩니다. 이처럼 하나하나 알아내야 하므로, 브루트포스와 비슷한 방식으로 공격을 수행해야 합니다.

 

Error Based SQl Injection

Error Based SQL Injection은 SQL 구문을 삽입했을 때 에러 내용이 출력되는 경우에 사용할 수 있습니다. 예를 들어 아래와 같이 에러 화면이 출력되는 환경이 있다고 하겠습니다.

이렇게 에러 화면이 출력되게 되면, 사용하는 SQL DB 버전이 출력되는 취약점 뿐만 아니라 ExtractValue를 이용해서 SQL 구문을 실행시킬 수도 있게 됩니다. 예를 들어서 아래와 같이 구문을 입력하게 되면, 

1' and extractvalue(1, concat(0x3a, database()))--

 

ExtractValue를 실행하다가 에러가 발생하므로, concat 내부에 있는 database() 함수가 실행되게 됩니다. 그 결과를 확인해보면 다음과 같습니다.

users라는 database 이름이 유출된 것을 확인할 수 있습니다.