티스토리 뷰
회사에서 웹공격 관련한 솔루션을 만들고 있어서 간단히 개념 공부를 위해 드림핵으로 웹해킹 개념 공부를 하려고 한다.
참고 사이트 : https://dreamhack.io/lecture/roadmaps/1
(드림핵에서 워게임 문제도 몇 개 풀어보고 했지만, PS 푸는 게 더 재밌는 거 같다.)
1. Cookie & Session
HTTP 특징 : Connectionless, Stateless 을 기본적으로 가짐
Connectionless : 하나의 요청에 하나의 응답을 한 후 연결을 종료하는 것. 이후 요청이 있을 때마다 새로운 연결을 만든다.
Stateless : 통신이 끝난 후 상태 정보를 저장하지 않는 것. 다른 연결에서 이전 연결에서 사용한 데이터를 요구할 수 없음
HTTP 프로토콜에서 클라이언트가 서버에 Cookie를 전송함으로써, 서버가 클라이언트를 구분할 수 있도록 한다.
즉, 서버와 연결을 종료하더라도, 다음 연결 때 쿠키를 같이 전송함으로써, 이전에 연결했던 클라이언트임을 서버가 인식하도록 한다.
Cookie 는 Key, Value 형식으로 서버가 클라이언트 별로 쿠키를 발급한다.
쿠키 변조 : 공격자는 이미 쿠키를 발급받은 클라이언트인 척 쿠키를 변조에 서버에 요청을 보낼 수 있다.
=> 즉, 쿠키 변조로 다른 클라이언트가 서버에 전송한 데이터를 가져올 수 있다.
Session : 인증 정보를 서버에 저장하고 해당 데이터에 접근할 수 있는 키 (랜덤 문자열) 를 만들어 클라이언트에게 전달.
해당 키를 Session ID 라 부름
Cookie : 클라이언트가 저장하는 값
Session : 서버가 저장하는 값
이라는 차이가 존재
Session Hijacking : Session ID는 클라이언트가 인증 시, 서버에서 발급됨.
이후 Session ID 를 Cookie 에 포함하여 클라이언트가 서버에 요청을 보내면, 서버는 이전에 연결했던 사용자임을 판별함.
Cookie는 클라이언트가 직접 수정 가능하므로,
공격자가 다른 클라이언트의 Session ID를 훔치고, Cookie 를 해당 클라이언트 값으로 바꾸어 서버에 요청을 보내게 되면, 서버는 기존 인증했던 클라이언트로 인식하게 됨.
또는, js 등을 이용해 특정 사이트에 글을 올리거나 하는 스크립트를 공격자가 만들어 두고,
정상 클라이언트가 해당 스크립트를 클릭한 순간, 해당 사이트 서버에는 정상 클라이언트가 글을 업로드한 것으로 인식된다.
이러한 공격 방식이 Session Hijacking
SOP (Same Origin Policy) : Session Hijacking과 같은 Cookie, Session 관련 공격을 방지하기 위해 나온 것이 SOP
SOP는 말 그대로 특정 웹 서비스에 접속할 때 동일한 브라우저를 통해 접속하라 라는 정책이다.
여기서 Origin 은 Protocol, Scheme, Port, Host 로 구성
Protocol, Scheme, Port, Host 값이 모두 일치해야 이전 세션에 연결했던 사용자와 동일한 사용자로 판단한다.
예를 들어, https://test.com 이라는 곳에서 세션 연결을 클라이언트가 진행했었다면
https://test.com/index.html : Same Origin (Path 만 다름)
http://test.com : Cross Origin (Scheme 다름)
https://test.test.com : Cross Origin (Host 다름)
https://test.com:8443 : Cross Origin (Port 다름)
과 같이 구분된다.
브라우저에서는 Same Origin 일 때만 서버에 요청을 진행한다. 하지만, Cross Origin 일 때 데이터 읽기에는 에러를 발생시키지만, 쓰기에는 에러가 발생하지 않는다.
또한, 다양한 서비스를 운영 중인 환경에서 서로 다른 Host 간에 데이터를 주고 받아야 할 필요도 있다.
(ex. 카페, 블로그, 메일 간 데이터 주고 받기)
이러한 상황에서 자원을 공유하기 위해 사용하는 방식이 교차 출처 리소스 공유, CORS (Cross Origin Resource Sharing) 이다.
발신 측에서 CORS 헤더를 설정해 요청하면, 수신 측에서 헤더를 구분해 정해진 규칙에 맞게 데이터를 가져갈 수 있도록 설정한다. 브라우저는 수신측 응답과 발신측 요청이 서로 맞는 지 확인하고, 일치한 뒤 요청을 처리하게 된다.
2. XSS
XSS : Cross Site Scripting. 클라이언트 사이드의 대표적인 취약점
공격자가 악성 스크립트를 삽입한 글, 이미지 등을 클라이언트가 클릭, 실행시키도록 하여 해당 스크립트가 동작하도록 하는 것
예를 들어, 페이스북에 악성 광고글을 올린다. 라는 스크립트가 포함된 게시글을 업로드 후, 해당 게시글을 다른 사용자가 클릭할 때, 해당 사용자가 페이스북에 자동로그인 등 세션을 만들어 놓은 상태라면, 악성 광고글이 자동으로 올라간다.
XSS 종류
Stored XSS : XSS에 사용되는 악성 스크립트가 서버에 저장되고, 서버의 응답에 담겨오는 XSS
Reflected XSS : XSS에 사용되는 악성 스크립트가 URL에 삽입되고, 서버의 응답에 담겨오는 XSS
DOM-based XSS : XSS에 사용되는 악성 스크립트가 fragment에 삽입되는 XSS
Universal XSS : 클라이언트 브라우저, 브라우저 플러그인에서 발생하는 취약점으로 SOP 정책을 우회하는 XSS
일반적으로 <script> </script> 에 악의적인 코드 (ex. 쿠키 탈취 : document.cookie 값 가져와서 특정 행동 후 해당 쿠키를 서버에 같이 전송) 를 작성함으로써 XSS가 이루어진다.
3. CSRF
CSRF : Cross Site Request Forgery
교차 사이트 요청 위조로, 서버에 요청하는 인증을 속이는 공격 기법으로, 인증을 완료한 클라이언트의 세션 값을 이용해 해당 사용자인 척 인증을 속인다 .
Session Hijacking이 단순히 세션 ID 값을 쿠키에 넣어 요청을 보내는 것이라면, CSRF는 악성 스크립트를 클라이언트가 실행시키도록 한 뒤, 세션이 맺어진 서버에 요청을 보내도록 한다.
XSS와 CSRF 모두 클라이언트가 악성 스크립트를 실행시키도록 하는 공통점이 있지만,
XSS는 악성 스크립트를 이용해 클라이언트의 쿠키와 세션을 탈취하고, 공격할 사이트 오리진에서 스크립트를 실행시킨다.
CSRF는 정상 클라이언트인 척 http 요청을 보내는 것을 목적으로 하며, 공격할 사이트에 정상 클라이언트 권한으로 특정 기능을 수행한다.
4. SQL Injection
RDBMS에서 데이터베이스 쿼리를 위한 문법인 SQL을 이용한 공격으로, 데이터베이스에 해당 쿼리 권한이 없는 공격자가 SQL 문을 실행시키도록 하는 공격이다.
일반적으로 input form 의 입력값에 SQL 문법을 입력해 해당 input 값 처리 시, SQL 문법이 실행되도록 하거나, --, # 등 주석 구문으로 추가 입력이 필요한 input 을 없애버리는 방법으로 SQL Injection 이 발생된다.
예를 들어 id 가 admin인 입력 시 pw 를 올바르게 입력해야만 관리자 계정으로 로그인이 될 때,
id 에 admin' -- 을 입력함으로써 pw 검사 구문을 없애는 식으로 SQL Injection 이 동작한다.
SQL Injection을 방지하기 위해서는 사용자 입력에 SQL 문법 (Select, From, Union 등) 을 금지 입력 값으로 설정하거나, 입력되는 값으로 바로 SQL 을 실행하는 것이 아닌, string 자체로 받고 그 다음에 SQL 문을 실행시키도록 할 수 있다.
예를 들어 위 예시에서 사용자 입력이 admin' -- 으로 들어왔을 때, Select * where id='admin' -- pw= 이 실행되는 것이 아닌, Select * where id="admin' --" and pw= 이 실행되도록 하여 pw 일치 검색이 정상적으로 동작하도록 한다.
Blind SQL Injection 은 SQL Injection 결과를 True False 로 받음으로써 스무고개 스타일로 특정 정보를 알아내는 공격이다. 주로 에러 메시지를 통해 True, False를 판단한다.
예를 들어, pw 가 알파벳, 숫자만 허용할 때, 입력한 값과 pw의 값의 첫 번째 값이 일치하는 지 여부를 요청으로 보내 일치하는 지를 체크한다. 그렇다면 26 + 26 + 10 = 62 개만 체크하면 첫 번째 글자를 알 수 있다.
그런 다음 두 번째 pw 값도 일치 여부를 체크한다.
이런 식으로 스무고개를 하며 한 자리씩 값을 알아내는 것이 Blind SQL Injection 이다.
Blind SQL Injection 은 SQL 문을 직접적으로 input에 입력하는 것이 아니기 때문에 SQL 문을 금지 입력으로 처리하는 것으로는 해결할 수 없다. 따라서 에러 메시지를 성공 외에는 항상 동일한 에러 메시지를 출력시키도록 하며, 특정 횟수 이상으로는 로그인 시도 차단 등 요청 성공 이전 시도 횟수를 제한하는 방식으로 해결할 수 있다.
5. Command Injection
Command Injection은 입력에 서버에서 실행 가능한 command를 삽입하는 공격으로, 서버의 정보를 탈취하거나, 파일 임의 생성, 삭제 등을 수행할 수 있는 공격 방식이다.
예를 들어 특정 ip 에 ping을 보내는 서비스가 있을 때 해당 서비스가 /ping?ip=1.1.1.1 과 같이 입력을 받는다고 가정하자.
이 때 입력으로 /ping?ip=1.1.1.1%20&&%20rm%20-rf%20* 와 같이 입력한다면 1.1.1.1 로 정상적으로 ping을 보냄과 동시에 해당 코드가 실행되는 디렉토리의 모든 파일을 삭제 시킨다. 특히 프로세스가 sudo 권한으로 실행되고 있었다면 더욱 위험하다.
Command Injection을 막기 위해서는 코드 내에서 system 관련 함수 실행은 최대한 지양하도록 하며, 불가피하게 필요하더라도, 입력값에 command 실행 관련이 있는 지, 필요한 값 이외의 값이 들어 있는 지 등의 검사 로직이 필요하다.
6. File Vulnerability
File Upload Vulnerability는 말그대로 파일 업로드와 관련된 취약점을 의미한다. File Upload Vulnerability는 Path Traversal과 악성 파일 업로드로 구분된다.
Path Traversal 은 해당 서비스를 이루는 구조를 파악하는 공격으로, 일반적인 스캐닝 툴로 스캔을 하거나, 업로드 하는 파일의 이름에 .., ../.. 등을 삽입하여 업로드 후, 원래 업로드되어야 하는 곳에 해당 파일이 안 보인다면 상위에 어떤 디렉토리가 존재한다는 것을 파악하는 공격을 뜻한다.
악성 파일 업로드는 파일 이름에 .., ../.., / 등을 추가하여 파일을 의도되지 않은 곳에 업로드하고, 해당 악성 파일이 실행되도록 하는 공격이다.
예를 들어, python으로 동작하는 서비스의 ./upload 디렉토리에 업로드한 파일을 저장하도록 하는 로직이고, ./app.py 에서 해당 로직을 실행 중이라고 하자.
이 때 업로드하는 파일의 이름을 ../app.py 로 지정함으로써 원래 app.py 를 덮어쓰고, 서버가 새로 실행될 때 악의적인 코드가 담긴 app.py 가 실행되도록 한다.
또는 php 파일 등을 업로드하여 웹셸을 실행시키도록 하거나, 악의적인 스크립트가 포함된 html 파일을 업로드하여, 추후 다른 정상 클라이언트를 해당 html 으로 접속하도록 하여 XSS 공격을 유도하거나 하는 등의 공격을 수행할 수 있다.
File Download Vulnerability는 클라이언트가 다운로드할 파일을 직접 선택할 수 있을 때 발생되는 취약점으로, 다운로드를 의도한 정상적인 파일이 아닌, 입력값으로 ../app.py, ~/.bash_rc, ~/.bash_history 등 서버 실행의 직접적인 파일, 서버 시스템과 관련된 설정 파일 등에 접근하는 공격이다.
File Upload Vulnerability를 막기 위해서는 파일 업로드 디렉토리를 웹 서버에서 직접 접근할 수 없도록 하거나, 업로드 디렉토리에서는 CGI 가 실행되지 않도록 해야 한다. 그리고 업로드된 파일은 이름을 그대로 사용하는 것이 아닌, 파일 이름을 검증 후 변경하는 등의 작업을 해야 한다. 그리고 특정 확장자 외에는 업로드 자체를 금지하도록 해야 한다.
File Downlaod Vulnerability를 막기 위해서는 요청된 파일 이름이 정상적인지, 특정 path를 요구하는 지 등을 검사해야 하며, 파일을 이름이 아닌 특정 키로 매핑하여 해당 키 값을 요청하도록 해야 한다.