Web

웹 기본 ~ CSRF

werty2 2025. 7. 16. 21:24

Building a Web Service

1. 웹 기본상식

- 웹은 인터넷을 기반으로 구현된 서비스 중 HTTP를 이용해 정보를 공유하는 서비스

- 웹 서버- 정보 제공 주체, 웹 클라이언트- 정보 받는 이용자

- 웹 리소스란 웹에 갖춰진 정보 자산, 모든 웹 리소스는 고유의 URI를 가짐.

 

인코딩

- 컴퓨터의 모든 데이터는 0과 1로 구성되는데 이 0과 1로 우리가 사용하는 문자를 표현함

- 문자를 표현하는 약속들을 인코딩 표준이라고 부르는데, 대표적으로 아스키와 유니코드가 있음.

- 초기에는 각 문자권마다 고유의 인코딩 표준을 사용해 영어: 아스키, 한글: CP-949, EUC-KR 등을 사용했지만 호환성 측면에서 어려움이 있어 하나의 표준으로 모든 언어의 문자를 표현하기 위해 유니코드가 만들어짐.

 

HTTP(Hyper Text Transfer Protocol)

- 서버와 클라이언트의 데이터 교환을 RequestResponse 형식으로 정의한 프로토콜

- 클라이언트가 서버에게 요청하면 서버가 응답

- HTTP 메시지는 HTTP 요청과 HTTP 응답이 있고, 이들은 HTTP 헤더와 바디로 구성된다.

  • HTTP 헤더의 첫 줄은 시작 줄, 나머지 줄은 헤더라고 부른다. HTTP 바디는 헤드 뒤의 모든 줄을 가리킴. 클라이언트나 서버에게 전송하려는 데이터가 바디에 담김.
  • HTTP 요청의 시작 줄은 Method, Request target, HTTP 버전으로 구성되며 각각은 띄어쓰기로 구분함.                              메소드는 쵸정 대상에 대해 서버가 수행하길 바라는 동작으로 GET과 POST 메소드가 자주 사용됨, GET은 새로운 페이지를 렌더링하기 위한 리소스를 요청하는 메소드이고 POST는 요청 대상에게 데이터를 전송하는 메소드
  • HTTP 응답의 시작 줄은 HTTP 버전, 상태 코드, 처리 사유로 구성됨.                                                                                  상태 코드는 요청에 대한 처리 결과를 세 자릿수로 나타내며, 첫 번째 자릿수에 따라 5개의 클래스로 분류됨.                        (첫 번째 자릿수 - 설명 | 1 - 요청 잘 받음, 처리 진행중 / 2 - 요청이 잘 처리됨 / 3 - 요청 처리를 위해 클라이언트의 추가 동작 필요 /  4 - 클라이언트의 잘못된 요청으로 처리 실패 / 5 - 클라이언트 요청은 유효하지만 서버에 에러 발생해 처리 실패)

HTTPS

 - HTTPS는 TLS 프로토콜을 도입해 서버와 클라이언트 사이에 오가는 모든 HTTP 메시지 암호화

 - 복호화할 수 있는 키가 없다면 공격자가 메시지를 탈취해도 해석이 불가 

 

2. 웹 브라우저

 - 웹 브라우저는 서버와 HTTP 통신을 대신해주고, 수신한 리소스를 시각화 해 뛰어난 이용자 경험(UX)를 제공

 

URL

 - 웹에 있는 리소스의 위치를 표현하는 문자열.

 - Scheme, Authority(Userinfo, Host, Porf), Path, Query, Fragment 등으로 구성

이미지 출처: http://www.codns.com/b/B05-246 (코디엔에스)

 

/ 로 구분되는 건 접근할 웹 서버의 리소스 경로, ? 뒤에 위치하는 건 웹 서버에 전달하는 파라미터, 사진에는 없지만 # 뒤에는 메인 리소스에 존재하는 서브 리소스를 접근할 때 식별하는 정보를 담음.

 

Domain name

- URL 구성 요소 중 Host는 웹 서버의 주소로 Domain name, IP address 값을 가질 수 있음.

- IP 주소는 사람이 외우기 어렵기 때문에 일반적으로는 도메인의 특성을 담은 이름(Domain name)을 정의해 사용

- 브라우저는 DNS (Domain Name Server) 에 Domain name을 물어보고 응답으로 받은 IP 주소를 사용

- 일상생활에서의 114가 우리가 모르는 지점의 전화번호를 알려주는 것과 같이 모르는 IP 주소를 브라우저에게 알려줌.

 

웹 렌더링

 - 웹 렌더링은 서버로부터 받은 리소스를 이용자에게 시각화하는 행위

 - 웹 렌더링 엔진에 의해 이루어지며, 브라우저별로 서로 다른 엔진 사용 (사파리 - 웹킷, 크롬 - 블링크, 파이어폭스 - 개코)

   모두 HTML을 파싱하고 시각화 해 이용자에게 보여주는 역할을 함.

 

브라우저 개발자 도구

 - 브라우저에서 웹 서비스를 진단할 수 있게 해줌

 - 브라우저를 열고 f12를 누르면 개발자 도구가 나옴

크롬에서 구글 첫 화면을 열고 f12를 누르면 다음과 같은 개발자 도구가 나옴.

가장 왼쪽의 두 아이콘은 요소 검사와 디바이스 툴바

  • 요소 검사 버튼을 누르고 웹 페이지의 원하는 요소에 마우스를 올리면 대상의 정보가 출력된다. 그 상태에서 클릭을 하면 그 요소의 HTML 코드가 개발자도구에서 하이라이팅 됨.
  • 디바이스 툴바를 활용하면 현재 브라우저의 화면 비율을 원하는 값으로 변경할 수 있음

- Elements: 현재 페이지를 구성하는 HTML

- Console: 프론트엔드의 자바스크립트 코드에서 발생한 각종 메시지 출력, 이용자가 입력한 자바스크립트 코드 실행 후 결과 확인 가능

- Sources: 현재 페이지를 구성하는 웹 리소스, 아래 첫 번째 사진의 가장 오른쪽 부분은 디버깅 부분으로 원하는 자바스크립트를 디버깅할 수 있음, breakpoint로 중단점을 설정할 수 있고 scope로 현재 스코프의 변수값을 확인할 수 있음.

 

- Network: 서버와 오가는 데이터 확인 가능, 원하는 항목 선택 시 해당 요청 확인 가능, 위의 두 번째 사진과 같이 로그를 copy as fetch로 복사하고 console 패널에 붙여서 실행해보면 동일한 요청 서버에 재전송 가능

- Application: 쿠키, 캐시, 이미지, 폰트, 스타일시트 등의 웹 애플리케이션과 관련된 리소스 조회

 

+ esc키를 누르면 개발자 도구에서 새로운 콘솔창을 열 수 있음.

+ 기타 기능으로는 ctrl+u 를 통해 페이지와 관련된 소스 코드들을 확인할 수 있음.

+ 브라우저 종료 시 방문 기록, 쿠키, 입력한 데이터, 부여된 권한 등이 저장되지 않는 시크릿 모드는 ctrl+shift+n 을 통해 설정할 수 있음

(모두 윈도우 기준)

 

3. Cookie & Session

 

HTTP 프로토콜의 특징

 - connctionlss: 하나의 요청에 하나의 응답을 한 후 연결 종료

 - stateless: 통신이 끝난 후 상태 정보를 저장하지 않음

이러한 특징들 때문에 클라이언트의 정보 기록과 상태 정보를 표현하는 용도로 쿠키가 등장

 - 쿠키: key-value로 이루어짐

 - 클라이언트는 서버에 요청을 보낼 때마다 자동으로 쿠키를 헤더에 포함, 서버는 해당 쿠키로 클라이언트 식별

 - 악의적인 클라이언트가 쿠키 정보를 변조해 서버에 요청 보낼 수 있음 → 별다른 검증이 없다면 타 이용자 사칭해 정보 탈취 가능

 

세션

 -세션은 인증 정보를 서버에 저장하고 해당 데이터에 접근할 수 있는 (랜덤한 문자열, session ID 라고 함)을 만들어 클라이언트에 전달

 -브라우저는 전달된 키를 쿠키에 저장해 이후 HTTP 요청에 사용

 - 공격자가 이용자의 쿠키를 훔칠 수 있으면 세션에 해당하는 이용자의 인증 상태를 훔칠 수 있는데, 이를 세션 하이재킹이라고 함.

 - 개발자도구의 application의 cookies 에서 원하는 사이트를 클릭해 각 쿠키의 key와 그에 대응되는 value를 볼 수 있고, 이를 조작하거나 삭제할 수도 있음

 - console 탭에서 document.cookie를 입력해 쿠키 정보를 확인할 수도 있음.

 

4. SOP

 - 사용자가 한 사이트에 로그인을 해 관련 쿠키가 브라우저에 있는 상태에서 악의적인 사이트에 접속을 하게 되면 악의적인 사이트가 쿠키 정보가 있는 서버에 요청을 보내 응답으로 받은 사용자의 정보를 알 수 있음.

 - SOP는 Same Origin Policy의 약자로, 악의적인 페이지가 클라이언트의 권한을 이용해 대상 사이트에게서 HTTP 응답 정보를 읽을 수 없게 함. (데이터를 쓰는 건 동작함)

  • same-origin: 출처가 완전히 같음(프로토콜, 호스트, 포트가 모두 같음)
  • cross-origin: 셋 중 하나라도 다름 → SOP가 요청의 응답을 차단

CORS

 - Cross-Origin 간에 리소스를 공유하는 방법

 - 발신측(브라우저)이 HTTP 메소드 중 OPTIONS를 통해 수신측(서버)에게 웹 리소스를 요청해도 되는지 물어봄(preflight)

 → 서버에게 받은 응답이 발신측의 요청과 상응(Origin, Method, Credentials, Headers 등이 허용됨)하는지 확인

 → 확인 후, POST 요청을 보내 수신측의 웹 리소스를 진짜로 요청

 

5. HTML

 - HTML이란 HyperText Markup Language의 약자로 웹페이지를 구성하는 언어

 - HTML 요소는 웹 페이지를 구성하는 기본 단위, 하나의 HTML 요소는 <태그이름>내용</태그이름>과 같이 이루어짐.

 - 속성은 태그에 추가 정보를 제공하거나 특정 동작 지정을 위해 사용, 키-값 쌍의 형태로 작성되며 여는 태그 안에 위치함, 여러 개의 속성이 여는 태그 안에 존재할 수 있음.

 - 태그는 대소문자를 구분하지는 않지만 소문자로 작성하는 것이 권장됨.

 - <img>, <input>, <hr>, <br> 과 같은 일부 태그는 닫는 태그가 존재하지 않기도 함.

 

HTML 문서 기본 구조

 - 아래와 같은 HTML 문서가 있다고 할 때 각 라인이 수행하는 동작은

<!DOCTYPE html>
<html>
<head>
  <title>My First Page</title>
</head>
<body>
  <h1>Welcome to HTML!</h1>
  <p>Hello, World!</p>
</body>
</html>

 

  • <!DOCTYPE html> : HTML 문서의 유형을 브라우저에게 알려주는 선언문, HTML 태그가 아니며 HTML 버전에 대한 정보, 이 문서가 HTML5 문서임을 명시
  • <html> : HTML 문서의 시작을 나타냄, 끝을 나타내는 </html>과 짝을 이루며 모든 HTML 문서는 필수로 포함해야 함.
  • <head> : 문서의 메타데이터(데이터 자제가 아닌, 데이터를 설명하는 데이터) 작성, 위의 코드에서는 <head> 사이의 <title> 안의 데이터가 웹 페이지 탭 이름으로 설정됨, HTML5부터는 생략 가능
  • <body> : html 문서의 본문 정의, 웹 페이지에서 이용자가 직접 볼 수 있는 콘텐츠 포함, 모든 HTML 문서는 필수로 포함해야 함.

6. Flask

- 웹 서버란 브라우저의 요청을 받으면 처리해서 알맞은 웹 페이지를 응답으로 반환하도록 구현된 프로그램,  요청된 경로에 따라 다른 웹 페이지 반환

 

웹 프레임워크

- 웹 개발을 위해 반복적이거나 기본적으로 필요한 기능과 뼈대를 제공하는 개발 환경으로, 일반적으로 개발할 때 사용됨.

- Flask는 파이썬 언어를 기반으로 하는 웹 프레임워크

- app.py 가 flask 로 만들어진 파일일 때, 아래와 같은 디렉토리 트리 구조로 배치되어야 함.

top  -> 최상위 디렉토리
├── app.py  -> 웹 서버 파일
└── templates  ->html 문서를 담는 디렉토리 반드시 이름은 templates 이어야 함.
    └── page.html  ->html 문서

 

flask 에서 자주 등장하는 코드들

 - from flask import Flask, render_template -> Flask 생성 시 사용되는 클래스, HTML 파일 렌더링 해 클라이언트에게 반환하는 함수 가져옴.

- app = Flask(__name__) -> Flask 클래스의 인스턴스를 생성해 app 변수에 할당,  이 파일이 직접 실행되면 __name__ ==       "__main__" 이 됨.

- @app.route('/test') -> 파이썬의 데코레이터 기능 활용, /test 경로로 들어오는 HTTP 요청을 아래 위치한 함수로 연결시킴.

- return render_template('page.html') -> HTML 문서인 simple_page.html을 반환

- if __name__ == '__main__':
      app.run(host='0.0.0.0', port=31337) -> flask 웹 서버 실행, 인자를 '0.0.0.0' 으로 설정함으로써 외부 모든 이용자 접근 가능,                                                                     31337번 포트에 웹 서비스가 열리도록 지정 

 

템플릿 렌더링

- HTML 템플릿: 뼈대인 HTML 코드

- 최종 HTML 문서: 템플릿에 실제 데이터가 채워져서 최종적으로 완성된 HTML 문서  

 -->return render_template('page.html, 표현식=변수명') 과 같이 파이썬 함수에서의 변수값을 HTML의 표현식에 넣어서 전달함.

 

템플릿 렌더링 기호

  • {{ 표현식 }}  : HTML에서 사용되며, 템플릿 안에 파이썬 변수나 계산 결과를 출력
  • {% 구문 %} : 조건의 참 또는 거짓 여부에 따라 템플릿 HTML 문서에 데이터 다르게 삽입, 조건문은 {% endif %}로 끝나야함.
{% if 조건1 %}
    <!-- 조건1이 참일 때 최종 html 문서에 반영 -->
{% elif 조건2 %}
    <!-- 조건2가 참일 때 최종 html 문서에 반영 -->
{% else %}
    <!-- 모든 조건이 거짓일 때 최종 html 문서에 반영 -->
{% endif %}
  • {% 구문 %} 반복문 : 순회가능한데이터는 순회할 대상, 아이템명은 각 반복의 현재 요소, 모든 반복 for문은 {% endfor %}로 끝나야함.
<ul>
    {% for 아이템명 in 순회가능한데이터 %}
        <li>{{ 아이템명 }}</li>
    {% endfor %}
</ul>

다음과 같이 flask 에서 리스트와 같이 순회가능한데이터를 반환하면 HTML 에서 그 데이터를 반복적으로 출력함.

  • {% 구문 %} 템플릿 상속 구문 : 여러 HTML 파일 간에 공통 템플릿을 공유하고 재사용할 수 있도록 돕는 기능, 부모 템플릿과 해당 템플릿을 상속받을 자식 템플릿이 필요함.
  • {# 주석 #} : 최종 결과문에 출력되지 않는 주석이나 참고 정보, 렌더링 과정에서 제거가 되어 최종 HTML 소스 코드에 노출X

이용자로부터 데이터 입력을 받는 방식

 - 웹 서버는 이용자와 상호작용할 수 있어야 함.

  1. URL 경로 매개변수 : 데이터를 URL 경로의 일부로 포함시켜 서버에 전달하는 방식                                                                 @app.route() 데코레이터에서 경로 매개변수로 사용할 부분을 <>로 감싸면 경로 매개변수로 정의할 수 있음. 정의된 경로 매개변수는 아래 함수의 매개변수로도 넣어주어야 내부 코드에서 사용할 수 있음. -> url 경로에 전달된 인자값이 그대로 표시됨
  2. URL 쿼리 매개변수 : URL의 ? 뒤에 오는 매개변수로 이용작 데이터를 서버로 전달하는 방식 중 하나.                            request.args 는 이용자로부터 전달받은 쿼리 매개변수를 담고있는 객체이며, 이 객체의 get() 메서드를 사용해 매개변수를 가져올 수 있음-> url 쿼리 매개변수에 전달된 인자 값이 그대로 표시됨
  3. <form> 태그를 통한 POST 데이터 입력 처리 : <form> 태그는 웹 페이지에 이용자가 값을 입력할 수 있는 양식을 만듦, 데이터 전송을 위해 설정이 필요한 속성들이 있음.                                                                                                                        속성으로는 입력 값을 전송할 url을 지정하는 action, 입력 값 전송시 사용하는 HTTP 메시지의 메서드(GET, POST ..)를 설정하는 method가 있음. 

<input> 태그는 입력 양식을 만드는 태그로, <form> 태그는 <input> 태그를 함께 사용해야 입력 가능한 폼 만들 수 O

<input> 태그에서 자주 사용되는 속성

  - type : 입력 필드의 유형 지정, 대표적으로 text - 텍스트 입력받는 폼 / number - 숫자만 입력받는 폼/ password - 비밀번호를  *로 표시하며 입력받는 폼 같은 유형이 존재함.

  - name : 서버로 전송 시, 데이터의 키 설정, 서버로 전달되는 데이터는 키-값 쌍 형태로 전달

  - id : 입력 폼의 고유 식별자

<form> 태그를 통한 POST 데이터는 url 부분에 포함되지 않고 HTTP 메시지의 바디 부분에 포함되어 서버에 전송됨.

 - <form> 태그를 통한 POST 데이터 입력 처리 : request.form.get("키")로 form 태그를 통해 전송된 POST 요청의 body에 담긴 값을 가져옴.

 

Web Hacking

1. XSS

웹사이트에 악의적인 스크립트를 심어 다른 사람의 브라우저에서 그 스크립트가 실행되도록 유도함.

  • Stored XSS: 게시물과 댓글에 악성 스크립트를 포함해 업로드 ( 서버에 데이터베이스 또는 파일 등의 형태로 저장된 악성 스크립트 )
  • Reflected XSS: 이용자가 게시물을 검색하면 일부 서버에서는 검색 결과를 응답에 포함해 이용자에게 반환하는데, 이 검색 문자열에 악성 스크립트가 포함시킴( 검색 문자열이 악성 스크립트인 URL과 같은 링크 접속 유도 )
  • render_template 함수는 HTML 템플릿 파일을 렌더링. 이 함수를 사용하면, 전달된 템플릿 변수가 기록될 때 HTML 엔티티코드로 변환해 저장되어서 XSS가 발생하지 않음 ( 사용자가 입력한 값 그대로 페이지에 출력X )

innerHTML

document.getElementById("요소의 특정 id").innerHTML = “HTML OR 자바스크립트 코드”
  • 기존 id의 내용을 새로운 내용으로 읽거나 덮어쓰는 속성을 가짐 ( XSS에 위험한 것은 덮어쓰는 속성이고 위의 코드도 덮어쓰는 코드임 )
  • 대체하는 코드를 문자로 보지 않고 실제 태그로 해석해 코드를 삽입함 → 악성 스크립트가 들어가면 그대로 실행됨

2. CSRF(Cross Site Request Forgery)

 - 그럴듯한 웹페이지를 만들어서 이용자의 입력을 유도하고, 이용자가 값을 입력하면 이를 은행이나 중요 포털 사이트 등으로 전송하여 마치 이용자가 동의한 것 같은 요청을 발생시킴

 - 브라우저에 세션 쿠키가 저장되어 있다면 요청에 쿠키가 자동으로 포함되기 때문에 서버는 내가 보낸 요청이라고 생각하고 처리

 

악성 스크립트를 이용자가 실행하도록 하는 방법

 - HTML: img 태그로 이미지 불러오기, form 태그로 입력된 양식 전송 ( 서버에 쿠키와 함께 전송이 되어서 서버는 이용자 인줄 알고 민감한 정보를 처리함 )

 

ex) HTML

<img src=’민감한 요청을 하는 서버 링크' width=0px height=0px>

 

 이미지 크기를 0으로 해서 이용자가 악성 스크립트가 실행됐는지 모르게 할 수 있음.

javascript

window.open('민감한 요청 링크');  //새 창에서 요청 자동 실행, 사용자가 요청 과정 볼 수 있음
location.href = '민감한 요청 링크';  //현재 페이지에서 강제로 이동 시켜 실행, 눈치챌 가능성 있음
location.replace('민감한 요청 링크');  //현재 페이지를 민감한 요청으로 덮어씀, 눈치채기 어려움

 

'Web' 카테고리의 다른 글

WebGoat A1_IDOR  (0) 2026.04.28
WebGoat A3, A5, A7  (0) 2025.09.03