부적절한 XML 외부 개체 참조
정의
- XML 문서에는 DTD(Document Type Definition)를 포함할 수 있으며, DTD는 XML 엔티티(entitiy)를 정의
- 서버에서 XML 외부 엔티티를 처리할 수 있도록 설정된 경우에 발생
- 취약한 XML parser가 외부값을 참조하는 XML을 처리할 때, 공격자가 삽입한 공격 구문이 동작되어 서버 파일 접근, 불필요한 자원 사용, 인증 우회, 정보 노출 등이 발생
안전한 코딩기법
- 로컬 정적 DTD를 사용하도록 설정하고, 외부에서 전송된 XML 문서에 포함된 DTD를 완전하게 비활성화해야 한다. 비활성화를 할 수 없는 경우에는 외부 엔티티 및 외부 문서 유형 선언을 각 파서에 맞는 고유한 방식으로 비활성화 한다.
- 외부 라이브러리를 사용할 경우 기본적으로 외부 엔티티에 대한 구문 분석 기능을 제공하는지 확인하고, 제공이 되는 경우 해당 기능을 비활성화 할 수 있는 방법을 확인해 외부 엔티티 구문 분석 기능을 비활성화 한다.
코드예제
다음은 XML 소스를 읽어 분석하는 코드입니다. 공격자는 XML 외부 엔티티를 참조하는 xxe.xml 데이터를 전송하고, 이를 파싱할 때 /etc/passwd 파일을 참조할 수 있습니다. 만약 sax 패키지를 사용해 XML을 파싱할 경우, 외부 엔티티를 처리하는 방식의 옵션(feature_external_ges)을 False로 설정해야 합니다.
from .models import comments
def get_xml(request):
if request.method == "GET":
data = comments.objects.all()
com = data[0].comment
return render(request, 'xml_view.html', {'com': com})
elif request.method == "POST":
parser = make_parser()
parser.setFeature(feature_external_ges, True) #안전하지 않은 코드
#parser.setFeature(feature_external_ges, Fasle) #안전한 코드
doc = parseString(request.body.decode('utf-8'), parser=parser)
for event, node in doc:
if event == START_ELEMENT and node.tagName == "foo":
doc.expandNode(node)
text = node.toxml()
comments.objects.filter(id=1).update(comment=text)
return render(request, 'xml_view.html')
입력데이터 검증 및 표현/부적절한 XML 외부 개체 참조
[참고문헌] Python 시큐어코딩 가이드(2022) / KISA(한국인터넷진흥원)