해당 문서는 위의 트윗을 보고 추가적인 연구를 진행해 Theori 내부 세미나에서 발표한 결과물이다.(사장님 허락받고 올린다)
(%C4%B1)
는 LATIN SMALL LETTER DOTLESS I를,
(%E2%84%AA)
KELVIN SIGN을,
(%C5%BF)
는 LATIN SMALL LETTER LONG S를,
(%C4%B0)
는 LATIN CAPITAL LETTER I WITH DOT ABOVE 를 의미한다.
그런데 자바스크립트 환경에서 %C4%B1를 touppercase() 하면 == “I”가, %c5%bf를 touppercase()하면 == “S”가 되고,
%E2%84%AA 를 tolowercase() 하면 == “k”가, %c4%b0을 tolowercase()하면 == “i” 가 되는 현상이 발생한다는 것이 해당 트윗의 요지이다.
이미 CTF에서 출제된적이 있는 트릭이지만 제대로 정리된 문서가 없는 것 같아서, 연구를 진행해 보았다.
우선은 다른 언어에서 같은 트릭이 발생하는지 여부를 확인해 보았다.
유니코드 범위 내에서 for문 오지게 돌렸다ㅡㅡ;;
그 결과는 다음과 같다.
대체로 유니코드를 제대로 지원하는 언어에서 해당 트릭이 발생하는것을 알 수 있었다.
php의 경우에는 일반 strtolower(), strtoupper() 함수에서는 발생하지 않고, 멀티바이트를 따로 지원해주는 mb_strtolower(), mb_strtoupper() 함수를 사용해야 한다.
그러면 이 트릭을 어떻게 악용할 수 있을까?
2가지 방법이 있다.
1. WAF BYPASS
라는 간단한 프로그램을 만들고 서버에 WAF를 설치한 후 /?ID=<script>VAR=1</script>URI에 접속해보면 결과는 다음과 같다.
방화벽에 탐지당한것이다.
하지만 URI를 /?ID=<%C5%BFCRIPT>VAR=1</%C5%BFCRIPT> 와 같이 해준다면?
WAF가 보기에는 <%C5%BFCRIPT> 라는 생소한 문자열이 들어왔으니 패스시켜주지만 웹어플리케이션단에서는 “%C5%BF” 문자열이 mb_strtoupper() 함수를 거치며 일반 알파벳 “S” 로 바뀌어 WAF가 우회된다.
WAF의 경우에는 설치가 까다롭고 오래걸려 ModSecurity 한가지에 대해서만 테스트 해보았다.
결과는 아래와 같다.
일부 유니코드는 통과시키고 일부 유니코드는 필터하는 모습을 볼 수 있다.
방화벽마다 필터되지 않는 유니코드가 있을 수 있다.
2. BROWSER XSS FILTER BYPASS
브라우저 XSS 필터는 사용자를 위한 강력한 XSS 방어수단이다.
보통은 위와같은 정규식을 거쳐 유저인풋과 HTTP Response 값 간에 정규식에 매칭되는 패턴이 있으면 아래처럼 작동을 중지시킨다.
하지만 WAF의 경우와 마찬가지로 유저인풋 %c5%bf 와 HTTP Response 에서의 “S” 를 XSS 필터에서 같다고 검증할 수 있을까?
테스트해본 결과는 아래와 같다.
MS 계열의 브라우저에서만 필터가 되는것을 확인할 수 있다.
다만 테스트할 때 내 Edge 브라우저가 최신버전이 아니였는데, 최신버전의 Edge 브라우저에는 XSS 필터가 제거되었다.
(https://blogs.windows.com/windowsexperience/2018/07/25/announcing-windows-10-insider-preview-build-17723-and-build-18204/)
그러므로 사실상 IE를 제외하면 해당 트릭은 모든 브라우저 XSS 필터 우회에 악용할 수 있다.
python3, js, java 로 이루어진 웹어플리케이션 상에서 문자열을 대문자 혹은 소문자로 강제로 치환하는 경우에는 해당 트릭을 시도해볼 가치가 있을것이다.
8 Comments
질문!
질문 있습니다!
지금 그누보드 보안 어떤가요?
최근에 뜯어보신적 있으신지..
root
많은 해커들의 제보로 지금은 비교적 안전해진걸로 알고있습니다만은… 아직은 갈 길이 멀죠..ㅎㅎ
질문!
혹시 0 day 알고 계신건아닌지 ㅎㅎ
서버단에서도 신경쓰면 그래도 뚫리진 않겟죠?ㅎ
root
저는 그누보드는 각잡고 뜯어본적이 없습니다.
하지만 그누보드 사용하느니 차라리 워드프레스나 최소한 xe정도를 사용하시는걸 권장해요
posix
귀중한 정보 공유 감사드립니다.
질문드립니다
좋은정보 감사합니다!
혹시 mb_strtolower()에 관한 트릭 또한 존재하는지 여쭤봐도 될까요?
8바이트, 12바이트 데이터를 여러 방식의 인코딩을 사용하여 찾고있는데,
도무지 임의의 데이터 -> s, c, r, i, p, t, j, a, v 로 대응되는 케이스가 나오질 않는군요 ㅠㅠ
rubiya
자료를 본 적이 있는데 찾으려니 못찾겠네요@_@ 8~12바이트짜리 문자가 1바이트로 바뀌는 경우는 없지만 2~3바이트로 바뀌는 경우는 존재했습니다. 코드를 수정해보세요!
rajat kanti dutta
Really interesting. I’m frm india. Thanks