Hi, The application is currently showing the following security vulnerabilities: Content security Policy (CSP) Header not set (3 instances)- GET: http://localhost:8080/favicon.ico GET: http://localhost:8080/favicon.test GET: http://localhost:8080/favicon.test\
Missing Anti-clickjacking Header (2 instances)- GET: http://localhost:8080/favicon.test GET: http://localhost:8080/favicon.test\ Cookie without SameSite Attribute (2 instances) GET: http://localhost:8080/favicon.test GET: http://localhost:8080/favicon.test\ X-Content-Type-Options Header Missing (2 instances) GET: http://localhost:8080/favicon.test GET: http://localhost:8080/favicon.test\ I’ve made efforts to address these vulnerabilities and have shared the relevant code snippet below for your reference. The code is intended to mitigate CSRF and other related issues: @Override public String intercept(ActionInvocation ai) throws Exception { 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; } Pls suggest necessary improvements. Regards, Shivam test.war <https://drive.google.com/open?id=1ChtdOQKVdehi27j0Q-xth0w_9H7qD3wg> On Wed, Apr 16, 2025 at 4:17 PM Lukasz Lenart <lukaszlen...@apache.org> wrote: > śr., 16 kwi 2025 o 07:30 Shivam Agrahari > <shivamagrahari2...@gmail.com> napisał(a): > > 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. > > The best option is to read through OWASP recommendations PDFs and > apply them one by one > > Cheers > Łukasz > > --------------------------------------------------------------------- > To unsubscribe, e-mail: user-unsubscr...@struts.apache.org > For additional commands, e-mail: user-h...@struts.apache.org > >
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; } }
<%@ 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.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 } }
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" ?> <!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>
<?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: user-unsubscr...@struts.apache.org For additional commands, e-mail: user-h...@struts.apache.org