WAS
에서 발생할 수 있는 위험들에 대해 연구하는 오픈 소스 프로젝트로서 3~4년 마다 OWASP Top 10
이라는 웹 애플리케이션 10대 주요 취약점을 발표한다.
클라이언트 외부에 프록시 서버가 존재하는 것을 의미한다. 클라이언트의 IP주소를 숨길 수 있다.
클라이언트 PC내에 설치하는 프록시이다. 클라이언트-서버 통신간에 HTTP
통신을 분석 및 변조하는 데 사용할 수 있다.
대표적인 도구로는 BurpSuite
, Zed Attack Proxy(ZAP)
등이 있다.
웹 해킹 실습에 이용할 예정이다.
위 그림에서 버그는 프로그래머의 의도와 달리 설계상의 오류가 발생하는 부분을 의미하고 취약점은 버그 중에서도 정보보안의 3요소(기밀성, 무결성, 가용성)을 위협하는 부분을 의미한다. 모든 프로그래머가 프로그램을 설게할 때 완벽하게 설계할 수 없기 때문에 취약점은 항상 발생할 수밖에 없다.
SQL Injection
은 데이터베이스와 연동된 애플리케이션에서 입력된 데이터에 대한 유효성 검증을 하지 않을 경우, 공격자가 입력 데이터에 SQL Query
를 삽입하여 데이터베이스로부터 정보를 열람하거나 조작할 수 있는 보안 취약점이다.
SQL Injection
의 공격 쿼리문들은 보통 논리적 오류를 발생시키는 쿼리문들이다.
실습 환경은 이전 네트워크 공격 실습에 활용했던 VROOM환경을 그대로 이용한다. OWASP
에서 개발한 OWASP Top 10
취약점에 대한 웹해킹 실습을 할 수 있는 WebGoat7
을 기반으로 진행한다.
위 문제는 모든 지역의 날씨 데이터를 가져오는 문제이다. 따로 입력할 수 있는 텍스트 박스가 없고 Go!
버튼을 눌러 데이터를 전송하는 형식인 것 같으니, 우선 BurpSuite
를 켜서 데이터가 어떻게 전송되는지 확인해보자. BurpSuite
에서 Intercept
옵션을 활성화한 뒤 Go!
버튼을 눌러보았다.
POST /WebGoat/attack?Screen=101829144&menu=1100 HTTP/1.1
Host: webgoat7.com
Content-Length: 22
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.93 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://webgoat7.com
Referer: http://webgoat7.com/WebGoat/start.mvc
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=538A37330CE5AB846B3EFA27B44CE7F9
Connection: close
station=101&SUBMIT=Go!
맨 아래 station=101&SUBMIT=Go!
가 데이터를 전송하는 부분임을 알 수 있다. station
파라미터에 임의의 값(1234)을 넣어보자.
SELECT * FROM weather_data WHERE station = 1234
문제 하단에 표시되는 SQL
구문 힌트가 1234로 업데이트 됨을 볼 수 있다. 그렇다면 삽입할 SQL
쿼리도 해당 부분에 삽입됨을 알 수 있다. '' or 1=1
쿼리를 삽입해보자.
weather_data
의 모든 데이터가 불러와진 것을 확인할 수 있다. String SQL Injection
문제도 풀어보자.
이 문제의 목적은 모든 사용자의 카드번호를 불러오는 것이다. 이전 문제와 입력창이 존재하고, 입력값을 전송했을 때 입력값의 양 옆에 따옴표가 붙는 것을 알 수 있다. 이것을 잘 이용해서 쿼리문을 넣어보자. 입력값 양 옆에 안 보이는 따옴표가 있다고 생각하고 ' or '1'='1
이라는 쿼리를 넣어보도록 하겠다.
깔끔하게 잘 풀린 것을 볼 수 있다. 조금 더 어려운 문제들로 넘어가보자.
우선 아까와 마찬가지로 입력창이 존재하는데, 아무 값이나 넣은 후 BurpSuite
에서 확인해보자.
employee_id=101&password=1234&action=Login
의 형태로 데이터를 전송하게 되는데, employee_id
가 사용자의 번호인 것 같고 password
에 내가 입력한 데이터가 들어간다. 따라서 password
에 무언가 '참'을 만들 수 있는 쿼리를 넣어본다면? 이라는 생각이 든다.
사용자를 Neville
로 바꾼 후, 이전 문제와 동일한 쿼리를 BurpSuite
를 이용해 날려보았다.
employee_id=101&password=' or '1'='1&action=Login
Neville
의 계정으로 접속이 잘 된 모습을 확인할 수 있다.
이 문제는 Larry
로 접속해서 보스인 Neville
의 정보를 조회하는 것이 목표이다. 우선 방금 전과 같은 방법으로 로그인해보자.
이러한 화면이 보이게 되는데, 우리가 보아야 할 곳은 ViewProfile
인 것 같다. BurpSuite
로 인터셉트를 잡고 눌러보자.
employee_id=101&action=ViewProfile
의 형식으로 데이터가 날아가는데, 조작할만한 부분은 employee_id=101
인 것 같다. 우선 이전의 문제를 푸는 과정에서 Neville
의 employee_id
가 112번인 것을 확인할 수 있다. 먼저 그냥 112를 넣어보자.
에러가 발생하는 것을 보니 단순 값 변경으로는 불가한 것 같다. 쿼리를 넣어야 하는데, 이번에는 다른 문제들처럼 쿼리문이 주어져 있지 않아서 쿼리문을 예측을 해야한다.
쿼리문을 예측하려면 우선 테이블 이름부터 알아야 하는데, employee_id
라는 파라미터에서 추측해볼 수 있는 테이블명은 employee
정도가 될 수 있을 것 같다. 쿼리문의 형태를 예측해보자면 employee_id
를 입력 받아서 해당 직원의 프로필을 보여주는 것이므로 select * from employee where employee_id = ?
의 형태가 될 것 같다. 보스인 Neville
의 id를 가장 하단에서 선택할 수 있는 것으로 유추해보아 아마 데이터가 가장 하단에 위치할 확률이 높다. 따라서 employee_id
를 기준으로 내림차순 정렬을 해보자. 삽입할 쿼리문은 101 or 1=1 order by employee_id desc
이다.
Neville
의 프로필이 잘 보이는 것을 확인할 수 있다. 이 외에도 Blind SQL Injection
에 관한 내용도 있지만 다룰 부분이 많아 다음 글에서 다루도록 하겠다.
Command Injection
은 말 그대로 명령어를 삽입하는 공격이다. 사용자의 입력 값이 운영체제 명령어로 실행되는 경우 의도치 않은 시스템 명령어가 실행돼 부적절하게 권한이 변경되거나 시스템 동작 및 운영에 악영향을 줄 수 있다. 일반적으로 명령어 라인의 파라미터나 스트림 입력 등 외부 입력을 사용하여 시스템 명령어를 생성하는 프로그램에서 발생한다.
우선 입력창이 없으니 기본적으로 BurpSuite
프록시로 데이터가 전송되는 모양을 살펴보자.
HelpFile=AccessControlMatrix.help&SUBMIT=View
데이터는 위와 같은 모양으로 전송된다. 결과를 살펴보자.
ExecResults for '[/bin/sh, -c, cat "/home/webgoat/.extract/webapps/WebGoat/plugin_extracted/plugin/CommandInjection/resources/AccessControlMatrix.html"]'
Output...
결과를 보면 AccessControlMatrix.help
라는 데이터가 전송되면 AccessControlMatrix.html
을 cat
명령어로 보여주는 식의 동작 방식인 것 같다.
리눅스에서는 세미 콜론(;)을 사용하면 이전 명령어의 실행 여부와 관계없이 뒤에 위치한 명령어를 실행할 수 있다. 이 정보를 이용해서 알맞은 명령어 구문을 날려보자. 우선 ;ls
구문을 날려보자.
ExecResults for '[/bin/sh, -c, cat "/home/webgoat/.extract/webapps/WebGoat/plugin_extracted/plugin/CommandInjection/resources/AccessControlMatrix.html;ls"]'
Returncode: 1
Bad return code (expected 0)
모양을 살펴보니 ;ls
뒤에 큰 따옴표가 하나 붙어있다. 그렇다면 큰 따옴표를 신경써서 ";"ls
라는 명령어를 날려보자.
Command Injection
이 성공적으로 진행되었다.
Log Spoofing
은 말 그대로 로그를 변조하는 공격이다.
admin
이 로그인 했던 것처럼 로그를 변조하는것이 목표인 문제이다. 우선 그냥 admin
으로 로그인해보자.
로그인이 실패했다는 로그가 남았다. 그렇다면 입력창 내부에서 개행을 한 후 똑같은 문자열을 입력해주면 되지 않을까? 입력창 내부 개행은 %0d%0a
로 진행해준다.
admin%0d%0aLogin successed for username: admin
를 입력해보자
성공적으로 admin
이 로그인 했다는 허위 로그를 남길 수 있었다.
쿠키는 사용자의 웹 브라우저에 저장되는 작은 기록 정보 파일이다. 중요한 점은 웹 브라우저에 저장된다는 점이다. 저장된 정보를 다른 사람이 확인 가능하며, 유효시간이 지나면 사라진다. 쿠키를 사용하는 목적은 우선 세션 관리의 관점이 있고, 브라우저 개인 맞춤화, 트래킹 등의 목적이 있다.
사용자는 webgoat/webgoat
, aspect/aspect
로 로그인할 수 있고, alice
의 쿠키를 알아내어 계정을 전환하는것이 목표이다.
우선 각 계정의 쿠키값을 알아보자.
webgoat
의 쿠키값은 65432ubphcfx
이다.
aspect
의 쿠키값은 65432udfqtb
이다.
이 둘 사이에서의 규칙을 찾은 후 alice
의 쿠키값을 유추하는 문제로 보인다.
webgoat
:65432ubphcfx
aspect
:65432udfqtb
alice
:?
webgoat
과 aspect
의 공통점은 둘 다 t
로 끝난다는 것이고, 각각의 쿠키값의 공통점은 65432
로 시작하고u
로 시작한다는 점이다. 이러한 규칙으로 유추할 수 있는 부분은 각각의 문자를 알파벳 순서상 다음 문자로 변환한 후 반전시켰다는 것이다. 이러한 규칙으로 미루어보아 alice
의 쿠키는 65432fdjmb
로 유추할 수 있다. 개발자 도구를 이용해 쿠키값을 변경한 후 새로고침해보자.
로그인에 성공했다.
HTTP Session ID
를 식별자로 구별하여 데이터를 사용자의 브라우저에 쿠키형태로 저장하는 것이 아닌 접속한 서버 DB에 저장한다. 세션 ID만 웹 브라우저에 저장되고 다른 정보들은 서버에 저장된다.
하지만 쿠키가 탈취되는 것 처럼 세션 ID도 탈취당하면 공격자가 해당 세션으로 접속할 수 있다. 하지만 사용자가 해당 웹 서버에서 로그아웃하게되면 세션 ID를 탈취한 공격자의 브라우저에서도 로그아웃된다.
웹 페이지에 악의적인 스크립트를 삽입하여 피해자의 브라우저에서 실행되게 유도하는 공격 기법이다.
Reflect XSS
공격자가 피해자의 이메일로 피싱 URL
을 전달하고 피해자가 해당 링크를 클릭하게 되면 악성 스크립트가 담긴 응답 메시지를 서버로부터 받게된다. 공격자의 서버에서 피해자의 PC로 공격 스크립트가 전달되는 방식이고, 서버에 로그가 남지 않는 것이 특징이다.
Stored XSS
공격자가 서버에 스크립트가 담긴 게시글 등을 등록한 후 피해자가 해당 게시글을 열람하게 되면 악성 스크립트가 실행되는 방식이다. 무작위 공격에는 편하지만 서버에 로그가 남는 것이 특징이다.
Stored XSS
입력창에 스크립트를 삽입하여 alert
을 뛰워보자.
Reflect XSS
비슷한 방식으로 모든 입력창에 스크립트를 삽입한다.
UpdateCart
버튼을 누르면 스크립트가 실행된다.
불특정 다수를 대상으로 로그인 된 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록, 송금 등)를 하게 만드는 공격이다.