Skip to content
Closed
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
98 changes: 98 additions & 0 deletions src/it/java/servlets/module/challenge/UrlAccess2AdminIT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package servlets.module.challenge;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import dbProcs.GetterIT;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletConfig;
import testUtils.TestProperties;

/**
* Regression coverage for the "Failure to Restrict URL Access 2" challenge. The admin-only function
* must reject any session that is not actually holding the admin role, even when the caller already
* knows (or has guessed/reverse-engineered) the hidden request parameters the admin action expects.
*/
public class UrlAccess2AdminIT {

private static final Logger log = LogManager.getLogger(UrlAccess2AdminIT.class);
private static final String LANG = "en_GB";
private static final String applicationRoot = "";

private MockHttpServletRequest request;
private MockHttpServletResponse response;

@BeforeAll
public static void resetDatabase() throws IOException, SQLException {
TestProperties.setTestPropertiesFileDirectory(log);
TestProperties.createMysqlResource();
TestProperties.ensureSchemaReady(log);
TestProperties.reseedTestData();
}

@BeforeEach
public void setup() {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
}

private UrlAccess2Admin newServletInstance() throws ServletException {
UrlAccess2Admin servlet = new UrlAccess2Admin();
servlet.init(new MockServletConfig("UrlAccess2Admin"));
return servlet;
}

@Test
public void nonAdminPlayerIsForbiddenFromAdminFunction() throws Exception {
String userName = "urlAccess2Player";
GetterIT.verifyTestUser(applicationRoot, userName, userName);
TestProperties.loginDoPost(log, request, response, userName, userName, null, LANG);
request.setCookies(response.getCookies());

// Fresh response for the challenge call: the mock response object still carries the 302
// status set by the login redirect above, and the servlet under test never calls
// setStatus() on a success path (only sendError() on rejection), so reusing it would let a
// stale 302 mask a missing access-control check.
MockHttpServletResponse challengeResponse = new MockHttpServletResponse();
request.addParameter("adminData", "youAreAnAdminOfAwesomenessWoopWoop");

newServletInstance().doPost(request, challengeResponse);

assertEquals(
HttpServletResponse.SC_FORBIDDEN,
challengeResponse.getStatus(),
"A regular player must not be able to invoke the admin-only URL Access 2 function.");
}

@Test
public void adminUserReceivesResultKey() throws Exception {
String userName = "urlAccess2Admin";
GetterIT.verifyTestAdmin(applicationRoot, userName, userName);
TestProperties.loginDoPost(log, request, response, userName, userName, null, LANG);
request.setCookies(response.getCookies());

MockHttpServletResponse challengeResponse = new MockHttpServletResponse();
request.addParameter("adminData", "youAreAnAdminOfAwesomenessWoopWoop");

newServletInstance().doPost(request, challengeResponse);

assertEquals(
HttpServletResponse.SC_OK,
challengeResponse.getStatus(),
"A real admin must still be able to complete the legitimate admin function.");
String body = challengeResponse.getContentAsString();
assertTrue(
body != null && !body.isEmpty() && !body.contains("failue"),
"Admin response should contain the result key output, not the failure branch.");
}
}
10 changes: 10 additions & 0 deletions src/main/java/servlets/module/challenge/UrlAccess2Admin.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ public void doPost(HttpServletRequest request, HttpServletResponse response)
ses.getAttribute("userName").toString());
log.debug(levelName + " servlet accessed by: " + ses.getAttribute("userName").toString());
PrintWriter out = response.getWriter();

if (!Validate.validateAdminSession(ses)) {
log.fatal(
levelName
+ " admin-only servlet accessed by non-admin user: "
+ ses.getAttribute("userName").toString());
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}

out.print(getServletInfo());
String htmlOutput = new String();

Expand Down
Loading