1
+ package com .example ;
2
+
1
3
import java .io .InputStream ;
2
4
import java .io .IOException ;
3
5
import java .nio .file .Path ;
13
15
import javax .servlet .ServletContext ;
14
16
15
17
public class UnsafeResourceGet extends HttpServlet {
18
+ private static final String BASE_PATH = "/pages" ;
19
+
16
20
@ Override
17
21
// BAD: getResource constructed from `ServletContext` without input validation
18
22
protected void doGet (HttpServletRequest request , HttpServletResponse response )
@@ -23,6 +27,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
23
27
ServletConfig cfg = getServletConfig ();
24
28
ServletContext sc = cfg .getServletContext ();
25
29
30
+ // A sample request /fake.jsp/../WEB-INF/web.xml can load the web.xml file
26
31
URL url = sc .getResource (requestUrl );
27
32
28
33
InputStream in = url .openStream ();
@@ -43,13 +48,15 @@ protected void doGetGood(HttpServletRequest request, HttpServletResponse respons
43
48
ServletContext sc = cfg .getServletContext ();
44
49
45
50
Path path = Paths .get (requestUrl ).normalize ().toRealPath ();
46
- URL url = sc .getResource (path .toString ());
51
+ if (path .startsWith (BASE_PATH )) {
52
+ URL url = sc .getResource (path .toString ());
47
53
48
- InputStream in = url .openStream ();
49
- byte [] buf = new byte [4 * 1024 ]; // 4K buffer
50
- int bytesRead ;
51
- while ((bytesRead = in .read (buf )) != -1 ) {
52
- out .write (buf , 0 , bytesRead );
54
+ InputStream in = url .openStream ();
55
+ byte [] buf = new byte [4 * 1024 ]; // 4K buffer
56
+ int bytesRead ;
57
+ while ((bytesRead = in .read (buf )) != -1 ) {
58
+ out .write (buf , 0 , bytesRead );
59
+ }
53
60
}
54
61
}
55
62
@@ -63,6 +70,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)
63
70
ServletConfig cfg = getServletConfig ();
64
71
ServletContext sc = cfg .getServletContext ();
65
72
73
+ // A sample request /fake.jsp/../WEB-INF/web.xml can load the web.xml file
66
74
InputStream in = request .getServletContext ().getResourceAsStream (requestPath );
67
75
byte [] buf = new byte [4 * 1024 ]; // 4K buffer
68
76
int bytesRead ;
@@ -89,4 +97,81 @@ protected void doPostGood(HttpServletRequest request, HttpServletResponse respon
89
97
}
90
98
}
91
99
}
100
+
101
+ @ Override
102
+ // BAD: getResource constructed from `Class` without input validation
103
+ protected void doHead (HttpServletRequest request , HttpServletResponse response )
104
+ throws ServletException , IOException {
105
+ String requestUrl = request .getParameter ("requestURL" );
106
+ ServletOutputStream out = response .getOutputStream ();
107
+
108
+ // A sample request /fake.jsp/../../../WEB-INF/web.xml can load the web.xml file
109
+ // Note the class is in two levels of subpackages and `Class.loadResource` starts from its own directory
110
+ URL url = getClass ().getResource (requestUrl );
111
+
112
+ InputStream in = url .openStream ();
113
+ byte [] buf = new byte [4 * 1024 ]; // 4K buffer
114
+ int bytesRead ;
115
+ while ((bytesRead = in .read (buf )) != -1 ) {
116
+ out .write (buf , 0 , bytesRead );
117
+ }
118
+ }
119
+
120
+ // GOOD: getResource constructed from `Class` with input validation
121
+ protected void doHeadGood (HttpServletRequest request , HttpServletResponse response )
122
+ throws ServletException , IOException {
123
+ String requestUrl = request .getParameter ("requestURL" );
124
+ ServletOutputStream out = response .getOutputStream ();
125
+
126
+ Path path = Paths .get (requestUrl ).normalize ().toRealPath ();
127
+ if (path .startsWith (BASE_PATH )) {
128
+ URL url = getClass ().getResource (path .toString ());
129
+
130
+ InputStream in = url .openStream ();
131
+ byte [] buf = new byte [4 * 1024 ]; // 4K buffer
132
+ int bytesRead ;
133
+ while ((bytesRead = in .read (buf )) != -1 ) {
134
+ out .write (buf , 0 , bytesRead );
135
+ }
136
+ }
137
+ }
138
+
139
+ @ Override
140
+ // BAD: getResourceAsStream constructed from `ClassLoader` without input validation
141
+ protected void doPut (HttpServletRequest request , HttpServletResponse response )
142
+ throws ServletException , IOException {
143
+ String requestPath = request .getParameter ("requestPath" );
144
+ ServletOutputStream out = response .getOutputStream ();
145
+
146
+ ServletConfig cfg = getServletConfig ();
147
+ ServletContext sc = cfg .getServletContext ();
148
+
149
+ // A sample request /fake.jsp/../../../WEB-INF/web.xml can load the web.xml file
150
+ // Note the class is in two levels of subpackages and `ClassLoader.getResourceAsStream` starts from its own directory
151
+ InputStream in = getClass ().getClassLoader ().getResourceAsStream (requestPath );
152
+ byte [] buf = new byte [4 * 1024 ]; // 4K buffer
153
+ int bytesRead ;
154
+ while ((bytesRead = in .read (buf )) != -1 ) {
155
+ out .write (buf , 0 , bytesRead );
156
+ }
157
+ }
158
+
159
+ // GOOD: getResourceAsStream constructed from `ClassLoader` with input validation
160
+ protected void doPutGood (HttpServletRequest request , HttpServletResponse response )
161
+ throws ServletException , IOException {
162
+ String requestPath = request .getParameter ("requestPath" );
163
+ ServletOutputStream out = response .getOutputStream ();
164
+
165
+ ServletConfig cfg = getServletConfig ();
166
+ ServletContext sc = cfg .getServletContext ();
167
+
168
+ if (!requestPath .contains (".." ) && requestPath .startsWith ("/trusted" )) {
169
+ InputStream in = getClass ().getClassLoader ().getResourceAsStream (requestPath );
170
+ byte [] buf = new byte [4 * 1024 ]; // 4K buffer
171
+ int bytesRead ;
172
+ while ((bytesRead = in .read (buf )) != -1 ) {
173
+ out .write (buf , 0 , bytesRead );
174
+ }
175
+ }
176
+ }
92
177
}
0 commit comments