반복된 인증시도 제한 기능 부재

김경민·2022년 6월 27일
1

security

목록 보기
10/15
post-thumbnail

반복된 인증시도 제한 기능 부재

일정 시간 내에 여러 번의 인증을 시도하여도 계정 잠금 또는 추가 인증 방법 등의 충분한 조치가 수행되지 않는 경우, 공격자는 성공할법한 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 시큐어코딩 가이드

Python 시큐어코딩 가이드

0개의 댓글