[시큐어코딩 가이드] 2-1-10. LDAP 삽입

LDAP 삽입

정의

입력값을 적절한 처리 없이 LDAP 쿼리문이나 결과의 일부로 사용하는 경우, LDAP 쿼리문이 실행될 때 공격자는 LDAP 쿼리문의 내용을 마음대로 변경할 수 있으며, 이로 인해 프로세스가 명령을 실행한 컴포넌트와 동일한 권한을 가지고 동작하게 된다.

 

안전한 코딩기법

기본적인 방어법은 유효성 검사이다.

  • 올바른 인코딩 함수를 사용해 모든 변수 이스케이프 처리
  • 화이트리스트 방식의 입력값 유효성 검사
  • 민감한 정보(사용자 패스워드 등)가 포함된 필드 인덱싱
  • LDAP 바인딩 계정에 할당된 권한 최소화

 

코드예제

안전하지 않은 코드예제로, 사용자 입력을 그대로 LDAP 질의문에 사용하고 있으며 이 경우 권한 상승 등 공격에 노출될 수 있습니다.

#LDAP 삽입(안전X)
config = {
    "bind_dn": "cn=read-only-admin,dc=example,dc=com",
    "password": "password",
}
def ldap_query_bad(request):
    search_keyword = request.POST.get('search_keyword', '')

    dn = config['bind_dn']
    password = config['password']
    address = 'ldap.badSource.com'
    server = Server(address, get_info=ALL)
    conn = Connection(server, user=dn, password, auto_bind=True)

    search_str = '(&(objectclass=%s))' % search_keyword

    conn.search('dc=company,dc=com', search_str, attributes=['sn', 'cn', 'address', 'mail', 'mobile', 'uid'])
    
    return render(request, 'success.html', {'data': conn.entries})

 

다음은 안전한 코드 예제로, 사용자 입력 중 LDAP 질의문에 사용될 변수를 이스케이프하여 질의문 실행 시 공격에 노출되는 것을 예방할 수 있습니다.

#LDAP 삽입(안전O)
def ldap_query_good(request):
    search_keyword = request.POST.get('search_keyword', '')

    dn = config['bind_dn']
    password = config['password']
    address = 'ldap.goodSource.com'
    server = Server(address, get_info=ALL)
    conn = Connection(server, user=dn, password, auto_bind=True)

    escape_keyword = escape_filter_chars(search_keyword)
    search_str = '(&(objectclass=%s))' % escape_keyword

    conn.search('dc=company,dc=com', search_str, attributes=['sn', 'cn', 'address', 'mail', 'mobile', 'uid'])

    return render(request, 'success.html', {'data': conn.entries})

 

 

 

입력데이터 검증 및 표현/LDAP 삽입

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