django에서, 파일을 form에 넣었을 때, 어떤 경우에는 파일 이름이 바뀌었습니다. 이는 get_valid_filename 때문입니다. 이게 무엇을 하는 것인지 간단하게 보겠습니다.

 

 먼저, 양 끝에 붙은 공백을 제거한 다음에, 중간에 있는 공백들은 모두 _로 치환합니다. 다음에 re.sub인데요. 앞에 (?u)가 붙어있고, 뒤에 [^-\\w.]이 있습니다. 무엇을 의미할까요? 먼저, re.sub는 특정 패턴에 걸려들면, 다른 패턴으로 치환하는 역할을 합니다. 2번째 인자에 빈 문자열이 들어갔기 때문에, 1번째 패턴에 걸리면, 빈 문자열로 치환하겠구나. 정도는 알 수 있습니다.

 

 예를 들어, s="abcde"라고 한다면, s=re.sub(r"a", "", s)의 결과는 "bcde"가 나옵니다. 패턴 "a"에 걸리는 "a"는 빈 문자열로 치환되어버리기 때문입니다. 이제 앞에 붙는 (?a)나 (?u)가 무엇을 의미하는지 보면 되겠네요.

 


 테스트 문자열은 "각ab-+|.cd"라고 해 보겠습니다. [^-\w.]은 -이나 문자나, .이 아닌 패턴을 의미합니다.

 

 결과를 보면, "ab-.cd"가 나왔음을 볼 수 있는데요. 제거된 문자를 보면, "각", "+", "|"이 있습니다. +이나 |은 그렇다 쳐도, 각은 왜 제거가 되었을까요? str 패턴이긴 했는데, (?a)의 경우 아스키 플래그가 활성화가 되었기 때문에, [a-zA-Z0-9_] 만 걸려버리게 됩니다. 결국, 숫자, 영어 대소문자, _, -, .이 아닌 것들은 모두 빈 문자열로 치환되게 됩니다.

 

 

 반면에, 앞에 (?u)가 붙은 경우, 이야기가 달라집니다. 이 때에는 유니코드 문자들과 매치가 되는데요.

 

 

 아까와는 다르게 각이 나왔음을 알 수 있습니다.

 

 

 실제로, \w 패턴에 매치되지 않은 것들만 뽑아보면 특수 기호들이 많음을 알 수 있습니다. !이나 ", #, $와 같은 것들도 이 중 하나입니다.

 

 

 한글처럼 보이지만, 다른 것들입니다.

 

 


 그러면 이런 것들은 어떻게 치환이 될까요?

 

 

 path traveral 공격에서 자주 보이는 패턴입니다. ..이 상위 디렉터리를 의미합니다. 상위 디렉토리로 여러 번 가면 결국 루트에 도달하게 됩니다. 그리고, 리눅스에서 계정 정보들이 담긴 파일은 보통 /etc/passwd에 있는 경우가 꽤 있습니다. 그만큼 중요한 파일이라고 할 수 있는데요. 저 이름으로 인풋이 넘어간 경우 아래와 같이 파일 이름이 바뀌게 됩니다.

 

 

 .................etcpasswd로 바뀌었습니다. 허용되는 문자들을 가지고 1차 필터링을, 패턴 발견을 통해서 2차 필터링을 하는 전략을 썼다는 것을 알 수 있습니다.