├── README.md ├── build.xml ├── checkstyle ├── zap-checkstyle-suppressions.xml └── zap-checkstyle.xml ├── lib ├── ant.jar ├── cglib-nodep-2.2.jar ├── hamcrest-all-1.3.jar ├── helpertasks.jar ├── javassist-3.16.1-GA.jar ├── junit-dep-4.11.jar ├── mockito-all-1.9.0.jar ├── objenesis-1.2.jar ├── powermock-mockito-1.4.12-full.jar └── simple-5.0.2.jar ├── src-build └── org │ └── zaproxy │ └── ant │ └── zap │ └── taskdefs │ └── StopZapTimeout.java ├── src └── org │ ├── parosproxy │ └── paros │ │ └── core │ │ └── proxy │ │ ├── HttpProxyConnectionIntegrationTest.java │ │ ├── WebSocketsConnectionIntegrationTest.java │ │ └── WithBasicInfrastructureIntegrationTest.java │ └── zaproxy │ ├── ZapAllTestSuite.java │ ├── clientapi │ └── core │ │ ├── ReflectedXssDetectionIntegrationTest.java │ │ └── WavsepStatic.java │ └── zap │ ├── DaemonWaveIntegrationTest.java │ ├── TestWebAppUtils.java │ ├── ZaproxyIntegrationTestSuite.java │ ├── authentication │ ├── AbstractAuthenticationMethodUnitTest.java │ ├── AuthenticationIntegrationTestSuite.java │ ├── FormBasedAuthenticationIntegrationTest.java │ ├── FormBasedAuthenticationMethodIntegrationTest.java │ ├── HttpAuthenticationIntegrationTest.java │ ├── HttpAuthenticationMethodIntegrationTest.java │ └── ManualAuthenticationMethodIntegrationTest.java │ ├── extension │ ├── ZapExtensionsIntegrationTestSuite.java │ └── sse │ │ └── EventStreamObserverIntegrationTest.java │ ├── model │ └── InMemoryContextDataMockSession.java │ └── session │ ├── AbstractSessionManagementMethodIntegrationTest.java │ ├── CookieBasedSessionManagementMethodIntegrationTest.java │ └── SessionManagementMethodIntegrationTestSuite.java └── test-webapp ├── WebContent ├── META-INF │ └── MANIFEST.MF ├── WEB-INF │ └── web.xml ├── form-based-auth │ ├── d.jsp │ ├── error.jsp │ ├── index.jsp │ ├── login.jsp │ ├── loginCheck.jsp │ ├── logout.jsp │ └── restricted │ │ ├── a.jsp │ │ ├── ac.jsp │ │ ├── b.jsp │ │ └── home.jsp ├── http-auth │ ├── d.jsp │ ├── index.jsp │ └── restricted │ │ ├── a.jsp │ │ ├── ac.jsp │ │ ├── b.jsp │ │ └── home.jsp └── index.jsp ├── build.xml ├── src └── placeholder └── zap-test-webapp.war /README.md: -------------------------------------------------------------------------------- 1 | # zaproxy-test 2 | This project was exported from https://code.google.com/p/zaproxy-test 3 | 4 | > Note that the plan is to move all of the tests into the relevant projects, at which point this project will be frozen and just maintained for historical purposes. 5 | 6 | The zaproxy-test project contains all developer's test code for the OWASP Zed Attack Proxy (ZAP) and its extensions. This includes (but is not limited to) 7 | 8 | * Unit Tests for ensuring the intended behavior of individual classes 9 | * Integration Tests verifying correct interaction between classes or components 10 | * Supporting classes like builders, matchers etc. 11 | 12 | ## Goal 13 | 14 | The main goal of zaproxy-test is to make sure that changes, fixes and refactorings on the ZAP code base can be done fearlessly and without causing harm to existing functionality! Adequate developer's tests and a clean code base can help keeping ZAP an active project with a low entrance barrier for new contributors! 15 | Dependencies 16 | 17 | This project is directly depending on the projects containing the classes and components under test 18 | 19 | * [zaproxy](https://github.com/zaproxy/zaproxy) 20 | * [zap-extensions](https://github.com/zaproxy/zap-extensions) 21 | 22 | ## Must reads before working on zaproxy-test 23 | 24 | Please refer to the [GettingStarted](https://github.com/zaproxy/zaproxy-test/blob/wiki/GettingStarted.md) page to set-up zaproxy-test alongside its parent projects. 25 | 26 | Prior to committing to zaproxy-test please make sure you have read the [TestingGuidelines](https://github.com/zaproxy/zaproxy-test/blob/wiki/TestingGuidelines.md). 27 | 28 | _Happy testing!_ 29 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | Run the ZAP JUnit tests. 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 | 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 | 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 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | -------------------------------------------------------------------------------- /checkstyle/zap-checkstyle-suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /checkstyle/zap-checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 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 | -------------------------------------------------------------------------------- /lib/ant.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaproxy/zaproxy-test/f351caa2b3fee92e60c328c74a29520fa34aba0f/lib/ant.jar -------------------------------------------------------------------------------- /lib/cglib-nodep-2.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaproxy/zaproxy-test/f351caa2b3fee92e60c328c74a29520fa34aba0f/lib/cglib-nodep-2.2.jar -------------------------------------------------------------------------------- /lib/hamcrest-all-1.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaproxy/zaproxy-test/f351caa2b3fee92e60c328c74a29520fa34aba0f/lib/hamcrest-all-1.3.jar -------------------------------------------------------------------------------- /lib/helpertasks.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaproxy/zaproxy-test/f351caa2b3fee92e60c328c74a29520fa34aba0f/lib/helpertasks.jar -------------------------------------------------------------------------------- /lib/javassist-3.16.1-GA.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaproxy/zaproxy-test/f351caa2b3fee92e60c328c74a29520fa34aba0f/lib/javassist-3.16.1-GA.jar -------------------------------------------------------------------------------- /lib/junit-dep-4.11.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaproxy/zaproxy-test/f351caa2b3fee92e60c328c74a29520fa34aba0f/lib/junit-dep-4.11.jar -------------------------------------------------------------------------------- /lib/mockito-all-1.9.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaproxy/zaproxy-test/f351caa2b3fee92e60c328c74a29520fa34aba0f/lib/mockito-all-1.9.0.jar -------------------------------------------------------------------------------- /lib/objenesis-1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaproxy/zaproxy-test/f351caa2b3fee92e60c328c74a29520fa34aba0f/lib/objenesis-1.2.jar -------------------------------------------------------------------------------- /lib/powermock-mockito-1.4.12-full.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaproxy/zaproxy-test/f351caa2b3fee92e60c328c74a29520fa34aba0f/lib/powermock-mockito-1.4.12-full.jar -------------------------------------------------------------------------------- /lib/simple-5.0.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaproxy/zaproxy-test/f351caa2b3fee92e60c328c74a29520fa34aba0f/lib/simple-5.0.2.jar -------------------------------------------------------------------------------- /src-build/org/zaproxy/ant/zap/taskdefs/StopZapTimeout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Zed Attack Proxy (ZAP) and its related class files. 3 | * 4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 5 | * 6 | * Copyright 2014 The ZAP Development Team 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package org.zaproxy.ant.zap.taskdefs; 21 | 22 | import java.io.IOException; 23 | import java.net.InetSocketAddress; 24 | import java.net.Socket; 25 | import java.net.SocketTimeoutException; 26 | 27 | import org.apache.tools.ant.BuildException; 28 | import org.apache.tools.ant.Project; 29 | import org.zaproxy.clientapi.ant.ZapTask; 30 | 31 | /** 32 | * Helper task that stops ZAP, using the API, waiting up to the given seconds before failing. 33 | *

34 | * It tries to check if ZAP is ready to receive API calls by attempting to establish a connection to ZAP's proxy, in a given 35 | * time, failing if the connection is not successful. If the connection is successful it calls the shutdown API action. 36 | *

37 | */ 38 | public class StopZapTimeout extends ZapTask { 39 | 40 | private static final int MILLISECONDS_IN_SECOND = 1000; 41 | 42 | private static final int DEFAULT_SLEEP_TIME_BETWEEN_CONNECTION_POOLING_IN_MS = getMilliseconds(1); 43 | 44 | private int timeout; 45 | private int pollingIntervalInMs; 46 | 47 | public StopZapTimeout() { 48 | pollingIntervalInMs = DEFAULT_SLEEP_TIME_BETWEEN_CONNECTION_POOLING_IN_MS; 49 | } 50 | 51 | public void setTimeout(int seconds) { 52 | if (seconds <= 0) { 53 | throw new BuildException("Attribute timeout must be greater than zero."); 54 | } 55 | this.timeout = seconds; 56 | } 57 | 58 | public void setPollingInterval(int seconds) { 59 | if (seconds <= 0) { 60 | throw new BuildException("Attribute pollinginterval must be greater than zero."); 61 | } 62 | this.pollingIntervalInMs = getMilliseconds(seconds); 63 | } 64 | 65 | @Override 66 | public void execute() throws BuildException { 67 | if (timeout == 0) { 68 | throw new BuildException("Attribute timeout must be set."); 69 | } 70 | 71 | log("Waiting for a successful connection to ZAP...", Project.MSG_VERBOSE); 72 | waitForSuccessfulConnectionToZap(timeout); 73 | 74 | try { 75 | log("Calling shutdown API action...", Project.MSG_VERBOSE); 76 | this.getClientApi().core.shutdown(null); 77 | } catch (Exception e) { 78 | throw new BuildException(e); 79 | } 80 | } 81 | 82 | private void waitForSuccessfulConnectionToZap(int timeout) { 83 | int timeoutInMs = getMilliseconds(timeout); 84 | int connectionTimeoutInMs = timeoutInMs; 85 | boolean connectionSuccessful = false; 86 | long startTime = System.currentTimeMillis(); 87 | do { 88 | try (Socket socket = new Socket()) { 89 | try { 90 | socket.connect(new InetSocketAddress(getZapAddress(), getZapPort()), connectionTimeoutInMs); 91 | connectionSuccessful = true; 92 | } catch (SocketTimeoutException ignore) { 93 | throw new BuildException("Unable to connect to ZAP's proxy after " + timeout + " seconds."); 94 | } catch (IOException ignore) { 95 | // and keep trying but wait some time first... 96 | try { 97 | Thread.sleep(pollingIntervalInMs); 98 | } catch (InterruptedException e) { 99 | throw new BuildException("The task was interrupted while sleeping between connection polling.", e); 100 | } 101 | 102 | long ellapsedTime = System.currentTimeMillis() - startTime; 103 | if (ellapsedTime >= timeoutInMs) { 104 | throw new BuildException("Unable to connect to ZAP's proxy after " + timeout + " seconds."); 105 | } 106 | connectionTimeoutInMs = (int) (timeoutInMs - ellapsedTime); 107 | } 108 | } catch (IOException ignore) { 109 | // the closing state doesn't matter. 110 | } 111 | } while (!connectionSuccessful); 112 | } 113 | 114 | private static int getMilliseconds(int seconds) { 115 | return seconds * MILLISECONDS_IN_SECOND; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/org/parosproxy/paros/core/proxy/HttpProxyConnectionIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Zed Attack Proxy (ZAP) and its related class files. 3 | * 4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 5 | * 6 | * Copyright 2010 psiinon@gmail.com 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package org.parosproxy.paros.core.proxy; 21 | 22 | import static org.junit.Assert.assertEquals; 23 | 24 | import java.net.HttpURLConnection; 25 | import java.net.URL; 26 | 27 | import javax.net.ssl.HttpsURLConnection; 28 | 29 | import org.junit.Test; 30 | 31 | /** 32 | * This test loads the image http://code.google.com/p/zaproxy/logo 33 | * to assert a working proxy. 34 | */ 35 | public class HttpProxyConnectionIntegrationTest extends WithBasicInfrastructureIntegrationTest { 36 | 37 | @Test 38 | public void receiveImage() throws Exception { 39 | URL url = new URL("http://code.google.com/p/zaproxy/logo"); 40 | HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 41 | 42 | assertEquals("image/png", connection.getContentType()); 43 | 44 | connection.disconnect(); 45 | } 46 | 47 | @Test 48 | public void receiveSecureImage() throws Exception { 49 | URL url = new URL("https://code.google.com/p/zaproxy/logo"); 50 | HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); 51 | 52 | assertEquals("image/png", connection.getContentType()); 53 | 54 | connection.disconnect(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/org/parosproxy/paros/core/proxy/WebSocketsConnectionIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Zed Attack Proxy (ZAP) and its related class files. 3 | * 4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 5 | * 6 | * Copyright 2010 psiinon@gmail.com 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package org.parosproxy.paros.core.proxy; 21 | 22 | import static org.junit.Assert.assertEquals; 23 | import static org.junit.Assert.assertTrue; 24 | 25 | import java.io.BufferedInputStream; 26 | import java.io.IOException; 27 | import java.io.InputStream; 28 | import java.io.OutputStream; 29 | import java.net.Socket; 30 | import java.net.SocketException; 31 | import java.util.Arrays; 32 | 33 | import org.apache.commons.httpclient.HttpClient; 34 | import org.apache.commons.httpclient.HttpException; 35 | import org.apache.commons.httpclient.params.HttpConnectionManagerParams; 36 | import org.junit.BeforeClass; 37 | import org.junit.Test; 38 | import org.parosproxy.paros.control.Control; 39 | import org.zaproxy.zap.ZapGetMethod; 40 | import org.zaproxy.zap.ZapHttpConnectionManager; 41 | import org.zaproxy.zap.extension.websocket.ExtensionWebSocket; 42 | 43 | /** 44 | * This test uses the Echo Server from websockets.org 45 | * for testing a valid WebSockets connection. 46 | */ 47 | public class WebSocketsConnectionIntegrationTest extends WithBasicInfrastructureIntegrationTest { 48 | 49 | private static String ECHO_SERVER = "http://echo.websocket.org/?encoding=text"; 50 | 51 | @BeforeClass 52 | public static void setup() throws Exception { 53 | System.getProperties().setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true"); 54 | WithBasicInfrastructureIntegrationTest.setup(); 55 | 56 | // load WebSockets extension 57 | Control.initSingletonForTesting(); 58 | Control.getSingleton().getExtensionLoader().addExtension(new ExtensionWebSocket()); 59 | } 60 | 61 | @Test 62 | public void doWebSocketsHandshakeViaClient() throws Exception { 63 | // use HTTP-client with custom connection manager 64 | // that allows us to expose the SocketChannel 65 | HttpClient client = new HttpClient(new ZapHttpConnectionManager()); 66 | client.getHostConfiguration().setProxy(PROXY_HOST, PROXY_PORT); 67 | 68 | // create minimal HTTP request 69 | ZapGetMethod method = new ZapGetMethod(ECHO_SERVER); 70 | method.addRequestHeader("Connection", "upgrade"); 71 | method.addRequestHeader("Upgrade", "websocket"); 72 | method.addRequestHeader("Sec-WebSocket-Version", "13"); 73 | method.addRequestHeader("Sec-WebSocket-Key", "5d5NazNjJ5hafSgFYJ7SOw=="); 74 | client.executeMethod(method); 75 | 76 | int status = method.getStatusCode(); 77 | assertEquals("HTTP status code of WebSockets-handshake response should be 101.", 101, status); 78 | 79 | Socket socket = method.getUpgradedConnection(); 80 | 81 | assertWorkingWebSocket(socket); 82 | 83 | // send hello message a second time to ensure that socket is not closed after first time 84 | assertWorkingWebSocket(socket); 85 | 86 | properlyCloseWebSocket(socket); 87 | } 88 | 89 | @Test 90 | public void doSecureWebSocketsHandshake() throws Exception { 91 | // use HTTP-client with custom connection manager 92 | // that allows us to expose the SocketChannel 93 | HttpClient client = new HttpClient(new ZapHttpConnectionManager()); 94 | client.getHostConfiguration().setProxy(PROXY_HOST, PROXY_PORT); 95 | 96 | // create minimal HTTP handshake request 97 | ZapGetMethod method = new ZapGetMethod("https://echo.websocket.org/?encoding=text"); 98 | method.addRequestHeader("Connection", "upgrade"); 99 | method.addRequestHeader("Upgrade", "websocket"); 100 | method.addRequestHeader("Sec-WebSocket-Version", "13"); 101 | method.addRequestHeader("Sec-WebSocket-Key", "5d5NazNjJ5hafSgFYJ7SOw=="); 102 | client.executeMethod(method); 103 | 104 | assertEquals("HTTP status code of WebSockets-handshake response should be 101.", 101, method.getStatusCode()); 105 | 106 | Socket socket = method.getUpgradedConnection(); 107 | 108 | assertWorkingWebSocket(socket); 109 | 110 | // send hello message a second time to ensure that socket is not closed after first time 111 | assertWorkingWebSocket(socket); 112 | 113 | properlyCloseWebSocket(socket); 114 | } 115 | 116 | @Test 117 | public void getAutobahnCaseCount() throws HttpException { 118 | // use HTTP-client with custom connection manager 119 | // that allows us to expose the SocketChannel 120 | 121 | HttpConnectionManagerParams connectionParams = new HttpConnectionManagerParams(); 122 | connectionParams.setTcpNoDelay(true); 123 | connectionParams.setStaleCheckingEnabled(false); 124 | connectionParams.setSoTimeout(500); 125 | 126 | ZapHttpConnectionManager connectionManager = new ZapHttpConnectionManager(); 127 | connectionManager.setParams(connectionParams); 128 | 129 | HttpClient client = new HttpClient(connectionManager); 130 | client.getHostConfiguration().setProxy(PROXY_HOST, PROXY_PORT); 131 | 132 | // create minimal HTTP handshake request 133 | ZapGetMethod method = new ZapGetMethod("http://localhost:9001/getCaseCount"); 134 | method.addRequestHeader("Connection", "upgrade"); 135 | method.addRequestHeader("Upgrade", "websocket"); 136 | method.addRequestHeader("Sec-WebSocket-Version", "13"); 137 | method.addRequestHeader("Sec-WebSocket-Key", "5d5NazNjJ5hafSgFYJ7SOw=="); 138 | try { 139 | client.executeMethod(method); 140 | } catch (IOException e) { 141 | assertTrue("executing HTTP method failed", false); 142 | } 143 | 144 | assertEquals( 145 | "HTTP status code of WebSockets-handshake response should be 101.", 146 | 101, method.getStatusCode()); 147 | 148 | InputStream remoteInput = method.getUpgradedInputStream(); 149 | 150 | byte[] caseCountFrame = new byte[3]; 151 | int readBytes = 0; 152 | 153 | try { 154 | readBytes = remoteInput.read(caseCountFrame); 155 | } catch (IOException e) { 156 | assertTrue("reading websocket frame failed", false); 157 | } 158 | 159 | assertEquals("Expected some bytes in the first frame.", 3, readBytes); 160 | assertEquals("First WebSocket frame is text message with the case count.", 0x1, caseCountFrame[0] & 0x0f); 161 | 162 | byte[] closeFrame = new byte[2]; 163 | readBytes = 0; 164 | try { 165 | readBytes = remoteInput.read(closeFrame); 166 | } catch (IOException e) { 167 | assertTrue("reading websocket frame failed: " + e.getMessage(), false); 168 | } 169 | 170 | assertEquals("Expected some bytes in the second frame.", 2, readBytes); 171 | 172 | assertEquals("Second WebSocket frame is a close message.", 0x8, closeFrame[0] & 0x0f); 173 | 174 | // now I would send back a close frame and close the physical socket connection 175 | } 176 | // requires Autobahn to be running via "wstest -m fuzzingserver" 177 | @Test 178 | public void doAutobahnTest() throws HttpException, SocketException { 179 | // use HTTP-client with custom connection manager 180 | // that allows us to expose the SocketChannel 181 | HttpClient client = new HttpClient(new ZapHttpConnectionManager()); 182 | client.getHostConfiguration().setProxy(PROXY_HOST, PROXY_PORT); 183 | 184 | // create minimal HTTP handshake request 185 | ZapGetMethod method = new ZapGetMethod( 186 | "http://localhost:9001/runCase?case=1&agent=Proxy"); 187 | method.addRequestHeader("Connection", "upgrade"); 188 | method.addRequestHeader("Upgrade", "websocket"); 189 | method.addRequestHeader("Sec-WebSocket-Version", "13"); 190 | method.addRequestHeader("Sec-WebSocket-Key", "5d5NazNjJ5hafSgFYJ7SOw=="); 191 | try { 192 | client.executeMethod(method); 193 | } catch (IOException e) { 194 | assertTrue("executing HTTP method failed", false); 195 | } 196 | 197 | assertEquals( 198 | "HTTP status code of WebSockets-handshake response should be 101.", 199 | 101, method.getStatusCode()); 200 | 201 | Socket socket = method.getUpgradedConnection(); 202 | socket.setTcpNoDelay(true); 203 | socket.setSoTimeout(500); 204 | 205 | byte[] dst = new byte[20]; 206 | try { 207 | socket.getInputStream().read(dst); 208 | } catch (IOException e) { 209 | assertTrue("reading websocket frame failed: " + e.getMessage(), false); 210 | } 211 | } 212 | 213 | // /** 214 | // * Cannot use this SOCKS approach, as ZAP does not support SOCKS. 215 | // * So I had to use the HttpClient for that purpose. Another try 216 | // * to work with UrlConnection failed, as I was not able to set 217 | // * custom HTTP headers (I was only able to override existing ones). 218 | // * 219 | // * @throws IOException 220 | // */ 221 | // @Test 222 | // public void doWebSocketsHandshakeViaSocks() throws IOException { 223 | // Socket socket = new Socket(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_HOST, PROXY_PORT))); 224 | // socket.connect(new InetSocketAddress("echo.websocket.org", 80), 1000); 225 | // 226 | // PrintWriter writer = new PrintWriter(socket.getOutputStream ()); 227 | // BufferedReader reader = new BufferedReader(new InputStreamReader (socket.getInputStream ())); 228 | // 229 | // writer.print("GET /?encoding=text HTTP/1.1\r\n"); 230 | // writer.print("Host: echo.websocket.org\r\n"); 231 | // writer.print("Connection: keep-alive, Upgrade\r\n"); 232 | // writer.print("Sec-WebSocket-Version: 13\r\n"); 233 | // writer.print("Sec-WebSocket-Key: 5d5NazNjJ5hafSgFYJ7SOw==\r\n"); 234 | // writer.print("Upgrade: websocket\r\n"); 235 | // writer.print("\r\n"); 236 | // writer.flush(); 237 | // 238 | // assertEquals("HTTP/1.1 101 Web Socket Protocol Handshake", reader.readLine()); 239 | // while(!reader.readLine().isEmpty()) { 240 | // // do something with response 241 | // } 242 | // 243 | // socket.close(); 244 | // reader.close(); 245 | // writer.close(); 246 | // } 247 | 248 | private void properlyCloseWebSocket(Socket socket) throws IOException { 249 | assertTrue("Retrieved SocketChannel should not be null.", socket != null); 250 | 251 | byte[] maskedClose = {(byte) 0x88, (byte) 0x82, 0x46, 0x59, (byte) 0xdc, 0x4a, 0x45, (byte) 0xb1}; 252 | 253 | socket.getOutputStream().write(maskedClose); 254 | socket.close(); 255 | } 256 | 257 | /** 258 | * Sends a Hello message into the channel and asserts that 259 | * the same message is returned by the Echo-Server. 260 | * The outgoing message is masked, while the incoming 261 | * contains the message in cleartext. 262 | * 263 | * @param socket 264 | * @throws IOException 265 | */ 266 | private void assertWorkingWebSocket(Socket socket) throws IOException { 267 | assertTrue("Retrieved SocketChannel should not be null.", socket != null); 268 | socket.setSoTimeout(500); 269 | socket.setTcpNoDelay(true); 270 | socket.setKeepAlive(true); 271 | 272 | byte[] maskedHelloMessage = {(byte) 0x81, (byte) 0x85, 0x37, (byte) 0xfa, 0x21, 0x3d, 0x7f, (byte) 0x9f, 0x4d, 0x51, 0x58}; 273 | byte[] unmaskedHelloMessage = {(byte) 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f}; 274 | 275 | InputStream inpStream = new BufferedInputStream(socket.getInputStream()); 276 | 277 | OutputStream out = socket.getOutputStream(); 278 | out.write(maskedHelloMessage); 279 | out.flush(); 280 | 281 | byte[] dst = new byte[7]; 282 | inpStream.read(dst); 283 | 284 | // use Arrays class to compare two byte arrays 285 | // returns true if it contains the same elements in same order 286 | assertTrue("Awaited unmasked hello message from echo server.", Arrays.equals(unmaskedHelloMessage, dst)); 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /src/org/parosproxy/paros/core/proxy/WithBasicInfrastructureIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Zed Attack Proxy (ZAP) and its related class files. 3 | * 4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 5 | * 6 | * Copyright 2010 psiinon@gmail.com 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package org.parosproxy.paros.core.proxy; 21 | 22 | import java.io.ByteArrayInputStream; 23 | import java.io.IOException; 24 | import java.security.KeyManagementException; 25 | import java.security.KeyStore; 26 | import java.security.KeyStoreException; 27 | import java.security.NoSuchAlgorithmException; 28 | import java.security.SecureRandom; 29 | import java.security.UnrecoverableKeyException; 30 | import java.security.cert.CertificateException; 31 | import java.security.cert.X509Certificate; 32 | import java.util.Properties; 33 | 34 | import javax.net.ssl.HostnameVerifier; 35 | import javax.net.ssl.HttpsURLConnection; 36 | import javax.net.ssl.SSLContext; 37 | import javax.net.ssl.SSLSession; 38 | import javax.net.ssl.TrustManager; 39 | import javax.net.ssl.X509TrustManager; 40 | 41 | import org.apache.commons.codec.binary.Base64; 42 | import org.apache.commons.httpclient.protocol.Protocol; 43 | import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; 44 | import org.apache.log4j.ConsoleAppender; 45 | import org.apache.log4j.Level; 46 | import org.apache.log4j.Logger; 47 | import org.apache.log4j.PatternLayout; 48 | import org.junit.After; 49 | import org.junit.Before; 50 | import org.junit.BeforeClass; 51 | import org.parosproxy.paros.Constant; 52 | import org.parosproxy.paros.model.Model; 53 | import org.parosproxy.paros.network.SSLConnector; 54 | import org.parosproxy.paros.security.SslCertificateService; 55 | import org.parosproxy.paros.security.SslCertificateServiceImpl; 56 | 57 | /** 58 | * Provides basic infrastructure. See {@link WebSocketsConnectionIntegrationTest} for an example. 59 | */ 60 | public abstract class WithBasicInfrastructureIntegrationTest { 61 | 62 | protected ProxyServer proxyServer; 63 | 64 | protected static String PROXY_HOST = "127.0.0.1"; 65 | protected static int PROXY_PORT = 8087; 66 | 67 | @Before 68 | public void start() throws Exception { 69 | proxyServer = new ProxyServer(); 70 | proxyServer.startServer(PROXY_HOST, PROXY_PORT, false); 71 | } 72 | 73 | @After 74 | public void stop() { 75 | proxyServer.stopServer(); 76 | } 77 | 78 | @BeforeClass 79 | public static void setup() throws Exception { 80 | initializeLogger(); 81 | initializeProxySettings(); 82 | initializeLocalSecurity(); 83 | initializeRootCertificate(); 84 | initializeLocale(); 85 | } 86 | 87 | private static void initializeLocale() throws Exception { 88 | Constant.setLocale("de_DE"); 89 | Model.getSingleton().init(null); 90 | } 91 | 92 | /** 93 | * Set up logging levels, to ease debugging of tests. 94 | * @throws IOException 95 | */ 96 | protected static void initializeLogger() throws IOException { 97 | // systemProperties.setProperty("javax.net.debug", "ssl"); 98 | 99 | Logger rootLogger = Logger.getRootLogger(); 100 | if (!rootLogger.getAllAppenders().hasMoreElements()) { 101 | rootLogger.setLevel(Level.DEBUG); 102 | rootLogger.addAppender(new ConsoleAppender(new PatternLayout("%-5p [%t]: %m%n"))); 103 | 104 | Logger httpClientLogger = rootLogger.getLoggerRepository().getLogger("org.apache.commons.httpclient"); 105 | httpClientLogger.setLevel(Level.DEBUG); 106 | 107 | Logger httpWireLogger = rootLogger.getLoggerRepository().getLogger("org.apache.commons.wire"); 108 | // httpWireLogger.addAppender(new org.apache.log4j.FileAppender(new PatternLayout("%5p [%c] %m%n"), "wire.log")); 109 | httpWireLogger.setLevel(Level.DEBUG); 110 | } 111 | } 112 | 113 | /** 114 | * Set system property values for proxy settings. 115 | * These settings will be used by Http(s)URLConnection. 116 | */ 117 | protected static void initializeProxySettings() { 118 | Properties systemProperties = System.getProperties(); 119 | systemProperties.setProperty("http.proxyHost", PROXY_HOST); 120 | systemProperties.setProperty("http.proxyPort", PROXY_PORT+""); 121 | systemProperties.setProperty("https.proxyHost", PROXY_HOST); 122 | systemProperties.setProperty("https.proxyPort", PROXY_PORT+""); 123 | } 124 | 125 | /** 126 | * Use custom TrustManager that trusts everything. 127 | * Moreover setup custom ProtocolSocketFactory as done in ZAP. 128 | * 129 | * @throws NoSuchAlgorithmException 130 | * @throws KeyManagementException 131 | */ 132 | protected static void initializeLocalSecurity() throws NoSuchAlgorithmException, KeyManagementException { 133 | SSLContext sslContext = SSLContext.getInstance("SSL"); 134 | 135 | // set up a TrustManager that trusts everything 136 | sslContext.init( null, new TrustManager[] 137 | { 138 | new X509TrustManager() 139 | { 140 | @Override 141 | public void checkClientTrusted(X509Certificate[] chain, 142 | String authType) throws CertificateException { 143 | // everything is trusted 144 | } 145 | 146 | @Override 147 | public void checkServerTrusted(X509Certificate[] chain, 148 | String authType) throws CertificateException { 149 | // everything is trusted 150 | } 151 | 152 | @Override 153 | public X509Certificate[] getAcceptedIssuers() { 154 | return null; 155 | } 156 | } 157 | }, new SecureRandom()); 158 | 159 | // this doesn't seem to apply to connections through a proxy 160 | HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); 161 | 162 | // setup a hostname verifier that verifies everything 163 | HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { 164 | 165 | @Override 166 | public boolean verify(String hostname, SSLSession session) { 167 | return true; 168 | } 169 | }); 170 | 171 | Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) new SSLConnector(), 443)); 172 | } 173 | 174 | /** 175 | * Helper method to set the root certificate for this test. 176 | * 177 | * @throws KeyStoreException 178 | * @throws NoSuchAlgorithmException 179 | * @throws CertificateException 180 | * @throws IOException 181 | * @throws UnrecoverableKeyException 182 | */ 183 | protected static void initializeRootCertificate() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException { 184 | final SslCertificateService service = SslCertificateServiceImpl.getService(); 185 | final byte[] bytes = Base64.decodeBase64("_u3-7QAAAAIAAAABAAAAAQARb3dhc3BfemFwX3Jvb3RfY2EAAAE2LA_eqAAABQIwggT-MA4GCisGAQQBKgIRAQEFAASCBOqboCBB1-ZSxYZqYDwdOLd22xkq1R3-ZJMVlt2ad-SMKGTG52RVHNhAfYYUS14QDwD6LF2TxKuHxKQt-CH2QXGZaRtWNzksTLl50J-irz9l7cDNkS-HI7l3ZLK3Hl8Fr_tx3pi91h1uw9qc5xLl0euLZYDo-bnqtqmrvqzBXS7Th0cDa7IDWWTN1foxoyV-26lc9O_abpcTd8ugJqC5_DoDJ1-yW_eIRT4vqiRl1cxcrZGSrA255O21l1CwBxE3y34HqdQf2eDWpPmVDA5qeLTwUWj_AAeXW574jtjvG42sB1mxk5bhSmp53jGBbQqSh4qgvfsnyS54BicWQFtI5NRy0Bb8KuZe4DmPFkhw9fV6ayMC1ZBE8M1mSvhMaHlxq-NWriH0YAoiTd2g66OXFciPVfQJn6ebu7FLq33LjlxADsVnwdGgHbXeJ85vCprB3VxuRbVDGsch0kfGteunHh5ldYI9rbiurVJOr0r4zx76XyCsf-5BqHS_jey8x7udHEq7orkEzngCQ2lxEY64WKMY4coclHC1FVZqyqJVgXHtRZAc-6UFV1QSCeNBiBaQKtLp9UOS8UbkK4qGvfFOpaGHu14fuM-qcwYnYTrONmNfi6tDdxuLMSPoHGtyMpSwn8yz6g-iHWMBcTccThCmeF40Ns23pjiwDD1weTCEVJwq8oN0v_CUVyysMCqSACtQK9U89R3e_bv-b2losQvVEEzi_R92sXVMe9VctkVAkGJi8gkgl6H1sFyZ4aAA9iUBT7bMCroUmM5V6si8NGJAwlyoNcNGy5SvQBzhmAV2TjukuUoD28ZlWMSqmKbLw0Zb3BFxxEh-sj5Vrquw8YNywAeAHMk0M5esX8Bdh2hmhcRXvYozMjlurs8k0KvmkEDJa0Jw8SfEgHc1sqB0OU3Fg3uKpHOLGCffOk3LiW5UP6hetIvrRl-tFJokHWxXm7E2ORED1LZNPRUU5g_YcSiHpyADRt_LujL30eNbgRPIly_Ra6D6v3Detgd7iqD63GSSxNNBuZ_faYQrdQAXt-UaMCfJS_0e7vaLtrlcV36OcyT7jPVZdtqq9BzfIBeYqNO-TOjaq_pyrtZ6G21F2ttjFzuA2aHi6f3sGdaQ7GxmDvI6s8InMLsvZNmQo7EvLqzv1gVo4594nwGtv9CnRCM7qyZ9GkDjqFySy3OtdkJSOeGLvmZu0c0KHVmeOT2b3J0IwExUwkZ5cKHVyxMUE7BWcZxYIyf9l-Laxp0jdfhPyamRmvAXjXSP6d6Fds7Xntf5WINGrSDwkNTBgqoYB3DpN2ZAtWEhC5riiEuK-AkeSqszc_0Fcs8OM8q2azAgNC1RXYAT5Spbhn_M01IlDXUxVWyxtt92opDnZiLTLSwSBIeb3Bz_xTvkA5AATP5w8p8XF1XF1aaubiiIQItdg1e1IzOhDfbddV-qoCErfvzV_buFLzq-nzdC6dtRRvBPItEKbEyn4I45H2ekRzTUagj7RJqePXvUKVEHfSKcOduM19-sJlMl8dCBWikJfU2yEwys-1VAeVzHjsanL551M6A3X8SWde27wvIvuRL6BEa_3vJo-ggoF6uBFpKZvmqMnFuZyC5sEsEcGhNjnVtt8Cw8VDov9prSf1T5ZmCPlk1Twa0KAjw7quLMEcCVRpPmD91npCnhXKR8TnBexk5MAAAAAQAFWC41MDkAAAPiMIID3jCCAsagAwIBAgIFAMr-ur4wDQYJKoZIhvcNAQEFBQAwgYUxJzAlBgNVBAMMHk9XQVNQIFplZCBBdHRhY2sgUHJveHkgUm9vdCBDQTEZMBcGA1UEBwwQYzhkMmJkODI2ZTZmOWQyMzEWMBQGA1UECgwNT1dBU1AgUm9vdCBDQTEaMBgGA1UECwwRT1dBU1AgWkFQIFJvb3QgQ0ExCzAJBgNVBAYTAnh4MB4XDTEyMDMxOTE3NDQ1OFoXDTEzMDMxOTE3NDQ1OFowgYUxJzAlBgNVBAMMHk9XQVNQIFplZCBBdHRhY2sgUHJveHkgUm9vdCBDQTEZMBcGA1UEBwwQYzhkMmJkODI2ZTZmOWQyMzEWMBQGA1UECgwNT1dBU1AgUm9vdCBDQTEaMBgGA1UECwwRT1dBU1AgWkFQIFJvb3QgQ0ExCzAJBgNVBAYTAnh4MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiUrTsz8fgb0GRo8yikEj7bEg_jCm0BKn_azJIqcJWqCEOhMD38MFDSWOn4LLAZWHLs3YBmwwoyLoNg6aTXj-Cwa6D_NvWSBfMSyqfpFdVFAo3AVfLkWZXoY5cviemr8LRSVAt-2TTYb0JArDY6i23kRFWUSKZcdVMU0hwoq9YAfI_E3FWJ9QH5l_P5EWYK9om349w1Ypl5Y4n1V74yEHeRZo8Fw0BFjk9uLLUTa_NUqEP24q3q7v1MD6-kUZFJJxlyyiGwbtBglxymkMwXKQL1GEPSb0ZOoxjSbDxOUsDjLHW9A8Xh6JQKYL0lMJ6clplrbaNjwtMIM26xJozpRQwQIDAQABo1MwUTAgBgNVHQ4BAf8EFgQUY7QvhPIV67X8kAxEoQTCoyp3N60wDwYDVR0TAQH_BAUwAwEB_zALBgNVHQ8EBAMCAbYwDwYDVR0lBAgwBgYEVR0lADANBgkqhkiG9w0BAQUFAAOCAQEAX5pQ0Pcgy8lEzK3xJaztS3OjUoI1UhJKIqgQeXujXDowMqCLPFHGeN6uVhi4ktjFuun4sfwLBE7CXACl5ZMUpjArD18qdQKQ6glHJ9HYrxKi0lJM2maYt5rkpAhHI8EHnX5IdsDEr2ihoCQUou1h8gGHIe1a6QkeCD_1VrRfKAdwt6UTE6RyaP6nTyr58IZ6Pdw5EQP3FmtA0yXRVapHodQPpudkS24Lj9cxSrpo_gJBSIb-LHpl81TVZg0SAROikcDk69qZDgnbQqLPz6WxsZtWcET1ACOqPHovQIPK6utkyOeOLm-uJL3Iqx84b4yQqnFkG-y-nlDmNWR33DOtE8rTqmBfifcjGibDbx0z26ogkB6I"); 186 | final ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 187 | final KeyStore rootca = KeyStore.getInstance(KeyStore.getDefaultType()); 188 | rootca.load(bais, "0w45P.Z4p".toCharArray()); 189 | bais.close(); 190 | service.initializeRootCA(rootca); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/org/zaproxy/ZapAllTestSuite.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.junit.runners.Suite; 5 | import org.junit.runners.Suite.SuiteClasses; 6 | import org.zaproxy.zap.ZaproxyIntegrationTestSuite; 7 | import org.zaproxy.zap.extension.ZapExtensionsIntegrationTestSuite; 8 | 9 | /** 10 | * Suite for all tests of ZAP and ZAP Extensions. This is the top of the suite 11 | * stack, so there must never be a suite above this one. 12 | * 13 | * @author bjoern.kimminich@gmx.de 14 | */ 15 | @RunWith(Suite.class) 16 | @SuiteClasses({ ZaproxyIntegrationTestSuite.class, ZapExtensionsIntegrationTestSuite.class }) 17 | public final class ZapAllTestSuite { 18 | 19 | } -------------------------------------------------------------------------------- /src/org/zaproxy/clientapi/core/ReflectedXssDetectionIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Zed Attack Proxy (ZAP) and its related class files. 3 | * 4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package org.zaproxy.clientapi.core; 19 | 20 | import org.junit.Test; 21 | 22 | public class ReflectedXssDetectionIntegrationTest { 23 | 24 | @Test 25 | public void testCase01 () throws Exception { 26 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case01-Tag2HtmlPageScope.jsp?userinput=textvalue", 27 | // Ignore alerts 28 | new Alert[] { 29 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 30 | // Require alerts 31 | new Alert[] { 32 | WavsepStatic.CROSS_SITE_SCRIPTING}); 33 | } 34 | 35 | @Test 36 | public void testCase02 () throws Exception { 37 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case02-Tag2TagScope.jsp?userinput=textvalue", 38 | // Ignore alerts 39 | new Alert[] { 40 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 41 | // Require alerts 42 | new Alert[] { 43 | WavsepStatic.CROSS_SITE_SCRIPTING}); 44 | } 45 | 46 | @Test 47 | public void testCase03 () throws Exception { 48 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case03-Tag2TagStructure.jsp?userinput=textvalue", 49 | // Ignore alerts 50 | new Alert[] { 51 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 52 | // Require alerts 53 | new Alert[] { 54 | WavsepStatic.CROSS_SITE_SCRIPTING}); 55 | } 56 | 57 | @Test 58 | public void testCase04 () throws Exception { 59 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case04-Tag2HtmlComment.jsp?userinput=textvalue", 60 | // Ignore alerts 61 | new Alert[] { 62 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 63 | // Require alerts 64 | new Alert[] { 65 | WavsepStatic.CROSS_SITE_SCRIPTING}); 66 | } 67 | 68 | @Test 69 | public void testCase05 () throws Exception { 70 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case05-Tag2Frameset.jsp?userinput=textvalue", 71 | // Ignore alerts 72 | new Alert[] { 73 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 74 | // Require alerts 75 | new Alert[] { 76 | WavsepStatic.CROSS_SITE_SCRIPTING}); 77 | } 78 | 79 | @Test 80 | public void testCase06 () throws Exception { 81 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case06-Event2TagScope.jsp?userinput=textvalue", 82 | // Ignore alerts 83 | new Alert[] { 84 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 85 | // Require alerts 86 | new Alert[] { 87 | WavsepStatic.CROSS_SITE_SCRIPTING}); 88 | } 89 | 90 | @Test 91 | public void testCase07 () throws Exception { 92 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case07-Event2DoubleQuotePropertyScope.jsp?userinput=textvalue", 93 | // Ignore alerts 94 | new Alert[] { 95 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 96 | // Require alerts 97 | new Alert[] { 98 | WavsepStatic.CROSS_SITE_SCRIPTING}); 99 | } 100 | 101 | @Test 102 | public void testCase08 () throws Exception { 103 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case08-Event2SingleQuotePropertyScope.jsp?userinput=textvalue", 104 | // Ignore alerts 105 | new Alert[] { 106 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 107 | // Require alerts 108 | new Alert[] { 109 | WavsepStatic.CROSS_SITE_SCRIPTING}); 110 | } 111 | 112 | @Test 113 | public void testCase09 () throws Exception { 114 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case09-SrcProperty2TagStructure.jsp?userinput=textvalue", 115 | // Ignore alerts 116 | new Alert[] { 117 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 118 | // Require alerts 119 | new Alert[] { 120 | WavsepStatic.CROSS_SITE_SCRIPTING}); 121 | } 122 | 123 | @Test 124 | public void testCase10 () throws Exception { 125 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case10-Js2DoubleQuoteJsEventScope.jsp?userinput=textvalue", 126 | // Ignore alerts 127 | new Alert[] { 128 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 129 | // Require alerts 130 | new Alert[] { 131 | WavsepStatic.CROSS_SITE_SCRIPTING}); 132 | } 133 | 134 | @Test 135 | public void testCase11 () throws Exception { 136 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case11-Js2SingleQuoteJsEventScope.jsp?userinput=textvalue", 137 | // Ignore alerts 138 | new Alert[] { 139 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 140 | // Require alerts 141 | new Alert[] { 142 | WavsepStatic.CROSS_SITE_SCRIPTING}); 143 | } 144 | 145 | @Test 146 | public void testCase12 () throws Exception { 147 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case12-Js2JsEventScope.jsp?userinput=1234", 148 | // Ignore alerts 149 | new Alert[] { 150 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 151 | // Require alerts 152 | new Alert[] { 153 | WavsepStatic.CROSS_SITE_SCRIPTING}); 154 | } 155 | 156 | @Test 157 | public void testCase13 () throws Exception { 158 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case13-Vbs2DoubleQuoteVbsEventScope.jsp?userinput=textvalue", 159 | // Ignore alerts 160 | new Alert[] { 161 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 162 | // Require alerts 163 | new Alert[] { 164 | WavsepStatic.CROSS_SITE_SCRIPTING}); 165 | } 166 | 167 | @Test 168 | public void testCase14 () throws Exception { 169 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case14-Vbs2SingleQuoteVbsEventScope.jsp?userinput=textvalue", 170 | // Ignore alerts 171 | new Alert[] { 172 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 173 | // Require alerts 174 | new Alert[] { 175 | WavsepStatic.CROSS_SITE_SCRIPTING}); 176 | } 177 | 178 | @Test 179 | public void testCase15 () throws Exception { 180 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case15-Vbs2VbsEventScope.jsp?userinput=1234", 181 | // Ignore alerts 182 | new Alert[] { 183 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 184 | // Require alerts 185 | new Alert[] { 186 | WavsepStatic.CROSS_SITE_SCRIPTING}); 187 | } 188 | 189 | @Test 190 | public void testCase16 () throws Exception { 191 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case16-Js2ScriptSupportingProperty.jsp?userinput=dummy.html", 192 | // Ignore alerts 193 | new Alert[] { 194 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 195 | // Require alerts 196 | new Alert[] { 197 | WavsepStatic.CROSS_SITE_SCRIPTING}); 198 | } 199 | 200 | @Test 201 | public void testCase17 () throws Exception { 202 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case17-Js2PropertyJsScopeDoubleQuoteDelimiter.jsp?userinput=david", 203 | // Ignore alerts 204 | new Alert[] { 205 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 206 | // Require alerts 207 | new Alert[] { 208 | WavsepStatic.CROSS_SITE_SCRIPTING}); 209 | } 210 | 211 | @Test 212 | public void testCase18 () throws Exception { 213 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case18-Js2PropertyJsScopeSingleQuoteDelimiter.jsp?userinput=david", 214 | // Ignore alerts 215 | new Alert[] { 216 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 217 | // Require alerts 218 | new Alert[] { 219 | WavsepStatic.CROSS_SITE_SCRIPTING}); 220 | } 221 | 222 | @Test 223 | public void testCase19 () throws Exception { 224 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case19-Js2PropertyJsScope.jsp?userinput=1234", 225 | // Ignore alerts 226 | new Alert[] { 227 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 228 | // Require alerts 229 | new Alert[] { 230 | WavsepStatic.CROSS_SITE_SCRIPTING}); 231 | } 232 | 233 | @Test 234 | public void testCase20 () throws Exception { 235 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case20-Vbs2PropertyVbsScopeDoubleQuoteDelimiter.jsp?userinput=david", 236 | // Ignore alerts 237 | new Alert[] { 238 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 239 | // Require alerts 240 | new Alert[] { 241 | WavsepStatic.CROSS_SITE_SCRIPTING}); 242 | } 243 | 244 | @Test 245 | public void testCase21 () throws Exception { 246 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case21-Vbs2PropertyVbsScope.jsp?userinput=david", 247 | // Ignore alerts 248 | new Alert[] { 249 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 250 | // Require alerts 251 | new Alert[] { 252 | WavsepStatic.CROSS_SITE_SCRIPTING}); 253 | } 254 | 255 | @Test 256 | public void testCase22 () throws Exception { 257 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case22-Js2ScriptTagDoubleQuoteDelimiter.jsp?userinput=david", 258 | // Ignore alerts 259 | new Alert[] { 260 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 261 | // Require alerts 262 | new Alert[] { 263 | WavsepStatic.CROSS_SITE_SCRIPTING}); 264 | } 265 | 266 | @Test 267 | public void testCase23 () throws Exception { 268 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case23-Js2ScriptTagSingleQuoteDelimiter.jsp?userinput=david", 269 | // Ignore alerts 270 | new Alert[] { 271 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 272 | // Require alerts 273 | new Alert[] { 274 | WavsepStatic.CROSS_SITE_SCRIPTING}); 275 | } 276 | 277 | @Test 278 | public void testCase24 () throws Exception { 279 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case24-Js2ScriptTag.jsp?userinput=1234", 280 | // Ignore alerts 281 | new Alert[] { 282 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 283 | // Require alerts 284 | new Alert[] { 285 | WavsepStatic.CROSS_SITE_SCRIPTING}); 286 | } 287 | 288 | @Test 289 | public void testCase25 () throws Exception { 290 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case25-Vbs2ScriptTagDoubleQuoteDelimiter.jsp?userinput=david", 291 | // Ignore alerts 292 | new Alert[] { 293 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 294 | // Require alerts 295 | new Alert[] { 296 | WavsepStatic.CROSS_SITE_SCRIPTING}); 297 | } 298 | 299 | @Test 300 | public void testCase26 () throws Exception { 301 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case26-Vbs2ScriptTag.jsp?userinput=1234", 302 | // Ignore alerts 303 | new Alert[] { 304 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 305 | // Require alerts 306 | new Alert[] { 307 | WavsepStatic.CROSS_SITE_SCRIPTING}); 308 | } 309 | 310 | @Test 311 | public void testCase27 () throws Exception { 312 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case27-Js2ScriptTagOLCommentScope.jsp?userinput=1234", 313 | // Ignore alerts 314 | new Alert[] { 315 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 316 | // Require alerts 317 | new Alert[] { 318 | WavsepStatic.CROSS_SITE_SCRIPTING}); 319 | } 320 | 321 | @Test 322 | public void testCase28 () throws Exception { 323 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case28-Js2ScriptTagMLCommentScope.jsp?userinput=1234", 324 | // Ignore alerts 325 | new Alert[] { 326 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 327 | // Require alerts 328 | new Alert[] { 329 | WavsepStatic.CROSS_SITE_SCRIPTING}); 330 | } 331 | 332 | @Test 333 | public void testCase29 () throws Exception { 334 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case29-Vbs2ScriptTagOLCommentScope.jsp?userinput=1234", 335 | // Ignore alerts 336 | new Alert[] { 337 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 338 | // Require alerts 339 | new Alert[] { 340 | WavsepStatic.CROSS_SITE_SCRIPTING}); 341 | } 342 | 343 | @Test 344 | public void testCase30 () throws Exception { 345 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case30-Tag2HtmlPageScopeMultipleVulnerabilities.jsp?userinput=1234&userinput2=1234", 346 | // Ignore alerts 347 | new Alert[] { 348 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 349 | // Require alerts 350 | new Alert[] { 351 | WavsepStatic.CROSS_SITE_SCRIPTING, WavsepStatic.CROSS_SITE_SCRIPTING}); 352 | } 353 | 354 | @Test 355 | public void testCase31 () throws Exception { 356 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case31-Tag2HtmlPageScopeDuringException.jsp?userinput=textvalue", 357 | // Ignore alerts 358 | new Alert[] { 359 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 360 | // Require alerts 361 | new Alert[] { 362 | WavsepStatic.CROSS_SITE_SCRIPTING}); 363 | } 364 | 365 | @Test 366 | public void testCase32 () throws Exception { 367 | WavsepStatic.genericTest("/wavsep/active/RXSS-Detection-Evaluation-GET/Case32-Tag2HtmlPageScopeValidViewstateRequired.jsp?userinput=textvalue&__VIEWSTATE=%2FwEPDwUENTM4MWRkhsjF%2B62gWnhYUcEyuRwTHxGDVzA%3D", 368 | // Ignore alerts 369 | new Alert[] { 370 | WavsepStatic.INFO_DISCLOSURE_IN_URL, WavsepStatic.X_CONTENT_TYPE_HEADER_MISSING, WavsepStatic.X_FRAME_OPTIONS_HEADER_MISSING}, 371 | // Require alerts 372 | new Alert[] { 373 | WavsepStatic.CROSS_SITE_SCRIPTING}); 374 | } 375 | } 376 | -------------------------------------------------------------------------------- /src/org/zaproxy/clientapi/core/WavsepStatic.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Zed Attack Proxy (ZAP) and its related class files. 3 | * 4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package org.zaproxy.clientapi.core; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.Iterator; 23 | import java.util.List; 24 | import java.util.SortedSet; 25 | import java.util.TreeSet; 26 | import java.util.regex.Pattern; 27 | 28 | import org.apache.commons.httpclient.URI; 29 | import org.zaproxy.clientapi.core.Alert.Confidence; 30 | import org.zaproxy.clientapi.core.Alert.Risk; 31 | 32 | public class WavsepStatic { 33 | 34 | private static Pattern staticPatternParam = Pattern.compile("&", Pattern.CASE_INSENSITIVE); 35 | 36 | // Change these statics to match you local setup 37 | private static String wavsepHost = "http://localhost:8080"; 38 | private static String zapHost = "localhost"; 39 | private static int zapPort = 8090; 40 | private static int sleepInMs = 1000; 41 | 42 | // Alerts for use in require/exclude lists, in alphabetical order - add any new ones required 43 | public static Alert CROSS_SITE_SCRIPTING = 44 | new Alert("Cross Site Scripting", "", Risk.High, null, "", ""); 45 | public static Alert INFO_DISCLOSURE_IN_URL = 46 | new Alert("Information disclosure - sensitive informations in URL", "", Risk.Informational, Confidence.Medium, "", ""); 47 | public static Alert X_CONTENT_TYPE_HEADER_MISSING = 48 | new Alert("X-Content-Type-Options header missing", "", Risk.Low, Confidence.Medium, "", ""); 49 | public static Alert X_FRAME_OPTIONS_HEADER_MISSING = 50 | new Alert("X-Frame-Options header not set", "", Risk.Informational, Confidence.Medium, "", ""); 51 | 52 | 53 | private static ClientApi initClientApi() throws Exception { 54 | ClientApi client = new ClientApi(zapHost, zapPort); 55 | client.core.newSession("", "Wavsep test", "true"); 56 | return client; 57 | } 58 | 59 | // Note that this method is a copy of the code in org.parosproxy.paros.model 60 | private static TreeSet getParamNameSet(String params) throws Exception { 61 | TreeSet set = new TreeSet<>(); 62 | String[] keyValue = staticPatternParam.split(params); 63 | String key = null; 64 | int pos = 0; 65 | for (int i=0; i 0) { 69 | // param found 70 | key = keyValue[i].substring(0,pos); 71 | 72 | //!!! note: this means param not separated by & and = is not parsed 73 | } else { 74 | key = keyValue[i]; 75 | } 76 | 77 | if (key != null) { 78 | set.add(key); 79 | } 80 | } 81 | 82 | return set; 83 | } 84 | 85 | // Note that this method is a copy of the code in org.parosproxy.paros.model 86 | private static String getQueryParamString(SortedSet querySet) { 87 | StringBuilder sb = new StringBuilder(); 88 | Iterator iterator = querySet.iterator(); 89 | for (int i=0; iterator.hasNext(); i++) { 90 | String name = iterator.next(); 91 | if (name == null) { 92 | continue; 93 | } 94 | if (i > 0) { 95 | sb.append(','); 96 | } 97 | if (name.length() > 40) { 98 | // Truncate 99 | name = name.substring(0, 40); 100 | } 101 | sb.append(name); 102 | } 103 | 104 | String result = ""; 105 | if (sb.length()>0) { 106 | result = sb.insert(0, '(').append(')').toString(); 107 | } 108 | 109 | return result; 110 | } 111 | 112 | private static Alert[] setAlertsUrl(Alert[] alerts, String url) { 113 | String baseUrl = url; 114 | if (baseUrl.indexOf("?") > 0) { 115 | baseUrl = url.substring(0, url.indexOf("?")); 116 | } 117 | for (Alert alert : alerts) { 118 | alert.setUrl(baseUrl + ".*"); 119 | } 120 | return alerts; 121 | } 122 | 123 | public static void genericTest(String relativeUrl, Alert[] ignoreAlerts, Alert[] requireAlerts) throws Exception { 124 | String url = wavsepHost + relativeUrl; 125 | 126 | ClientApi client = initClientApi(); 127 | 128 | client.accessUrl(url); 129 | Thread.sleep(sleepInMs); 130 | 131 | String nodeName = url; 132 | 133 | if (nodeName.indexOf("?") >0) { 134 | String query = new URI(nodeName, true).getQuery(); 135 | if (query == null) { 136 | query = ""; 137 | } 138 | nodeName = nodeName.substring(0, nodeName.indexOf("?")) + getQueryParamString(getParamNameSet(query)); 139 | } 140 | 141 | // Dont actually seem to need to spider the URLs... 142 | //client.spiderUrl(nodeName); 143 | //Thread.sleep(sleepInMs); 144 | 145 | client.ascan.scan("", nodeName, "true", "false"); 146 | Thread.sleep(sleepInMs); 147 | 148 | List ignoreAlertsList = new ArrayList<>(ignoreAlerts.length); 149 | ignoreAlertsList.addAll(Arrays.asList(setAlertsUrl(ignoreAlerts, url))); 150 | 151 | List requireAlertsList = new ArrayList<>(requireAlerts.length); 152 | requireAlertsList.addAll(Arrays.asList(setAlertsUrl(requireAlerts, url))); 153 | 154 | client.checkAlerts(ignoreAlertsList, requireAlertsList); 155 | } 156 | 157 | } 158 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/DaemonWaveIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.InputStreamReader; 7 | import java.net.HttpURLConnection; 8 | import java.net.InetSocketAddress; 9 | import java.net.Proxy; 10 | import java.net.URL; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | import net.sf.json.JSONArray; 15 | 16 | import org.junit.Test; 17 | 18 | public class DaemonWaveIntegrationTest { 19 | 20 | private List openUrlViaProxy (Proxy proxy, String apiurl) throws Exception { 21 | List response = new ArrayList<>(); 22 | URL url = new URL(apiurl); 23 | HttpURLConnection uc = (HttpURLConnection)url.openConnection(proxy); 24 | uc.connect(); 25 | 26 | BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream())); 27 | 28 | String inputLine; 29 | 30 | while ((inputLine = in.readLine()) != null) { 31 | response.add(inputLine); 32 | } 33 | 34 | in.close(); 35 | return response; 36 | } 37 | 38 | private void startZAP () throws Exception { 39 | ZAP.main(new String[]{"-daemon"}); 40 | 41 | Thread.sleep(5000); 42 | } 43 | 44 | private void stopZAP (Proxy proxy) throws Exception { 45 | // TODO not found a reliable way of doing this inline yet :( 46 | } 47 | 48 | @Test 49 | public void testDaemonWave () throws Exception { 50 | startZAP(); 51 | 52 | Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8090)); 53 | 54 | // View (empty) hosts 55 | assertEquals("[[]]", openUrlViaProxy(proxy, "http://zap/json/core/view/hosts").toString()); 56 | assertEquals("[, ]", 57 | openUrlViaProxy(proxy, "http://zap/xml/core/view/hosts").toString()); 58 | 59 | // View (empty) sites 60 | assertEquals("[[]]", openUrlViaProxy(proxy, "http://zap/json/core/view/sites").toString()); 61 | assertEquals("[, ]", 62 | openUrlViaProxy(proxy, "http://zap/xml/core/view/sites").toString()); 63 | 64 | // View (empty) URLs 65 | assertEquals("[[]]", openUrlViaProxy(proxy, "http://zap/json/core/view/urls").toString()); 66 | assertEquals("[, ]", 67 | openUrlViaProxy(proxy, "http://zap/xml/core/view/urls").toString()); 68 | 69 | // View (empty) alerts 70 | assertEquals("[[]]", openUrlViaProxy(proxy, "http://zap/json/core/view/alerts").toString()); 71 | assertEquals("[, ]", 72 | openUrlViaProxy(proxy, "http://zap/xml/core/view/alerts").toString()); 73 | 74 | // Access one page via the proxy 75 | openUrlViaProxy(proxy, "http://localhost:8080/zap-wave/"); 76 | Thread.sleep(2000); 77 | 78 | // View hosts (localhost) 79 | assertEquals("[[\"localhost\"]]", openUrlViaProxy(proxy, "http://zap/json/core/view/hosts").toString()); 80 | assertEquals("[, localhost]", 81 | openUrlViaProxy(proxy, "http://zap/xml/core/view/hosts").toString()); 82 | 83 | // View sites (localhost) 84 | assertEquals("[[\"http://localhost:8080\"]]", openUrlViaProxy(proxy, "http://zap/json/core/view/sites").toString()); 85 | assertEquals("[, http://localhost:8080]", 86 | openUrlViaProxy(proxy, "http://zap/xml/core/view/sites").toString()); 87 | 88 | 89 | // View URLs (2) 90 | assertEquals("[[\"http://localhost:8080\",\"http://localhost:8080/zap-wave/\"]]", 91 | openUrlViaProxy(proxy, "http://zap/json/core/view/urls").toString()); 92 | assertEquals("[, http://localhost:8080" + 93 | "http://localhost:8080/zap-wave/]", 94 | openUrlViaProxy(proxy, "http://zap/xml/core/view/urls").toString()); 95 | 96 | // Spider status - not started 97 | assertEquals("[[\"0\"]]", openUrlViaProxy(proxy, "http://zap/json/spider/view/status").toString()); 98 | assertEquals("[, 0]", 99 | openUrlViaProxy(proxy, "http://zap/xml/spider/view/status").toString()); 100 | 101 | // Spider 102 | assertEquals("[[\"OK\"]]", openUrlViaProxy(proxy, "http://zap/json/spider/action/scan/?url=http://localhost:8080/zap-wave/").toString()); 103 | 104 | // wait till finished 105 | while ( ! openUrlViaProxy(proxy, "http://zap/json/spider/view/status").toString().equals("[[\"100\"]]")) { 106 | Thread.sleep(1000); 107 | } 108 | 109 | JSONArray jsonResponse; 110 | 111 | // Check all urls spidered 112 | jsonResponse = JSONArray.fromObject(openUrlViaProxy(proxy, "http://zap/json/core/view/urls").toString()); 113 | assertEquals(1, jsonResponse.size()); 114 | assertEquals(true, jsonResponse.get(0) instanceof JSONArray); 115 | assertEquals(38, ((JSONArray)jsonResponse.get(0)).size()); 116 | 117 | // Ensure the passive scanning has been done 118 | Thread.sleep(5000); 119 | 120 | // View alerts (3) 121 | JSONArray alerts = JSONArray.fromObject(openUrlViaProxy(proxy, "http://zap/json/core/view/alerts").toString()); 122 | assertEquals(1, alerts.size()); 123 | assertEquals(true, alerts.get(0) instanceof JSONArray); 124 | assertEquals(3, ((JSONArray)alerts.get(0)).size()); 125 | 126 | // Active Scan status - not started 127 | assertEquals("[[\"0\"]]", openUrlViaProxy(proxy, "http://zap/json/ascan/view/status").toString()); 128 | assertEquals("[, 0]", 129 | openUrlViaProxy(proxy, "http://zap/xml/ascan/view/status").toString()); 130 | 131 | // Active Scan 132 | assertEquals("[[\"OK\"]]", openUrlViaProxy(proxy, "http://zap/json/ascan/action/scan/?url=http://localhost:8080/").toString()); 133 | 134 | // wait till finished 135 | while ( ! openUrlViaProxy(proxy, "http://zap/json/ascan/view/status").toString().equals("[[\"100\"]]")) { 136 | Thread.sleep(1000); 137 | } 138 | 139 | // View alerts (11) 140 | // TODO check this is the right number! 141 | alerts = JSONArray.fromObject(openUrlViaProxy(proxy, "http://zap/json/core/view/alerts").toString()); 142 | assertEquals(1, alerts.size()); 143 | assertEquals(true, alerts.get(0) instanceof JSONArray); 144 | assertEquals(11, ((JSONArray)alerts.get(0)).size()); 145 | 146 | // Bad view 147 | assertEquals("[{\"code\":\"bad_view\",\"message\":\"Bad View\"}]", 148 | openUrlViaProxy(proxy, "http://zap/json/core/view/xxx").toString()); 149 | assertEquals("[, bad_viewBad View]", 150 | openUrlViaProxy(proxy, "http://zap/xml/core/view/xxx").toString()); 151 | 152 | // Bad action 153 | assertEquals("[{\"code\":\"bad_action\",\"message\":\"Bad Action\"}]", 154 | openUrlViaProxy(proxy, "http://zap/json/core/action/xxx").toString()); 155 | assertEquals("[, bad_actionBad Action]", 156 | openUrlViaProxy(proxy, "http://zap/xml/core/action/xxx").toString()); 157 | 158 | stopZAP(proxy); 159 | 160 | } 161 | 162 | public static void main(String[] args) throws Exception { 163 | DaemonWaveIntegrationTest test = new DaemonWaveIntegrationTest(); 164 | test.testDaemonWave (); 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/TestWebAppUtils.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * Helper class for storing various data and constants related to the test webapp (zap-test-webapp) 7 | */ 8 | public class TestWebAppUtils { 9 | 10 | public static final String APP_BASE_URL = "http://localhost:8080/zap-test-webapp/"; 11 | 12 | // HTTP AUTHENTICATION SECTION 13 | public static final String HTTP_AUTH_APP_BASE_URL = APP_BASE_URL + "http-auth/"; 14 | public static final String HTTP_AUTH_RESTRICTED_APP_BASE_URL = APP_BASE_URL + "http-auth/restricted/"; 15 | public static final String HTTP_AUTH_USERNAME = "tomcat"; 16 | public static final String HTTP_AUTH_USERPASS = "tomcat"; 17 | public static final String HTTP_AUTH_HOSTNAME = "localhost"; 18 | public static final String HTTP_AUTH_REALM = "Zaproxy"; 19 | public static final int HTTP_AUTH_PORT = 8080; 20 | public static ArrayList httpAuthRestrictedPages; 21 | public static ArrayList httpAuthUnrestrictedPages; 22 | public static TestPage httpAuthLogoutPage = new TestPage( 23 | HTTP_AUTH_APP_BASE_URL + "logout.jsp", "fb-unrestricted-logout-512873"); 24 | public static TestPage httpAuthErrorPage = new TestPage( 25 | HTTP_AUTH_APP_BASE_URL + "error.jsp", "fb-unrestricted-error-498762"); 26 | static { 27 | httpAuthRestrictedPages = new ArrayList<>(); 28 | httpAuthRestrictedPages.add(new TestPage(HTTP_AUTH_RESTRICTED_APP_BASE_URL + "home.jsp", 29 | "http-restricted-home-872642")); 30 | httpAuthRestrictedPages.add(new TestPage(HTTP_AUTH_RESTRICTED_APP_BASE_URL + "a.jsp", 31 | "http-restricted-a-432342")); 32 | httpAuthRestrictedPages.add(new TestPage(HTTP_AUTH_RESTRICTED_APP_BASE_URL + "b.jsp", 33 | "http-restricted-b-915324")); 34 | httpAuthRestrictedPages.add(new TestPage(HTTP_AUTH_RESTRICTED_APP_BASE_URL + "ac.jsp", 35 | "http-restricted-ac-328712")); 36 | 37 | 38 | httpAuthUnrestrictedPages = new ArrayList<>(); 39 | httpAuthUnrestrictedPages.add(new TestPage(HTTP_AUTH_APP_BASE_URL + "", 40 | "http-unrestricted-index-142628")); 41 | httpAuthUnrestrictedPages.add(new TestPage(HTTP_AUTH_APP_BASE_URL + "d.jsp", 42 | "http-unrestricted-d-692731")); 43 | } 44 | 45 | // FORM BASED AUTHENTICATION SECTION 46 | public static final String FORM_BASED_AUTH_APP_BASE_URL = APP_BASE_URL + "form-based-auth/"; 47 | public static final String FORM_BASED_AUTH_RESTRICTED_APP_BASE_URL = APP_BASE_URL 48 | + "form-based-auth/restricted/"; 49 | public static ArrayList formBasedAuthRestrictedPages; 50 | public static ArrayList formBasedAuthUnrestrictedPages; 51 | public static TestPage formBasedAuthLogoutPage = new TestPage( 52 | FORM_BASED_AUTH_APP_BASE_URL + "logout.jsp", "fb-unrestricted-logout-512873"); 53 | public static TestPage formBasedAuthErrorPage = new TestPage( 54 | FORM_BASED_AUTH_APP_BASE_URL + "error.jsp", "fb-unrestricted-error-498762"); 55 | static { 56 | formBasedAuthRestrictedPages = new ArrayList<>(); 57 | formBasedAuthRestrictedPages.add(new TestPage(FORM_BASED_AUTH_RESTRICTED_APP_BASE_URL + "home.jsp", 58 | "fb-restricted-home-269039")); 59 | formBasedAuthRestrictedPages.add(new TestPage(FORM_BASED_AUTH_RESTRICTED_APP_BASE_URL + "a.jsp", 60 | "fb-restricted-a-382641")); 61 | formBasedAuthRestrictedPages.add(new TestPage(FORM_BASED_AUTH_RESTRICTED_APP_BASE_URL + "ac.jsp", 62 | "fb-restricted-ac-863602")); 63 | formBasedAuthRestrictedPages.add(new TestPage(FORM_BASED_AUTH_RESTRICTED_APP_BASE_URL + "b.jsp", 64 | "fb-restricted-b-972631")); 65 | 66 | formBasedAuthUnrestrictedPages = new ArrayList<>(); 67 | formBasedAuthUnrestrictedPages.add(new TestPage(FORM_BASED_AUTH_APP_BASE_URL + "", 68 | "fb-unrestricted-index-198734")); 69 | formBasedAuthUnrestrictedPages.add(new TestPage(FORM_BASED_AUTH_APP_BASE_URL + "d.jsp", 70 | "fb-unrestricted-d-629742")); 71 | } 72 | 73 | public static class TestPage { 74 | public String url; 75 | public String identifier; 76 | 77 | public TestPage(String page, String identifier) { 78 | this.url = page; 79 | this.identifier = identifier; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/ZaproxyIntegrationTestSuite.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.junit.runners.Suite; 5 | import org.junit.runners.Suite.SuiteClasses; 6 | import org.parosproxy.paros.core.proxy.HttpProxyConnectionIntegrationTest; 7 | import org.parosproxy.paros.core.proxy.WebSocketsConnectionIntegrationTest; 8 | import org.zaproxy.clientapi.core.ReflectedXssDetectionIntegrationTest; 9 | import org.zaproxy.zap.authentication.AuthenticationIntegrationTestSuite; 10 | import org.zaproxy.zap.session.SessionManagementMethodIntegrationTestSuite; 11 | 12 | /** 13 | * Suite for all integration tests of ZAP. Tests attached to this suite may 14 | * depend on certain environmental settings or preferences but should still be 15 | * able to execute on any possible machine. 16 | * 17 | * @author bjoern.kimminich@gmx.de 18 | */ 19 | @RunWith(Suite.class) 20 | @SuiteClasses({ ReflectedXssDetectionIntegrationTest.class, 21 | HttpProxyConnectionIntegrationTest.class, 22 | WebSocketsConnectionIntegrationTest.class, 23 | DaemonWaveIntegrationTest.class, 24 | AuthenticationIntegrationTestSuite.class, 25 | SessionManagementMethodIntegrationTestSuite.class }) 26 | public final class ZaproxyIntegrationTestSuite { 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/authentication/AbstractAuthenticationMethodUnitTest.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.authentication; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertFalse; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import java.sql.SQLException; 8 | 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.mockito.Mockito; 12 | import org.mockito.runners.MockitoJUnitRunner; 13 | import org.parosproxy.paros.Constant; 14 | import org.parosproxy.paros.model.Session; 15 | import org.zaproxy.zap.authentication.AuthenticationMethodType.UnsupportedAuthenticationMethodException; 16 | import org.zaproxy.zap.model.InMemoryContextDataMockSession; 17 | 18 | @RunWith(MockitoJUnitRunner.class) 19 | public abstract class AbstractAuthenticationMethodUnitTest { 20 | 21 | protected abstract AuthenticationMethodType getMethodTypeImplementation(); 22 | 23 | @Test 24 | public void isTypeForMethodShouldReturnProperResult() { 25 | // Given 26 | AuthenticationMethod method = getMethodTypeImplementation().createAuthenticationMethod(0); 27 | AuthenticationMethod wrongMethod = Mockito.mock(AuthenticationMethod.class); 28 | 29 | // When/Then 30 | assertTrue(getMethodTypeImplementation().isTypeForMethod(method)); 31 | assertFalse(getMethodTypeImplementation().isTypeForMethod(wrongMethod)); 32 | } 33 | 34 | @Test 35 | public void shouldReturnProperType() { 36 | // Given 37 | AuthenticationMethod method = getMethodTypeImplementation().createAuthenticationMethod(0); 38 | // When/Then 39 | assertTrue(method.getType().getClass().equals(getMethodTypeImplementation().getClass())); 40 | } 41 | 42 | @Test 43 | public void shouldImplementCloneEqualsAndHashProperly() { 44 | // Given 45 | AuthenticationMethod method = getMethodTypeImplementation().createAuthenticationMethod(0); 46 | // When 47 | AuthenticationMethod clone = method.clone(); 48 | // Then 49 | assertEquals(method, clone); 50 | assertEquals(method.hashCode(), clone.hashCode()); 51 | } 52 | 53 | @Test 54 | public void shouldPersistAndLoadFromSession() throws UnsupportedAuthenticationMethodException, 55 | SQLException { 56 | 57 | // Given 58 | Constant.getInstance(); 59 | AuthenticationMethod method = getMethodTypeImplementation().createAuthenticationMethod(0); 60 | Session session = new InMemoryContextDataMockSession(); 61 | 62 | // When 63 | getMethodTypeImplementation().persistMethodToSession(session, 0, method); 64 | AuthenticationMethod restoredMethod = getMethodTypeImplementation().loadMethodFromSession(session, 0); 65 | 66 | // Then 67 | assertEquals(method, restoredMethod); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/authentication/AuthenticationIntegrationTestSuite.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.authentication; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.junit.runners.Suite; 5 | import org.junit.runners.Suite.SuiteClasses; 6 | 7 | /** 8 | * Suite for all Authentication related integration tests of ZAP. Tests attached 9 | * to this suite may depend on certain environmental settings or preferences but 10 | * should still be able to execute on any possible machine. 11 | * 12 | * @author cosmin stefan 13 | */ 14 | @RunWith(Suite.class) 15 | @SuiteClasses({ FormBasedAuthenticationIntegrationTest.class, 16 | HttpAuthenticationIntegrationTest.class, 17 | ManualAuthenticationMethodIntegrationTest.class, 18 | FormBasedAuthenticationMethodIntegrationTest.class, 19 | HttpAuthenticationMethodIntegrationTest.class }) 20 | public final class AuthenticationIntegrationTestSuite { 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/authentication/FormBasedAuthenticationIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.authentication; 2 | 3 | import static org.hamcrest.Matchers.containsString; 4 | import static org.junit.Assert.assertNotNull; 5 | import static org.junit.Assert.assertThat; 6 | import static org.mockito.Mockito.doReturn; 7 | import static org.mockito.Mockito.spy; 8 | import static org.mockito.Mockito.times; 9 | import static org.mockito.Mockito.verify; 10 | import static org.mockito.Mockito.when; 11 | 12 | import java.io.IOException; 13 | import java.util.List; 14 | 15 | import org.apache.commons.httpclient.URI; 16 | import org.apache.commons.httpclient.URIException; 17 | import org.junit.Before; 18 | import org.junit.BeforeClass; 19 | import org.junit.Test; 20 | import org.junit.runner.RunWith; 21 | import org.mockito.Mockito; 22 | import org.mockito.runners.MockitoJUnitRunner; 23 | import org.parosproxy.paros.Constant; 24 | import org.parosproxy.paros.model.Model; 25 | import org.parosproxy.paros.network.HttpMalformedHeaderException; 26 | import org.parosproxy.paros.network.HttpMessage; 27 | import org.parosproxy.paros.network.HttpRequestHeader; 28 | import org.parosproxy.paros.network.HttpSender; 29 | import org.zaproxy.zap.TestWebAppUtils; 30 | import org.zaproxy.zap.TestWebAppUtils.TestPage; 31 | import org.zaproxy.zap.authentication.FormBasedAuthenticationMethodType.FormBasedAuthenticationMethod; 32 | import org.zaproxy.zap.model.Context; 33 | import org.zaproxy.zap.session.CookieBasedSessionManagementMethodType; 34 | import org.zaproxy.zap.session.SessionManagementMethod; 35 | import org.zaproxy.zap.users.User; 36 | 37 | /** 38 | * A set of integration tests for {@link FormBasedAuthenticationMethod}. In order for the test to 39 | * properly work, the following configuration must be done: 40 | *
    41 | *
  • The test-webapp (test-webapp/zap-test-webapp.war) should be started and deployed on localhost 42 | * (more specifically deployed on the path specified by {@link TestWebAppUtils#APP_BASE_URL}).
  • 43 | *
44 | */ 45 | @RunWith(MockitoJUnitRunner.class) 46 | public class FormBasedAuthenticationIntegrationTest { 47 | 48 | private static final String LOGGED_IN_INDICATOR = "Welcome:\\s*[^\\s]*"; 49 | private static final String LOGIN_REQUEST_URL = TestWebAppUtils.FORM_BASED_AUTH_APP_BASE_URL 50 | + "loginCheck.jsp"; 51 | private static final String LOGIN_REQUEST_BODY = "username=" 52 | + FormBasedAuthenticationMethod.MSG_USER_PATTERN + "&password=" 53 | + FormBasedAuthenticationMethod.MSG_PASS_PATTERN; 54 | private static final String USER_NAME = "user1"; 55 | private static final String USER_PASS = "user1"; 56 | private static FormBasedAuthenticationMethodType type; 57 | 58 | private User user; 59 | private static SessionManagementMethod sessionManagementMethod; 60 | private static Context mockedContext; 61 | private static FormBasedAuthenticationMethod method; 62 | private static HttpSender httpSender; 63 | 64 | private static final List restrictedPages = TestWebAppUtils.formBasedAuthRestrictedPages; 65 | private static final List unrestrictedPages = TestWebAppUtils.formBasedAuthUnrestrictedPages; 66 | private static final TestPage logoutPage = TestWebAppUtils.formBasedAuthLogoutPage; 67 | 68 | @BeforeClass 69 | public static void classSetUp() throws Exception { 70 | // Make sure Constant is loaded for messages 71 | Constant.getInstance(); 72 | type = new FormBasedAuthenticationMethodType(); 73 | 74 | // Prepare session management method 75 | sessionManagementMethod = new CookieBasedSessionManagementMethodType() 76 | .createSessionManagementMethod(0); 77 | 78 | // Prepare authentication method 79 | method = spy(type.createAuthenticationMethod(0)); 80 | method.setLoggedInIndicatorPattern(LOGGED_IN_INDICATOR); 81 | method.setLoginRequest(LOGIN_REQUEST_URL, LOGIN_REQUEST_BODY); 82 | 83 | // Prepare mocked context 84 | mockedContext = Mockito.mock(Context.class); 85 | when(mockedContext.getSessionManagementMethod()).thenReturn(sessionManagementMethod); 86 | when(mockedContext.getAuthenticationMethod()).thenReturn(method); 87 | 88 | // Prepare HttpSender 89 | httpSender = new HttpSender(Model.getSingleton().getOptionsParam().getConnectionParam(), false, 90 | HttpSender.SPIDER_INITIATOR); 91 | } 92 | 93 | @Before 94 | public void setup() { 95 | // Prepare a test user 96 | user = spy(new User(0, USER_NAME)); 97 | UsernamePasswordAuthenticationCredentials credentials = new UsernamePasswordAuthenticationCredentials( 98 | USER_NAME, USER_PASS); 99 | user.setAuthenticationCredentials(credentials); 100 | doReturn(mockedContext).when(user).getContext(); 101 | } 102 | 103 | private HttpMessage buildMessage(String url) throws URIException, HttpMalformedHeaderException, 104 | NullPointerException { 105 | HttpMessage msg = new HttpMessage(); 106 | msg.setRequestHeader(new HttpRequestHeader(HttpRequestHeader.GET, new URI(url, false), 107 | HttpRequestHeader.HTTP10)); 108 | return msg; 109 | } 110 | 111 | private HttpMessage sendMessage(String url, boolean asUser) throws NullPointerException, IOException { 112 | HttpMessage msg = buildMessage(url); 113 | if (asUser) 114 | msg.setRequestingUser(user); 115 | httpSender.sendAndReceive(msg); 116 | return msg; 117 | } 118 | 119 | private void visitAndCheckPagesSet(List pages) throws NullPointerException, IOException { 120 | for (TestPage pageEntry : pages) 121 | visitAndCheckCorrectPage(pageEntry); 122 | } 123 | 124 | private void visitAndCheckCorrectPage(TestPage page) throws NullPointerException, IOException { 125 | visitAndCheckCorrectPage(page, true); 126 | } 127 | 128 | private void visitAndCheckCorrectPage(TestPage page, boolean asUser) throws NullPointerException, 129 | IOException { 130 | assertThat(sendMessage(page.url, asUser).getResponseBody().toString(), 131 | containsString(page.identifier)); 132 | } 133 | 134 | @Test 135 | public void shouldHaveThingsConfigured() { 136 | // Given/When/Then 137 | assertNotNull(method.authenticate(sessionManagementMethod, user.getAuthenticationCredentials(), user)); 138 | } 139 | 140 | @Test 141 | public void shouldHaveEverythingSetupToSendMessages() throws Exception { 142 | // Given/When/Then 143 | visitAndCheckCorrectPage(unrestrictedPages.get(0), false); 144 | } 145 | 146 | @Test 147 | public void shouldNotAccessRestrictedAreaUnauthenticated() throws NullPointerException, IOException { 148 | // Given 149 | HttpMessage msg = buildMessage(restrictedPages.get(0).url); 150 | // When 151 | httpSender.sendAndReceive(msg, true); 152 | // Then 153 | assertThat(msg.getResponseBody().toString(), 154 | containsString(TestWebAppUtils.formBasedAuthErrorPage.identifier)); 155 | assertThat(msg.getResponseBody().toString(), containsString("Unauthorized")); 156 | } 157 | 158 | @Test 159 | public void shouldAuthenticateInRestrictedArea() throws Exception { 160 | // Given/When/Then 161 | visitAndCheckPagesSet(restrictedPages); 162 | } 163 | 164 | @Test 165 | public void shouldAuthenticateOnlyOnceOnTheSite() throws NullPointerException, IOException { 166 | // Given/When 167 | visitAndCheckPagesSet(restrictedPages); 168 | visitAndCheckPagesSet(unrestrictedPages); 169 | 170 | // Then 171 | verify(method, times(1)).authenticate(sessionManagementMethod, user.getAuthenticationCredentials(), 172 | user); 173 | } 174 | 175 | @Test 176 | public void shouldAuthenticateAfterLogout() throws NullPointerException, IOException { 177 | // Given/When 178 | visitAndCheckCorrectPage(restrictedPages.get(0)); 179 | visitAndCheckCorrectPage(logoutPage); 180 | visitAndCheckCorrectPage(restrictedPages.get(1)); 181 | 182 | // Then 183 | verify(method, times(3)).authenticate(sessionManagementMethod, user.getAuthenticationCredentials(), 184 | user); // 3 times as after the first logout it tries again to authenticate 185 | } 186 | 187 | @Test 188 | public void shouldNotAuthenticateMoreThanNecessary() throws NullPointerException, IOException { 189 | // Given/When 190 | visitAndCheckCorrectPage(restrictedPages.get(0)); 191 | visitAndCheckCorrectPage(restrictedPages.get(1)); 192 | visitAndCheckCorrectPage(logoutPage); 193 | visitAndCheckCorrectPage(restrictedPages.get(2)); 194 | visitAndCheckCorrectPage(logoutPage); 195 | visitAndCheckCorrectPage(restrictedPages.get(3)); 196 | visitAndCheckCorrectPage(unrestrictedPages.get(0)); 197 | 198 | // Then 199 | verify(method, times(5)).authenticate(sessionManagementMethod, user.getAuthenticationCredentials(), 200 | user); // 5 Times as after each logout it tries again to authenticate 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/authentication/FormBasedAuthenticationMethodIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.authentication; 2 | 3 | import static org.hamcrest.Matchers.containsString; 4 | import static org.hamcrest.Matchers.notNullValue; 5 | import static org.junit.Assert.assertEquals; 6 | import static org.junit.Assert.assertThat; 7 | import static org.junit.Assert.assertTrue; 8 | import static org.mockito.Matchers.anyObject; 9 | import static org.mockito.Mockito.doAnswer; 10 | import static org.mockito.Mockito.mock; 11 | import static org.mockito.Mockito.spy; 12 | import static org.mockito.Mockito.when; 13 | 14 | import org.junit.BeforeClass; 15 | import org.junit.Test; 16 | import org.junit.runner.RunWith; 17 | import org.mockito.Mockito; 18 | import org.mockito.invocation.InvocationOnMock; 19 | import org.mockito.runners.MockitoJUnitRunner; 20 | import org.mockito.stubbing.Answer; 21 | import org.parosproxy.paros.Constant; 22 | import org.parosproxy.paros.network.HttpMessage; 23 | import org.parosproxy.paros.network.HttpRequestHeader; 24 | import org.parosproxy.paros.network.HttpResponseHeader; 25 | import org.parosproxy.paros.network.HttpSender; 26 | import org.parosproxy.paros.network.HttpStatusCode; 27 | import org.zaproxy.zap.TestWebAppUtils; 28 | import org.zaproxy.zap.authentication.AuthenticationMethod.UnsupportedAuthenticationCredentialsException; 29 | import org.zaproxy.zap.authentication.FormBasedAuthenticationMethodType.FormBasedAuthenticationMethod; 30 | import org.zaproxy.zap.session.SessionManagementMethod; 31 | import org.zaproxy.zap.session.WebSession; 32 | import org.zaproxy.zap.users.User; 33 | 34 | /** 35 | * A set of unit tests for {@link FormBasedAuthenticationMethod}. In order for the test to properly 36 | * work, the following configuration must be done: 37 | *
    38 | *
  • The test-webapp (test-webapp/zap-test-webapp.war) should be started and deployed on localhost 39 | * (more specifically deployed on the path specified by {@link TestWebAppUtils#APP_BASE_URL}).
  • 40 | *
41 | */ 42 | @RunWith(MockitoJUnitRunner.class) 43 | public class FormBasedAuthenticationMethodIntegrationTest extends AbstractAuthenticationMethodUnitTest { 44 | 45 | private static FormBasedAuthenticationMethodType type; 46 | private static final String LOGGED_IN_INDICATOR = "Welcome [^\\s]*"; 47 | private static final String LOGIN_REQUEST_URL = "http://localhost:8080/zap-test-webapp/form-based-auth/loginCheck.jsp"; 48 | private static final String LOGIN_REQUEST_BODY = "username=" 49 | + FormBasedAuthenticationMethod.MSG_USER_PATTERN + "&password=" 50 | + FormBasedAuthenticationMethod.MSG_PASS_PATTERN; 51 | private static final String USER_NAME = "user1"; 52 | private static final String USER_PASS = "user1"; 53 | private static final String WRONG_USER_PASS = "testing"; 54 | 55 | @BeforeClass 56 | public static void classSetUp() { 57 | // Make sure Constant is loaded for messages 58 | Constant.getInstance(); 59 | 60 | type = new FormBasedAuthenticationMethodType(); 61 | } 62 | 63 | private UsernamePasswordAuthenticationCredentials getMockedCredentials() { 64 | UsernamePasswordAuthenticationCredentials mockedCredentials = Mockito 65 | .mock(UsernamePasswordAuthenticationCredentials.class); 66 | when(mockedCredentials.getUsername()).thenReturn(USER_NAME); 67 | when(mockedCredentials.getPassword()).thenReturn(USER_PASS); 68 | return mockedCredentials; 69 | } 70 | 71 | private FormBasedAuthenticationMethod createMethod(String loginRequestUrl, String loginRequestBody) 72 | throws Exception { 73 | FormBasedAuthenticationMethod method = type.createAuthenticationMethod(0); 74 | method.setLoggedInIndicatorPattern(LOGGED_IN_INDICATOR); 75 | method.setLoginRequest(loginRequestUrl, loginRequestBody); 76 | return method; 77 | } 78 | 79 | @Test 80 | public void shouldBuildCorrectPostAuthenticationMessage() throws Exception { 81 | // Given 82 | HttpSender mockedSender = mock(HttpSender.class); 83 | doAnswer(new Answer() { 84 | @Override 85 | public HttpMessage answer(InvocationOnMock invocation) throws Throwable { 86 | HttpMessage authMessage = ((HttpMessage) invocation.getArguments()[0]); 87 | 88 | // Then 89 | assertEquals(authMessage.getRequestHeader().getMethod(), HttpRequestHeader.POST); 90 | assertEquals(authMessage.getRequestHeader().getURI().toString(), LOGIN_REQUEST_URL); 91 | assertThat(authMessage.getRequestBody().toString(), containsString("username=" + USER_NAME 92 | + "&password=" + USER_PASS)); 93 | return (HttpMessage) invocation.getArguments()[0]; 94 | } 95 | }).when(mockedSender).sendAndReceive((HttpMessage) anyObject()); 96 | 97 | FormBasedAuthenticationMethod spiedMethod = spy(createMethod(LOGIN_REQUEST_URL, LOGIN_REQUEST_BODY)); 98 | when(spiedMethod.getHttpSender()).thenReturn(mockedSender); 99 | 100 | SessionManagementMethod mockedSessionManagementMethod = Mockito.mock(SessionManagementMethod.class); 101 | User mockedUser = mock(User.class); 102 | 103 | // When 104 | spiedMethod.authenticate(mockedSessionManagementMethod, getMockedCredentials(), mockedUser); 105 | } 106 | 107 | @Test 108 | public void shouldAuthenticateWithRightCredentials() 109 | throws UnsupportedAuthenticationCredentialsException, Exception { 110 | // Given 111 | SessionManagementMethod mockedSessionManagementMethod = mock(SessionManagementMethod.class); 112 | doAnswer(new Answer() { 113 | 114 | @Override 115 | public WebSession answer(InvocationOnMock invocation) throws Throwable { 116 | HttpMessage authMessage = ((HttpMessage) invocation.getArguments()[0]); 117 | // Then 118 | assertTrue(HttpStatusCode.isRedirection(authMessage.getResponseHeader().getStatusCode())); 119 | assertEquals(authMessage.getResponseHeader().getHeader(HttpResponseHeader.LOCATION), 120 | "http://localhost:8080/zap-test-webapp/form-based-auth/restricted/home.jsp"); 121 | return mock(WebSession.class); 122 | } 123 | }).when(mockedSessionManagementMethod).extractWebSession((HttpMessage) anyObject()); 124 | 125 | User mockedUser = mock(User.class); 126 | 127 | // When 128 | createMethod(LOGIN_REQUEST_URL, LOGIN_REQUEST_BODY).authenticate(mockedSessionManagementMethod, 129 | getMockedCredentials(), mockedUser); 130 | } 131 | 132 | @Test 133 | public void shouldNotAuthenticateWithWrongCredentials() 134 | throws UnsupportedAuthenticationCredentialsException, Exception { 135 | // Given 136 | SessionManagementMethod mockedSessionManagementMethod = mock(SessionManagementMethod.class); 137 | doAnswer(new Answer() { 138 | 139 | @Override 140 | public WebSession answer(InvocationOnMock invocation) throws Throwable { 141 | HttpMessage authMessage = ((HttpMessage) invocation.getArguments()[0]); 142 | // Then 143 | assertTrue(HttpStatusCode.isRedirection(authMessage.getResponseHeader().getStatusCode())); 144 | assertEquals(authMessage.getResponseHeader().getHeader(HttpResponseHeader.LOCATION), 145 | "http://localhost:8080/zap-test-webapp/form-based-auth/error.jsp"); 146 | return mock(WebSession.class); 147 | } 148 | }).when(mockedSessionManagementMethod).extractWebSession((HttpMessage) anyObject()); 149 | 150 | UsernamePasswordAuthenticationCredentials mockedCredentials = getMockedCredentials(); 151 | when(mockedCredentials.getPassword()).thenReturn(WRONG_USER_PASS); 152 | 153 | User mockedUser = mock(User.class); 154 | 155 | // When 156 | createMethod(LOGIN_REQUEST_URL, LOGIN_REQUEST_BODY).authenticate(mockedSessionManagementMethod, 157 | mockedCredentials, mockedUser); 158 | } 159 | 160 | @Test 161 | public void shouldBuildCorrectGetAuthenticationMessage() throws Exception { 162 | // Given 163 | HttpSender mockedSender = mock(HttpSender.class); 164 | doAnswer(new Answer() { 165 | @Override 166 | public HttpMessage answer(InvocationOnMock invocation) throws Throwable { 167 | // Then 168 | HttpMessage authMessage = ((HttpMessage) invocation.getArguments()[0]); 169 | assertEquals(authMessage.getRequestHeader().getMethod(), HttpRequestHeader.GET); 170 | assertEquals(authMessage.getRequestHeader().getURI().toString(), LOGIN_REQUEST_URL); 171 | return (HttpMessage) invocation.getArguments()[0]; 172 | } 173 | }).when(mockedSender).sendAndReceive((HttpMessage) anyObject()); 174 | 175 | FormBasedAuthenticationMethod spiedMethod = spy(createMethod(LOGIN_REQUEST_URL, null)); 176 | when(spiedMethod.getHttpSender()).thenReturn(mockedSender); 177 | 178 | User mockedUser = mock(User.class); 179 | SessionManagementMethod mockedSessionManagementMethod = Mockito.mock(SessionManagementMethod.class); 180 | 181 | // When 182 | spiedMethod.authenticate(mockedSessionManagementMethod, getMockedCredentials(), mockedUser); 183 | } 184 | 185 | @Test 186 | public void typeShouldReturnProperImplementation() { 187 | // Given 188 | AuthenticationMethod method = type.createAuthenticationMethod(0); 189 | // When/Then 190 | assertThat(method, notNullValue()); 191 | assertTrue(method instanceof FormBasedAuthenticationMethod); 192 | 193 | } 194 | 195 | @Override 196 | protected AuthenticationMethodType getMethodTypeImplementation() { 197 | return type; 198 | } 199 | 200 | } 201 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/authentication/HttpAuthenticationIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.authentication; 2 | 3 | import static org.hamcrest.Matchers.containsString; 4 | import static org.junit.Assert.assertEquals; 5 | import static org.junit.Assert.assertNotNull; 6 | import static org.junit.Assert.assertNull; 7 | import static org.junit.Assert.assertThat; 8 | import static org.mockito.Mockito.doReturn; 9 | import static org.mockito.Mockito.spy; 10 | import static org.mockito.Mockito.times; 11 | import static org.mockito.Mockito.verify; 12 | import static org.mockito.Mockito.when; 13 | 14 | import java.io.IOException; 15 | import java.util.List; 16 | 17 | import org.apache.commons.httpclient.URI; 18 | import org.apache.commons.httpclient.URIException; 19 | import org.junit.Before; 20 | import org.junit.BeforeClass; 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | import org.mockito.Mockito; 24 | import org.mockito.runners.MockitoJUnitRunner; 25 | import org.parosproxy.paros.Constant; 26 | import org.parosproxy.paros.model.Model; 27 | import org.parosproxy.paros.network.HttpMalformedHeaderException; 28 | import org.parosproxy.paros.network.HttpMessage; 29 | import org.parosproxy.paros.network.HttpRequestHeader; 30 | import org.parosproxy.paros.network.HttpResponseHeader; 31 | import org.parosproxy.paros.network.HttpSender; 32 | import org.parosproxy.paros.network.HttpStatusCode; 33 | import org.zaproxy.zap.TestWebAppUtils; 34 | import org.zaproxy.zap.TestWebAppUtils.TestPage; 35 | import org.zaproxy.zap.authentication.HttpAuthenticationMethodType.HttpAuthenticationMethod; 36 | import org.zaproxy.zap.model.Context; 37 | import org.zaproxy.zap.session.HttpAuthSessionManagementMethodType; 38 | import org.zaproxy.zap.session.SessionManagementMethod; 39 | import org.zaproxy.zap.users.User; 40 | 41 | /** 42 | * A set of unit tests for {@link HttpAuthenticationMethod}. In order for the test to properly work, 43 | * the following configuration must be done: 44 | *
    45 | *
  • The test-webapp (test-webapp/zap-test-webapp.war) should be started and deployed on localhost 46 | * (more specifically deployed on the path specified by {@link TestWebAppUtils#APP_BASE_URL}).
  • 47 | *
48 | */ 49 | @RunWith(MockitoJUnitRunner.class) 50 | public class HttpAuthenticationIntegrationTest { 51 | 52 | private static final List restrictedPages = TestWebAppUtils.httpAuthRestrictedPages; 53 | private static final List unrestrictedPages = TestWebAppUtils.httpAuthUnrestrictedPages; 54 | 55 | private User user; 56 | private static HttpAuthenticationMethod method; 57 | private static SessionManagementMethod sessionManagementMethod; 58 | private static HttpAuthenticationMethodType type; 59 | private static Context mockedContext; 60 | private static HttpSender httpSender; 61 | 62 | @BeforeClass 63 | public static void classSetUp() throws Exception { 64 | // Make sure Constant is loaded for messages 65 | Constant.getInstance(); 66 | 67 | type = new HttpAuthenticationMethodType(); 68 | 69 | // Prepare session management method 70 | sessionManagementMethod = new HttpAuthSessionManagementMethodType().createSessionManagementMethod(0); 71 | 72 | // Prepare authentication method 73 | method = spy(type.createAuthenticationMethod(0)); 74 | method.hostname = TestWebAppUtils.HTTP_AUTH_HOSTNAME; 75 | method.realm = TestWebAppUtils.HTTP_AUTH_REALM; 76 | method.port = TestWebAppUtils.HTTP_AUTH_PORT; 77 | 78 | // Prepare mocked context 79 | mockedContext = Mockito.mock(Context.class); 80 | when(mockedContext.getSessionManagementMethod()).thenReturn(sessionManagementMethod); 81 | when(mockedContext.getAuthenticationMethod()).thenReturn(method); 82 | 83 | // Prepare HttpSender 84 | httpSender = new HttpSender(Model.getSingleton().getOptionsParam().getConnectionParam(), false, 0); 85 | } 86 | 87 | @Before 88 | public void setup() { 89 | // Prepare a test user 90 | user = spy(new User(0, TestWebAppUtils.HTTP_AUTH_USERNAME)); 91 | UsernamePasswordAuthenticationCredentials credentials = new UsernamePasswordAuthenticationCredentials( 92 | TestWebAppUtils.HTTP_AUTH_USERNAME, TestWebAppUtils.HTTP_AUTH_USERPASS); 93 | user.setAuthenticationCredentials(credentials); 94 | doReturn(mockedContext).when(user).getContext(); 95 | } 96 | 97 | private HttpMessage buildMessage(String url) throws URIException, HttpMalformedHeaderException, 98 | NullPointerException { 99 | HttpMessage msg = new HttpMessage(); 100 | msg.setRequestHeader(new HttpRequestHeader(HttpRequestHeader.GET, new URI(url, false), 101 | HttpRequestHeader.HTTP10)); 102 | return msg; 103 | } 104 | 105 | private HttpMessage sendMessage(String url, boolean asUser) throws NullPointerException, IOException { 106 | HttpMessage msg = buildMessage(url); 107 | if (asUser) 108 | msg.setRequestingUser(user); 109 | httpSender.sendAndReceive(msg); 110 | return msg; 111 | } 112 | 113 | private void visitAndCheckPagesSet(List pages) throws NullPointerException, IOException { 114 | for (TestPage pageEntry : pages) 115 | visitAndCheckCorrectPage(pageEntry); 116 | } 117 | 118 | private void visitAndCheckCorrectPage(TestPage page) throws NullPointerException, IOException { 119 | visitAndCheckCorrectPage(page, true); 120 | } 121 | 122 | private void visitAndCheckCorrectPage(TestPage page, boolean asUser) throws NullPointerException, 123 | IOException { 124 | assertThat(sendMessage(page.url, asUser).getResponseBody().toString(), 125 | containsString(page.identifier)); 126 | } 127 | 128 | @Test 129 | public void shouldHaveThingsConfigured() { 130 | // Given/When/Then 131 | assertNotNull(method.authenticate(sessionManagementMethod, user.getAuthenticationCredentials(), user)); 132 | } 133 | 134 | @Test 135 | public void shouldHaveEverythingSetupToSendMessages() throws Exception { 136 | // Given/When/Then 137 | visitAndCheckCorrectPage(unrestrictedPages.get(0), false); 138 | } 139 | 140 | @Test 141 | public void shouldNotAccessRestrictedAreaUnauthenticated() throws NullPointerException, IOException { 142 | // Given 143 | HttpMessage msg = buildMessage(restrictedPages.get(1).url); 144 | // When 145 | httpSender.sendAndReceive(msg, true); 146 | // Then 147 | assertEquals(HttpStatusCode.UNAUTHORIZED, msg.getResponseHeader().getStatusCode()); 148 | assertNotNull(msg.getResponseHeader().getHeader(HttpResponseHeader.WWW_AUTHENTICATE)); 149 | } 150 | 151 | @Test 152 | public void shouldAuthenticateInRestrictedArea() throws Exception { 153 | // Given/When/Then 154 | visitAndCheckPagesSet(restrictedPages); 155 | } 156 | 157 | @Test 158 | public void shouldAuthenticateOnlyOnceOnTheSite() throws NullPointerException, IOException { 159 | // Given/When 160 | visitAndCheckPagesSet(restrictedPages); 161 | visitAndCheckPagesSet(unrestrictedPages); 162 | 163 | // Then 164 | verify(method, times(1)).authenticate(sessionManagementMethod, user.getAuthenticationCredentials(), 165 | user); 166 | } 167 | 168 | @Test 169 | public void shouldNotAuthenticateWhereNotNeeded() throws NullPointerException, IOException, 170 | InterruptedException { 171 | for (TestPage p : unrestrictedPages) { 172 | // Given/When 173 | HttpMessage msg = sendMessage(p.url, true); 174 | // Then 175 | assertNull(msg.getRequestHeader().getHeader(HttpRequestHeader.AUTHORIZATION)); 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/authentication/HttpAuthenticationMethodIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.authentication; 2 | 3 | import static org.hamcrest.Matchers.notNullValue; 4 | import static org.junit.Assert.assertEquals; 5 | import static org.junit.Assert.assertNotNull; 6 | import static org.junit.Assert.assertThat; 7 | import static org.junit.Assert.assertTrue; 8 | import static org.mockito.Mockito.doReturn; 9 | import static org.mockito.Mockito.when; 10 | 11 | import org.apache.commons.httpclient.HttpState; 12 | import org.apache.commons.httpclient.UsernamePasswordCredentials; 13 | import org.apache.commons.httpclient.auth.AuthScope; 14 | import org.junit.BeforeClass; 15 | import org.junit.Test; 16 | import org.junit.runner.RunWith; 17 | import org.mockito.Mockito; 18 | import org.mockito.runners.MockitoJUnitRunner; 19 | import org.parosproxy.paros.Constant; 20 | import org.zaproxy.zap.TestWebAppUtils; 21 | import org.zaproxy.zap.authentication.HttpAuthenticationMethodType.HttpAuthenticationMethod; 22 | import org.zaproxy.zap.session.SessionManagementMethod; 23 | import org.zaproxy.zap.session.WebSession; 24 | import org.zaproxy.zap.users.User; 25 | 26 | /** 27 | * A set of unit tests for {@link HttpAuthenticationMethod}. In order for the test to properly work, 28 | * the following configuration must be done: 29 | *
    30 | *
  • The test-webapp (test-webapp/zap-test-webapp.war) should be started and deployed on localhost 31 | * (more specifically deployed on the path specified by {@link TestWebAppUtils#APP_BASE_URL}).
  • 32 | *
33 | */ 34 | @RunWith(MockitoJUnitRunner.class) 35 | public class HttpAuthenticationMethodIntegrationTest extends AbstractAuthenticationMethodUnitTest { 36 | 37 | private static HttpAuthenticationMethodType type; 38 | 39 | @BeforeClass 40 | public static void classSetup() { 41 | // Make sure Constant is loaded for messages 42 | Constant.getInstance(); 43 | 44 | type = new HttpAuthenticationMethodType(); 45 | } 46 | 47 | @Override 48 | protected AuthenticationMethodType getMethodTypeImplementation() { 49 | return type; 50 | } 51 | 52 | private User getMockedUser() { 53 | UsernamePasswordAuthenticationCredentials mockedCredentials = Mockito 54 | .mock(UsernamePasswordAuthenticationCredentials.class); 55 | when(mockedCredentials.getUsername()).thenReturn(TestWebAppUtils.HTTP_AUTH_USERNAME); 56 | when(mockedCredentials.getPassword()).thenReturn(TestWebAppUtils.HTTP_AUTH_USERPASS); 57 | 58 | User mockedUser = Mockito.mock(User.class); 59 | when(mockedUser.getAuthenticationCredentials()).thenReturn(mockedCredentials); 60 | 61 | return mockedUser; 62 | } 63 | 64 | private HttpAuthenticationMethod createMethod() { 65 | HttpAuthenticationMethod method = type.createAuthenticationMethod(0); 66 | method.hostname = TestWebAppUtils.HTTP_AUTH_HOSTNAME; 67 | method.realm = TestWebAppUtils.HTTP_AUTH_REALM; 68 | method.port = TestWebAppUtils.HTTP_AUTH_PORT; 69 | return method; 70 | } 71 | 72 | @Test 73 | public void typeShouldReturnProperImplementation() { 74 | // Given 75 | AuthenticationMethod method = type.createAuthenticationMethod(0); 76 | // When/Then 77 | assertThat(method, notNullValue()); 78 | assertTrue(method instanceof HttpAuthenticationMethod); 79 | } 80 | 81 | @Test 82 | public void shouldSetDefaultValuesForAuthenticationFields() { 83 | // Given 84 | HttpAuthenticationMethod method = type.createAuthenticationMethod(0); 85 | method.hostname = TestWebAppUtils.HTTP_AUTH_HOSTNAME; 86 | 87 | HttpState state = new HttpState(); 88 | 89 | WebSession mockedSession = Mockito.mock(WebSession.class); 90 | when(mockedSession.getHttpState()).thenReturn(state); 91 | 92 | SessionManagementMethod mockedSessionManagementMethod = Mockito.mock(SessionManagementMethod.class); 93 | doReturn(mockedSession).when(mockedSessionManagementMethod).createEmptyWebSession(); 94 | 95 | User mockedUser = getMockedUser(); 96 | 97 | // When 98 | method.authenticate(mockedSessionManagementMethod, mockedUser.getAuthenticationCredentials(), 99 | mockedUser); 100 | AuthScope scope = new AuthScope(TestWebAppUtils.HTTP_AUTH_HOSTNAME, 80, AuthScope.ANY_REALM); 101 | UsernamePasswordCredentials configuredCredentials = (UsernamePasswordCredentials) state 102 | .getCredentials(scope); 103 | 104 | // Then 105 | assertNotNull(configuredCredentials); 106 | } 107 | 108 | @Test 109 | public void shouldProperlySetAuthenticationInHttpState() { 110 | // Given 111 | HttpState state = new HttpState(); 112 | 113 | WebSession mockedSession = Mockito.mock(WebSession.class); 114 | when(mockedSession.getHttpState()).thenReturn(state); 115 | 116 | SessionManagementMethod mockedSessionManagementMethod = Mockito.mock(SessionManagementMethod.class); 117 | doReturn(mockedSession).when(mockedSessionManagementMethod).createEmptyWebSession(); 118 | 119 | User mockedUser = getMockedUser(); 120 | 121 | // When 122 | createMethod().authenticate(mockedSessionManagementMethod, mockedUser.getAuthenticationCredentials(), 123 | mockedUser); 124 | AuthScope scope = new AuthScope(TestWebAppUtils.HTTP_AUTH_HOSTNAME, TestWebAppUtils.HTTP_AUTH_PORT, 125 | TestWebAppUtils.HTTP_AUTH_REALM); 126 | UsernamePasswordCredentials configuredCredentials = (UsernamePasswordCredentials) state 127 | .getCredentials(scope); 128 | 129 | // Then 130 | assertNotNull(configuredCredentials); 131 | assertEquals(configuredCredentials.getUserName(), TestWebAppUtils.HTTP_AUTH_USERNAME); 132 | assertEquals(configuredCredentials.getPassword(), TestWebAppUtils.HTTP_AUTH_USERPASS); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/authentication/ManualAuthenticationMethodIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.authentication; 2 | 3 | import static org.hamcrest.Matchers.notNullValue; 4 | import static org.junit.Assert.assertThat; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import org.junit.BeforeClass; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.mockito.runners.MockitoJUnitRunner; 11 | import org.parosproxy.paros.Constant; 12 | import org.zaproxy.zap.authentication.ManualAuthenticationMethodType.ManualAuthenticationMethod; 13 | 14 | @RunWith(MockitoJUnitRunner.class) 15 | public class ManualAuthenticationMethodIntegrationTest extends AbstractAuthenticationMethodUnitTest { 16 | 17 | private static ManualAuthenticationMethodType type; 18 | 19 | @BeforeClass 20 | public static void classSetUp() { 21 | // Make sure Constant is loaded for messages 22 | Constant.getInstance(); 23 | 24 | type = new ManualAuthenticationMethodType(); 25 | } 26 | 27 | @Test 28 | public void typeShouldReturnProperImplementation() { 29 | // Given 30 | AuthenticationMethod method = type.createAuthenticationMethod(0); 31 | // When/Then 32 | assertThat(method, notNullValue()); 33 | assertTrue(method instanceof ManualAuthenticationMethod); 34 | 35 | } 36 | 37 | @Override 38 | protected AuthenticationMethodType getMethodTypeImplementation() { 39 | return type; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/extension/ZapExtensionsIntegrationTestSuite.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.extension; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.junit.runners.Suite; 5 | import org.junit.runners.Suite.SuiteClasses; 6 | import org.zaproxy.zap.extension.sse.EventStreamObserverIntegrationTest; 7 | 8 | /** 9 | * Suite for all integration tests of ZAP Extensions. Tests attached to this 10 | * suite may depend on certain environmental settings or preferences but should 11 | * still be able to execute on any possible machine. 12 | * 13 | * @author bjoern.kimminich@gmx.de 14 | */ 15 | @RunWith(Suite.class) 16 | @SuiteClasses({EventStreamObserverIntegrationTest.class}) 17 | public final class ZapExtensionsIntegrationTestSuite { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/extension/sse/EventStreamObserverIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.extension.sse; 2 | 3 | import static org.mockito.Mockito.inOrder; 4 | import static org.mockito.Mockito.never; 5 | import static org.mockito.Mockito.times; 6 | import static org.mockito.Mockito.verify; 7 | import static org.mockito.Mockito.when; 8 | 9 | import java.io.BufferedWriter; 10 | import java.io.IOException; 11 | 12 | import org.junit.Test; 13 | import org.junit.runner.RunWith; 14 | import org.mockito.InOrder; 15 | import org.mockito.Mockito; 16 | import org.mockito.runners.MockitoJUnitRunner; 17 | 18 | @RunWith(MockitoJUnitRunner.class) 19 | public class EventStreamObserverIntegrationTest extends BaseEventStreamTest { 20 | 21 | @Test 22 | public void shouldInformObserversOnceForAnEvent() throws IOException { 23 | // Given 24 | EventStreamProxy proxy = new EventStreamProxy(getMockHttpMessage(), null, null); 25 | 26 | EventStreamObserver mockObserver = Mockito.mock(EventStreamObserver.class); 27 | proxy.addObserver(mockObserver); 28 | 29 | // When 30 | proxy.processEvent("data:blub"); 31 | 32 | // Then 33 | verify(mockObserver, times(1)).onServerSentEvent(Mockito.any(ServerSentEvent.class)); 34 | } 35 | 36 | @Test 37 | public void shouldCallObserversWithLowerOrderingFirst() throws IOException { 38 | // Given 39 | BufferedWriter writer = Mockito.mock(BufferedWriter.class); 40 | EventStreamProxy proxy = new EventStreamProxy(getMockHttpMessage(), null, writer); 41 | 42 | // create two mocks and add as observer 43 | EventStreamObserver mockObserver1 = Mockito.mock(EventStreamObserver.class); 44 | when(mockObserver1.getServerSentEventObservingOrder()).thenReturn(20); 45 | when(mockObserver1.onServerSentEvent(Mockito.any(ServerSentEvent.class))).thenReturn(true); 46 | 47 | EventStreamObserver mockObserver2 = Mockito.mock(EventStreamObserver.class); 48 | when(mockObserver2.getServerSentEventObservingOrder()).thenReturn(10); 49 | when(mockObserver2.onServerSentEvent(Mockito.any(ServerSentEvent.class))).thenReturn(true); 50 | 51 | proxy.addObserver(mockObserver1); 52 | proxy.addObserver(mockObserver2); 53 | 54 | final String event1 = "data:blub"; 55 | 56 | // When 57 | proxy.processEvent(event1); 58 | 59 | // Then 60 | InOrder inOrder = inOrder(mockObserver2, mockObserver1); 61 | inOrder.verify(mockObserver2).onServerSentEvent(Mockito.any(ServerSentEvent.class)); 62 | inOrder.verify(mockObserver1).onServerSentEvent(Mockito.any(ServerSentEvent.class)); 63 | } 64 | 65 | @Test 66 | public void shouldNotInformFurtherObserverWhenAnotherReturnedFalse() throws IOException { 67 | // Given 68 | BufferedWriter writer = Mockito.mock(BufferedWriter.class); 69 | EventStreamProxy proxy = new EventStreamProxy(getMockHttpMessage(), null, writer); 70 | 71 | // create two mocks and add as observer 72 | EventStreamObserver mockObserver1 = Mockito.mock(EventStreamObserver.class); 73 | when(mockObserver1.onServerSentEvent(Mockito.any(ServerSentEvent.class))).thenReturn(false); 74 | 75 | EventStreamObserver mockObserver2 = Mockito.mock(EventStreamObserver.class); 76 | 77 | proxy.addObserver(mockObserver1); 78 | proxy.addObserver(mockObserver2); 79 | 80 | // When 81 | proxy.processEvent("data:blub"); 82 | 83 | // Then 84 | verify(mockObserver1, times(1)).onServerSentEvent(Mockito.any(ServerSentEvent.class)); 85 | verify(mockObserver2, never()).onServerSentEvent(Mockito.any(ServerSentEvent.class)); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/model/InMemoryContextDataMockSession.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.model; 2 | 3 | import java.sql.SQLException; 4 | import java.util.HashMap; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import org.mockito.Mockito; 10 | import org.parosproxy.paros.model.Model; 11 | import org.parosproxy.paros.model.Session; 12 | 13 | /** 14 | * A Mock for Session that stores Context data in memory instead of using a database. 15 | */ 16 | public class InMemoryContextDataMockSession extends Session { 17 | public Map>> data; 18 | 19 | public InMemoryContextDataMockSession() { 20 | super(Mockito.mock(Model.class)); 21 | this.data = new HashMap<>(); 22 | } 23 | 24 | @Override 25 | public List getContextDataStrings(int contextId, int type) throws SQLException { 26 | List d = getMapForContext(contextId).get(type); 27 | if (d != null) 28 | return d; 29 | else 30 | return new LinkedList<>(); 31 | } 32 | 33 | @Override 34 | public void setContextData(int contextId, int type, List dataList) throws SQLException { 35 | this.getMapForContext(contextId).put(type, new LinkedList<>(dataList)); 36 | } 37 | 38 | private Map> getMapForContext(int contextId) { 39 | if (data.get(contextId) == null) 40 | data.put(contextId, new HashMap>()); 41 | return data.get(contextId); 42 | } 43 | } -------------------------------------------------------------------------------- /src/org/zaproxy/zap/session/AbstractSessionManagementMethodIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.session; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertFalse; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import java.sql.SQLException; 8 | 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.mockito.Mockito; 12 | import org.mockito.runners.MockitoJUnitRunner; 13 | import org.parosproxy.paros.Constant; 14 | import org.parosproxy.paros.model.Session; 15 | import org.zaproxy.zap.model.InMemoryContextDataMockSession; 16 | import org.zaproxy.zap.session.SessionManagementMethodType.UnsupportedSessionManagementMethodException; 17 | 18 | @RunWith(MockitoJUnitRunner.class) 19 | public abstract class AbstractSessionManagementMethodIntegrationTest { 20 | 21 | protected abstract SessionManagementMethodType getMethodTypeImplementation(); 22 | 23 | @Test 24 | public void isTypeForMethodShouldReturnProperResult() { 25 | // Given 26 | SessionManagementMethod method = getMethodTypeImplementation().createSessionManagementMethod(0); 27 | SessionManagementMethod wrongMethod = Mockito.mock(SessionManagementMethod.class); 28 | 29 | // When/Then 30 | assertTrue(getMethodTypeImplementation().isTypeForMethod(method)); 31 | assertFalse(getMethodTypeImplementation().isTypeForMethod(wrongMethod)); 32 | } 33 | 34 | @Test 35 | public void shouldReturnProperType() { 36 | // Given 37 | SessionManagementMethod method = getMethodTypeImplementation().createSessionManagementMethod(0); 38 | // When/Then 39 | assertTrue(method.getType().getClass().equals(getMethodTypeImplementation().getClass())); 40 | } 41 | 42 | @Test 43 | public void shouldImplementCloneEqualsAndHashProperly() { 44 | // Given 45 | SessionManagementMethod method = getMethodTypeImplementation().createSessionManagementMethod(0); 46 | // When 47 | SessionManagementMethod clone = method.clone(); 48 | // Then 49 | assertEquals(method, clone); 50 | assertEquals(method.hashCode(), clone.hashCode()); 51 | } 52 | 53 | @Test 54 | public void shouldPersistAndLoadFromSession() throws UnsupportedSessionManagementMethodException, 55 | SQLException { 56 | 57 | // Given 58 | Constant.getInstance(); 59 | SessionManagementMethod method = getMethodTypeImplementation().createSessionManagementMethod(0); 60 | Session session = new InMemoryContextDataMockSession(); 61 | 62 | // When 63 | getMethodTypeImplementation().persistMethodToSession(session, 0, method); 64 | SessionManagementMethod restoredMethod = getMethodTypeImplementation().loadMethodFromSession(session, 0); 65 | 66 | // Then 67 | assertEquals(method, restoredMethod); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/session/CookieBasedSessionManagementMethodIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.session; 2 | 3 | import static org.hamcrest.Matchers.notNullValue; 4 | import static org.junit.Assert.assertThat; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import org.junit.BeforeClass; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.mockito.runners.MockitoJUnitRunner; 11 | import org.parosproxy.paros.Constant; 12 | import org.zaproxy.zap.session.CookieBasedSessionManagementMethodType.CookieBasedSessionManagementMethod; 13 | 14 | @RunWith(MockitoJUnitRunner.class) 15 | public class CookieBasedSessionManagementMethodIntegrationTest extends AbstractSessionManagementMethodIntegrationTest { 16 | 17 | private static CookieBasedSessionManagementMethodType type; 18 | 19 | @BeforeClass 20 | public static void classSetUp() { 21 | // Make sure Constant is loaded for messages 22 | Constant.getInstance(); 23 | 24 | type = new CookieBasedSessionManagementMethodType(); 25 | } 26 | 27 | @Test 28 | public void typeShouldReturnProperImplementation() { 29 | // Given 30 | SessionManagementMethod method = type.createSessionManagementMethod(0); 31 | // When/Then 32 | assertThat(method, notNullValue()); 33 | assertTrue(method instanceof CookieBasedSessionManagementMethod); 34 | 35 | } 36 | 37 | @Override 38 | protected CookieBasedSessionManagementMethodType getMethodTypeImplementation() { 39 | return type; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/org/zaproxy/zap/session/SessionManagementMethodIntegrationTestSuite.java: -------------------------------------------------------------------------------- 1 | package org.zaproxy.zap.session; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.junit.runners.Suite; 5 | import org.junit.runners.Suite.SuiteClasses; 6 | 7 | /** 8 | * Suite for all Authentication related unit tests of ZAP. Tests attached to this suite must run 9 | * independent of any environmental settings or preferences on any possible machine. 10 | * 11 | * @author cosminstefanxp@gmail.com 12 | */ 13 | @RunWith(Suite.class) 14 | @SuiteClasses({ 15 | CookieBasedSessionManagementMethodIntegrationTest.class}) 16 | public final class SessionManagementMethodIntegrationTestSuite { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /test-webapp/WebContent/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /test-webapp/WebContent/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | Weak authentication - basic 10 | /http-auth/restricted/* 11 | 12 | 13 | tomcat 14 | 15 | 16 | 17 | 18 | 19 | BASIC 20 | Zaproxy 21 | 22 | 23 | 24 | 25 | 26 | The role that is required to access protected pages 27 | 28 | tomcat 29 | 30 | 31 | -------------------------------------------------------------------------------- /test-webapp/WebContent/form-based-auth/d.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Form Based Authentication - 24 | UnAuthenticated Page D 25 | 26 | 27 |

OWASP ZAP Test WebApp - Authenticated Session

28 | <% 29 | if (session.getAttribute("username") != null) { 30 | %>

31 | Welcome: 32 | <%=session.getAttribute("username").toString()%> 33 | - Logout 34 |

35 | <% 36 | } 37 | %> 38 | 39 |

This section is accessible to all users, no matter whether they 40 | are authenticated or not.

41 | 42 |

43 | Go back 44 |

45 | 46 |

Unique Identifier usable in tests: fb-unrestricted-d-629742

47 | 48 | -------------------------------------------------------------------------------- /test-webapp/WebContent/form-based-auth/error.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Form Based Authentication - Error 24 | 25 | 26 |

OWASP ZAP Test WebApp - Form Based Authentication - Error

27 | 28 | <% 29 | Object error = session.getAttribute("error"); 30 | session.removeAttribute("error"); 31 | if (error != null) { 32 | %> 33 |

An error has occurred:

34 | <% 35 | out.println(error.toString()); 36 | } 37 | %> 38 | 39 |

40 | Back to home 41 |

42 | 43 |

Unique Identifier usable in tests: fb-unrestricted-error-498762

44 | 45 | -------------------------------------------------------------------------------- /test-webapp/WebContent/form-based-auth/index.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Form Based Authentication 24 | 25 | 26 |

OWASP ZAP Test WebApp - Form Based Authentication

27 | <% 28 | if (session.getAttribute("username") != null) { 29 | %>

30 | Welcome: 31 | <%=session.getAttribute("username").toString()%> 32 | - Logout 33 |

34 | <% 35 | } 36 | %> 37 | 38 |

This section allows testing of various ZAP features which 39 | require user authentication. Authentication is done using forms.

40 | 41 |

42 | You can visit this restricted page. 43 |

44 | 45 |

46 | Or you can visit this unrestricted page. 47 |

48 | 49 |

50 | Login 51 |

52 | 53 |

Unique Identifier usable in tests: fb-unrestricted-index-198734

54 | 55 | 56 | -------------------------------------------------------------------------------- /test-webapp/WebContent/form-based-auth/login.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Form Based Authentication 24 | 25 | 26 |

OWASP ZAP Test WebApp - Form Based Authentication

27 | <% 28 | if (session.getAttribute("username") != null) { 29 | response.sendRedirect("restricted/home.jsp"); 30 | return; 31 | } 32 | %> 33 |

In order to enter the authenticated section of the website, 34 | please insert your credentials below:

35 |
36 |
Username:
Password:
39 |
40 |

41 | Valid username / password pairs: user1 / user1,user2 / 42 | user2,user3 / user3 43 |

44 |

Unique Identifier usable in tests: fb-unrestricted-login-238934

45 | 46 | 47 | -------------------------------------------------------------------------------- /test-webapp/WebContent/form-based-auth/loginCheck.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Form Based Authentication - Login 24 | 25 | 26 | <% 27 | String username = request.getParameter("username"); 28 | String password = request.getParameter("password"); 29 | 30 | if ((username.equals("user1") && password.equals("user1")) 31 | || (username.equals("user2") && password.equals("user2")) 32 | || (username.equals("user3") && password.equals("user3"))) { 33 | session.setAttribute("username", username); 34 | response.sendRedirect("restricted/home.jsp"); 35 | } else { 36 | session.setAttribute("error", "Login Error"); 37 | response.sendRedirect("error.jsp"); 38 | } 39 | %> 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /test-webapp/WebContent/form-based-auth/logout.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Form Based Authentication 24 | 25 | 26 | <% 27 | session.removeAttribute("username"); 28 | session.removeAttribute("password"); 29 | session.invalidate(); 30 | %> 31 |

Logout was done successfully.

32 |

33 | Back to home 34 |

35 |

Unique Identifier usable in tests: fb-unrestricted-logout-512873

36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /test-webapp/WebContent/form-based-auth/restricted/a.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Form Based Authentication - 24 | Authenticated Page A 25 | 26 | 27 |

OWASP ZAP Test WebApp - Authenticated Session

28 | <% 29 | if (session.getAttribute("username") == null) { 30 | session.setAttribute("error", "Unauthorized"); 31 | response.sendRedirect("../error.jsp"); 32 | return; 33 | } 34 | %> 35 |

36 | Welcome: 37 | <%=session.getAttribute("username").toString()%> 38 | - Logout 39 |

40 |

This section is accessible only to authenticated users.

41 |

42 | You can also visit this page. 43 |

44 | 45 |

46 | Back Home 47 |

48 | 49 |

Unique Identifier usable in tests: fb-restricted-a-382641

50 | 51 | -------------------------------------------------------------------------------- /test-webapp/WebContent/form-based-auth/restricted/ac.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Form Based Authentication - 24 | Authenticated Page AC 25 | 26 | 27 |

OWASP ZAP Test WebApp - Authenticated Session

28 | <% 29 | if (session.getAttribute("username") == null) { 30 | session.setAttribute("error", "Unauthorized"); 31 | response.sendRedirect("../error.jsp"); 32 | return; 33 | } 34 | %> 35 |

36 | Welcome: 37 | <%=session.getAttribute("username").toString()%> 38 | - Logout 39 |

40 |

This section is accessible only to authenticated users.

41 | 42 |

43 | Back Home 44 |

45 |

Unique Identifier usable in tests: fb-restricted-ac-863602

46 | 47 | -------------------------------------------------------------------------------- /test-webapp/WebContent/form-based-auth/restricted/b.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Form Based Authentication - 24 | Authenticated Page B 25 | 26 | 27 |

OWASP ZAP Test WebApp - Authenticated Session

28 | <% 29 | if (session.getAttribute("username") == null) { 30 | session.setAttribute("error", "Unauthorized"); 31 | response.sendRedirect("../error.jsp"); 32 | return; 33 | } 34 | %> 35 |

36 | Welcome: 37 | <%=session.getAttribute("username").toString()%> 38 | - Logout 39 |

40 |

This section is accessible only to authenticated users.

41 | 42 |

43 | Back Home 44 |

45 |

Unique Identifier usable in tests: fb-restricted-b-972631

46 | 47 | -------------------------------------------------------------------------------- /test-webapp/WebContent/form-based-auth/restricted/home.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Form Based Authentication - 24 | Authenticated 25 | 26 | 27 |

OWASP ZAP Test WebApp - Authenticated Session

28 | <% 29 | if (session.getAttribute("username") == null) { 30 | session.setAttribute("error", "Unauthorized"); 31 | response.sendRedirect("../error.jsp"); 32 | return; 33 | } 34 | %> 35 |

36 | Welcome: 37 | <%=session.getAttribute("username").toString()%> 38 | - Logout 39 |

40 |

This section is accessible only to authenticated users.

41 |

42 | You can also visit this page. 43 |

44 |

45 | You can also visit this other page. 46 |

47 |

Unique Identifier usable in tests: fb-restricted-home-269039

48 | 49 | -------------------------------------------------------------------------------- /test-webapp/WebContent/http-auth/d.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Http Authentication 24 | 25 | 26 |

OWASP ZAP Test WebApp - Http Authentication

27 | 28 |

This section is accessible to all users, no matter whether they 29 | are authenticated or not.

30 | 31 |

32 | Back Home 33 |

34 |

Unique Identifier usable in tests: http-unrestricted-d-692731

35 | 36 | 37 | -------------------------------------------------------------------------------- /test-webapp/WebContent/http-auth/index.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Http Authentication 24 | 25 | 26 |

OWASP ZAP Test WebApp - Http Authentication

27 | 28 |

This section allows testing of various ZAP features which 29 | require user authentication. Authentication is done using HTTP 30 | Authentication.

31 |

32 | To access the restricted section, you will need to use a role named 33 | 'tomcat'. For example, if using Tomcat server, the roles are defined 34 | in the {tomcat-home}/conf/tomcat-users.xml file. 35 |

36 | 37 |

38 | You can visit this restricted page. 39 |

40 | 41 |

42 | Or you can visit this unrestricted page. 43 |

44 | 45 |

Unique Identifier usable in tests: 46 | http-unrestricted-index-142628

47 | 48 | 49 | -------------------------------------------------------------------------------- /test-webapp/WebContent/http-auth/restricted/a.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Http Authentication - Authenticated 24 | 25 | 26 |

OWASP ZAP Test WebApp - Http Authentication - Authenticated

27 | 28 |

This section is accessible only to authenticated users.

29 | 30 |

31 | You can now visit this new page. 32 |

33 | 34 |

35 | Back Home 36 |

37 |

Unique Identifier usable in tests: 38 | http-restricted-a-432342

39 | 40 | 41 | -------------------------------------------------------------------------------- /test-webapp/WebContent/http-auth/restricted/ac.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Http Authentication - 24 | Authenticated 25 | 26 | 27 |

OWASP ZAP Test WebApp - Http Authentication - Authenticated

28 | 29 |

This section is accessible only to authenticated users.

30 |

31 | Back Home 32 |

33 | 34 |

Unique Identifier usable in tests: http-restricted-ac-328712

35 | 36 | 37 | -------------------------------------------------------------------------------- /test-webapp/WebContent/http-auth/restricted/b.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Http Authentication - 24 | Authenticated 25 | 26 | 27 |

OWASP ZAP Test WebApp - Http Authentication - Authenticated

28 | 29 |

This section is accessible only to authenticated users.

30 |

31 | Back Home 32 |

33 | 34 |

Unique Identifier usable in tests: http-restricted-b-915324

35 | 36 | 37 | -------------------------------------------------------------------------------- /test-webapp/WebContent/http-auth/restricted/home.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp - Http Authentication - 24 | Authenticated 25 | 26 | 27 |

OWASP ZAP Test WebApp - Http Authentication - Authenticated

28 | 29 |

This section is accessible only to authenticated users.

30 | 31 |

32 | You can visit this page. 33 |

34 | 35 |

36 | Or you can visit this other page. 37 |

38 |

39 | Back Home 40 |

41 |

Unique Identifier usable in tests: http-restricted-home-872642

42 | 43 | 44 | -------------------------------------------------------------------------------- /test-webapp/WebContent/index.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 20 | 21 | 22 | 23 | OWASP ZAP Test WebApp 24 | 25 | 26 |

OWASP ZAP Test WebApp

27 | 28 | The OWASP Zed Attack Proxy - Testing Web Application is an application 29 | used for testing various features of ZAP. 30 | 31 | -------------------------------------------------------------------------------- /test-webapp/build.xml: -------------------------------------------------------------------------------- 1 | 2 | Build ZAP TEST Web App 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test-webapp/src/placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaproxy/zaproxy-test/f351caa2b3fee92e60c328c74a29520fa34aba0f/test-webapp/src/placeholder -------------------------------------------------------------------------------- /test-webapp/zap-test-webapp.war: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaproxy/zaproxy-test/f351caa2b3fee92e60c328c74a29520fa34aba0f/test-webapp/zap-test-webapp.war --------------------------------------------------------------------------------