├── 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 |
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 TreeSetbad_view
bad_action
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 |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 |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 |In order to enter the authenticated section of the website, 34 | please insert your credentials below:
35 | 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 |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 |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 |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 |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 |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 |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 |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 |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 |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 |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 |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 |