본문 바로가기
AI 스쿨 리팩토링 보안직무 과정

39주차 과제 - SQL Injection (LOW)

by IT스터디큐브 2024. 3. 24.

 

 

자동목차

서론

 이번 시간에는 SQL Injection에 대해 간략히 알아보고, DVWA를 통하여 SQL Injection 실습을 진행하여 보도록 하겠습니다.

 

39주차 과제 - 웹 모의해킹 4.pptx
1.94MB

 

 발표에 사용한 PPT 파일을 첨부합니다. 이 과제는 AI 스쿨의 리팩토링과정을 수행한 것 입니다. 해당 커리큘럼에 대한 더 자세한 내용을 원하신다면 카페를 통해 알아봐주시기 바랍니다.
https://cafe.naver.com/itscholar

 

정보보안전문가 취업카페 스칼라 : 네이버 카페

비전공자 전문IT교육, 정보보안전문가, 보안을 아는 개발자, AI 양성교육, IT기술리더, 창업가 양성

cafe.naver.com

 


본론

사진 출처 : 안랩

 

 SQL Injection(이하 SQLi)이란, 모종의 조작으로 애플리케이션의 데이터베이스에 SQL 질의문을 삽입할 수 있는 취약점입니다. 이렇게 SQL 질의문을 사용자가 삽입할 수 있게 된다면, 서버의 데이터베이스 상에 있는 정보들을 열람하고 편집할 수 있게됩니다.

SQLi 실습 - 기본 방식

 

 이제 DVWA에서 해당 공격 기법을 시연해 보도록 하겠습니다. DVWA에 접속하고 SQL Injection 탭을 선택합니다.

 

 해당 탭에 접근 한다면 회원 번호를 입력할 시 해당하는 회원의 정보를 출력하는 애플리케이션을 확인할 수 있습니다. SQLi 기법을 활용하여 해당 애플리케이션으로 중요한 정보를 탈취할 것 입니다.

 이곳에 '2 를 입력하고 제출 버튼을 클릭하여 오류를 유도하였습니다. 오류 화면을 확인한 결과 1번 라인에 있는 '2 입력이 문제가 되어 오류가 발생했다는 것을 확인할 수 있습니다. 이를 통해서 이 애플리케이션이 사용자 입력을 검증하는 과정이 취약하며, 이 취약점을 통하여 SQLi를 시연해 볼 수 있다는 것을 확인할 수 있습니다.

 

 

 좌측의 텍스트는 입력 결과를 바탕으로 애플리케이션에 적용된 SQL 질의문을 추정해 본 것 입니다. 애플리케이션에 있는 입력 칸에 들어가는 입력을 id로 지정하고 쿼리문에서 그 id문을 검색하는 구조라고 추정하였습니다. 이에 애플리케이션에  1' or '1'='1' 을 입력하여 모든 데이터 값을 출력하도록 하였습니다.  참고로 1=1 같은 경우 SQL 질의문 Where의 조건을 무시하고 모든 데이터를 출력하도록 하는 역할을 합니다. 

 

 데이터베이스 상의 모든 데이터가 출력되는 것을 확인했습니다. 이에 추론했던 SQL 질의문 구조가 거의 들어맞는 다는 것을 확인하고 다음 단계로 진입하도록 하겠습니다.

 

 SQL 질의문 중, UNION 구문이 존재합니다. 이는 두개 이상의 SELECT 문을 연결하여 표현할 수 있는 구문인데, 이를 사용하여 SQLi를 시도할 것 입니다. UNION 구문을 사용하려면 가장 먼저 Column의 수가 같아야 하는데, Column의 수를 알아보기 위해 Order by 함수를 사용하여 기존 테이블의 Column의 수를 확인해 보도록 하겠습니다.

 

 

 Order by 함수를 이용해 본 결과 3을 입력했을 때 부터 결과가 비 정상적으로 나타나는 것을 보아, Column의 수는 2라는 것을 확인할 수 있었습니다. 이제 UNION 을 이용하여 SQL 상의 중요 정보를 열람해 보도록 하겠습니다.

 SQL 상에는 Information_schema라는 이름의 관리용 데이터베이스가 존재합니다. 이 데이터베이스는 관리를 위해서 현재 SQL이 사용하고 있는 모든 데이터베이스의 정보가 저장되게 됩니다. 우선 Information_schema의 schemata DB에 접근하여 서버에서 운영하고 있는 DB를 알아보도록 하겠습니다.

 

 시도 결과 서버에서 운영하고 있는 DVWA라는 이름의 DB를 발견하였습니다. 이제 해당 DB의 내용을 조회해 보도록 하겠습니다.

 

 

' UNION SELECT table_name, 2 from information_schema.tables WHERE table_schema='dvwa’#

 

 이미지는 위 질의문을 입력하여 얻어낸 결과입니다. DVWA의 데이터베이스 상에 users, guestbook이라는 이름의 테이블이 있는 것을 확인할 수 있습니다. users 테이블에 사용자 관련 정보들이 존재할 것으로 예상되므로 해당 테이블의 내용을 한번 조회해 보도록 하겠습니다.

 

' UNION SELECT column_name, 2 from information_schema.columns WHERE table_schema='dvwa' and table_name='users’#

 

해당 테이블 안에 user_id와 password라는 Column이 존재하는 것을 확인했습니다. 해당 Column의 이름으로 추측하건데 상당히 중요한 정보를 포함하고 있을 가능성이 높습니다. 이에 해당 Column들의 내용을 조회해 보도록 하겠습니다.

 

' UNION SELECT user, password FROM users#

 

예상대로 사용자의 ID와 비밀번호를 저장하고 있는 모습을 확인할 수 있습니다.

 

 

 하지만 해당 정보를 이용하여 로그인을 시도했을 때, 로그인에 실패했습니다. 이 경우 높은 확률로 해당 비밀번호가 암호화 후 저장되어 있기 때문일 가능성이 높습니다. 그리고 일반적인 경우 암호화 되어 있는 비밀번호를 복호화 하기는 매우 어렵습니다.

 

 하지만 널리 알려져 있는 비밀번호가 암호화 되어 해쉬값으로 저장되어 있는 경우, 해당 해쉬값을 검색하는 것으로 어떤 암호화가 적용되어 있는 지 유추할 수 있습니다. 그리고 이전에 사용한 admin 계정의 비밀번호가 password로 지정되어 있어 매우 간단한 비밀번호이니 이 비밀번호의 해쉬값을 검색하여 어떤 암호화 알고리즘을 사용했는지 확인해보겠습니다.

 

 password의 해쉬값 5f4dcc3b5aa765d61d8327deb882cf99을 구글에 검색하여 해당 해쉬값이 MD5 알고리즘을 사용한 암호화의 결과물이라는 것을 확인할 수 있었습니다. 또한 MD5의 경우 인터넷에서도 복호화를 해주는 서비스를 쉽게 발견할 수 있었습니다.

 

 이를 통해 gordonb 계정의 비밀번호가 abc123인것을 확인하고 해당 정보를 기반으로 로그인 시도를 해 보았습니다.

결과는 로그인 성공입니다.

 


SQLi 실습 - 블라인드 방식

 이번에는 블라인드 방식으로 진행해 보겠습니다. SQL Injection (Blind) 탭에 접근합니다. 이 웹 애플리케이션은 많은 부분에서 이전에 실습한 SQL Injection 탭과 유사합니다. 하지만 중요한 차이점이 존재합니다.

 이전 탭과 다르게 이번 탭에서는 회원번호를 입력할 경우 회원 정보를 바로 알려주는 것이 아니라 그 회원이 존재하는지 존재하지 않는지에 대한 정보만을 출력합니다.

 SQL의 대표적 취약점인 1 = 1 구문을 이용하여 해당 애플리케이션이 취약한지 확인해 보았습니다. 삽입 값에 따라 T/F 값이 달라지는 것으로 보아 해당 애플리케이션은 SQLi에 취약하다는 것을 확인할 수 있었습니다.

 

 이번 애플리케이션은 이전에 실습한 애플리케이션과 다르게 출력값이 T/F만으로 제한되어 있습니다. 이 경우 이전에 사용하던 웹 애플리케이션에 비하면 번거롭지만 그렇다고 SQLi를 통해 정보를 추출하는 것이 불가능한 것은 아닙니다. 공격자가 SQL문을 수차례 입력하여 유의미한 정보를 추출하여 활용하는 것이 충분히 가능합니다. 

 

 그 순서는 다음과 같습니다.

  1. Column 수 확인
  2. DB 명(스키마) 길이 확인
  3. DB 명(스키마) 문자열 확인
  4. Table 이름 길이 확인
  5. Table 이름(스키마) 문자열 확인
  6. Column 이름 길이 확인
  7. Column (스키마) 문자열 확인
  8. 값(value) 문자열 확인

먼저 수작업으로 해당 과정이 어떤 방식으로 이루어 지는지 간단히 보여드리도록 하겠습니다.

 해당 애플리케이션에 column의 수를 확인하는 과정입니다. 이 과정에서 ' union select 1 # 입력 시 오류가 발생하고 ' union select 1,2 # 입력 시 참 값 출력, ' union select 1,2,3 # 입력 시 오류가 일어나는 것을 통해 column값이 2라는 것을 확인할 수 있습니다.

 

 비슷하게 1' and length(database()) =  질의문을 이용하여 DB의 이름 길이를 알아낼 수 있습니다. 위 사진에서 보듯이 1, 2, 3 값을 입력했을 때는 오류가 나타나지만 4 값을 입력했을 때는 참 값을 출력하는 것을 확인할 수 있습니다. 이를 통해서 DB의 이름이 4글자라는 것을 확인할 수 있습니다.

 

 이제 데이터베이스의 이름 길이를 알아냈으니, 데이터베이스의 이름을 알아내기 위해 모든 알파벳을 대입해 보는 방식으로 데이터베이스의 이름을 알아낼 수 있습니다.

하지만 수작업으로 이 모든 과정을 처리한다면 막대한 시간이 소요되기 때문에, 이후 실습은 자동화 프로그램을 사용하여 진행하는 모습을 보이도록 하겠습니다.

 

 사용할 자동화 프로그램의 이름은 SQLmap입니다. 실습 환경인 칼리 리눅스 상에는 해당 프로그램이 설치되어 있는 상태이기에 설치 방법은 생략하도록 하겠습니다.

 

 먼저 버프스위트의 http history에 들어가서 지금 사용하던 웹 애플리케이션의 쿠키값을 추출합니다. 

 그리고 터미널에서 쿠키값을 이용하여 SQLmap을 작동시킵니다. 명령어는 다음과 같습니다.


sqlmap --cookie="PHPSESSID=sde47ip9o98u3klbqbklav6i1d; security=low" -u "http://localhost/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit" -p id
해당 명령어는 ID 변수가 취약한지 확인하는 역할을 하는데, ID 변수가 취약하다는 결과를 얻을 수 있었습니다.

이제 접근 가능한 데이터베이스의 목록을 확인할 것 입니다. 다음 명령어를 입력합니다.

 sqlmap --cookie="PHPSESSID=sde47ip9o98u3klbqbklav6i1d; security=low" -u "http://localhost/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit" -p id --dbs

 

dvwa와 information_schema라는 데이터베이스에 접근할 수 있다는 것을 확인하였습니다.

 

 이번에는 DVWA 데이터베이스에 있는 테이블의 목록을 확인해 보겠습니다. 

 

sqlmap --cookie="PHPSESSID=sde47ip9o98u3klbqbklav6i1d; security=low" -u "http://localhost/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit" -p id -D dvwa –tables

 

여기서 guestbook, users라는 테이블이 있다는 것을 확인할 수 있었습니다.

 

users 테이블에 있는 Colomn을 조회해 보도록 하겠습니다. 

 

sqlmap --cookie="PHPSESSID=sde47ip9o98u3klbqbklav6i1d; security=low" -u "http://localhost/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit" -p id -D dvwa -T users --columns 

 

여기서 user, avatar, failed_login, last_login, last_name, password, user_id 의 Colomn이 존재한다는 것을 확인할 수 있었습니다. 해당 정보들을 그 이름으로 보아 사용자의 이름, ID, 비밀번호 및 기타 민감한 정보를 포함하고 있는 것으로 보입니다.

 

 

 이제 users 테이블에 있는 모든 데이터를 덤프하겠습니다.

sqlmap --cookie="PHPSESSID=sde47ip9o98u3klbqbklav6i1d; security=low" -u "http://localhost/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit" -p id -D dvwa -T users --dump

 

덤프한 파일에서 사용자들의 비밀번호등을 확인할 수 있었습니다.

 


대처방안

 

 

 SQLi는 사용자가 입력한 값을 검증한다면 막을 수 있습니다. 이는 크게 두가지 방식이 존재하는데, 주로 Prepared Statement 기능과 Escape 기능이 그것입니다.

 

Prepared Statement 기능은 준비된 선언이라고도 번역되는데, 사용자의 입력을 미리 설정된 Statement에 연결되게 만들어 처리속도를 올리고 사용자의 다른 입력을 차단하는 역할을 합니다.

 

Escape 기능은 사용자가 입력하는 일부 문자열을 다른 것으로 치환하도록 만드는 기능입니다. 예를 들어 이번 실습에 자주 사용하였던 ' 문자열을 %등 SQL 질의문으로 해석될 수 없는 다른 문자열로 교체하는 것 입니다. 

 

 

 

댓글