SQL 인젝션 취약점은 웹 서버 영역의 데이터베이스로 전송되는 SQL 쿼리문을 사용자가 임의로 조작할 수 있는 경우 발생한다. 공격자는 이 취약점을 이용하여 데이더베이스에 저장되어 있는 다른 사용자의 개인정보 등 허가되지 않은 정보에 접근하거나 데이터를 변조할 수 있다.
WHERE 구문 우회
1을 입력하면 ID가 1인 사용자의 정보가 출력된다. ID가 1인 사용자로 admin 사용자가 출력되었다.
1' or '1'='1 를 입력해 보면 admin 사용자 외에도 다른 사용자의 정보가 같이 출력된다. SQL 쿼리문이 조작되어 WHERE 조건문이 '1' or '1'='1' 과 같이 항상 참이 되는 조건문이 됨으로써 모든 사용자의 정보가 출력된 것이다.
ORDER BY 및 UNION 공격
UNION은 합집합이기 때문에 UNION을 사용하기 위해서는 원래의 SQL 쿼리문이 조회하는 SELECT 문의 칼럼 개수와 UNION 두의 SELECT 문에서 요청하는 칼럼개수가 같아야만 한다. UNION 공격을 성공시키기 위해서는 먼저 원래의 SQL 쿼리문이 몇 개의 칼럼을 반환하는지 알아내야 한다.
ORDER BY 뒤의 숫자를 증가시켜 가다가 에러가 발생하면 그 전 값이 칼럼의 개수가 된다.
UNION SELECT 1, 2와 같이 일련의 번호를 사용하여 어떤 칼럼의 정보가 웹 페이지의 어느 위치에 나타나는지 확인할 수 있다.
Mysql 데이터베이스는 information_schema라는 데이터베이스에서 데이터베이스 이름, 테이블, 칼럼 정보 등을 관리하고 있다. information_schema의 schemata 테이블로부터 schema_name을 가져오는 SQL 쿼리문을 이용하면 데이터베이스 이름을 알아낼 수 있다.
데이터베이스의 이름이 모두 First name 뒤에 출력되고 있다. DVWA에서 사용하는 데이터베이스의 이름은 dvwa임을 추측할 수 있다. 또한 DVWA 외에도 drupageddon, bWAPP 등 다른 데이터베이스의 존재도 알 수 있다.
table_schema가 dvwa인지를 확인하는 조건을 주어 dvwa 데이터베이스의 테이블만 출력시킨다.
guestbook과 users라는 테이블이 출력되었다. 이번에는 users 테이블의 칼럼 목록을 알아내본다.
출력된 칼럼 중에서 user와 password 칼럼의 내용을 확인해본다.
admin 사용자의 패스워드 해시를 복원한 값이 password임을 알려주고 있다.
블라인드 SQL 인젝션 공격
사용자 ID 입력란에 1을 입력하니 단지 사용자가 데이터베이스에 존재한다는 메시지만 표시된다.
'를 입력하면 SQL 해당 사용자 ID가 데이터베이스에 없다는 메시지가 출력된다.
And 1=1#을 추가로 입력하면 WHERE user_id = '1' AND 1=1과 같이 전체가 참인 조건문이 되어 사용자가 존재한다고 출력된 것이고, AND 1=2를 입력하면 WHERE 구문이 거짓이 되어 사용자가 없다고 출력된 것이다. AND 연산을 이용하여 입력값을 보낼 때 연산에 따라 결과가 달라진다면 블라인드 SQL 인젝션 취약점을 의심해볼 수 있다.
비록 일반적인 SQL 인젝션 공격과 같이 특정 테이블의 결과를 모두 출력하는 것처럼 직접적으로 알아낼 수는 없더라도, "어떤 사용자가 웹사이트에 존재하는가?"와 같은 식으로 어떤 명제를 제시하고 그 명제가 참인지 거짓인지는 알아낼 수 있다. 참과 거짓일 때의 결과 차이를 분석하여 어떤 정보를 알아내는 기법을 블라인드(blind) SQL 인젝션 공격이라고 한다.
웹 요청이 응답되는 시간의 차이를 이용하여 참과 거짓을 구별해내는 방법을 시도해볼 수 있다. 예를 들면, 결과가 참이 되도록 만들 경우에는 다음과 같이 AND와 함께 SLEEP 키워드를 이용하여 거짓인 경우보다 응답을 몇 초 늦게 오도록 만드는 것이다. 참일 때에만 SLEEP() 함수가 실행된다. 조건이 거짓이 되는 상황에서는 SLEEP이 실행되지 않는다.
sqlmap 자동화 공격
sqlmap 프로그램을 이용하면 데이터베이스의 정보를 획득할 수 있다.
sqlmap 프로그램을 이용해서 URL에 포함된 각 파라미터를 자동으로 테스트하여 SQL 인젝션 공격 가능 여부를 확인할 수 있다. 이와 더불어 웹 애플레케이션 개발 언어와 버전, 웹 서버, DBMS 버전 등의 유용한 정보도 알 수 있다.
SQL 인젝션 공격 대응
SQL 인젝션 공격과 같은 모든 파라미터 입력값 조작으로 이루어지는 공격은 입력값 검증을 통해 대응할 수 있다. 사용자가 입력한 값은 SQL 쿼리문에서 오직 데이터로만 사용되어야 하지 SQL 쿼리문의 구조에 영향을 줄 수 없도록 해야한다.
특히 prepare() 부분을 보면 미리 실행할 쿼리문의 형태를 작성해두고 있다. 이것을 프리페어드 스테이트먼트(prepared statement)라고 한다. 그리고 사용자 입력값이 들어갈 id 부분은 bindParam()에서 설정되도록 하고 있다. 이 경우 사용자가 입력한 값이 쿼리문의 일부가 될 수가 없고 온전히 데이터로만 처리되기 때문에 or나 UNION 등과 같은 키워드가 입력되어도 무의미한 문자열이 된다. 결과적으로 사용자가 SQL 쿼리문을 조작할 방법이 없어 SQL 인젝션 공격을 효과적으로 방지할 수 있다.
'Study records > Web hacking' 카테고리의 다른 글
[Beebox] HTML 인젝션 (0) | 2024.06.20 |
---|---|
크로스 사이트 스크립팅 공격 (1) | 2024.05.25 |
커맨드 인젝션 공격 (0) | 2024.05.25 |
취약한 인증 공격 (0) | 2024.05.24 |
정보 수집과 대응 방법 (0) | 2024.05.23 |