Hi,
I am currently developing a Java web application using the Struts 7.0.3
framework, JDK 23, and Tomcat 11.0.5, with a Dynamic Web Module version
6.1. Although the application is intended for an intranet environment, VA
(Vulnerability Assessment) clearance is still required.
To address security concerns, I have implemented a CspInterceptor class.
However, after scanning the application with OWASP ZAP, several
vulnerabilities were reported.
Could you please advise on how to resolve these issues? For your reference,
I have attached the WAR file of the test project along with a few relevant
pages.
Thanks and regards,
Shivam
test.war
<https://drive.google.com/open?id=1ChtdOQKVdehi27j0Q-xth0w_9H7qD3wg>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<s:form method="post" validate="true" theme="simple" name="form" action="Login"
id="paraFrm">
<s:token />
<table style="margin-left: 40%; margin-top: 20%;">
<tr>
<td style="color: maroon;">User Name :</td>
<td><s:textfield
cssStyle="width:100%;text-align:LEFT;font-size: 12PX;background-color: #FDEBD0;"
name="username" /></td>
</tr>
<tr>
<td style="color: maroon;">Password :</td>
<td><s:password
cssStyle="width:100%;text-align:LEFT;font-size: 12PX;background-color: #FDEBD0;"
name="passwd" /></td>
</tr>
<tr>
<td align="center"> </td>
</tr>
<tr>
<td colspan="2"><s:submit cssClass="pagebutton"
cssStyle="width:100%" value="Submit"
onclick="return callSubmit();" /></td>
</tr>
</table>
</s:form>
<script>
function callSubmit(){
var username =
document.getElementById('paraFrm_username').value;
var passwd =
document.getElementById('paraFrm_passwd').value;
if(username==""||passwd==""){
alert("User Id or password can not be blank");
}
else{
document.getElementById('paraFrm').target="_self";
document.getElementById('paraFrm').action="submitpage";
document.getElementById('paraFrm').submit();
return true;
}
}
</script>
package org.paradyne.lib;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.apache.struts2.ActionInvocation;
import org.apache.struts2.ActionContext;
import org.apache.struts2.interceptor.Interceptor;
public class CspInterceptor implements Interceptor {
private static final long serialVersionUID = -4628112275531928102L;
@Override
public void destroy() {
System.out.println("CSP interceptor destroy method!!!!!");
}
@Override
public void init() {
System.out.println("CSP interceptor init method!!!!!");
}
@Override
public String intercept(ActionInvocation ai) throws Exception {
System.out.println("Before actionInvocation.invoke()
called!!!!");
final ActionContext ac = ai.getInvocationContext();
HttpServletResponse myresponse = ac.getServletResponse();
HttpSession session =
org.apache.struts2.ServletActionContext.getRequest().getSession();
final String jsessionid = session.getId();
String cookieValue = "JSESSIONID=" + jsessionid + ";
Path=/test; HttpOnly; SameSite=Strict";
myresponse.setHeader("Set-Cookie", cookieValue);
myresponse.setHeader("X-Frame-Options", "SAMEORIGIN");
myresponse.setHeader("X-Content-Type-Options", "nosniff");
myresponse.setHeader("Content-Security-Policy", "default-src
'self'; img-src 'self'; frame-src 'self'; connect-src 'self'; frame-ancestors
'self'; font-src 'self'; base-uri 'self'; form-action 'self'; 'unsafe-inline'
'unsafe-eval' prefetch-src 'none'; manifest-src 'none'; object-src 'self';
media-src 'none'; ");
String resultString = ai.invoke();
System.out.println("before result");
return resultString;
}
}
package org.struts.action.common;
import org.apache.struts2.ActionSupport;
import org.apache.struts2.ModelDriven;
import org.apache.struts2.Preparable;
import org.apache.struts2.action.ServletContextAware;
import org.apache.struts2.action.ServletRequestAware;
import org.apache.struts2.action.ServletResponseAware;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.interceptor.parameter.StrutsParameter;
import org.paradyne.bean.common.LoginBean;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Namespace("/common")
@Action("Login")
@Results({
@Result(name = "success", location =
"login.Login", type = "tiles"),
@Result(name = "welcomepage", location =
"login.successpage", type = "tiles"),
@Result(name = "input", location =
"login.Login", type = "tiles")
})
public class LoginAction extends ActionSupport implements
ModelDriven<Object>, Preparable, ServletRequestAware,ServletResponseAware,
ServletContextAware{
/**
*
*/
private static final long serialVersionUID = 1L;
LoginBean bean;
@StrutsParameter(depth = 1)
@Override
public Object getModel() {
// TODO Auto-generated method stub
return bean;
}
@Action("loginpage")
public String loginpage() {
return "input";
}
@Action("submitpage")
public String submitpage() {
System.out.println("password is:"+bean.getUsername());
System.out.println("user id is:"+bean.getPasswd());
if(bean.getUsername().equals("aa")&&bean.getPasswd().equals("aa")) {
return "welcomepage";
}
return "input";
}
@Override
public void withServletResponse(HttpServletResponse arg0) {
// TODO Auto-generated method stub
}
@Override
public void withServletRequest(HttpServletRequest arg0) {
// TODO Auto-generated method stub
}
@Override
public void prepare() throws Exception {
// TODO Auto-generated method stub
bean=new LoginBean();
}
@Override
public void withServletContext(ServletContext arg0) {
// TODO Auto-generated method stub
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 6.5//EN"
"struts-6.5.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.mapper.action.prefix.enabled" value="true"/>
<constant name="struts.custom.i18n.resources" value="globalMessages" />
<constant name="struts.multipart.maxSize" value="100000000" />
<constant name="struts.allowlist.packageNames"
value="org.paradyne.bean.common" />
<constant name="struts.convention.default.parent.package"
value="default" />
<package name="default" extends="struts-default">
<result-types>
<result-type name="tiles"
class="org.apache.struts2.views.tiles.TilesResult"/>
</result-types>
<interceptors>
<interceptor name="CSPInterceptor"
class="org.paradyne.lib.CspInterceptor"/>
<interceptor-stack name="customStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="CSPInterceptor" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="customStack" />
</package>
</struts>
package org.paradyne.bean.common;
import java.io.Serializable;
import org.apache.struts2.interceptor.parameter.StrutsParameter;
public class LoginBean implements Serializable{
private static final long serialVersionUID = 1L;
private String username="";
private String passwd="";
public String getPasswd() {
return passwd;
}
public String getUsername() {
return username;
}
@StrutsParameter(depth=1)
public void setUsername(String username) {
this.username = username;
}
@StrutsParameter(depth=1)
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://jakarta.ee/xml/ns/jakartaee"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd" id="WebApp_ID"
version="6.0">
<display-name>pims</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.apache.struts2.tiles.StrutsTilesListener
</listener-class>
</listener>
<context-param>
<param-name>org.apache.tiles.definition.DefinitionsFactory.DEFINITIONS_CONFIG</param-name>
<param-value>/WEB-INF/tiles.xml</param-value>
</context-param>
<welcome-file-list>
<welcome-file>/WEB-INF/home.jsp</welcome-file>
</welcome-file-list>
<error-page>
<error-code>401</error-code>
<location>/error401.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error404.jsp</location>
</error-page>
<error-page>
<error-code>408</error-code>
<location>/error408.jsp</location>
</error-page>
<session-config>
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
</web-app>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]