이전에 만들었던 코드는 HTML 파일로 사용자에게 변경을 요청하는 페이지가 보이기 때문에 좋지 않습니다
이제는 사용자가 이 코드를 실행한다면 보이지 않고 자동으로 제출하도록 만들 수 있습니다
모든 것을 숨기기 위해 모든 입력에 hidden을 추가합니다
기존 코드
<form action="http://192.168.75.129/dvwa/vulnerabilities/csrf/" method="GET"> New password:<br>
<input type="password" autocomplete="off" name="password_new"><br>
Confirm new password: <br>
<input type="password" autocomplete="off" name="password_conf">
<br>
<input type="submit" value="Change" name="Change">
</form>
수정 코드 - 1
<form action="http://192.168.75.129/dvwa/vulnerabilities/csrf/" method="GET">
<input type="hidden" autocomplete="off" name="password_new" value="666666">
<input type="hidden" autocomplete="off" name="password_conf" value="666666">
<input type="hidden" value="Change" name="Change">
</form>
이제 저장 후 csrf.html 파일을 열게 되면 페이지에 아무것도 보여지지 않습니다
하지만 브라우저의 인스펙션 기능을 활용하여 삽입된 코드를 볼 수 있습니다
실제로 코드가 잘 삽입되어있는 것을 확인했습니다
이후 페이지를 실행했을 때 자동으로 제출을 하도록 코드 수정이 필요합니다
먼저 자바스크립트를 이용하여 위해서 입력 폼 구문에 ID를 설정합니다
<form id=form1 action="http://192.168.75.129/dvwa/vulnerabilities/csrf/" method="GET">
그런 다음 해당 ID를 가져와 자동으로 제출을 위한 구문을 추가합니다
<script>document.getElementById('form1').submit();</script>
getElementById
이후 저장을 통해 저장한 뒤 csrf.html을 열면 사용자가 아무 행동도 하지 않아도 비밀번호가 변경된 것을 확인할 수 있습니다
value로 666666으로 설정했으니 비밀번호를 입력해본다면 변경된 것을 확인할 수 있습니다
이러한 파일을 사용자가 실행하도록 만드는 것이 어렵다는 것입니다
하지만 이를 가능하도록 하는 여러 방법들이 존재합니다
그 중 하나인 웹 호스팅 서버를 이용하는 것입니다
또한 URL 단축 서비스를 통해 URL을 단축 후 희생자에게 보낼 수도 있습니다
먼저 이전에 생성했던 파일에서 value를 777777로 변경 후 저장합니다
이제 해당 파일을 웹 서버가 존재하는 파일인 /var/www/html 디렉터리로 이동시킵니다
이제 윈도우 10 가상머신으로 이동하여 실제 일반 사용자 인듯 웹사이트에 접속했습니다
아파치 웹 서버가 구동중인 시스템의 아이피 주소를 이용하여 접속합니다
192.168.75.132/csrf.html
먼저 일반적으로 DVWA로 접속을합니다
로그인 페이지가 나타나게 됩니다
로그인 후 탭을 닫은 뒤 이제 아파치 웹서버 안에 csrf.html 파일을 실행합니다
주소창으로 이동하자마자 아무행동을 하지 않았지만 비밀번호가 변경되었다는 메시지를 볼 수 있습니다
로그아웃 후 새로운 비밀번호를 통해 로그인하면 정상적으로 로그인되는 것을 볼 수 있습니다
결론적으로 CSRF 취약점은 요청이 서버 측에서 유효성을 검사하지 않아서 발생합니다
서버는 요청이 사용자에 의해서 생성되었는지 확인하지 않습니다
요청들은 그들의 의도와 완전히 반대되는 행동을 하도록 요청할 수도 있습니다
패스워드 변경 웹사이트에서 취약점을 막는 가장 쉬운 방법은 기존 패스워드를 묻는 것입니다
현재 암호를 모르기 때문에 새로운 비밀번호로 변경하지 못합니다
하지만 이 방법은 비밀번호 변경에 한해서 보호합니다
따라서 CSRF 취약점을 방지하는 가장 좋은 방법은 어떠한 페이지를 통해 데이터를 제출하는 것이 맞는지 확인하는 과정이 필요합니다
이를 구현하기 위해 동기화 토큰을 사용합니다
그런 다음 페이지가 로드될 때, 양식이 로드될 때 생성된 토큰을 포함합니다
예를들어 페이스북 비밀번호 변경 페이지를 사용자가 요청합니다
그러면 서버는 해당하는 페이지와 함께 유니크한 토큰을 제공합니다
사용자가 요청을 보낼때 토큰과 같이 보내며 서버는 해당 토큰을 비교한 후에 응답을 결정하게 됩니다
토큰은 아래와 같은 특성을 가집니다
Matilda에서 토큰을 구현해놨습니다
이를 실습하려고 합니다
블로그에 게시글을 남기는 페이지입니다
보안 설정을 5로 설정했습니다
그리고 Inspect를 통해 해당하는 요소로 이동하여 분석했습니다
입력 부분에 토큰이 있는것을 확인할 수 있습니다
이 특정한 토큰 없이 게시글을 등록할 수 없도록 서버 측에서 비교를 진행합니다
토큰의 마지막 j를 J로 변경한 후 게시글을 등록해보았습니다
게시글 등록에 실패하였습니다
마지막으로 새로고침을 통해 이전에 보았던 토큰과 비교해봤습니다
새로고침 전 토큰
Lg1ZXXwKkAwTQFUCmR2thLXZ3NZ3nZWc
새로고침 후 토큰
nclg4sI3fRq2wPBG8SCEepSC1evPA2Ma
토큰을 통해 CSRF 취약점은 방지가 됩니다