Post
KO

spring 3.0 xss 공격 차단 전자정부프레임워크 filter 적용

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

web.xml


  

  

         XSSHTMLTagFilter

         

             easyframework.common.security.XSSFilter

         </filter-class>

     </filter>

   

         XSSHTMLTagFilter

         *.do

     </filter-mapping>

     

 XSSFilter Class


public class XSSFilter implements Filter{

private FilterConfig config;

public void doFilter(ServletRequest request, ServletResponse response,

   FilterChain chain) throws IOException, ServletException {

  chain.doFilter(new HTMLTagFilterRequestWrapper((HttpServletRequest)request), response);

}

public void init(FilterConfig config) throws ServletException {

  this.config = config;

}

public void destroy() {

}

}

HTMLTagFilterRequestWrapper Class


public class HTMLTagFilterRequestWrapper extends HttpServletRequestWrapper {

 public HTMLTagFilterRequestWrapper(HttpServletRequest request) {

  super(request);

 }

public String[] getParameterValues(String parameter) {

  String[] values = super.getParameterValues(parameter);

  if (values == null) {

   return null;

  }

  for (int i = 0; i < values.length; i++) {

   if (values[i] != null) {

    values[i] = EgovWebUtil.clearXSSMinimum(values[i]);

   } else {

    values[i] = null;

   }

  }

  return values;

 }

 public String getParameter(String parameter) {

  String value = super.getParameter(parameter);

  if (value == null) {

   return null;

  }

  value = EgovWebUtil.clearXSSMinimum(value);

  return value;

 }

}

WebUtil.class


public class EgovWebUtil {

 @Value(“#{global[‘File.UploadMimeType’]}”)

 private String UploadMimeType;  // properties 에서 제외 UploadMimeType 가져오기.

public static String clearXSSMinimum(String value) {

  if (value == null     value.trim().equals(“”)) {

   return ””;

  }

  String returnValue = value;

  returnValue = returnValue.replaceAll(“&”, ”&”);

  returnValue = returnValue.replaceAll(“<”, ”<”);

  returnValue = returnValue.replaceAll(“>”, ”>”);

  returnValue = returnValue.replaceAll(“"”, ”"”);

  returnValue = returnValue.replaceAll(“'”, ”'”);

  returnValue = returnValue.replaceAll(“~!left!~”, ”<”);

  returnValue = returnValue.replaceAll(“~!right!~”, ”>”);

  return returnValue;

 }

 public static String clearXSSMaximum(String value) {

  String returnValue = value;

  returnValue = clearXSSMinimum(returnValue);

  returnValue = returnValue.replaceAll(“%00”, null);

  returnValue = returnValue.replaceAll(“%”, ”%”);

  // \. => .

  returnValue = returnValue.replaceAll(“\.\./”, ””); // ../

  returnValue = returnValue.replaceAll(“\.\.\\”, ””); // ..\

  returnValue = returnValue.replaceAll(“\./”, ””); // ./

  returnValue = returnValue.replaceAll(“%2F”, ””);

  return returnValue;

 }

 public static String filePathBlackList(String value) {

  String returnValue = value;

  if (returnValue == null     returnValue.trim().equals(“”)) {

   return ””;

  }

  returnValue = returnValue.replaceAll(“\.\./”, ””); // ../

  returnValue = returnValue.replaceAll(“\.\.\\”, ””); // ..\

  return returnValue;

 }

 / 행안부 보안취약점 점검 조치 방안.   @param value  @return /

 public static String filePathReplaceAll(String value) {

  String returnValue = value;

  if (returnValue == null     returnValue.trim().equals(“”)) {

   return ””;

  }

  returnValue = returnValue.replaceAll(“/”, ””);

  returnValue = returnValue.replaceAll(“\”, ””);

  returnValue = returnValue.replaceAll(“\.\.”, ””); // ..

  returnValue = returnValue.replaceAll(“&”, ””);

  return returnValue;

 }

 public static String filePathWhiteList(String value) {

  return value; // TODO

 }

  public static boolean isIPAddress(String str) {

  Pattern ipPattern = Pattern.compile(“\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}”);

  return ipPattern.matcher(str).matches();

    }

  public static String removeCRLF(String parameter) {

   return parameter.replaceAll(“\r”, ””).replaceAll(“\n”, ””);

  }

  public static String removeSQLInjectionRisk(String parameter) {

   return parameter.replaceAll(“\p{Space}”, ””).replaceAll(“\*”, ””).replaceAll(“%”, ””)

                                                                        .replaceAll(“;”, ””).replaceAll(“-“, ””).replaceAll(“\+”, ””).replaceAll(“,”, ””);

  }

  public static String removeOSCmdRisk(String parameter) {

   return parameter.replaceAll(“\p{Space}”, ””).replaceAll(“\*”, ””).replaceAll(“ ”, ””).replaceAll(“;”, ””);

  }

  //파일 MIME타입 확인

  public static boolean isFileUpload(String mimetype)

  {

   boolean boo = false;

   String excludeFile = EgovProperties.getProperty(“File.UploadMimeType”);

   System.out.println(“ ::::::::::::::::::::::::::::::::::> ” + excludeFile);

  String [] excludeUrlArray= excludeFile.split(“,”);

  int length = excludeUrlArray.length;

  for(int i=0; i<length; i++){

   if(excludeUrlArray[i].indexOf(mimetype) > -1){

    boo=true;

   }

  }

  System.out.println(“——————–> boo : ” +  boo);

   return boo;

  }

    /* public static void main(String[] args) {

String test = null; test = ”<script language=’javascript’ encoding="utf-8">q&a</script>”;

 System.out.println(“clearXSSMinimum() Test”); System.out.println(test);

System.out.println(“=>”); System.out.println(clearXSSMinimum(test));

 System.out.println(); test = ”/a/b/c../..\”; System.out.println(“clearXSSMaximum() Test”);

System.out.println(test); System.out.println(“ =>”); System.out.println(clearXSSMaximum(test));

System.out.println(); test = ”/a/b/c/../../../..\..\”; System.out.println(“filePathBlackList() Test”);

System.out.println(test); System.out.println(“=>”); System.out.println(filePathBlackList(test)); System.out.println();

 test = ”192.168.0.1”; System.out.println(“isIPAddress() test”); System.out.println(“IP : ” + test + ” => ” + isIPAddress(test));

 test = ”abc def*%;-+,ghi”; System.out.println(“removeSQLInjectionRisk() test”); System.out.println(test + ” => ” + removeSQLInjectionRisk(test));

 } //*/

}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ 2015.08.03 ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

현대에서 able framework에다가 적용해보니 잘 안되서 찾다보니 해결책을 알게되었다.

그래서 공유하게 되었다.

http://trudger.tistory.com/m/post/entry/Tomcat6%EC%97%90%EC%84%9C-Spring-3-%EC%9D%98-MultipartFile-%EC%B2%98%EB%A6%AC

*

Tomcat6에서 Spring 3 의 MultipartFile 처리Tomcat6에서 Spring 3 의 MultipartFile 처리시 Servlet 버전의 차이로 인해 이슈가 발생할 수 있다. [원인] 문제의 발단을 이렇습니다. chro…trudger.tistory.com

Tomcat6에서 Spring 3 의 MultipartFile 처리시 Servlet 버전의 차이로 인해 이슈가 발생할 수 있다.

[원인]

문제의 발단을 이렇습니다.

chrome의 RestConsole app을 이용하여 file upload를 테스트 하려는데

다음과 같은 error 가 발생했습니다.

[2012.07.11 09:38:50.251][DEBUG][o.s.w.m.support.MultipartFilter] Resolving multipart request [/master/api/v1/device-platforms/6698/images/ICON] with MultipartFilter**7월 11, 2012 9:38:50 오전 org.apache.catalina.core.StandardWrapperValve invoke 심각: Servlet.service() for servlet dispatcher threw exception java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.getParts()Ljava/util/Collection; at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.(StandardMultipartHttpServletRequest.java:57) at org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:58) at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:110)

MultipartFilter에서 file을 처리하다가 HttpServletRequest의 getParts() 메소드를 호출하는데

그런 메소드는 없다는 거죠..

[결론]**

web.xml 에 다음과 같은 설정이 있습니다.

multipartFilter org.springframework.web.multipart.support.MultipartFilter multipartResolverBeanName multipartResolver multipartFilter /*

MultipartFilter를 사용하겠다는 것이고요.

이 클래스는 default로 filterMultipartResolver bean을 찾는데

대신 multipartResolver를 찾아라 라는 설정입니다.

빈 등록은 다음과 같습니다.

근데 에러메세지를 보면 CommonsMultipartResolver가 아닌 StandardServletMultipartResolver를 쓰고 있네요.

API를 보면 다음과 같은 내용이 있습니다.

Looks up the MultipartResolver on each request, to avoid initialization order issues (when using ContextLoaderServlet, the root application context will get initialized after*** this filter).

ContextLoaderServlet은 ContextLoaderListener의 예전 버전이라 할수 있죠.

프로젝트에서는 classpath:dispatcherServlet.xml 하나로 설정을 다 하고 있어서.

ContextLoaderListener를 쓰지 않았습니다.

다음을 추가 했습니다.

contextConfigLocation classpath:dispatcherServlet.xml ContextLoader org.springframework.web.context.ContextLoaderListener

삽질이 궁금하시다면 ~

[문제 해결 과정]

검색-

getParts() 메소드는 servlet-api 3.0 에서 지원되는 메소드네요.

pom.xml에 servlet-api 3.0 을 넣어줬습니다.

같은 에러~

tomcat 라이브러리를 쓰니까 연결이 안되는 것인가?

검색-

tomcat6는 servlet-api 2.5            , tomcat7는 servlet-api 3.0

spring 3.0.7은 servlet-api 2.5 기반  , spring 3.1.1은 tomcat7 기반

어라? 3.1.1은 tomcat7기반인데 왜 tomcat6를 쓰지?

이슈제기-

store 에서는 잘 되고 있다는 박병주 책임님의 제보-

어떻게??

Spring doc 분석 -

StandardServletMultipartResolver 는 servlet 3 를 사용한다.

CommonsMultipartResolver 를 bean으로 등록했다

MultipartFilter 는 왜 CommonsMultipartResolver를 찾지 못하는가?

api 분석 -

아하!! ContextLoader가 필요하구나

ref

http://mvnrepository.com/artifact/org.springframework/spring-webmvc/3.1.1.RELEASE

http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/multipart/support/MultipartFilter.html

http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-multipart-resolver-commons ——————————— 2015.08.04 —————————————-

추가된 내용.

문제는 위 내용대로 적용하면 filter는 걸린다 하지만. multiRequest 에 파일이 안따라 온다는거 ㅡㅡ;

따라서

    multipartFilter     org.springframework.web.multipart.support.MultipartFilter         multipartResolverBeanName multipartResolver    

부분에서

    multipartFilter     org.springframework.web.multipart.support.MultipartFilter    

삭제해주고 multipartRequest 가 등록되어있는 bean로 이동하여

id 값을 filterMultipartResolver 로 변경시켜야 한다.

그럼 해결됨

This article is licensed under CC BY 4.0 by the author.