설명
LDAP 검색 필터는 단순한 데이터 문자열이 아니라 &, |, !, *, 괄호 등으로 조건을 표현하는 문법입니다. 요청에서 받은 값을 System.DirectoryServices.DirectorySearcher.Filter, DirectorySearcher 생성자의 필터 인수 또는 System.DirectoryServices.Protocols.SearchRequest의 필터에 그대로 결합하면 공격자가 원래 조건 밖의 연산자나 와일드카드를 삽입할 수 있습니다.
예를 들어 애플리케이션이 (cn= + 사용자명 + )을 만들 때 사용자명이 *이면 결과 (cn=*)는 cn 속성이 존재하는 항목을 선택하는 조건이 됩니다. 더 복잡한 입력은 애플리케이션이 추가한 사용자·그룹·테넌트 조건의 의미를 바꿀 수 있습니다.
LDAP 검색 필터 값과 고유 이름(DN)은 서로 다른 문맥입니다. 필터의 어설션 값은 RFC 4515에 따라 이스케이프하고, DN의 속성 값은 RFC 4514에 따라 이스케이프해야 합니다. 한 문맥의 인코더를 다른 문맥에 대신 사용하면 안전하지 않습니다.
잠재적 영향
- 사용자 또는 그룹 조회 조건을 넓혀 인증·권한 검사를 우회할 수 있습니다.
- 디렉터리의 계정, 그룹, 전자우편 주소 등 허가되지 않은 정보를 조회할 수 있습니다.
- 공격자가 비용이 큰 필터를 선택해 LDAP 서버와 애플리케이션 자원을 소모시킬 수 있습니다.
- 쓰기 또는 관리 기능이 같은 동적 필터를 신뢰하면 의도하지 않은 디렉터리 개체가 수정될 수 있습니다.
해결 방법
- 클라이언트가 완성된 LDAP 필터, 속성명 또는 연산자를 보내도록 허용하지 않습니다. 검색 종류가 선택 가능해야 한다면 짧은 키를 서버가 소유한 고정 필터에 매핑합니다.
- 외부 값이 필터의 어설션 값에 반드시 들어가야 한다면 유지보수되는 LDAP 필터 빌더 또는 RFC 4515 인코더를 사용합니다.
*,(,),\, NUL을 올바른\hh옥텟 형식으로 이스케이프해야 합니다. - .NET 10의
System.DirectoryServices및System.DirectoryServices.Protocols에는 공개된 기본 필터 이스케이퍼가 없습니다. 적합한 유지보수 라이브러리를 사용할 수 없다면 조직에서 승인한 하나의 RFC 4515 헬퍼로 구현을 중앙화하고, ASP.NET Core 10의 내부 구현과 RFC 예제를 기준으로 단위 테스트합니다. - RFC 4514 DN 인코더, HTML·URL 인코더, 부분적인
Replace, 메서드 이름이Sanitize또는Escape인 임의 헬퍼를 필터 인코딩의 증거로 간주하지 않습니다. - LDAP 바인드 계정에 최소 권한을 부여하고, 검색 범위·반환 개수·페이지 크기·시간 제한을 적용합니다. 이러한 제한은 인코딩을 대체하지 않지만 공격 성공 시 영향을 줄입니다.
OWASP의 현재 LDAP 치트시트는 문맥에 맞는 인코더 사용을 권고하지만 C# 예시에서 2014년에 마지막으로 출시된 AntiXSS 4.3.0을 언급합니다. 기존 .NET Framework 코드의 Microsoft.Security.Application.Encoder.LdapFilterEncode는 필터 값용 레거시 API로 검토할 수 있지만, 새 .NET 10 애플리케이션에 이 오래된 패키지를 기본 해결책으로 추가하지 마세요.
예시
변경 전
using Microsoft.AspNetCore.Mvc;
using System.DirectoryServices;
public sealed class DirectoryController
{
public SearchResult? Find(
[FromQuery] string username,
DirectorySearcher searcher)
{
searcher.Filter =
"(&(objectClass=user)(cn=" + username + "))";
return searcher.FindOne();
}
}
변경 후
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.DirectoryServices;
public sealed class DirectoryController
{
private static readonly IReadOnlyDictionary<string, string> Filters =
new Dictionary<string, string>(StringComparer.Ordinal)
{
["active-users"] = "(&(objectClass=user)(accountStatus=active))",
["disabled-users"] = "(&(objectClass=user)(accountStatus=disabled))"
};
public SearchResult? Find(
[FromQuery] string filterKey,
DirectorySearcher searcher)
{
if (!Filters.TryGetValue(filterKey, out var filter))
{
throw new ArgumentException("Unsupported filter.", nameof(filterKey));
}
searcher.Filter = filter;
searcher.SizeLimit = 100;
searcher.ServerTimeLimit = TimeSpan.FromSeconds(2);
return searcher.FindOne();
}
}
설명:
- 변경 전: 요청의
username이 필터 문법 안에 그대로 들어가므로 공격자가 와일드카드나 추가 조건을 삽입할 수 있습니다. - 변경 후: 외부 입력은 서버가 작성한 두 개의 고정 필터 중 하나를 선택하는 키일 뿐이며 필터 문법이나 값으로 들어가지 않습니다. 결과 수와 서버 처리 시간도 제한합니다.
예시의 accountStatus는 실제 디렉터리 스키마에 맞게 조정하고, 각 조회에 필요한 권한도 별도로 확인하세요.
자유 형식의 값을 지원해야 하고 승인된 라이브러리가 없다면 다음과 같이 RFC 4515 필터 값 전용 헬퍼를 중앙에서 관리할 수 있습니다. 이 코드는 ASP.NET Core 10의 LDAP 클레임 조회 내부 구현과 같은 필수 문자를 이스케이프합니다.
using System;
using System.Text;
internal static class LdapFilterValue
{
internal static string Encode(string value)
{
ArgumentNullException.ThrowIfNull(value);
var escaped = new StringBuilder(value.Length);
foreach (var character in value)
{
escaped.Append(character switch
{
'\\' => @"\5c",
'*' => @"\2a",
'(' => @"\28",
')' => @"\29",
'\0' => @"\00",
_ => character.ToString()
});
}
return escaped.ToString();
}
}
이 헬퍼는 완성된 필터, 속성명, 연산자 또는 DN을 안전하게 만들지 않습니다. 필터 구조는 고정한 채 어설션 값 하나에만 적용하고, *, 괄호, 역슬래시, NUL 및 유니코드 입력을 단위 테스트해야 합니다.
참조
- Microsoft CA3005: LDAP 인젝션 취약점 검토
- DirectorySearcher.Filter (.NET 10)
- System.DirectoryServices 10.0.0
- System.DirectoryServices.Protocols 10.0.0
- .NET LDAP 필터 이스케이프 API 제안
- ASP.NET Core 10의 RFC 4515 필터 값 이스케이프 구현
- OWASP LDAP Injection Prevention Cheat Sheet
- OWASP Injection Prevention Cheat Sheet
- OWASP ASVS 5.0.0 V1.2.6
- RFC 4515: LDAP 검색 필터 문자열 표현
- RFC 4514: LDAP 고유 이름 문자열 표현
- CWE-90: LDAP Injection
- OWASP Top 10:2025 A05 Injection
- AntiXSS 4.3.0 패키지 이력
- KISA 소프트웨어 보안약점 진단가이드 2021