CSRF 공격이란?

|

개인적인 연습 내용을 정리한 글입니다.
잘못된 내용이 있다면 편하게 댓글 남겨주세요!


CSRF

CSRF(Cross Site Request Forgery) 공격이란 웹 어플리케이션 취약점 중 하나로 인터넷 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 만든는 공격이다.

이러한 CSRF를 통해 해커는 희생자의 권한을 도용해 중요 기능을 실행하는 것이 가능핟. 그치만 CSRF는 해커가 사용자의 컴퓨터를 감염시키거나 서버를 해킹해서 이뤄지는 공격은 아니다. 이러한 CSRF 공격이 이루어지려면 다음 조건이 만족되어야 한다.

  • 위조 요청을 전송하는 서비스에 희생자가 로그인한 상태
  • 희생자가 해커가 만든 피싱 사이트에 접속

이 두 조건을 모두 충족시키기는 어려워보이지만, 사실 그렇지도 않다. 예로들어 페이스북, 로그인과 같은 사이트에는 우리가 보통 자동 로그인을 해놓는 경우가 많다. 이렇게 자동 로그인이 되어있는 상태에서 해커가 만든 피싱사이트(메인, 음란 사이트 등)를 통해 접속을 하기만 하면 공격이 이루어지는 것이다. 또 사용자가 해커가 만든 피싱 사이트를 접속하지 않더라도 해커가 XSS 공격을 성공한 정상 사이트를 통해 CSRF 공격이 수행될 수도 있다.

CSRF 공격 방어

  • Referrer 검증
  • Security Token 사용(CSRF_token)

일반적으로 CSRF 공격 방어는 조회성 (HTTP GET Method) 데이터에는 방어 대상에 두지않고, 쓰기/변경이 가능한 POST, PATCH, DELETE Method에만 적용하면 된다. 물론 정말 중요한 데이터를 조회하거나 GET을 통해 쓰기/변경 등의 동작을 한다면 Get Method에도 방어를 해야할 수도 있다.

Referrer 검증

Back-end 단에서 request의 referrer을 확인하여 domain 이 일치하는 지 검증하는 방법이다.

일반적으로 referrer검증만으로 대부분의 CSRF 공격을 방어할 수 있다. 하지만 같은 도메인 내의 페이지에 XSS 취약점이 있는 경우는 CSRF 공격에 취약해질 수 있다. domain 단위 검증에서 좀 더 세밀하게 페이지 단위까지 일치하는 지 검증을 하면 도메인 내의 타 페이지에서의 XSS 취약점에 의한 CSRF 공격을 방어할 수 있다.

CSRF 토큰

Referrer 검증이 불가한 환경이라면, Security Token을 활용할 수 있다. 우선 사용자의 세션에 임의의 난수값을 저장하고 사용자의 요청마다 해당 난수 값을 포함시켜 전송한다. 이후 Back-end 단에서 요청을 받을 때마다 세션에 저장된 토큰값과 요청 파라미터에 전달되는 토큰값이 일치하는 지 검증한다. 이 방법 또한 같은 도메인 내에 XSS 취약점이 있다면 CSRF 공격에 취약해 진다.


<form>
    {% csrf_token %}
    <input type="text" name="text"/>
    <input type="submit" value="확인"/>
</form>

Django 에서는 자체적인 템플릿을 통해 {% csrf_token %}이라고 form에 넣는 것만으로도 토큰을 주고받을 수 있도록 쉽게 사용이 가능하다.

클라이언트에서 해당 페이지를 접속하게 되면 Django에서 자동으로 csrf 토큰을 클라이언트로 보내어 cookie에 저장하고, POST로 전송할 때 cookie의 csrf 토큰이 함께 전송되어 인증하는 방식이다.


XSS 공격이란?

XSS(Cross-site Scripting)는 웹 상에서 가장 기초적인 취약점 공격방법의 일종으로, 악의적인 사용자(권한이 없는 사용)가 공격하려는 사이트에 스크립트를 넣는 기법을 말한다. 공격에 성공하면 사이트에 접속한 사용자는 삽욉된 코드를 실행하게 되며, 의도치 않은 행동을 수행시키거나 쿠키나 세션 토큰 등의 민감한 정보를 탈취한다. (대부분 자바스크립트를 사용하여 공격하는 경우가 많다.)

공격 방법이 단순하고 가장 기초적이지만, 많은 웹사이트들이 XSS에 대한 방버조치를 해두지 않아 공격을 받는 경우가 많다. 여러 사용자가 접근 가능한 게시판 등에 코드를 삽입하는 경우도 많으며, 경우에 따라서는 메일과 같은 매체를 통해서도 전파가 된다.

XSS 공격은 주로 CSRF 공격을 하기 위해 사용되기 때문에 혼동되기가 쉬운데, CSRF는 특정한 행동을 시키는 것이고 XSS는 자바스크립트를 실행시키는 것으로 이해하면 된다.

git flow 사용해보기

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


git flow install

  • 홈페이지: git flow install
  • macOS: brew install git-flow-avh
  • linux: apt-get install git-flow

Git-flow 구성 살펴보기

git-flow에는 5가지 종류의 브랜치가 존재한다.
항상 유지되는 메인브랜치(master, develop)과 일정 기간동안만 유지되는 보조브랜치(feature, release, hotfix)

master

master 브랜치에 merge된 내역은 새로운 버전이 갱신되었다는 것을 의미한다. 즉, master 브랜치에 변경된 내역이 생기면 최종 버전인 Tag를 통해 Production에 배포된다.

develop

hotfix를 제외한 모든 변경내역이 출발하는 지점이다. develop브랜치의 코드가 안정화되고 배포할 준비가 되면 master를 통해 배포 버전의 태그를 단다.

feature

feature 브랜치는 배포하려고 하는 기능을 개발하는 브랜치다. 기능을 개발하기 시작할 때는 언제 배포할 수 있을지 알수 없다. 기능을 다 완성할 때까지 유지하고 있다가 다 완성되면 develop 브랜치로 병합한다.

  • 브랜치가 생성되는 대상: develop
  • merge 대상: develop

release

release 브랜치는 실제 배포할 상태가 된 경우에 생성하는 브랜치이다.

  • 브랜치가 생성되는 대상: develop
  • merge 대상: develop, master

hotfix

미리 계획되지 않은 브랜치다. 기본적인 동작방식은 release와 비슷하다. 배포 이후에 생긴 치명적인 버그는 즉시 해결해야하기 때문에 문제가 생기면 master 브랜치에 만들어둔 태그 tag로 부터 긴급 수정을 위한 브랜치를 생성한다.

  • 브랜치가 생성되는 대상: master
  • merge 대상: develop, master

즉, 처음에는 master와 develop 브랜치만 존재한다. 이때 develop 또한 master에서부터 시작된 브랜치이다.

새로운 기능에 대한 추가 작업이 있는 경우 develop에서 feature브랜치를 생성하고 해당 feature브랜치에서 새로운 기능을 개발한다. 즉, feature 브랜치는 항상 develop브랜치에서부터 시작하게 된다. 기능 추가 작업이 완료되었다면 feature브랜치는 develop 브랜치로 merge를 하게된다.

develop 브랜치에 feature 브랜치에서 만든 기능들이 merge 되었다면 QA를 하기 위해 develop브랜치에서부터 release 브랜치를 생성한다. QA를 진행하면서 발생한 버그들은 모두 release 브랜치에서 수정이 된다. QA를 무사히 통과했다면 release 브랜치를 master와 develop 브랜치에 merge를 한다.

마지막으로 출시된 master 브랜치에서 버전 태그를 추가하면 최종적으로 우리가 개발하고자했던 모든 기능들은 master 브랜치에 포함됨으로써 해당 기능을 출시할 수 있게 된다.

git flow 흐름 살펴보기

git flow

이미지원본: 우아한형제들 기술블로그

  • Upstream Remote Repository: 개발자들이 공유하는 저장소, 최신 코드가 저장되어 있는 원격저장소
  • Origin Remote Repository: Upstream Repository를 Fork한 원격 개인 저장소
  • Local Repository: 내 컴퓨터에 저장되어있는 개인 저장소

git flow 간단하게 시작해보기

  • Local Repository에서 작업을 완료한 후 작업 브랜치를 Origin Repository에 push
  • Github에서 Origin Repositorydp push한 브랜치를 Upstream Repository로 merge하는 pull request 생성
  • 코드리뷰를 거친 뒤 merge
  • 다시 새로운 작업을 할때 Local Repositorydptj Upstream Repository를 pull
1. Upstream Repository를 나의 Origin Remote Repository에 Fork
2. 해당 git url을 clone

git flow init

# 기본 설정이 develop에 되어있을 것
git flow feature start [생성할 branch name]
git merge develop
git flow feature finish [삭제할 branch name]

# release
git flow release start [생성할 release name]

# release를 master, develop에 merge
# tag로 master의 버전 확인
git flow release finish [완료할 release name]


git pull origin develop #이 상황 무한 반복

feature 브랜치에서의 참고사항

  • feature 브랜치에서 작업을 하는 동안은 develop 브랜치의 변경사항을 자주 동기화해준다.
  • 반대로 feature 브랜치의 변경사항은 develop 브랜치로 merge하는 경우는 기능 구현이 끝났을때, 딱 한번이다.
  • 작업을 완료한 feature브랜치는 삭제해도 괜찮다.

release 브랜치에서의 참고사항

  • release의 수정사항들은 develop으로 자주 동기화해준다.
  • 하지만 release 브랜치 생성 후의 develop 브랜치의 수정사항은 동기화 하지 않는다.
    • 해당 develop 브랜치의 변경사항은 다음 배포 버전에 대한 것이기 때문에 다음 release 생성까지 merge하지 않는다.

non-fast-forward 에러 해결하기

|

개인적인 연습 내용을 정리한 글입니다.
잘못된 내용이 있다면 편하게 댓글 남겨주세요!


문제 상황

  • github에서 저장소 생성 후 저장소 주소를 remote에 입력(git remote add origin https://github…..)
  • 로컬에서도 정상적으로 초기화(git init)
  • git pull 또는 git merge 명령이 동작하지 않음
  • git push origin master시 [rejected] master -> master (non-fast-forward)에러 발생
git push -u origin master  

To github.com:
! [rejected]        master -> master (non-fast-forward)

error: 레퍼런스를 'git@github.com:'에 푸시하는데 실패했습니다
힌트: 현재 브랜치의 끝이 리모트 브랜치보다 뒤에 있으므로 업데이트가
힌트: 거부되었습니다. 푸시하기 전에 ('git pull ...' 등 명령으로) 리모트
힌트: 변경 사항을 포함하십시오.
힌트: 자세한 정보는 'git push --help'"Note about fast-forwards' 부분을
힌트: 참고하십시오.

원인

깃헙에 생성된 원격 저장소와 로컬에 생성된 저장소 간 공통분모가 없는 상태에서 병합하려는 시도로 인해 발생.
기본적으로 관련 없는 두 저장소를 병합하는 것은 안되도록 설정되어 있음.

해결방법

아래와 같이 git pull 시에 –allow-unrelated-histories 옵션 추가하여 관련 없었던 두 저장소를 병합하도록 허용

git pull origin master --allow-unrelated-histories

pycharm 글자가 안써지는 경우 (IdeaVim 해제)

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


맥북 초기화를 한 다음 파이참을 재 설치하고나니 갑자기 파이참에 글자가 써지질 않는다.

  • 경로: Preferences > Plugins > IdeaVim 체크 옵션 해제
pycharm_preferences

체크 박스 해제 후 하단의 apply 또는 OK버튼을 눌러주면 되며,

이후 파이참을 재시작하겠냐는 메시지와 함께 재시작하면 적용되어 사용가능하다.

ideavim 해제를 하지않고 사용할 경우 a를 누르면 글자 입력이 가능하다.

Ubuntu에서 pyenv 통해 python 설치시 발생하는 에러 (zipimport.ZipImportError)

|

개인 프로젝트를 정리한 것입니다.
잘못된 내용이 있다면 편하게 댓글 남겨주세요!


ec2 연결과정에서 ubuntu에 접속 후 pyenv 를 통해 python을 설치하려고 하자 아래와 같은 에러가 발생했다.

~ pyenv install 3.7.1
zipimport.ZipImportError: cant decompress data; zlib not available
Makefile:1099: recipe for target 'install' failed
make: *** [install] Error 1

일반적인 경우에 (ubuntu환경이 아닌경우) 이러한 에러가 발생하는 이유는

Xcode Command Line Tools가 기본적으로 설치해주던 라이브러리 패키지를 설치해주지 않게 바뀌어 발생하는 문제라고 한다.

따라서 이 라이브러리 패키지를 깔아주면 되고 해당 환경에 맞춰서 install 해주면 된다.

pyenv Common build problem

해당 링크를 통해 들어가 ubuntu 환경에 맞는

  • Ubuntu
    sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
    libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
    xz-utils tk-dev libffi-dev liblzma-dev python-openssl git
    

설치 완료 후 pyenv install 3.7.1을 해주면 안정적으로 파이썬 설치가 완료되었다.