6 minute read

Day 39

웹 보안


  • 웹 보안이란 웹 사이트의 취약점을 공격하는 기술적 위협으로, 웹 페이지를 통하여 권한이 없는 시스템에 접근하거나 데이터 유출 및 파괴와 같은 행위를 말한다.

공격 기법들


SQL Injection

정의

  • 서버에서 실행되는 SQL을 악의적으로 이용하는 공격
  • 기존 SQL에 악의적인 SQL을 삽입한다.
  • 데이터 탈취, 삭제 등이 가능하다.

방어

  • SQL에서 특별한 의미를 가지는 문자를 이스케이프 한다.
    • ex) \n, \t, |, /, &, #,…
  • 준비된 선언을 사용한다.
    • placeholder를 담은 SQL을 먼저 DB에 보낸 후 placeholder에 해당하는 입력값을 DB에 보내는 방식
  • 요즘은 라이브러리, 프레임워크에서 아주 잘 막아준다.

심화 공격기법

Error based SQL Injection
  • 옛날 웹사이트는 발생한 에러를 웹사이트에 그대로 노출하는 경우가 많았다.
  • 그래서 일부러 SQL 에러를 발생시켜 원하는 정보(쿼리문 추측, DB명, 테이블명) 등을 취득할 수 있다.
  • 특정 테이블에 대한 공격을 할 수 있다.
Blind SQL Injection
  • DB명, table명, 속성명 추출에 특화된 공격 기법
  • SQLMAP이라는 자동화된 툴을 이용하기도 한다.
Union SQL Injection
  • Union 명령을 이용하여 정보를 취득한다.

XSS

정의

  • Cross-site Scripting
  • 웹 페이지에 악성 스크립트를 삽입하는 공격
  • 사이트 이용자 정보를 탈취한다.

방어

  • HTML 필터링을 한 후 DB에 저장
  • 만약을 위해 프론트엔드에서도 필터링한다.

심화 공격기법

Stored XSS
  • 게시판에 js코드를 작성해두면 사용자가 헤당 게시글을 클릭해서 확인하는 순간 해당 스크립트가 실행되면서 사용자의 쿠키정보나 session 정보를 탈취하는 공격 기법
Reflected XSS
  • 검색어등을 보여주는 곳에 스크립트를 심는 공격
  • URL을 사용자에게 누르게 만들면 공격 성공
DOM based XSS
  • DOM에 악의적인 스크립트를 심는 공격
  • 브라우저가 해석하는 단계에서 발생되는 공격

CSRF Attack

정의

  • Cross-site Request Forgery
  • 공격자가 사용자를 이용하여 웹 서버에 악의적인 요청을 보내는 공격

방어

  • Referrer Check : 허용한 도메인만 요청 허락하도록 설정
  • CSRF Token : 모든 요청에 토큰을 발급하여 서버에서 검증
  • CAPTCHA : 사람이 요청한 것이 맞는지 검증

Command Injection

정의

  • 애플리케이션에 사용되는 시스템 명령에 악의적인 명령어를 삽입하는 공격(WebShell attack)
  • 서버 root 권한을 취득할 수 있다.

방어

  • 가급적 시스템 함수는 사용하지 않는다.
  • 민감한 문자를 필터링한다 ex) , &, ;, >, <, …

FileUpload Attack

정의

  • 악성 스크립트 파일을 업로드하는 공격
  • 업로드 후 파일 위치를 찾아 실행시키면 공격 성공

방어

  • 확장자 / 파일 타입 검사
  • 업로드 파일을 난수화하여 저장
  • 특수 문자가 포함된 경우 업로드 금지

JavaScript Injection

정의

  • Client-side에서 JavaScript를 삽입시키는 공격
  • 크롬 console 등을 통해 조작이 가능하다.
  • Client-side에 민감한 데이터를 넣을 경우 탈취 가능

방어

  • Client-side엔 민감한 정보를 절대 넣지 않는다.
  • 데이터 유효성 검사가 필요한 경우 서버와 통신한다. 중요한 데이터는 Client와 Server 모두에서 검사한다.

DDos

정의

  • Distributed Denial of Service
  • 서버에 비정상적으로 많은 트래픽을 보내는 공격
  • 서비스가 마비되고 많은 비용이 소모된다.

방어

  • 제일 단순한데 제일 막기 어렵다.
  • 확장 가능한 서비스 구조 설계
  • IP 필터링
  • Rate limit
  • 솔루션 구매

Dictionary Attack

정의

  • 미리 사전에 등록해놓은 문자열을 암호로 대입하는 공격
  • Brute Force의 일종

방어

  • 의미있는 문자열은 암호로 등록 못하도록 설정
  • Account Lockout Policy
  • 2-factor 인증

Rainbow Table

정의

  • 해시 함수를 이용한 평문을 모두 저장시켜놓은 표를 이용하여 순차적 대입을 통해 비밀번호를 알아내는 공격 방법이다.

방어

  • Salt를 사용한다.
  • Key Stretching을 사용한다.
  • PBKDF2, Bcrypt 등의 암호화 알고리즘을 사용한다.

알아야 하는 보안 정책들


CORS

  • Cross-Origin Resource Sharing
  • 개발자가 지정한 프로토콜, 도메인, 포트가 아니라면 리소스를 가져올 수 없는 보안 정책이다.
  • Response header를 보고 허용 여부를 브라우저가 정한다.
  • 브라우저마다 구현이 다를 수 있다.

CSP

  • Content-Security-Policy
  • 실행 가능한 리소스에 대한 WhiteList를 정하는 정책
  • 웹 사이트가 허용되지 않은 리소스를 요청하지 못하도록 막는다.
  • XSS 방지에 도움이 된다.
  • 기본적으로 inline script는 실행을 막는다.
  • 메타 태그 혹은 HTTP Header로 설정 가능하다.

CSP_example

HTTPS

  • HTTP 프로토콜의 암호화된 버전
  • 소켓 통신에 암호화된 데이터를 전송한다.
  • SSL 인증서를 이용한다.

HTTPS_원리

axios를 이용한 네트워크 API 실습


  • axios를 이용한 네트워크 API를 호출하고 제어하는 방법에 대해 알아본다.
  • axios는 브라우저나 nodejs에서 사용가능한 http client library이다.
  • JSON Placeholder : 몇 가지 REST API를 테스트할 수 있는 endpoint를 무료로 제공하는 사이트
  • useReducer() : action.type에 따라서 사용자가 원하는대로 state를 변경해줄 수 있다. 여러가지의 행위들을 각각의 상태와 setter로 정의하는 것보다 하나의 useReducer()를 이용하는 것이 훨씬 간편하다. 단, async, await를 통한 네트워크 호출을 할 수 없다.
  • 컴포넌트는 최대한 순수할수록 좋다.
    • 사이드 이펙트를 걱정하지 않아도 좋다.
    • 확장에 유연하다.
    • 테스트가 쉽다.
    • 그래서 API 호출하는 건 컴포넌트에 삽입하기 보다는 App에서 호출하여 결과를 component에 넘겨서 처리를 해줘야 한다.
  • Provider에 API 호출하는 함수들을 넘겨줘서 provider내에서 그 함수를 실행시키도록 만든다.
  • axios를 이용해서 데이터를 호출하고 최대한 컴포넌트는 순수하게 유지하면서 context API를 이용하여 데이터를 제어하고 useReducer를 이용하여 상태를 관리하는 방법을 배웠다.

SPA의 역사


SPA가 등장하기까지의 과정

  • 웹 애플리케이션의 시초는 MPA(Multi Page Application)이였다.

MPA_원리

  • 점점 브라우저의 요구사항이 많아졌다.(화려한 애니메이션, 멀티미디어의 재생, 동적인 데이터 전송 => MPA로는 사용자에게 불편하게 되었다.)
  • 이를 해결하기 위해 AJAX(Asynchronous JavaScript and XML)가 등장하였다.
  • 대표적으로 페이지 이동없이 볼 수 있는 구글 지도가 AJAX의 예시이다.
  • Hashbang : URI Fragment(주소 맨 뒤 #부분을 뜻한다.)를 읽은 후 해당 경로에 해당하는 페이지를 Ajax를 불러오는 방식 2010년 쯤부터 유행했다.
  • Blick 제거, 로딩 표시 가능 → UX 개선
  • Hashbang의 가장 큰 문제점 = 검색 엔진에 잡히지 않는다.
  • History API(pushState(), replaceState())와 같은 기능이 생기면서 페이지 이동없이 브라우저의 주소를 변경할 수 있게 되었다.
  • pushState + ajax = pjax
  • Github Co-founder가 jquery+pjax를 만들면서 더욱 유행하게 되었다.

react-router


  • 공식 library는 아니다.
  • React Router tutorial
  • Page 컴포넌트들은 더러울 수 밖에 없다.
  • 하지만 Page 컴포넌트에 들어가는 컴포넌트들은 웬만하면 순수해야 한다.

Router 추가하기

  1. Broswer Router를 생성하고 route를 구성한다.
  2. Not Found Error를 처리한다.
  3. Contact UI를 route한다.
  4. 중첩 routes들을 관리한다.
    • 최상위 route의 children 속성에 배열을 두고 해당 배열에 자식 routes들을 열거한다.
    • 최상위 route의 어떤 요소에 자식 요소들을 배치할지 Outlet으로 결정한다.
  5. link를 클릭했을 때 full document request를 한다. 하지만 Link태그를 이용하여 Client Side Routing을 수행하면 서버에 요청을 보내지 않고 URL을 업데이트하도록 해준다.
  6. Loading Data
    • React Router는 data들을 route components로 쉽게 이동시켜줄 수 있는 data conventions이 존재한다.
    • 데이터를 가져올 때 2가지 API를 사용할 것이다. loaderuseLoaderData이다.
  7. Data Writes + HTML Forms
  8. Creating Contacts

React 배우기 (11) : useImperativeHandle


  • 평범한 component에서 쓰이기 보다 라이브러리 등의 특수한 컴포넌트에서 자주 사용되는 특수한 훅이다.
  • ref를 통해 사용자 정의 함수를 만들어서 상위 컴포넌트에 전달할 수 있다. 즉, 상위 컴포넌트에서 하위 컴포넌트를 함수호출로 제어할 수 있다.
  • 라이브러리를 만든다면 유용하게 쓰일 수 있다.
  • 상위 컴포넌트에서 하위 컴포넌트를 이용하기 위한 함수들을 정의해주는 훅이다.

컴포넌트 심화


  • 컴포넌트를 잘 설계하기 위한 방법에 대해 소개한다.
  • 컴포넌트는 어떻게 설계할까?
  • 아키텍쳐는 우리가 일을 잘하기 위한 방법이다.
  • 모듈을 잘 나눠서 구현하는 것이 좋다.
  • 모듈에서 중요한 것은 응집도와 결합도이다.

응집도

  • 모듈 내에 포함된 요소들이 서로 연괸되어 있는 정도
  • 즉, 모듈 내 기능들이 하나의 책임으로 잘 뭉쳐있는지를 나타낸다.
  • 높은 응집도일수록 좋은 설계이다.
  • 응집도가 중요한 이유는 응집도가 높을 수록 하나의 책임에 집중하고 독립성을 높이면서 우리가 수정하기 위한 요소를 빠르게 찾을 수 있기 때문이다.

높은 응집도를 만들기 위한 방법

공통 폐쇄 원칙

  • 같은 이유로 동일한 시점에 변경되는 기능을 하나의 모듈로 묶어야 한다는 원칙
  • 객체지향 원칙인 단일 책임 원칙을 컴포넌트 관점으로 바라본 것
  • 과하게 적용하면 재사용성이 줄어들 수 있다.
  • ex) 컴포넌트에 종속된 기능, 스타일 등을 묶기

공통 재사용 원칙

  • 모듈 내의 기능들을 함께 재사용이 될 수 있어야 한다는 원칙
  • 반대로 이야기하면 함께 재사용이 될 수 없다면 분리해야한다는 뜻
  • 과하게 적용되면 개발 용이성이 줄어들 수 있다.

원칙들

  • 무엇이 옳은가 정답은 없다. 상황에 따라 이 사이를 적절하게 조절하는 것이 개발자의 능력이다.

결합도

  • 다른 모듈과의 의존성에 대한 정도
  • 모듈과 모듈 사이의 관계가 어느 정도인지를 나타낸다.
  • 낮은 결합도일 수록 좋은 설계
  • 결합도가 높을수록 수정에 대해 영향을 미치는 정도가 증가한다.
  • 따라서 낮은 결합도일수록 안정성이 증가한다.
  • 결합도가 높으면 어디서 버그가 터질지 모른다.

낮은 결합도를 만들기 위한 방법

안정된 의존성 원칙

  • 의존할 바엔 더 안정된 모듈을 의존한다는 원칙
  • 의존하는 모듈이 적고 의존되는 모듈이 많을 수록 안정적인 모듈(컴포넌트)이다.
  • 안정성 지표는 Fan-out / (Fan-in + Fan-out)으로 계산 가능
    • Fan-out은 의존되는 것
    • Fan-in은 의존하는 것
    • 0에 가까울수록 안정되고 1에 가까울수록 불안정한 컴포넌트
  • 당연하지만 변화에 무겁도록 만들어야 한다.

안정된 추상화 원칙

  • 컴포넌트는 안정된 만큼 추상적이어야 한다는 원칙
  • 추상성은 추상 클래스 수/ 클래스 수로 계산된다.
    • React 컴포넌트는 UI 요소가 포함되어 있어 이런식으로 계산할 수 없다.
  • 레이어를 잘 나눠야 한다.

React에서 컴포넌트 추상성 계산 방법


  • Domain, Style, Semantic, Data, Network, Event, Route, Device, Context
  • 컴포넌트에서 고정적으로 사용된다면 해당된다.
  • 위 요소 중 1 - 해당하는 부분 / 9로 계산해보자
  • 외부에서 주입받아 제한이 없다면 추상적인 것으로 본다.
    • 단, 주입받는 요소가 특정 값으로 제한된다면 구체적인 것으로 본다.
  • 대략적으로 계산하는 방법이기 때문에 정확할 수는 없다.

컴포넌트를 나누는 방식


  • 프론트엔드는 변화가 큰 소프트웨어 백엔드처럼 기능, 도메인 단위로 레이어를 나누기엔 애매하다.
  • 웬만하면 추상화 단위로 나누는 것이 편하다.

결론


  • 경험과 숙련도가 높을수록 좋은 컴포넌트를 작성할 수 있다.

Categories:

Updated: