Flask 시 뮬 레이 션 CSRF 공격 실현 방법

CSRF
4.567914.전체 조합 은 4.567914 로 역 을 넘 어 위 조 를 요청 합 니 다.
4.567914.공격 자가 당신 의 신분 을 도용 하여 당신 의 이름 으로 악의 적 인 요 구 를 보 내 는 것 을 말 합 니 다.
포함:당신 의 명의 로 메 일 을 보 내 고,메 시 지 를 보 내 고,당신 의 계 정 을 훔 치고,심지어 상품 을 구 매 하고,가상 화폐 이 체 를 합 니 다.
문제:개인 프라이버시 누설 및 재산 안전.
CSRF 공격 설명도
클 라 이언 트 가 서버 에 접근 할 때 서버 와 보안 검증 을 하지 않 았 습 니 다.

CSRF 방지
1.클 라 이언 트 가 백 엔 드 에 인터페이스 데 이 터 를 요청 할 때 백 엔 드 는 응답 중인 쿠키 에 csrf 를 설정 합 니 다.token 의 값
2.Form 폼 에 숨겨 진 필드 를 추가 합 니 다.값 도 csrf 입 니 다.token
3.사용자 가 제출 을 클릭 할 때 이 두 값 을 가지 고 배경 으로 요청 합 니 다.
4.백 엔 드 에서 요청 을 받 으 면 다음 과 같은 이벤트 가 발생 합 니 다.•쿠키 에서 csrf 를 꺼 냅 니 다.token
  • 폼 데이터 에서 숨겨 진 csrf 꺼 내기token 의 값
  • 비교 하 다
    5.비교 후 두 값 이 같 으 면 정상 적 인 요청 임 을 의미 합 니 다.만약 에 받 지 못 하거나 다 르 면 정상 적 인 요청 이 아니 라 다음 작업 을 수행 하지 않 는 것 을 의미 합 니 다.
    코드 데모
    csrf 검사 가 진행 되 지 않 은 WebA
    백 엔 드 코드 구현
    
    from flask import Flask, render_template, make_response
    
    from flask import redirect
    
    from flask import request
    
    from flask import url_for
    
     
    
    app = Flask(__name__)
    
     
    
     
    
    @app.route('/', methods=["POST", "GET"])
    
    def index():
    
      if request.method == "POST":
    
        #             
    
        username = request.form.get("username")
    
        password = request.form.get("password")
    
     
    
        if not all([username, password]):
    
          print('    ')
    
        else:
    
          print(username, password)
    
          if username == 'laowang' and password == '1234':
    
            #     ,      cookie       
    
            response = redirect(url_for('transfer'))
    
            response.set_cookie('username', username)
    
            return response
    
          else:
    
            print('    ')
    
     
    
      return render_template('temp_login.html')
    
     
    
     
    
    @app.route('/transfer', methods=["POST", "GET"])
    
    def transfer():
    
      #  cookie      
    
      username = request.cookies.get('username', None)
    
      #       ,      
    
      if not username:
    
        return redirect(url_for('index'))
    
     
    
      if request.method == "POST":
    
        to_account = request.form.get("to_account")
    
        money = request.form.get("money")
    
        print('       ,                ')
    
        return '   %s    %s   ' % (money, to_account)
    
     
    
      #       
    
      response = make_response(render_template('temp_transfer.html'))
    
      return response
    
     
    
    if __name__ == '__main__':
    
      app.run(debug=True, port=9000) 
    전단 로그 인 페이지 코드
    
    <!DOCTYPE html>
    
    <html lang="en">
    
    <head>
    
      <meta charset="UTF-8">
    
      <title>  </title>
    
    </head>
    
    <body>
    
     
    
    <h1>    A,    </h1>
    
     
    
    <form method="post">
    
      <label>   :</label><input type="text" name="username" placeholder="      "><br/>
    
      <label>  :</label><input type="password" name="password" placeholder="     "><br/>
    
      <input type="submit" value="  ">
    
    </form>
    
     
    
    </body>
    
    </html>
    전단 이체 페이지 코드
    
    <!DOCTYPE html>
    
    <html lang="en">
    
    <head>
    
      <meta charset="UTF-8">
    
      <title>  </title>
    
    </head>
    
    <body>
    
    <h1>    A,    </h1>
    
     
    
    <form method="post">
    
      <label>  :</label><input type="text" name="to_account" placeholder="         "><br/>
    
      <label>  :</label><input type="number" name="money" placeholder="       "><br/>
    
      <input type="submit" value="  ">
    
    </form>
    
     
    
    </body>
    
    </html>
    테스트 를 실행 합 니 다.로그 인 하지 않 은 상태 에서 이체 페이지 에 직접 들 어 갈 수 없 으 면 이 체 를 테스트 하 는 데 성공 합 니 다.
    공격 사이트 B 의 코드
    백 엔 드 코드 구현
    
    from flask import Flask
    
    from flask import render_template
    
     
    
    app = Flask(__name__)
    
     
    
    @app.route('/')
    
    def index():
    
      return render_template('temp_index.html')
    
     
    
    if __name__ == '__main__':
    
      app.run(debug=True, port=8000)  
    전단 코드 구현
    
    <!DOCTYPE html>
    
    <html lang="en">
    
    <head>
    
      <meta charset="UTF-8">
    
      <title>Title</title>
    
    </head>
    
    <body>
    
     
    
    <h1>    B</h1>
    
     
    
    <form method="post" action="http://127.0.0.1:9000/transfer">
    
      <input type="hidden" name="to_account" value="999999">
    
      <input type="hidden" name="money" value="190000" hidden>
    
      <input type="submit" value="       ">
    
    </form>
    
     
    
    </body>
    
    </html>
    테스트 를 실행 하여 사용자 가 사이트 A 에 로그 인 한 상태 에서 사이트 B 버튼 을 클릭 하면 위조 방문 을 실현 할 수 있다.
    사이트 A 에서 csrf 시 뮬 레이 션 실현token 검사 절차
    생 성 csrf 추가token 의 함수
    
    #    csrf_token   
    def generate_csrf():
      return bytes.decode(base64.b64encode(os.urandom(48)))
    이체 페이지 를 렌 더 링 할 때 다음 과 같은 몇 가지 일 을 합 니 다.
    csrf 생 성token 의 값
  • 이체 페이지 로 돌아 가 는 응답 에 csrf 를 설정 합 니 다.쿠키
    csrftoken 은 폼 의 숨겨 진 필드 에 저 장 됩 니 다
  • 
    @app.route('/transfer', methods=["POST", "GET"])
    
    def transfer():
    
      ...
    
      #    csrf_token   
    
      csrf_token = generate_csrf()
    
     
    
      #       ,   csrf_token     
    
      response = make_response(render_template('temp_transfer.html', csrf_token=csrf_token))
    
      #   csrf_token cookie ,      
    
      response.set_cookie('csrf_token', csrf_token)
    
      return response
    이체 템 플 릿 폼 에 csrf 추가token 숨 김 필드
    
    <form method="post">
    
      <input type="hidden" name="csrf_token" value="{{ csrf_token }}">
    
      <label>  :</label><input type="text" name="to_account" placeholder="         "><br/>
    
      <label>  :</label><input type="number" name="money" placeholder="       "><br/>
    
      <input type="submit" value="  ">
    
    </form>  
    테스트 를 실행 하고 이체 페이지 에 들 어간 후 쿠키 와 html 소스 코드 를 봅 니 다.

    이체 논 리 를 실행 하기 전에 csrftoken 검사
    
    if request.method == "POST":
    
      to_account = request.form.get("to_account")
    
      money = request.form.get("money")
    
      #        csrf_token
    
      form_csrf_token = request.form.get("csrf_token")
    
      #    cookie    csrf_token
    
      cookie_csrf_token = request.cookies.get("csrf_token")
    
      #     
    
      if cookie_csrf_token != form_csrf_token:
    
        return 'token    ,       '
    
      print('       ,                ')
    
      return '   %s    %s   ' % (money, to_account)
    테스트 를 실행 하면 사용자 가 사이트 A 에서 직접 조작 하 는 데 문제 가 없 으 며 사이트 B 에 가서 조작 을 한 결과 계좌 이체 가 성공 하지 못 했 습 니 다.사이트 B 가 폼 에 있 는 csrf 를 얻 지 못 했 기 때 문 입 니 다.token 의 숨겨 진 필드,그리고 브 라 우 저 는 같은 소스 정책 을 가지 고 있 습 니 다.사이트 B 는 사이트 A 의 쿠키 를 얻 을 수 없 기 때문에 크로스 오 버 요청 위조 문 제 를 해결 하 였 습 니 다.
    Flask 프로젝트 에서 CSRF 공격 해결
    Flask 에서 Flask-wtf 확장 은 완벽 한 csrf 보호 체 계 를 가지 고 있 습 니 다.우리 개발 자 에 게 사용 하기 가 매우 간단 합 니 다.
    FlaskForm 에서 검증 실현
    응용 프로그램의 secret 설정key
    암호 화 생 성 에 사용 되 는 csrftoken 의 값
    
    app.secret_key = "#          #"
    템 플 릿 폼 에 다음 코드 를 추가 합 니 다.
    
    <form method="post">
    
      {{ form.csrf_token() }}
    
      {{ form.username.label }} {{ form.username }}<br/>
    
      {{ form.password.label }} {{ form.password }}<br/>
    
      {{ form.password2.label }} {{ form.password2 }}<br/>
    
      {{ form.submit }}
    
    </form>
    렌 더 링 된 전단 페이지 는:

    설정 완료,쿠키 의 csrftoken 은 우리 가 관심 을 가 질 필요 가 없습니다.자동 으로 설정 해 줍 니 다.
    단독으로 사용 하 다
    응용 프로그램의 secret 설정key
    암호 화 생 성 에 사용 되 는 csrftoken 의 값
    
    app.secret_key = "#          #"
    fllask 가 져 오기wtf.csrf 의 CSRFprotect 클래스 를 초기 화하 고 초기 화 할 때 app 와 연결 합 니 다.
    
    from flask.ext.wtf import CSRFProtect
    CSRFProtect(app)
    템 플 릿 에 폼 이 있 으 면 아무것도 할 필요 가 없습니다.이전 과 마찬가지 로:
    
    <form method="post">
    
      {{ form.csrf_token }}
    
      ...
    
    </form>
    그러나 템 플 릿 에 폼 이 없다 면 CSRF 토 큰 이 필요 합 니 다.
    
    <form method="post" action="/">
      <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
    </form>
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기