1. Question
이번 포스팅을 시작하기에 앞서 먼저 질문을 드리겠습니다.
아래 코드에서 TEST를 눌렀을 때와 TEST2를 눌렀을 때 결과가 어떻게 될 것이라 예상하시나요?
1 2 3 4 5 6 | <html> <body> <a onclick="alert('123')">TEST</a> <a onclick="alert('123')+alert('Hacked')">TEST2</a> </body> </html> | cs |
TEST를 클릭했을 때는 당연히 123이 출력이 될 것입니다.
그렇다면 TEST2를 클릭했을 때는?
123')+alert('Hacked 이라는 문자열이 출력될 것이라 예상하시나요?
정답은 [그렇지 않다] 입니다.
TEST2를 클릭하게 되면 123이 출력되고 이후 Hacked라는 문자열이 출력됩니다.
즉, <a onclick="alert('123')+alert('Hacked')">TEST2</a> 이라는 문장이
<a onclick="alert('123')+alert('Hacked')">TEST2</a>처럼 작동을 한다는 것이죠
2. Why?
이것은 왜 그럴까요?
대부분 XSS의 대응방안으로 싱글쿼터('), 더블쿼터(") 등을 HTML Entity로 인코딩하는 것으로 알고 계실겁니다.
사용자가 입력한 문자열이 자바스크립트 영역이나 HTML 영역에 포함이 되었다면 위와 같은 특수문자를 HTML Entity로 인코딩하여 대응이 가능합니다.
하지만, 위와 같이 사용자의 입력값이 Event Handler에 속하게 될 경우 브라우저가 이를 렌더링하여 원래 문자열로 변경하여 실행시키기 때문에 서버 측에서 사용자의 입력값을 HTML Entity로 변경하여도 실행이 되는 것입니다.
3. How?
그렇다면 위와 같이 사용자의 입력값이 이벤트 핸들러에 포함되는 경우 어떻게 대응을 해야할까요?
사용자가 입력한 값을 태그가 아닌 단순 문자열로 출력해주는 기능을 활용하면 됩니다.
JSP 언어 기준으로는 JSTL의 c:out이 있습니다.
c:out 태그의 escapeXml 옵션을 false로 지정하면 해당 스크립트가 실행이 되지만 true로 지정할 경우에는 값을 문자열 그대로 출력하기 때문에 스크립트 실행이 되지 않습니다.
◎ escapeXml=false
1 | <c:out value="<script>alert(1)</script>" escapeXml="false"/> | cs |
◎ escapeXml=true
1 | <c:out value="<script>alert(1)</script>"/> | cs |
따라서 만약 사용자로부터 입력받는 것을 단순히 ${input}이라고 지정했다면 c:out을 이용하여 아래와 같이 수정하면 됩니다.
<c:out value="${input}"/>
(참고)
https://needjarvis.tistory.com/51
https://webcoding.tistory.com/entry/JSP-JSTL-cout-%ED%83%9C%EA%B7%B8-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0
'Hacking > Web' 카테고리의 다른 글
WAF bypass using an uninitialized Bash variable (0) | 2021.07.16 |
---|---|
Liferay Portal RCE ( CVE-2020–7961 ) (0) | 2020.08.14 |
Content Security Policy(csp) (2) | 2020.07.28 |
python deserialize vulnerability in pickle module (1) | 2020.07.26 |
Filter bypass Using Multipart form data (0) | 2020.05.08 |