Web Hacking/XSS

Cross-Site Request Forgery Attack(CSRF Attack)

seungwon9201 2024. 6. 28. 19:53

CSRF Attack(크로스 사이트 요청 변조 공격)

공격자가 피싱을 이용하여 사용자에게 악성 링크를 누르게 하고, 링크를 클릭하면 사용자 모르게 사용자가 로그인되어 있는 웹사이트의 특정 기능을 실행하는 공격 기법

 

Reflected XSS의 이름과 일부 동일하고 두 개의 공격 모두 공격과정에서 피싱을 이용하기 때문에 헷갈릴 수 있지만 피싱 이후에 진행되는 과정이 아예 다르다.

 

 

CSRF Attack 실습

-실습 목표-
정상적인 패스워드 변경 페이지를 사용하지 않고 CSRF 공격 POC코드를 이용하여 사용자의 패스워드를 바꾸자.

 

우선 실습 페이지로 가보자.

 

이렇게 패스워드 변경하는 폼이 표시된다. 

일단 패스워드를 test로 바꿔보자.

패스워드를 변경한 후에 burp suite에서 proxy history를 확인해 보자.

 

위의 사진에서 GET 메소드로 요청이 전송되고, password_new와 password_conf 파라미터에 입력한 패스워드가 전달되고, Change 파라미터에는 Change라는 값이 전달된다. 또한 쿠키 헤더에는 PHPSESSID 쿠키와 다른 쿠키들이 전달되는 것을 확인할 수 있다.

 

정리하자면 이 요청에는 PHPSESSID 쿠키만 랜덤한 값을 갖고 있고 나머지 정보들은 지정된 값을 가지고 있다.

즉, 사용자의 랜덤한 PHPSESSID 쿠키값만 알아낸다면 패스워드를 변경시킬 수 있게 된다. 

 

사용자가 로그인되어 있는 경우에 사용자가 웹 페이지를 요청할 때마다 쿠키가 웹 브라우저에 의해서 자동으로 전달이 된다. 즉, 공격자가 피싱으로 사용자가 로그인된 웹사이트의 링크를 누르게 되면 쿠키를 전달시킬 수 있다!

 

이러한 이유로 CSRF Attack의 필수조건으로 사용자가 로그인되어 있어야 한다.(로그인이 되어 있지 않으면 쿠키전송 X)

 

-웹 모의해킹 팁-
어떤 정보를 변경하는 요청메시지에 쿠키 이외에 랜덤한 값이 없다면 CSRF Attack에 취약할 수 있다.

 

이제는 CSRF Attack을 수행하는 POC코드를 분석해 보자.

위의 코드에서 11~28번째 부분과 30~34 부분이 핵심 부분이다.

poc() 함수는 URL과 파라미터를 똑같이 구성한다. 여기서 패스워드 관련 파라미터가 test대신 hacker로 변경되었다.

즉, CSRF Attack이 성공하면 패스워드를 hacker로 변경시킨다.

 

18~23번째 줄에서 XMLHttpRequest() 함수를 사용한 AJAX 기법을 이용하여 poc() 함수가 호출될 때마다 새로운 요청이 전송되도록 만든다. 이를 통해서 21번째 줄인 withCredentials 속성을 true로 설정하여, 요청이 전송될 때 웹 브라우저가 쿠키를 자동으로 전송하도록 만든다.

 

31~33번째 줄에서 피싱을 위한 문구를 삽입했고, 피싱을 당한 사용자가 Click! 을 누르면 poc() 함수가 실행되도록 만들었다.

 

다시 말해, 공격자가 피싱으로 사용자가 위의 파일 안에 있는 링크를 누르면 자동으로 패스워드가 변경되는 CSRF Attack 요청이 전송된다.

 

이제 본격적으로 실습을 하기 전에 host의 DVWA의 IP주소를 변경시키자.

이렇게 변경시키고 웹 디렉터리인 /var/www/html로 옮기자.

파일의 위치를 옮긴 뒤에 apache2 서버를 다시 시작해 주자.

 

그 후에 아래의 주소에 접속을 하자.

http://localhost/csrf.html

CSRF 공격 예제 페이지

-한 가지 의문점-
왜 직접 링크를 입력하고 들어가지? 이 실습에서는 사용자가 피싱을 당해 csrf.html 파일을 의도치 않게 열게 되었다고 가정했기 때문이다. 실제 해킹에서는 사용자도 모르게 접속이 될 것이다.

 

자 이제 사용자가 보안이 강화된다는 메시지를 보고 실제로 click을 누른다고 해보자.

실제 공격이라면 이것보다 훨신 자연스럽게 출력된다.

그럼 이런 메시지가 뜨게 된다.

 

이제 다시 burp suite를 들어가서 확인해 보자.

proxy history를 확인해 보니 패스워드가 hacker로 변경하는 요청이 전송된 것을 확인 가능하다.

 

이때의 응답코드가 200으로 표시 됐다면 패스워드가 정상적으로 바뀐 것이다.


CSRF Attack 대응법

  1. 요청 메시지의 Referer 헤더를 검사하여, 메일이나 다른 사이트에서 피싱을 당해 전송되는 요청을 실행하지 않는다.
    • 실습할 때 해당 경로의 파일로부터 링크를 클릭했기 때문에 localhost로 나오지만 정상적인 경로였다면 DVWA 사이트 내부의 URL이 표시됐을 테니까 이 헤더를 확인해서 정상적인 사이트인지 판별하자
  2. CSRF 토큰을 사용한다. 
    • 웹 애플리케이션이 CSRF 토큰을 응답마다 랜덤 하게 생성해서 히든 폼 필드를 통해 클라이언트로 보낸다.
    • 클라이언트는 이전 응답 메시지에 포함된 토큰 값을 다음 요청값에 포함시켜 전송한다.
    • 웹 애플리케이션이 CSRF 토큰 값을 검사해서 정상적인 과정으로 온 요청인지 확인한다.

이 코드를 보면 user_token이라는 히든 타입의 폼 필드가 있다. 

value로 지정된 문자열이 웹 애플리케이션이 랜덤하게 생성한 CSRF 토큰 역할을 수행한다. 

이를 통해서 패스워드 변경 요청이 올 경우 CSRF 토큰이 user_token 파라미터를 통해 전달되게 된다.

 

웹 애플리케이션은 CSRF 토큰이 자신이 생성한 문자열이 맞는지 비교하여 공격에 대응할 수 있다.

 

그러나 동일한 웹 사이트에 XSS 취약점이 존재한다면 CSRF와 XSS공격을 조합해서 위의 두 가지 대응법을 뚫수도 있다.

 

How? 
POC코드에는 자바스크립트가 사용되는데, 임의의 자바스크립트를 실행할 수 있는 XSS 공격을 이용해서 POC코드와 같이 요청을 전송시키면 referer 헤더는 XSS 취약점이 있는 DVWA가 되기 때문에 referer 헤더 검사를 우회시킨다. 또한 자바스크립트를 이용하면 CSRF 토큰을 알아낼 수 있다.