- 개요
django.contrib.postgres.aggregates module에 존재하는 StringAgg 함수의 delimiter 파라미터에서
잠재적인 SQL Injection 취약점이 존재 합니다.
- 취약한 버전
1.11 < django < 1.11.28
2.2 < django < 2.2.10
3.0 < django < 3.0.3
- 취약점 설명 및 분석
먼저 취약점이 패치 된 로그를 확인하면 delimiter 파라미터를 삭제하고 Value라는 method와 함께
string 형태로 delimiter 값을 처리하도록 패치 된 것을 확인할 수 있습니다. 따라서 취약점이 존재하는
버전에서 delimiter 파라미터에 취약성이 존재한다고 파악할 수 있습니다.
Commit Log :
https://github.com/django/django/commit/eb31d845323618d688ad429479c6dda973056136
먼저 StringAgg 함수는 복수의 row데이터를 구분 기호와 함께 String 형태로 변환시켜 조회하기 위해
사용되며 원형은 아래 링크에서 확인할 수 있습니다.
Link : https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/aggregates/
delimiter 파라미터는 이어지는 문자열들의 구분 기호로 사용되는 것을 확인할 수 있습니다.
취약점은 간단합니다. 위의 패치 전 로직은 간단히 아래와 같은 쿼리문이 실행되는 것이며 이 경우
delimiter 값에 적절한 필터링이 존재하지 않으면 악의적인 SQL 쿼리문이 삽입되어 실행 됩니다.
먼저 정상적으로 데이터를 조회하려면 아래와 같이 사용합니다. 실 서비스에서 delimiter 파라미터를
사용자가 직접 입력할 수 있다면 취약점이 발생하게 됩니다.
Single Quote를 넣었을 때 아래와 같이 error가 나오게 되며 취약성을 확인할 수 있습니다.
" ')-- " 와 같은 구문을 삽입했을 시 "As ~~" 구문부터 주석 처리가 되며 필터링이 존재하지 않는다는
것을 알 수 있습니다.
주석 처리 구문과 union 함수를 이용하여 DB 서버의 정보를 탈취할 수 있습니다.
보안 패치는 delimiter 파라미터의 처리 방식을 바꿔서 패치 했는데 위와 같은 패치로 보안이 되는
이유는 아래와 같습니다.
위에서 패치 된 로직은 아래와 같은 쿼리문이 실행되는 것으로 이 경우 django의 내부 필터링에 의해
user_input 값에 악의적인 SQL 쿼리문을 삽입할 수 없습니다.
- 위협요소
잘못된 StringAgg 함수 사용으로 인해 DB 서버의 data가 유출될 수 있습니다.
- 대응방안
1) Django Version Update
1.x -> 1.11.28
2.x -> 2.2.10
3.x -> 3.0.3