반응형

XSS 란?


Cross-site Scripting. 링크 타고 들어갔는데 교차사이트 스크립팅 방지한다고 안 되면 진짜 짜증난다.

SQL injection과 함께[1] 웹 상에서 가장 기초적인 취약점 공격 방법의 일종으로, 악의적인 사용자가 공격하려는 사이트에 스크립트를 넣는 기법을 말한다. 공격에 성공하면 사이트에 접속한 사용자는 삽입된 코드를 실행하게 되며,[2] 보통 의도치 않은 행동을 수행시키거나 쿠키나 세션 토큰 등의 민감한 정보를 탈취한다.

크로스 사이트 스크립팅이란 이름 답게, 자바스크립트를 사용하여 공격하는 경우가 많다. 공격 방법이 단순하고 가장 기초적이지만, 많은 웹사이트들이 XSS에 대한 방어 조치를 해두지 않아 공격을 받는 경우가 많다. 여러 사용자가 접근 가능한 게시판 등에 코드를 삽입하는 경우도 많으며, 경우에 따라서는 메일과 같은 매체를 통해서도 전파된다. 

물론, HTML을 사용하는 것이기 때문에, Text-Only 게시판이나, BBCode를 이용하는 위키위키 등에서는 XSS가 발생할 일은 없다. 단, 나무위키의 경우 {{{#!html HTML}}} 을 이용해서 HTML 태그를 사용할 수 있으므로 취약점이 있을 수도 있다. 그래서 나무위키 초반에는 스크립트 태그와 이벤트 속성도 막지 않았다. 물론, 이는 후에 대부분 수정되었다.

주로 CSRF를 하기 위해서 사용되기 때문에 종종 CSRF와 혼동되는 경우가 있으나, XSS는 자바스크립트를 실행시키는 것이고, CSRF는 특정한 행동을 시키는 것이므로 다르다.



3.1. 스크립트 태그[편집]

방법

스크립트 태그로 자바스크립트를 실행한다.

예제

<script>alert('XSS');</script>

설명

스크립트 태그의 스크립트를 실행시킨다. 안타깝게도, 매우 정직한 방법이라 대부분의 사이트에서 막는 경우가 많다. 브라우저단에서 필터링 해주는 경우도 있다. 물론 예외도 있다.[5] 하지만 만들어진지 몇십 년 이상 되었거나, 보안 X까! 하면서 막지도 않는 경우도 있다. 애초에 비밀번호를 평문/MD5로 저장하는 경우도 있는데 새삼스럽게...

3.2. 자바스크립트 링크[편집]

방법

링크 태그로 자바스크립트를 실행한다.

예제

<a href="javascript:alert('XSS')">XSS</a>

설명

브라우저에서 about: 링크와 같이, javascript: 로 시작하는 링크는 스크립트를 실행시킨다. 스크립트 태그와 같이, javascript: 를 필터링하는 경우가 많아 많은 사이트에서 막는다.

3.3. 이벤트 속성[편집]

방법

이벤트 속성을 사용한다.

예제

<img src="#" onerror="alert('XSS')">

설명

이벤트 속성으로 스크립트를 실행할 수 있다. 주로 on 으로 시작하는 속성이 이벤트 속성이다. 자주 사용되는 이벤트 속성으로는 onload onerror onclick 등이 있다. 물론, 이 방법 역시 '자바스크립트 링크' 방법만큼 많이 막혔다.

3.4. 블랙리스트 우회[편집]

방법

알려지지 않은 태그와 속성들을 사용한다.

예제

<ruby oncopy="alert('XSS')">XSS</ruby>

설명

블랙 리스트 방식으로 막는 사이트에 사용할 수 있다. 이벤트 속성 목록을 참고하자. 위의 방법들보다는 적게 막혔으나, 여전히 최근 웹사이트들에선 화이트리스트 방식 차단이 대부분이라, 막혔을 가능성이 높다.

3.5. 내용 난독화[편집]

방법

따옴표로 감싸는 문자열 사이에 공백 문자들을 넣고, HTML 인코드를 하여 난독화한다.

예제

<a href="&#x6A;&#x61;&#x76;&#x61;&#x73;&#xA;&#x63;&#x72;&#x69;&#x70;&#x74;&#xA;&#x3A;&#xA;&#x61;&#x6C;&#x65;&#x72;&#x74;&#xA;&#x28;&#x27;&#x58;&#x53;&#x53;&#x27;&#x29;">XSS</a>

설명

일부 브라우저에서 javascript: 링크 사이에 공백 문자가 들어갈 수 있고, HTML 인코드를 해도 디코드된 내용이 출력된다는 점을 이용한다. 여기에서는 '자바스크립트 링크' 방법과 사용하였지만, 당연히 다른 방법과 함께 사용할 수 있다.

-나무 위키 발췌-



위와 같이 공격할 수 있다는 내용이다.

필자는 Spring-Boot를 사용하기 때문에 적용방법을 적어보자 한다.


naver에 lucy-xss-servlet-filter를 적용하고자 한다.

깃헙 주소 : https://github.com/naver/lucy-xss-servlet-filter


먼저 pom.xml에 디펜던시를 추가하거나 jar 파일을 받아 라이브러리 빌드패스에 추가한다.

<dependency>
	<groupId>com.navercorp.lucy</groupId>
	<artifactId>lucy-xss-servlet</artifactId>
	<version>2.0.0</version>
</dependency>



%%% 주의 사항 %%%

프로젝트 중 소켓통신이나 json데이터가 있을경우 json데이터 안에 있는 xss필터링 문자열도 걸러내는 경우가 생긴다. 해당 글은 이것을 해결하고 올린 글이다.




먼저 spring-boot의 핵심인 빈을 추가한다. XssServletFilter 클래스는 아래에 나온다.


1. WebMvcConfig.java


@Configuration

public class WebMvcConfig extends WebMvcConfigurerAdapter 

...

...

import 관련

org.springframework.boot.web.servlet.FilterRegistrationBean

org.springframework.boot.web.servlet.FilterRegistrationBean.FilterRegistrationBean()

 /*

     * lucy-xss-filter

     *  

     * */

    @Bean

    public FilterRegistrationBean getFilterRegistrationBean(){

        FilterRegistrationBean registrationBean = new FilterRegistrationBean();

        registrationBean.setFilter(new XssServletFilter(acceptUrls));

        registrationBean.setOrder(1);

        registrationBean.addUrlPatterns("/*");

        return registrationBean;

    }

...

...



2. XssServletFilter.java


import java.io.IOException;


import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;


import com.navercorp.lucy.security.xss.servletfilter.XssEscapeFilter;

import com.navercorp.lucy.security.xss.servletfilter.XssEscapeServletFilterWrapper;


public class XssServletFilter implements Filter {

private static final Logger logger = LoggerFactory.getLogger(XssServletFilter.class);

private String[] acceptUrls;

public XssServletFilter(String[] acceptUrls){

this.acceptUrls = acceptUrls;

}

private XssEscapeFilter xssEscapeFilter = XssEscapeFilter.getInstance();


@Override

public void init(FilterConfig filterConfig) throws ServletException {

}


@Override

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

if(excludeUrl(request)){

chain.doFilter(request, response); //걸러내는 URI일 경우 요청값 그대로 처리

}else{

chain.doFilter(new XssEscapeServletFilterWrapper(request, xssEscapeFilter), response);

}

}


private boolean excludeUrl(ServletRequest request) {

String uri = ((HttpServletRequest) request).getRequestURI().toString().trim();

logger.info("XssServletFilter Uri : {}", uri);

boolean returnValue = false;

for(String url : this.acceptUrls) {

if(uri.startsWith(url)){

returnValue = true;

}

}

return returnValue;

}


@Override

public void destroy() {

}

}

3. lucy-xss-servlet-filter-rule.xml


src/main/resources 에 넣어야함.


<?xml version="1.0" encoding="UTF-8"?>


<config xmlns="http://www.navercorp.com/lucy-xss-servlet">

    <defenders>

        <!-- XssPreventer 등록 -->

        <defender>

            <name>xssPreventerDefender</name>

            <class>com.navercorp.lucy.security.xss.servletfilter.defender.XssPreventerDefender</class>

        </defender>


        <!-- XssSaxFilter 등록 -->

        <defender>

            <name>xssSaxFilterDefender</name>

            <class>com.navercorp.lucy.security.xss.servletfilter.defender.XssSaxFilterDefender</class>

            <init-param>

                <param-value>lucy-xss-sax.xml</param-value>   <!-- lucy-xss-filter의 sax용 설정파일 -->

                <param-value>false</param-value>        <!-- 필터링된 코멘트를 남길지 여부, 성능 효율상 false 추천 -->

            </init-param>

        </defender>


        <!-- XssFilter 등록 -->

        <defender>

            <name>xssFilterDefender</name>

            <class>com.navercorp.lucy.security.xss.servletfilter.defender.XssFilterDefender</class>

            <init-param>

                <param-value>lucy-xss.xml</param-value>    <!-- lucy-xss-filter의 dom용 설정파일 -->

                <param-value>false</param-value>         <!-- 필터링된 코멘트를 남길지 여부, 성능 효율상 false 추천 -->

            </init-param>

        </defender>

    </defenders>


    <!-- default defender 선언, 필터링 시 지정한 defender가 없으면 여기 정의된 default defender를 사용해 필터링 한다. -->

    <default>

        <defender>xssPreventerDefender</defender>

    </default>


    <!-- global 필터링 룰 선언 -->

    <global>

        <!-- 모든 url에서 들어오는 globalParameter 파라메터는 필터링 되지 않으며

                또한 globalPrefixParameter1로 시작하는 파라메터도 필터링 되지 않는다.

                globalPrefixParameter2는 필터링 되며 globalPrefixParameter3은 필터링 되지 않지만

                더 정확한 표현이 가능하므로 globalPrefixParameter2, globalPrefixParameter3과 같은 불분명한 표현은 사용하지 않는 것이 좋다. -->

        <params>

<!--             <param name="JSONDS1" useDefender="false" /> -->

        </params>

    </global>

    <!-- url 별 필터링 룰 선언 -->

    <url-rule-set>

        <!-- url disable이 true이면 지정한 url 내의 모든 파라메터는 필터링 되지 않는다. -->

<!--         <url-rule> -->

<!--             <url disable="true">/eform/Clip.jsp</url> -->

<!--             <url disable="true">/ajax/eformUserData</url> -->

<!--         </url-rule> -->

    </url-rule-set>

</config>

4. application.properties


xss필터를 타지 않게 할 url 설정 


#xss accept uri 

xss.acceptUrls = /test, /admin


반응형
반응형

http://www.pyrasis.com/docker.html

반응형
반응형

 요즘 Spring Boot를 이용해서 Non-web application을 만드는 작업에 빠져서 Spring에 대해 많은 걸 배우고 공부하는 중이다. 그래서 이번에는 Spring Boot application을 위한 설정파일로 가장 간단하게 이용할 수 있는 방법인 application.properties를 이용하는 방법을 간단히 설명해 보려고 한다.


 Spring Boot를 이용할 때 대부분의 경우 설정 파일로 application.properties를 이용한다. application.properties는 기본적으로 Spring Boot가 읽어들이도록 되어있기 때문에 사실 파일만 만들어서 'src/main/resources' 폴더에 넣어주면 바로 설정파일로 이용이 가능하다. 이렇게 편한 방법이 있는데 따로 만들어서 사용할 이유가 없다.

 간단한 사용법을 보자.

# application.properties
name=Michael
import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*

@Component
public class MyBean {

    @Value("${name}")
    private String name;

    // ...

}
 위의 MyBean 클래스의 name 멤버변수는 @Value 어노테이션을 지정한 것만으로 application.properties에 있는 name속성 값 "Michael"로 초기화가 된다. 

 만약에 application.properties 파일에 name 속성이 정의되어있지 않았을 때 default값을 지정하는 방법도 있다. 아래와 같이 @Value 어노테이션에서 속성 이름 옆에 콜론(:)을 찍고 직접 지정해 주면 된다.

    @Value("${name:Michael}")
    private String name;

    @Value("${age:20}")
    private int age;
 위 예에서 지정된 default 값들은 application.properties에 값이 정의되어있지 않으면 각 변수의 타입에 맞게 변환되어 대입된다. 

 사실 Spring Boot의 문서를 보면 property source를 설정하는 다양한 방법이 제공된다.

  1. Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active).
  2. @TestPropertySource annotations on your tests.
  3. @SpringBootTest#properties annotation attribute on your tests.
  4. Command line arguments.
  5. Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property)
  6. ServletConfig init parameters.
  7. ServletContext init parameters.
  8. JNDI attributes from java:comp/env.
  9. Java System properties (System.getProperties()).
  10. OS environment variables.
  11. A RandomValuePropertySource that only has properties in random.*.
  12. Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)
  13. Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)
  14. Application properties outside of your packaged jar (application.properties and YAML variants).
  15. Application properties packaged inside your jar (application.properties and YAML variants).
  16. @PropertySource annotations on your @Configuration classes.
  17. Default properties (specified using SpringApplication.setDefaultProperties).

 위의 목록은 더 높은 우선순위를 갖는 property source부터 차례대로 나열한 것이다. 여기서 소개하는 application.properties 파일을 'src/main/resources' 폴더에 넣는 방법은 위의 목록 중 15번에 나오는 방법으로 우선순위로 보면 상당히 아래쪽에 나온다. 즉 상당히 우선순위가 낮다는 말이다. 'src/main/resources' 폴더에 application.properties 파일을 넣어 놓는다는 것은 배포 시에 jar 파일에 함께 묶여서 배포가 된다는 것이고 따라서 배포 후에 설정 값을 변경하려는 의도로 사용하기에는 적합하지 않다. 그러한 용도로 사용하려면 14번에서 말하는 jar 외부의 application.properties를 사용하면 된다. 그냥 application.properties 파일을 따로 만들어서 jar를 실행하는 directory에 두면 된다. jar 안에 있는 application.properties 파일보다 우선순위가 높기 때문에 둘 다 있는 경우 jar 외부의 application.properties 파일의 값이 더 높은 우선순위를 갖는다.

 여기서 많은 사람들이 우선순위에 대해서 오해하는 점 하나를 짚고 가야겠다. 예를 들어 jar안에 같이 포함된 application.properties파일과 jar 외부의 application.properties 파일이 둘 다 존재할 때 외부의 application.properties 파일이 더 우선순위가 높기 때문에 내부의 application.properties 파일이 완전히 무시된다고 생각하기 쉽다. 하지만 그렇지 않다. 우선순위가 높은 property source의 값들은 더 낮은 property source의 값들을 덮어쓰는 것이지 낮은 우선순위의 property source를 읽어들이지 않는 다는 뜻이 아니다. 즉 둘 다 name 속성이 정의되어있다면 더 높은 우선순위의 property source에 선언된 name 속성 값이 사용된다. 하지만 age라는 속성이 더 낮은 우선순위의 property source에만 선언되어있다면 낮은 우선순위의 property에 선언되었지만 그 값이 사용된다. (더 높은 우선순위에 값이 정의되지 않았으므로)

 즉 위 목록의 모든 property source들을 아래쪽부터 윗쪽으로 차례대로 다 찾아서 읽어들이면서 이미 정의된 property들은 덮어 쓰는 개념이다. 목록을 보면 테스트 환경을 제외하고 command line argument가 가장 우선순위가 높으므로 임시로 특정 값을 override하고 싶다면 command line을 이용해서 property를 전달하면 무조건 전달된 값이 이용될 것이다.

 command line을 이용하는 방법은 아래와 같은 방법으로 전달하면 된다. ('server.port' 속성값 지정)

$ java -jar myapp.jar --server.port=9000

 위 목록에 나열된 방법은 많지만 흔히 사용하는 방법으로 이 정도만 알고 있으면 대부분의 경우 문제없이 개발을 진행할 수 있다. 개념적으로 잘 이해하고 있다면 다른 나머지 방법을 이용하는 것도 사실 시간문제일 뿐 크게 어려운 부분은 없을 것이다.



출처 : http://progtrend.blogspot.kr/2017/07/spring-boot-applicationproperties.html

반응형

+ Recent posts