[시큐어코딩 가이드] 2-2-1. 적절한 인증 없는 중요 기능 허용

보안기능

보안기능(인증, 접근제어, 기밀성, 암호화, 권한관리 등)을 부적절하게 구현 시 발생할 수 있는 보안약점에는 적절한 인증 없는 중요기능 허용, 부적절한 인가 등이 있다.

 

적절한 인증 없는 중요 기능 허용

정의

보안기능을 부적절하게 구현 시 발생할 수 있는 보안약점

 

안전한 코딩기법

클라이언트의 보안 검사를 우회하여 서버에 접근하지 못하도록 설계하고 중요한 정보가 있는 페이지는 재인증을 적용

 

코드예제

다음은 안전하지 않은 코드 예제로, 패스워드 수정 시 수정을 요청한 패스워드와 DB에 저장된 패스워드 일치 여부를 확인하지 않고 처리하고 있으며, 패스워드 재확인 절차도 생략된 취약한 코드입니다.

<!--success.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>SUCCESS</title>
</head>
<body>
    <h2>SUCCESS</h2>
    <p>{{ msg }}</p>
</body>
</html>
<!--form.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form method="post">
        {% csrf_token %}
        <label>
            <input type="text" name="new_password"/>
        </label>
        <input type="submit" value="패스워드변경"/>
    </form>
</body>
</html>
#적절한 인증 없는 중요 기능 허용(안전X)
def update_password_from_db(user, sha_):
    pass
def change_password_bad(request):
    if request.method == 'GET':
        return render(request, 'form.html')

    new_pwd = request.POST.get('new_password')
    user = '%s' % escape('request.session["userId"]')
    sha = hashlib.sha256(new_pwd.encode())
    update_password_from_db(user, sha.hexdigest())

    return render(request, 'success.html', {'msg': '패스워드 변경'})

 

서버를 실행시켜 'http://127.0.0.1:8000/secure/change_password_bad/'를 주소창에 입력하면 패스워드를 입력하고 변경하는 폼이 나타납니다. 패스워드에 아무 값이나 넣고 변경버튼을 누르면 변경성공 화면이 뜹니다.

 

다음은 안전한 코드예제로, DB에 저장된 패스워드와 변경을 요청한 패스워드 일치 여부를 확인하고, 패스워드 재확인 절차도 포함된 코드입니다.

<!--error.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ERROR</title>
</head>
<body>
    <h2>ERROR</h2>
    <p>{{ msg }}</p>
</body>
</html>
<!--form.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form method="post">
        {% csrf_token %}
        <label>
            <input type="text" name="new_password"/>
            <input type="text" name="current_password"/>
        </label>
        <input type="submit" value="패스워드변경"/>
    </form>
</body>
</html>
#적절한 인증 없는 중요 기능 허용(안전O)
def get_password_from_db(user):
    return hashlib.sha256('abc1234'.encode()).hexdigest()

@login_required
def change_password_good(request):
    if request.method == 'GET':
        return render(request, 'form.html')

    new_pwd = request.POST.get('new_password')
    cmt_pwd = request.POST.get('current_password')

    user = '%s' % escape('request.session["userId"]')

    cmt_h = hashlib.sha256(cmt_pwd.encode())
    h_pwd = cmt_h.hexdigest()

    old_pwd = get_password_from_db(user)

    if old_pwd == h_pwd:
        new_h = hashlib.sha256(new_pwd.encode())
        update_password_from_db(user, new_h.hexdigest())
        return render(request, 'success.html', {'msg': '패스워드 변경'})
    else:
        return render(request, 'error.html', {'msg': '패스워드가 일치하지 않습니다.'})

 

서버를 실행시켜 'http://127.0.0.1:8000/secure/change_password_good/'을 주소창에 입력하면 패스워드를 입력하고 변경하는 폼이 나타납니다. 첫번째 입력칸은 새로운 패스워드, 두 번째 입력칸은 현재 패스워드(abc1234)를 넣는 것입니다.

 

첫 번째 칸: apple123 / 두 번째 칸: abababab

 

첫 번째 칸: apple123 / 두 번째 칸: abc1234

 

 

 

보안기능/적절한 인증 없는 중요 기능 허용

[참고문헌] Python 시큐어코딩 가이드(2022) / KISA(한국인터넷진흥원)