일정 시간 내에 여러 번의 인증을 시도하여도 계정 잠금 또는 추가 인증 방법 등의 충분한 조치가 수행되지 않는 경우, 공격자는 성공할법한 ID와 비밀번호들을 사전(Dictionary)으로 만들고 무차별 대입(brute-force)하여 로그인 성공 및 권한 획득이 가능하다.
Django 는 사용자 인증 요청 횟수에 대해 제어하지 않는다.
인증 시스템에 대한 무차별 대입 공격으로부터 보호하기 위해 Django 플러그인 (django-defender) 또는 웹 서버 모듈을 사용하여 요청을 제한할 수도 있다.
1: import hashlib
2: from django.shortcuts import render
3:
4: def login(request):
5: user_id = request.POST.get('user_id', '')
6: user_pw = request.POST.get('user_pw', '')
7:
8: sha = hashlib.sha256()
9: sha.update(user_pw)
10:
11: hashed_passwd = get_user_pw(user_id)
12:
13: # 인증시도에 따른 제한이 없어 반복적인 인증 시도가 가능
14: if sha.hexdigest() == hashed_passwd:
15: return render(request, '/index.html', {'state':'login_success'})
16: else:
17: return render(request, '/login.html', {'state':'login_failed'})
1: import hashlib
2: from django.shortcuts import render
3:
4: LOGIN_TRY_LIMIT = 5
5:
6: def login(request):
7: user_id = request.POST.get('user_id', '')
8: user_pw = request.POST.get('user_pw', '')
9:
10: # 로그인 실패기록 가져오기
11: login_fail = models.LoginFail.objects.filter(user_id)
12: # 로그인 실패횟수 초과로 인해 잠금된 계정에 대한 인증 시도 제한
13: if login_fail.count() >= LOGIN_TRY_LIMIT:
14: return render(request, '/account_lock.html', {'state':'account_lock'})
15: else:
16: sha = hashlib.sha256()
17: sha.update(user_pw)
18:
19: hashed_passwd = get_user_pw(user_id)
20: if sha.hexdigest() == hashed_passwd:
21: models.LoginFail.objects.filter(user_id).delete()
22: return render(request, '/index.html', {'state':'login_success'})
23: else:
24: # DB 로그인 실패횟수 기록
25: models.LoginFail.objects.create(user_id)
26: return render(request, '/login.html', {'state':'login_failed'})
27:
출처: 행정안전부 인터넷진흥원 Python 시큐어코딩 가이드