From 64f41611a3ee497671bf6afd34b56aa60392bed9 Mon Sep 17 00:00:00 2001 From: Simon Bennetts Date: Thu, 19 Dec 2024 15:22:20 +0000 Subject: [PATCH] Client: Flag nodes that redirect when spidered Signed-off-by: Simon Bennetts --- .../client/ExtensionClientIntegration.java | 9 ++++++ .../addon/client/internal/ClientMap.java | 22 +++++++++++++ .../client/internal/ClientSideComponent.java | 25 +++++++++++++++ .../client/internal/ClientSideDetails.java | 9 ++++++ .../addon/client/spider/ClientSpider.java | 4 +++ .../addon/client/spider/ClientSpiderTask.java | 4 +++ .../client/ui/ClientMapTreeCellRenderer.java | 30 ++++++++---------- .../client/resources/blue-document--minus.png | Bin 608 -> 0 bytes .../resources/blue-document-number-minus.png | Bin 2722 -> 0 bytes .../addon/client/resources/overlay-minus.png | Bin 0 -> 5521 bytes .../client/resources/overlay-redirect.png | Bin 0 -> 5449 bytes .../client/internal/ClientMapUnitTest.java | 30 ++++++++++++++++++ 12 files changed, 116 insertions(+), 17 deletions(-) delete mode 100644 addOns/client/src/main/resources/org/zaproxy/addon/client/resources/blue-document--minus.png delete mode 100644 addOns/client/src/main/resources/org/zaproxy/addon/client/resources/blue-document-number-minus.png create mode 100644 addOns/client/src/main/resources/org/zaproxy/addon/client/resources/overlay-minus.png create mode 100644 addOns/client/src/main/resources/org/zaproxy/addon/client/resources/overlay-redirect.png diff --git a/addOns/client/src/main/java/org/zaproxy/addon/client/ExtensionClientIntegration.java b/addOns/client/src/main/java/org/zaproxy/addon/client/ExtensionClientIntegration.java index 833b19ffb2d..10234feac00 100644 --- a/addOns/client/src/main/java/org/zaproxy/addon/client/ExtensionClientIntegration.java +++ b/addOns/client/src/main/java/org/zaproxy/addon/client/ExtensionClientIntegration.java @@ -456,6 +456,15 @@ public boolean addComponentToNode(ClientNode node, ClientSideComponent component return false; } + public boolean setRedirect(String originalUrl, String redirectedUrl) { + ClientNode node = this.clientTree.setRedirect(originalUrl, redirectedUrl); + if (node != null) { + this.clientNodeChanged(node); + return true; + } + return false; + } + public void deleteNodes(List nodes) { this.clientTree.deleteNodes(nodes); if (View.isInitialised()) { diff --git a/addOns/client/src/main/java/org/zaproxy/addon/client/internal/ClientMap.java b/addOns/client/src/main/java/org/zaproxy/addon/client/internal/ClientMap.java index beee0c02e6b..911f4f28862 100644 --- a/addOns/client/src/main/java/org/zaproxy/addon/client/internal/ClientMap.java +++ b/addOns/client/src/main/java/org/zaproxy/addon/client/internal/ClientMap.java @@ -167,6 +167,28 @@ public boolean addComponentToNode(ClientNode node, ClientSideComponent component } return componentAdded; } + + public ClientNode setRedirect(String originalUrl, String redirectedUrl) { + ClientNode node = getNode(originalUrl, false, false); + if (node != null) { + node.getUserObject().setRedirect(true); + node.getUserObject().setVisited(true); + node.getUserObject() + .addComponent( + new ClientSideComponent( + ClientSideComponent.REDIRECT, + null, + originalUrl, + redirectedUrl, + ClientSideComponent.REDIRECT, + null, + null, + -1)); + return node; + } + LOGGER.debug("setRedirect, no node for URL {}", originalUrl); + return null; + } } /** diff --git a/addOns/client/src/main/java/org/zaproxy/addon/client/internal/ClientSideComponent.java b/addOns/client/src/main/java/org/zaproxy/addon/client/internal/ClientSideComponent.java index 8abfcf8fb88..129e3fb133f 100644 --- a/addOns/client/src/main/java/org/zaproxy/addon/client/internal/ClientSideComponent.java +++ b/addOns/client/src/main/java/org/zaproxy/addon/client/internal/ClientSideComponent.java @@ -26,6 +26,8 @@ public class ClientSideComponent { + public static String REDIRECT = "Redirect"; + private String tagName; private String id; private String parentUrl; @@ -35,6 +37,26 @@ public class ClientSideComponent { private String tagType; private int formId = -1; + public ClientSideComponent( + String tagName, + String id, + String parentUrl, + String href, + String text, + String type, + String tagType, + int formId) { + super(); + this.tagName = tagName; + this.id = id; + this.parentUrl = parentUrl; + this.href = href; + this.text = text; + this.type = type; + this.tagType = tagType; + this.formId = formId; + } + public ClientSideComponent(JSONObject json) { this.tagName = json.getString("tagName"); this.id = json.getString("id"); @@ -99,6 +121,9 @@ public String getType() { } public boolean isStorageEvent() { + if (type == null) { + return false; + } switch (type) { case "Cookies", "localStorage", "sessionStorage": return true; diff --git a/addOns/client/src/main/java/org/zaproxy/addon/client/internal/ClientSideDetails.java b/addOns/client/src/main/java/org/zaproxy/addon/client/internal/ClientSideDetails.java index 95720ff6cc6..9427917bc82 100644 --- a/addOns/client/src/main/java/org/zaproxy/addon/client/internal/ClientSideDetails.java +++ b/addOns/client/src/main/java/org/zaproxy/addon/client/internal/ClientSideDetails.java @@ -27,6 +27,7 @@ public class ClientSideDetails { private String url; private boolean visited; private boolean storage; + private boolean redirect; private Set components = new HashSet<>(); @@ -72,4 +73,12 @@ public boolean isStorage() { protected void setStorage(boolean storage) { this.storage = storage; } + + public boolean isRedirect() { + return redirect; + } + + public void setRedirect(boolean redirect) { + this.redirect = redirect; + } } diff --git a/addOns/client/src/main/java/org/zaproxy/addon/client/spider/ClientSpider.java b/addOns/client/src/main/java/org/zaproxy/addon/client/spider/ClientSpider.java index 9a962ae5a08..9e8b59a99ab 100644 --- a/addOns/client/src/main/java/org/zaproxy/addon/client/spider/ClientSpider.java +++ b/addOns/client/src/main/java/org/zaproxy/addon/client/spider/ClientSpider.java @@ -284,6 +284,10 @@ private void addUriToAddedNodesModel(final String uri) { }); } + protected void setRedirect(String originalUrl, String redirectedUrl) { + ThreadUtils.invokeLater(() -> extClient.setRedirect(originalUrl, redirectedUrl)); + } + @Override public int getProgress() { if (finished && !stopped) { diff --git a/addOns/client/src/main/java/org/zaproxy/addon/client/spider/ClientSpiderTask.java b/addOns/client/src/main/java/org/zaproxy/addon/client/spider/ClientSpiderTask.java index 01d3cdc3094..c2cd5bb6867 100644 --- a/addOns/client/src/main/java/org/zaproxy/addon/client/spider/ClientSpiderTask.java +++ b/addOns/client/src/main/java/org/zaproxy/addon/client/spider/ClientSpiderTask.java @@ -58,6 +58,10 @@ public void run() { startTime = System.currentTimeMillis(); wd.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(this.timeout)); wd.get(url); + String actualUrl = wd.getCurrentUrl(); + if (!url.equals(actualUrl)) { + clientSpider.setRedirect(url, actualUrl); + } ok = true; } catch (Exception e) { LOGGER.warn("Task failed {} {}", url, e.getMessage(), e); diff --git a/addOns/client/src/main/java/org/zaproxy/addon/client/ui/ClientMapTreeCellRenderer.java b/addOns/client/src/main/java/org/zaproxy/addon/client/ui/ClientMapTreeCellRenderer.java index f6a58a2e47e..13481438f94 100644 --- a/addOns/client/src/main/java/org/zaproxy/addon/client/ui/ClientMapTreeCellRenderer.java +++ b/addOns/client/src/main/java/org/zaproxy/addon/client/ui/ClientMapTreeCellRenderer.java @@ -38,16 +38,16 @@ public class ClientMapTreeCellRenderer extends DefaultTreeCellRenderer { ExtensionClientIntegration.getIcon("sitemap-application-blue.png"); private static final ImageIcon LEAF_ICON = ExtensionClientIntegration.getIcon("blue-document.png"); - private static final ImageIcon LEAF_NOT_VISITED_ICON = - ExtensionClientIntegration.getIcon("blue-document--minus.png"); private static final ImageIcon FRAGMENT_ICON = ExtensionClientIntegration.getIcon("blue-document-number.png"); - private static final ImageIcon FRAGMENT_NOT_VISITED_ICON = - ExtensionClientIntegration.getIcon("blue-document-number-minus.png"); private static final ImageIcon FOLDER_OPEN_ICON = ExtensionClientIntegration.getIcon("blue-folder-horizontal-open.png"); private static final ImageIcon FOLDER_CLOSED_ICON = ExtensionClientIntegration.getIcon("blue-folder-horizontal.png"); + private static final ImageIcon NOT_VISITED_OVERLAY = + ExtensionClientIntegration.getIcon("overlay-minus.png"); + private static final ImageIcon REDIRECT_OVERLAY = + ExtensionClientIntegration.getIcon("overlay-redirect.png"); private static final ImageIcon DATABASE_ICON = ExtensionClientIntegration.getIcon("database.png"); @@ -83,27 +83,23 @@ public Component getTreeCellRendererComponent( setPreferredSize(null); // clears the preferred size, making the node visible super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); - // folder / file icons with scope 'target' if relevant if (node.isRoot()) { - component.add(wrap(ROOT_ICON)); // 'World' icon + component.add(wrap(ROOT_ICON)); } else { ClientSideDetails csd = node.getUserObject(); OverlayIcon icon; if (csd.isStorage()) { icon = new OverlayIcon(DATABASE_ICON); } else if (leaf) { - if (csd.isVisited()) { - if (csd.getUrl().contains("#")) { - icon = new OverlayIcon(FRAGMENT_ICON); - } else { - icon = new OverlayIcon(LEAF_ICON); - } + if (csd.getUrl().contains("#")) { + icon = new OverlayIcon(FRAGMENT_ICON); } else { - if (csd.getUrl().contains("#")) { - icon = new OverlayIcon(FRAGMENT_NOT_VISITED_ICON); - } else { - icon = new OverlayIcon(LEAF_NOT_VISITED_ICON); - } + icon = new OverlayIcon(LEAF_ICON); + } + if (!csd.isVisited()) { + icon.add(NOT_VISITED_OVERLAY); + } else if (csd.isRedirect()) { + icon.add(REDIRECT_OVERLAY); } } else { if (expanded) { diff --git a/addOns/client/src/main/resources/org/zaproxy/addon/client/resources/blue-document--minus.png b/addOns/client/src/main/resources/org/zaproxy/addon/client/resources/blue-document--minus.png deleted file mode 100644 index adcb19c6d56bdfb543a49632d406f5c8638d8cbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 608 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 diff --git a/addOns/client/src/main/resources/org/zaproxy/addon/client/resources/overlay-minus.png b/addOns/client/src/main/resources/org/zaproxy/addon/client/resources/overlay-minus.png new file mode 100644 index 0000000000000000000000000000000000000000..336956cd3d5aab3f1634c89464c6f80c127ada2b GIT binary patch literal 5521 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 Mxp-3Zmoqp07wD^Z=Kufz literal 0 HcmV?d00001 diff --git a/addOns/client/src/main/resources/org/zaproxy/addon/client/resources/overlay-redirect.png b/addOns/client/src/main/resources/org/zaproxy/addon/client/resources/overlay-redirect.png new file mode 100644 index 0000000000000000000000000000000000000000..b8671212b306f6eb3a1b236ee6960737d2b17a9d GIT binary patch literal 5449 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 literal 0 HcmV?d00001 diff --git a/addOns/client/src/test/java/org/zaproxy/addon/client/internal/ClientMapUnitTest.java b/addOns/client/src/test/java/org/zaproxy/addon/client/internal/ClientMapUnitTest.java index b69ec433b31..1aea7f2f668 100644 --- a/addOns/client/src/test/java/org/zaproxy/addon/client/internal/ClientMapUnitTest.java +++ b/addOns/client/src/test/java/org/zaproxy/addon/client/internal/ClientMapUnitTest.java @@ -21,12 +21,14 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; +import java.util.Set; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -336,4 +338,32 @@ void shouldClearTheMap() { // Then assertThat(map.getRoot().getChildCount(), is(0)); } + + @Test + void shouldSetKnownRedirectDetails() { + // Given + ClientNode node1 = map.getOrAddNode(BBB_DDD_URL + "/", false, false); + + // When + ClientNode node2 = map.setRedirect(BBB_DDD_URL + "/", AAA_URL); + Set components = node2.getUserObject().getComponents(); + ClientSideComponent c0 = components.iterator().next(); + + // Then + assertThat(node1, is(node2)); + assertThat(node2.getUserObject().isVisited(), is(true)); + assertThat(node2.getUserObject().isRedirect(), is(true)); + assertThat(components.size(), is(1)); + assertThat(c0.getTagName(), is("Redirect")); + assertThat(c0.getHref(), is(AAA_URL)); + } + + @Test + void shouldIngnoreUnknownRedirectDetails() { + // Given / When + ClientNode node = map.setRedirect(BBB_DDD_URL + "/", AAA_URL); + + // Then + assertThat(node, is(nullValue())); + } }