/* * Zed Attack Proxy (ZAP) and its related class files. * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * * Copyright 2017 The ZAP Development Team * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zaproxy.zap.spider.filters; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.mockito.BDDMockito.given; import static org.mockito.Matchers.anyString; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.commons.httpclient.URI; import org.apache.log4j.Logger; import org.apache.log4j.varia.NullAppender; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.zaproxy.zap.model.Context; import org.zaproxy.zap.spider.DomainAlwaysInScopeMatcher; import org.zaproxy.zap.spider.filters.FetchFilter.FetchStatus; /** * Unit test for {@link DefaultFetchFilter}. */ @RunWith(MockitoJUnitRunner.class) public class DefaultFetchFilterUnitTest { @Mock Context context; private DefaultFetchFilter filter; @BeforeClass public static void suppressLogging() { Logger.getRootLogger().addAppender(new NullAppender()); } @Before public void setUp() { filter = new DefaultFetchFilter(); } @Test public void shouldFilterUriWithNonSchemeAsIllegalProtocol() throws Exception { // Given URI uri = createUri("example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.ILLEGAL_PROTOCOL))); } @Test public void shouldFilterUriWithNonHttpOrHttpsSchemeAsIllegalProtocol() throws Exception { // Given URI uri = createUri("ftp://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.ILLEGAL_PROTOCOL))); } @Test public void shouldFilterUriWithHttpSchemeAsOutOfScopeByDefault() throws Exception { // Given URI uri = createUri("http://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.OUT_OF_SCOPE))); } @Test public void shouldFilterUriWithHttpsSchemeAsOutOfScopeByDefault() throws Exception { // Given URI uri = createUri("https://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.OUT_OF_SCOPE))); } @Test public void shouldFilterOutOfScopeUriAsOutOfScope() throws Exception { // Given filter.addScopeRegex("scope.example.com"); URI uri = createUri("http://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.OUT_OF_SCOPE))); } @Test public void shouldFilterInScopeUriAsValid() throws Exception { // Given filter.addScopeRegex("example.com"); URI uri = createUri("http://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.VALID))); } @Test public void shouldFilterNonAlwaysInScopeUriAsOutOfScope() throws Exception { // Given filter.setDomainsAlwaysInScope(domainsAlwaysInScope("scope.example.com")); URI uri = createUri("https://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.OUT_OF_SCOPE))); } @Test public void shouldFilterAlwaysInScopeUriAsValid() throws Exception { // Given filter.setDomainsAlwaysInScope(domainsAlwaysInScope("example.com")); URI uri = createUri("https://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.VALID))); } @Test public void shouldFilterExcludedInScopeUriAsUserRules() throws Exception { // Given filter.addScopeRegex("example.com"); filter.setExcludeRegexes(excludeRegexes(".*example\\.com.*")); URI uri = createUri("http://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.USER_RULES))); } @Test public void shouldFilterExcludedAlwaysInScopeUriAsUserRules() throws Exception { // Given filter.setDomainsAlwaysInScope(domainsAlwaysInScope("example.com")); filter.setExcludeRegexes(excludeRegexes(".*example\\.com.*")); URI uri = createUri("http://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.USER_RULES))); } @Test public void shouldFilterNonExcludedInScopeUriAsValid() throws Exception { // Given filter.addScopeRegex("example.com"); filter.setExcludeRegexes(excludeRegexes("subdomain\\.example\\.com.*")); URI uri = createUri("http://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.VALID))); } @Test public void shouldFilterNonExcludedAlwaysInScopeUriAsValid() throws Exception { // Given filter.setDomainsAlwaysInScope(domainsAlwaysInScope("example.com")); filter.setExcludeRegexes(excludeRegexes("subdomain\\.example\\.com.*")); URI uri = createUri("http://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.VALID))); } @Test public void shouldFilterOutOfContextUriAsOutOfContext() throws Exception { // Given filter.setScanContext(contextInScope(false)); URI uri = createUri("http://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.OUT_OF_CONTEXT))); } @Test public void shouldFilterInContextUriAsValid() throws Exception { // Given filter.setScanContext(contextInScope(true)); URI uri = createUri("http://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.VALID))); } @Test public void shouldFilterExcludedInContextUriAsUserRules() throws Exception { // Given filter.setScanContext(contextInScope(true)); filter.setExcludeRegexes(excludeRegexes(".*example\\.com.*")); URI uri = createUri("http://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.USER_RULES))); } @Test public void shouldFilterNonExcludedInContextUriAsValid() throws Exception { // Given filter.setScanContext(contextInScope(true)); filter.setExcludeRegexes(excludeRegexes("subdomain\\.example\\.com.*")); URI uri = createUri("http://example.com"); // When FetchStatus status = filter.checkFilter(uri); // Then assertThat(status, is(equalTo(FetchStatus.VALID))); } private static URI createUri(String uri) { try { return new URI(uri, true); } catch (Exception e) { throw new RuntimeException(e); } } private List<DomainAlwaysInScopeMatcher> domainsAlwaysInScope(String... domains) { if (domains == null || domains.length == 0) { return Collections.emptyList(); } List<DomainAlwaysInScopeMatcher> domainsAlwaysInScope = new ArrayList<>(1); for (String domain : domains) { domainsAlwaysInScope.add(new DomainAlwaysInScopeMatcher(domain)); } return domainsAlwaysInScope; } private List<String> excludeRegexes(String... regexes) { if (regexes == null || regexes.length == 0) { return Collections.emptyList(); } List<String> excludedRegexes = new ArrayList<>(1); for (String regex : regexes) { excludedRegexes.add(regex); } return excludedRegexes; } private Context contextInScope(boolean inScope) { given(context.isInContext(anyString())).willReturn(inScope); return context; } }