본문 바로가기

Webhacking/WebGoat

[WebGoat] Injection-SQL Injection (intro) 풀이

728x90
반응형

SQL Injection을 학습하는 챕터이다.
기본적인 SQL에 대한 설명을 하고, SQL Injection의 아주 기초적인 부분을 다루는 챕터이다.

문제 풀이 가자.

문제라기 보다는, 튜토리얼에 가깝다.
Employees 테이블의 정보를 보여주고, 이를 SQL Query를 이용해서 특정 정보를 조회하면 해결할 수 있는 문제이다.
문제에서 요구한건 BoB Franco의 정보. Select문을 이용하면 될것이고... first_name과 last_name column을 조건으로 조회하면 될것같다.

정답이다. 빠르게 다음으로 넘어가자.

DML에 대한 내용을 담은 부분이다.
DML은 데이터를 직접적으로 조회, 수정, 추가, 삭제 가능한 쿼리들을 말한다. Select/Insert/Delete/Update 가 있다.

문제 내용은 Tobi Barnett의 department 컬럼을 Sales로 바꾸면 해결된다.
Update문에 where로 이름을 조건으로 걸면 금방 풀릴것으로 보인다.

다음 문제로 넘어가자.

다음은 DDL에 대한 부분이다.
DDL은 데이터를 정의하는 쿼리들을 의미한다. 예를들어 데이터베이스나 테이블 자체에 대한 생성 또는 삭제 그리고 수정이 있을수있다. Create/Drop/Alter 문이 있다.

문제는 employees table에 phone 컬럼을 추가하면 되는 문제이다. 아마도 Alter문을 이용하면 쉽게 풀릴것같다.

다음 문제로 넘어가자.

이번엔 DCL 관련한 문제이다. 데이터를 제어할 수 있는 쿼리로 권한을 부여하거나, 뺄수 있는 Grant와 Revoke 쿼리가 해당한다.

문제 자체는 grant_rights라는 테이블에 unauthorized_user가 접근할 수 있게 권한을 주면 되는것으로 보인다. 다만 여기에 조금 함정이 있었다. 기본적으로 grant 쿼리는 권한을 줄 테이블에 대한 데이터베이스명을 알아야 db명.테이블명 이런식으로 쿼리를 짜는데... 데이터베이스명을 전혀 모른다...

이 부분은 WebGoat가 기본적으로 HSqlDB를 사용하고 있어 발생하는 이슈로, 메뉴얼을 보렴ㄴ HSqlDB는 grant나 revoke를 할때 db명 없이 바로 테이블명을 넣어 권한을 제어할 수 있다고 한다.

그렇다면 바로 grant명령어로 권한을 넣어줘보자. 어떤 권한을 넣으라고는 나오지 않았기에, 모든 권한을 넣어보자.

다음으로 넘어가자.

이제 SQL Injection이 나온다.
디테일하게 보면 String 형태에서 발생하는 SQL Injection이다. 위에서 제공한 쿼리 샘플을 보면, 사용자의 입력값을 그냥 문자열처럼 이어붙여서 사용하기때문에 SQL Injection으로부터 취약할 것임을 예상할 수 있다.

문제는 특정 사용자의 정보만을 보는것이 아닌, 모든 사용자를 조회하도록 공격을 시도해보라는 것이다.
우선 first_name 조건이 이미 John으로 세팅되어있으니, last_name을 일부러 틀리게 입력해야 특정 계정이 아닌 모든 계정을 조회할 기회가 생긴다. 맨 처음 제공해줬었던 employees 테이블의 정보를 보면 John의 last_name은 Smith이다. 우선 보기에서 Smith가 들어가면 제거하면 된다.
그러면 답은 자연스럽게 ' 하나가 있는게 답이 된다. 왜 싱글쿼터가 들어가는지는 다들 알 것이다. 문자열의 범위를 임의로 종료시켜, 다음에 입력한 값은 쿼리의 일부가 되도록 하기 위함이다. 
그렇다면 그 다음은 어떻게 해야할까? 앞에서 first_name과 last_name을 and로 묶어둔 조건은 거짓이 되었다. 그리고 내가 원하는 조건을 넣어 쿼리를 정상적으로 실행시키기 위해서는 or 구문을 사용해주어야 한다. 두번째 답은 or이 된다.
마지막은 그렇다면 무엇을 넣으면 될까? 모든 값을 조회하는것이 목적이니, 특정 조건이 아니라 무조건 참이 되는 조건을 넣어주면 된다. 1=1이라거나 1<2라거나.... 당연한 참값을 넣어주면 된다. 다만 여기서 한가지 생각해야하는것... 맨 뒤에 ' 가 하나 남아있다는 것이다. 이걸 그대로 두면 오류가 날 것이니, 오류가 나지않도록 조건문에 잘 녹여내면 된다. 예를들어 '1'='1 이렇게 조건을 넣어 일부러 '를 하나 빼고 넣어주면 뒤에있던 '가 자연스럽게 붙어 오류가 나지않을 것이다. 제공된 보기에도 동일한 것이 있으니 선택하면 된다.

다음으로 넘어가자. 
※ 맨 앞에 들어가는 답을 Smith' 로 해도 풀리는데, 이건 문제의 오류이다. 실제로 Smith' 로 하게되면 앞에 있는 first_name과 last_name이 and로 묶인 이 조건 자체가 참이 되면서 Smith의 정보만이 노출될 것이다. 문제상의 오류이니 무시하자.

다음은 '가 필요치 않은 숫자형태 입력에서 발생할 수 있는 SQL Injection이다. 
제공된 쿼리르 보면 Login_Count와 User_ID 둘다 '가 쓰이지 않아, 공격이 될것같은데... 문제를 보니 Warning으로 둘중 하나만 공격이 된다고 써놨다... 테스트 해보자.

Login_Count에 공격을 해보았다. 숫자 형태의 입력이니 범위를 벗어나기 위해 공백한칸을 넣고 공격 구문을 넣었는데... Could not parse라고 한다. 즉 Login_Count는 숫자가 아니면 입력이 안되는 형태로 방어가 되어있다. 우리가 공격해야할 대상은 User_Id가 된다.
Login_Count에도 임의의 숫자를 넣고, User_Id에도 임의의 값을 넣은 뒤 공백을 넣고, or문을 통해 당연히 참이되는 값을 넣어보자. 뒤에 에 남는 특수문자가 없어 주석을 넣지않아도 오류가 발생하지 않는다.

다음으로 넘어가자

이제부터는 보안의 3요소인 기밀성, 무결성, 가용성을 SQL Injection을 이용하여 해칠수 있다는 내용을 다루고 있다. 하지만 내용은 앞에서 다룬 String SQL Injection과 동일하다. 공격 역시 동일하다.

문제는 제공된 쿼리를 보고, 모든 employee의 데이터를 뽑아내라는것이다. 
Employee Name이나 Authentication TAN 둘다 공격이 가능할것 같다. 나는 Employee Name에 공격을 해볼것이다.
last_name 조건을 우선 거짓으로 만들기위해 임의의 값을 넣은뒤 뒤에 '를 넣어 문자열 범위를 종료시킨다. 이어 or 문을 통해 앞의 조건과 관계없이 내가 넣을 조건으로 쿼리가 실행되도록 한다. or 뒤에는 1=1을 넣어 당연히 모든 데이터에 대해 참이 되는 조건을 넣어준다. 그리고 뒤에 남아있는 조건문들은 모두 -- 주석처리한다. Authentication TAN에는 아무값이나 넣어도, 의도대로라면 주석처리되니 아무거나 넣으면 된다.

다음으로 넘어가자.

이어서 나온것은 무결성을 쿼리 체이닝을 이용하여 침해하는 행위를 설명하고있다.
쿼리 체이닝은 쿼리의 끝을 의미하는 세미콜론(;)을 이용하여, 임의로 쿼리를 종료시킨 뒤 뒤에 공격자가 원하는 쿼리를 넣어 같이 실행시키는것을 의미한다.

문제를 보면, John Smith의 salary를 많이 받도록 수정하라고 한다. update 쿼리가 필요하지만 문제를 보면 select를 이용한 Get department 기능만을 제공한다. 이걸 이제 쿼리 체이닝을 이용하여 update 쿼리를 실행시킬수 있도록 공격하면 된다. 
공격은 두 입력값 중 어디에 해도 상관없다. Employee Name에 공격하면 주석이 필요할 것이고, Authentication TAN에 공격하면 주석은 따로 필요치않을 것이다. 나는 Authentication TAN에 공격을 할 것이다.

쿼리체이닝에서 앞에 쿼리는 딱히 중요하지 않기때문에, Employee Name에는 아무거나 입력하고, Authentication TAN 에 우선 임의의 값을 입력한 뒤, TAN이 String타입임을 문제에서 제공해줬기때문에 '를 넣어 문자열의 범위를 임의로 닫아준 뒤, ;을 넣어 쿼리를 임의로 종료시킨다. 바로 이어서 update employees set salary=99999 where auth_tan='3SL99A 이렇게 공격을 이어간다. 여기서 테이블명과 컬럼명은 다 이전에 제공을 받았다, 이전문제들을 참고하면 되며, 마지막에 '를 넣지 않은 이유는, 마지막에 남아있는 '를 오류없이 활용하기 위해서이다. 

이제 마지막 문제로 넘어가자.

마지막은 가용성을 침해하는 경우이다. 데이터를 임의로 지우거나, 수정하거나 하면 서비스 가용성을 침해할 수 있다는 내용이다.
문제는 지금까지의 내 입력이 모두 access_log 테이블에 기록되었으니 완전범죄를 위해 지우라는 문제이다. 문제만 보면 delete를 이용하는것 같은데.. 함정이다. delete를 아무리 열심히해도 풀리지 않는다. 답은 그냥 table을 drop하는 것이다. 
문제에서는 select를 이용하는 Search logs 기능만을 제공하기 때문에, 쿼리체이닝을 이용하면 된다. 아무값이나 넣고 '; 을 넣어 문자열의 범위를 닫고, 쿼리를 끝낸다음 뒤에 drop 쿼리를 넣고 남은 '를 위해 주석을 넣어 문제를 풀면 된다. payload는 asdf'; drop table access_log-- 가 된다.

모든 과정 끝! 


 

728x90
반응형