상세 컨텐츠

본문 제목

Step3. SQL인젝션 공격

화이트 해커를 위한 웹 해킹의 기술

by 메리_99 2021. 2. 23. 13:01

본문

반응형

Step3. SQL 인젝션 공격

SQL 인젝션 공격

  • 오랜 시간 계속해서 가장 심각한 리스크로 선정된 인젝션 리스크의 대표적인 공격이며, 웹 사이트의 회원 정보 등 개인 정보를 탈취하고자 오래전부터 지속적으로 사용되어온 공격이다.

SQL 인젝션 공격 개요

  • SQL 인젝션 취약점은 웹 서버 영역의 데이터베이스로 전송되는 SQL 쿼리문을 사용자가 임의로 조작할 수 있는 경우 발생한다.

  • 공격자는 이 취약점을 이용하여 데이터베이스에 저장되어 있는 다른 사용자의 개인정보 등 허가되지 않은 정보에 접근하거나 데이터를 변조할 수 있다.

사례

  • 사용자는 ID가 1인 사용자 정보를 요청할 때, 이 요청을 받은 웹 애플리케이션은 내부의 데이터베이스로 다음과 같은 SQL 쿼리문을 전송한다. SELECT name, email FROM users WHERE ID='1'

  • 이는 users라는 사용자 테이블에서 ID가 1인 사용자의 이름과 이메일을 가져오는 쿼리문이다.

  • 이때, SQL 쿼리문을 구성하는 웹 애플리케이션의 소스코드가

    • $id = $_REQUEST[   'id'   ];

    • $query = "SELECT name, email FROM users WHERE id = '$id';";

  • 일 때, 사용자가 입력한 ID 파라미터의 값($id)이 쿼리문의 일부로 사용되고 있는데, 이런 경우 SQL 인젝션 취약점이 존재한다.

방법

  1. WHERE 구문 우회

    • 원래의 ID 값 1 대신 SQL 쿼리문을 직접 조작하기 위해 1' or '1'='1을 입력한다.

    • 입력 값이 SQL 쿼리문에 그대로 삽입된다면 쿼리문은 SELECT name, email FROM users WHERE id = '1' or '1'='1'이 되며, 이 결과 값은 ID가 1인 데이터뿐만 아니라 다른 데이터에 있어서도 모두 참의 결과를 갖기 때문에 모든 사용자의 이름과 이메일이 공격자에 전달된다.

  2. UNION 공격

    • 공격자는 or을 이용한 구문 대신에 UNION 키워드를 사입하고 그 뒤에 사용자 이름과 패스워드를 요청하는 SELECT 구문을 삽입한다.

    • SELECT name, email FROM users WHERE ID = '1' UNION SELECT name, pw FROM users#'

    • UNION은 합집합으로 두 개의 SELECT 구문의 결과를 모두 포함시키는 키워드이다.

    • 이렇게 되면 뒤의 SELECT 구문에는 WHERE가 없기 때문에 users 테이블에 존재하는 사용자 이름과 비밀번호도 같이 결과로 반환된다.

    • 추가로 코드의 마지막 부분에 있는 #은 뒤에 오는 내용을 주석 처리하여, 혹시 그 뒤에 있을지 모르는 다른 SQL 쿼리문이 공격자가 원하지 않는 명령문이 실행되거나 SQL 형식 에러가 발생하지 않도록 만들어 준다.

SQL 인젝션 공격 실습

WHERE 구문 우회 실습

1을 입력했을 때 정상적인 폼 처리

  • 이때, SQL 인젝션 공격에 취약한지 테스트해볼 수 있는 방법 중 가장 기본적인 방법은 '를 입력해보는 것이다.

'를 입력했을 때 SQL 형식 에러

  • 이렇게 뜨는 이유는 SQL 쿼리문이 SELECT name, email FROM users WHERE id=''';이 되기 때문이다(systax error)

  • 그러면 입력이 SQL 쿼리문에 영향을 줄 수 있다는 뜻이고, SQL 인젝션 공격 성공 가능성이 매우 높다.

1' or '1'='1을 입력 했을 때

  • 위와 같이 입력하면 WHERE 조건문이 항상 '참'의 결과를 가져오면서 모든 사용자의 정보가 출력된다.

ORDER BY 및 UNION 실습

  • UNION은 합집합이기 때문에 UNION을 사용하기 위해서는 원래의 SQL 쿼리문이 조회하는 SELECT 문의 칼럼 개수와 UNION 뒤의 SELECT 문에서 요청하는 칼럼 개수가 같아야만 한다.

  • 따라서 원래의 SQL 쿼리문이 몇 개의 칼럼을 반환하는지 알아내야 한다.

  • 칼럼 개수는 ORDER BY 구문으로 알아낼 수 있다.

    • ORDER BY : 지정된 칼럼을 기준으로 결과를 정렬할 때 사용하는 키워드

    • ex) ORDER BY 1 : 첫 번째 칼럼을 기준으로 정렬, ORDER BY 2 : 두 번째 칼럼을 기준으로 정렬

    • 이 때, 전체 칼럼 개수보다 큰 값을 입력하면 정렬을 할 수 없기에 에러를 발생시킨다.

    • 에러가 발생하기 직전의 값이 칼럼의 개수가 된다.

정상적인 출력
에러 발생

  • 여기서 봤을 때, 칼럼 개수 : 2

  • 이후 UNION SELECT1,2와 같이 일련의 번호를 사용 하여 어떤 칼럼의 정보가 웹 페이지의 어느 위치에 나타나는지 확인한다.

1번째 칼럼의 정보 : First name, 2번째 칼럼의 정보 : Surname임을 알 수 있다.

  • 웹 애플리케이션이 어떻게 구현되어 있느냐에 따라 칼럼의 정보가 모두 웹 페이지에 표시되는 것이 아니기 때문에 어떤 칼럼이 웹 페이지에 출력되는지도 이 방법을 이용하여 확인할 수 있다.

  • MySQL 데이터베이스는 information_schema라는 데이터베이스에서 데이터베이스 이름, 테이블, 칼럼 정보 등을 관리한다. -> 여기서 DB 이름 흭득

DB 이름 흭득(추가로 dvwa외에도 다른 데이터 베이스의 존재도 알 수 있음)

  • 추가로 dvwa 데이터베이스의 테이블 목록을 알아낸다.

dvwa의 테이블 확인

  • 확인 후 users 테이블에 데이터를 확인한다.

칼럼 목록 출력

  • 이어서 password 칼럼 내용을 확인해 본다.

password 칼럼

  • 여기서 패스워드는 평문이 아닌 해시의 값의 형태로 저장되어 있는데, 이는 쉽게 크래킹 될 수 있다.

크래킹된 해쉬값

  • 위와 같이 admin의 패스워드는 password임을 알 수 있다.

블라인드 SQL 인젝션 공격

SQL 인젝션 공격 파악 여부를 위해 '를 입력했을 때 뜨는 화면

  • 블라인드의 경우 단지 사용자의 존재 유무만 알려주는 메시지로 나타나기 때문에, 쉽게 정보를 빼내기도 어렵다.

  • 이와 같은 상황에서는 일반적인 SQL 인젝션 공격을 시도해 볼 수 없다.

AND 연산자를 통하여 이하 구문이 실행되는 지를 확인(1' AND 1=2#)

  • 위와 같이 AND이하 구문이 실행된다면 블라인드 SQL 인젝션 취약점을 의심해 볼 수 있다.

  • 위와 같이 응답 메시지가 달라지는 경우도 있지만, 어떤 경우에는 웹 사이트에 출력되는 메시지조차 같은 경우도 있다. 이 때는 웹 요청이 응답되는 시간의 차이를 이용하여 참과 거짓을 구별해내는 방법을 시도해 볼 수 있다. 1' AND SLEEP(5)#

  • 이와 같이 결과를 직접적으로 알 수는 없어도, 참과 거짓일 때의 결과 차이를 분석하여 어떤 정보를 알아내는 기법을 블라인드 SQL 인젝션 공격이라고 한다.

  • 다만 블라인드 SQL 인젝션 공격은 일일이 쿼리문을 만들고 실행해야 하기 때문에 시간이 많이 걸린다. 따라서 자동화 프로그램을 많이 사용한다.(일반 SQL 인젝션 공격도 자동화 프로그램으로 공격이 가능)

sqlmap 자동화 공격

  • -sqlmap -h : 옵션들을 볼 수 있다.

SQL 인젝션 취약 여부를 알아내고자 할 때 사용하는 옵션

  • -u : 필수 옵션으로 공격을 시도할 URL을 지정한다.

  • --cookie : 로그인이 필요한 경우, 로그인하고 난 다음 발급된 세션 쿠키 값을 지정한다.

  • --data : POST 요청의 폼을 공격하고자 할 때, 바디로 전달되는 데이터를 지정한다.

  • -p : 테스트할 파라미터를 지정한다.

  • --dbms : 데이터베이스의 종류를 알고 있는 경우 지정한다.(ex.mysql)

SQL 인젝션 공격이 가능한 경우 데이터를 입수할 때 사용하는 옵션

  • --current-db : 현재 데이터베이스의 이름을 알아낸다.

  • -D : 데이터를 입수할 데이터베이스를 지정한다.

  • -T : 데이터를 입수할 테이블 이름을 지정한다.

  • -C : 데이터를 입수할 칼럼을 지정한다.

  • --tables : 데이터베이스의 테이블들을 알아낸다. 주로 -D 옵션과 같이 사용한다.

  • --cuolumns : 데이터베이스의 칼럼들을 알아낸다. 주로 -D, -T 옵션과 같이 사용한다.

  • --dump : 데이터베이스의 정보들을 알아낸다.

실습

  • sqlmap 프로그램을 사용하기 위해 필요한 필수 옵션은 -u URL 정보이다.

    • DVWA처럼 로그인된 페이지에 SQL 인젝션 공격을 시도하는 경우에는 쿠키 정보도 필요하다.

URL과 개발자 도구의 document.cookie 명령어를 통해 쿠키 값을 확인

  • sqlmap을 열어 취약점을 분석한다.

-u와 --cookie옵션을 주어 취약점을 분석

  • 위의 내용에서 중요한 정보는 눈에 띄게 표시된다.

  • 표시된 내용에서 취약점, 버전 정보 등을 알 수 있다.

  • --current-db 옵션을 줘서 현재 데이터베이스의 정보를 알아낸다.

데이터베이스 이름이 dvwa임을 알 수 있다.

 

  • -D dvwa -tables 옵션을 줘서 데이터베이스의 테이블 정보를 알아낸다.

dvwa데이터베이스의 테이블들을 확인

  • -D dvwa -T users -dump 옵션을 통해 users테이블의 정보를 본다.

사용자 테이블 정보

SQL 인젝션 공격 대응

  • SQL 인젝션 공격과 같은 모든 파라미터 입력값 조작으로 이루어지는 공격은 입력값 검증을 통해 대응

  • 화이트리스트 검증을 하는 것이 좋다.

  • 사용자가 입력한 값은 SQL 쿼리문에서 오직 데이터로만 사용되어야지 SQL 쿼리문의 구조에 영향을 줄 수 없도록 해야 한다.

impossible 모드의 소스코드

 

  • 이럴 경우 prepare() 부분에서 미리 실행할 쿼리문의 형태를 작성(prepared statement)해두고 있기 때문에, 그리고 사용자 입력값이 들어갈 id부분은 bindParam()에서 설정했기 때문에 사용자가 입력한 값이 쿼리문의 일부가 될 수 없고, 온전히 데이터로만 처리되기 때문에 or나 UNION등과 같은 키워드가 입력되어도 무의미한 문자열이 된다.

  • 결과적으로 사용자가 SQL 쿼리문을 조작할 방법이 없어 SQL 인젝션 공격을 효과적으로 방지할 수 있다.


위 글은 '화이트 해커를 위한 웹 해킹의 기술 최봉환 저'를 공부하며 작성한 글입니다.
728x90

관련글 더보기

댓글 영역