Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client: Flag nodes that redirect when spidered #6026

Merged
merged 1 commit into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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<ClientNode> nodes) {
this.clientTree.deleteNodes(nodes);
if (View.isInitialised()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,18 @@
package org.zaproxy.addon.client.internal;

import java.util.Objects;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.sf.json.JSONObject;
import org.parosproxy.paros.Constant;
import org.zaproxy.addon.client.ExtensionClientIntegration;

@Getter
@AllArgsConstructor
public class ClientSideComponent {

public static String REDIRECT = "Redirect";

private String tagName;
private String id;
private String parentUrl;
Expand Down Expand Up @@ -74,31 +80,10 @@ public String getTypeForDisplay() {
}
}

public String getTagName() {
return tagName;
}

public String getId() {
return id;
}

public String getParentUrl() {
return parentUrl;
}

public String getHref() {
return href;
}

public String getText() {
return text;
}

public String getType() {
return type;
}

public boolean isStorageEvent() {
if (type == null) {
return false;
}
switch (type) {
case "Cookies", "localStorage", "sessionStorage":
return true;
Expand All @@ -107,14 +92,6 @@ public boolean isStorageEvent() {
}
}

public String getTagType() {
return tagType;
}

public int getFormId() {
return formId;
}

@Override
public int hashCode() {
return Objects.hash(href, id, parentUrl, tagName, text);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class ClientSideDetails {
private String url;
private boolean visited;
private boolean storage;
private boolean redirect;

private Set<ClientSideComponent> components = new HashSet<>();

Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down Expand Up @@ -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) {
Expand Down
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<ClientSideComponent> 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()));
}
}
Loading