-
Notifications
You must be signed in to change notification settings - Fork 307
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* SKF TSEC * Update tsec_jsp_code_example_CSRF.md * Update tsec_jsp_code_example_CSRF.md * Update tsec_jsp_code_example_CSRF.md * Update tsec_jsp_code_example_CSRF.md * Update tsec_jsp_code_example_CSRF.md * Update tsec_jsp_code_example_CSRF.md * Update tsec_jsp_code_example_CSRF.md * Update tsec_jsp_code_example_CSRF.md * Update tsec_jsp_code_example_CSRF.md * Update tsec_jsp_code_example_CSRF.md * Rename skf/markdown/code_examples/java/TwelveSec/tsec_jsp_code_example_CSRF.md to skf/markdown/code_examples/code_snipet_jsp_antiCSRF.md * Rename skf/markdown/code_examples/code_snipet_jsp_antiCSRF.md to skf/markdown/code_examples/java/TwelveSec/code_snipet_jsp_antiCSRF.md * Title changed * Title changed * Code changed * csrf * csrf * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * csrf JSF implementation * Update 1-code_example--CSRF_Token_JSF--.md * Update 1-code_example--CSRF_Token_JSF--.md * charsets * charset * code examples update * code examples update * code examples update * code examples update * code examples update * code examples update * code examples update * code examples update * Update 12-code_example--file_upload--.md * Update 12-code_example--file_upload--.md * code examples update * code examples update * code examples update * code examples update * code examples update * code examples update * code examples update * Update 11-code_example--enforce_secure_passwords--.md * Update 11-code_example--enforce_secure_passwords--.md * Update 21-code_example--Password_forget_and_disallow_old_passwords--.md * code examples update * Update * Update * Update * Update * Update * Delete ESAPI.properties * Delete validation.properties * xpath * xpath * xpath * Delete 1-code_examples--jsp_CSRF_tokens--.md * csrf code fixes * csrf code fixes * code fixes * code fixes * code fixes * code fixes * code example 26 changes * code example 11 changes * code example 26 changes * code example 12 added jsp page that shows the path to destination * changes at 10th snippet - encoding * changes at 1st snippet - CSRF jsp * changes at 11th snippet - password checking * changes at snippet 11 - enforce passwords * changes at snippet 12 - file upload * changes at snippet 12 - file upload * changes at snippet 31 - input Validation * changes at snippet 30 - Session hijacking * changes at snippet 21 - Password forget and password dissallow * changes at snippet 18 - Login * changes at snippet 6 - Audit Log * changes at snippet 1 - CSRF Token Jsp * changes at snippet 29 - Randomizer * changes at snippet 29 - Randomizer * changes at snippet 29 - Randomizer * changes at snippet 29 - Randomizer * general changes * general changes * changes at snippet 18 - Login * changes in snippet 17 - identifier based authorization * changes in snippet 8 - Rewrite * changes in many snippets - inputValidation to InputValidation * changes to java snippets - from randomizer to Randomizer * changes to code snippet 40 - from xpath to XPath * changes in code snippet 40 - from xpath to Xpath * changes in code snippets - from hashing to Hashing * changes in code snippets - from whitelisting to WhiteListing * changes in code snippet 1 - CSRF Token * remove TODO and stack traces * substitution of e.printStackTrace() with logger.error (...) * changes in snipet 11 and 31 * snippet changes * snippet changes * final changes * final changes
- Loading branch information
1 parent
641ca94
commit 10990c3
Showing
43 changed files
with
5,466 additions
and
0 deletions.
There are no files selected for viewing
111 changes: 111 additions & 0 deletions
111
skf/markdown/code_examples/java/1-code_example--CSRF_Token--.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
|
||
|
||
CSRF Token | ||
----------- | ||
|
||
***Example:*** | ||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
/* | ||
For CSRF tokens we used a separate class outside of the normal controller, since | ||
it must be re-used on several locations throughout the application | ||
First after a successful validation of a user login, the application must also start a session | ||
which contains the "cross site request forgery" token. | ||
For generating the token we want to use a secure cryptographic function | ||
SecureRandom random = new SecureRandom(); | ||
//Then we generate a long value token containing a high entropy | ||
byte[] randomBytes = new byte[128]; | ||
random.nextBytes(randomBytes); | ||
//Then we base64 encode the string | ||
String csrftoken = Base64.getEncoder().encodeToString(randomBytes); | ||
HttpSession session | ||
session.setAttribute( "CSRF", csrftoken); | ||
The next step is implementing this random token in each form field as a hidden input parameter | ||
and send it to a function which checks if the submitted token is equal to the one set after succesful validation. | ||
<% | ||
Object token = request.getSession().getAttribute("CSRF"); | ||
String tokenStr = ""; | ||
if (token != null) | ||
{ | ||
tokenStr = (String) token; | ||
} | ||
%> | ||
<html> | ||
<head> | ||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> | ||
<title>Insert title here</title> | ||
</head> | ||
<body> | ||
Welcome to the OWASP CSRFGuard Test Application! Where would you like to go? | ||
<br/> | ||
<form action="/Home/csrf" method="post"> | ||
<input type="text" name="testValue" /> | ||
<br/> | ||
<input type="hidden" value="<%=tokenStr%>" name="token"/> | ||
<input type="submit" value="login"> | ||
</form> | ||
*/ | ||
package com.edw; | ||
import java.io.IOException; | ||
import javax.servlet.RequestDispatcher; | ||
import javax.servlet.ServletException; | ||
import javax.servlet.annotation.WebServlet; | ||
import javax.servlet.http.HttpServlet; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
@WebServlet("/CheckCSRF") | ||
public final class CheckCSRF extends HttpServlet | ||
{ | ||
private static final long serialVersionUID = 1L; | ||
public CheckCSRF() { | ||
super(); | ||
} | ||
//here we are sending the token towards the function which does the token validation | ||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||
String token = request.getParameter("token"); | ||
String sessionToken = (String) request.getSession().getAttribute("CSRF") | ||
if(!sessionToken.equals(token)) | ||
{ | ||
/* | ||
If there was no match, the authentication session will be emptied and sessions will be abandoned. Then, the user must be redirected towards the login page. | ||
*/ | ||
if ("".equalsIgonereCase(request.getSession().getAttribute("authenticateUser"))) | ||
{ | ||
request.getSession().invalidate(); | ||
request.setAttribute("msg", "Served at: " + request.getContextPath()); | ||
RequestDispatcher rd = request.getRequestDispatcher("/login"); | ||
rd.forward(request, response); | ||
return; | ||
} | ||
} | ||
} | ||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||
super.doGet(request, response); | ||
} | ||
} | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
178 changes: 178 additions & 0 deletions
178
skf/markdown/code_examples/java/1-code_example--CSRF_Token_JSF--.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
CSRF Tokens - JSF | ||
----------------- | ||
|
||
|
||
***Example:*** | ||
|
||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
/* | ||
For CSRF tokens we used a separate class outside of the normal controller, since | ||
it must be re-used on several locations throughout the application | ||
After a successful validation of a user login, the application must also start a session | ||
which contains the "cross site request forgery" token. | ||
From the Randomizer class we are generating the token we want by using a secure cryptographic function | ||
SecureRandom csprng = new SecureRandom(); | ||
Then we generate a long value token containing a high entropy | ||
byte[] randomBytes = new byte[128]; | ||
prng.nextBytes(randombytes); | ||
Then we base64 encode the string | ||
String csrfToken = Base64.getEncoder().encodeToString(randomBytes); | ||
Then we set the session attribute. | ||
origRequest.getSession(false); | ||
origRequest.getSession().setAttribute("CSRF", csrfToken); | ||
The next step is to implement this random token in each form field as a hidden input parameter | ||
and send it to a function which checks if the submitted token is equal to the one set after succesful validation. | ||
The following .xhtml snippet shows the code used to place the antiCSRF token inside the page. | ||
When the page renders, the <cu:antiCSRF/> is created as a viewstate encoded html input tag | ||
which then carries the antiCSRF token. | ||
While in process of rendering the page, a new token is generated | ||
and added into the existing session. | ||
When the user press the commandButton | ||
then CSRF token parameter is compared with the CSRF session parameter. | ||
*/ | ||
/* | ||
<f:view contentType="text/html"> | ||
<f:event listener="#{userLoginView.isAuthenticated}" type="preRenderView" /> | ||
[ .... ] | ||
<p:commandButton action="password?faces-redirect=true" value="Add User" ajax="false"> | ||
<cu:antiCSRF/> | ||
</p:commandButton> | ||
</h:form> | ||
[ .... ] | ||
/* | ||
the following function used to generate the new Session which then is added to the already existing session. | ||
*/ | ||
public void generateToken(){ | ||
HttpServletRequest origRequest = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest(); | ||
//we include the random password/token class. | ||
Randomizer CSRF = new Randomizer(); | ||
/* | ||
Now we create a random value for our CSRF tokens. See "Random password token generation" in | ||
the code examples for more detailed information: | ||
*/ | ||
String CSRftoken = CSRF.generate(25); | ||
//Set an accesor session. | ||
origRequest.getSession(false); | ||
origRequest.getSession().setAttribute("CSRF", CSRftoken); | ||
} | ||
/* | ||
the following function used to destroy the cookie and invalidate the session when the CSRF tokens dont match | ||
*/ | ||
public void antiCSRF() throws IOException | ||
{ | ||
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext(); | ||
HttpServletRequest origRequest = (HttpServletRequest)externalContext.getRequest(); | ||
HttpServletResponse origResponse = (HttpServletResponse)externalContext.getResponse(); | ||
String AUTH_KEY = (String) externalContext.getSessionMap().get("AUTH_KEY"); | ||
externalContext.getSessionMap().remove(AUTH_KEY); | ||
externalContext.invalidateSession(); | ||
// Get an array of Cookies associated with this domain | ||
Cookie[] cookies = origRequest.getCookies(); | ||
for (Cookie cookie : cookies) | ||
{ | ||
if ("JSSESIONID".equalsIgnoreCase(cookie.getName())) | ||
{ | ||
cookie.setValue(null); | ||
origResponse.addCookie(cookie); | ||
Log.SetLog("", "", "Cookie has been desroyed!", LocalDateTime.now(), "", ""); | ||
} | ||
} | ||
} | ||
/* | ||
This function used to decode the viewstate and get the token value from the html input tag. Also it perfomrms token comparison between the anticsrf token values of the html component and the session attribute. If the comparison fails then the session must be invalid. | ||
*/ | ||
public void decode(FacesContext context) { | ||
FacesContext fc = FacesContext.getCurrentInstance(); | ||
// access the hidden input field value | ||
ExternalContext external = context.getExternalContext(); | ||
Map<?, ?> requestMap = external.getRequestParameterMap(); | ||
String value = String.valueOf(requestMap.get("_CSRFToken")); | ||
// access the session and get the token | ||
HttpSession session = (HttpSession) external.getSession(false); | ||
String token = (String) session.getAttribute("CSRF"); | ||
// check if the token exists | ||
if (value == null || "".equals(value)) { | ||
try { | ||
this.antiCSRF(); | ||
} catch (IOException e) { | ||
logger.error(e.toString()); | ||
} | ||
Log.SetLog("", "", "antiCSRF token doesnt match! Failed attempt", "", "NULL"); | ||
logger.info("antiCSRF token doesnt match! Failed attempt"); | ||
ConfigurableNavigationHandler nav = (ConfigurableNavigationHandler) fc.getApplication().getNavigationHandler(); | ||
nav.performNavigation("csrf"); | ||
} | ||
// check the values for equality | ||
if (!value.equalsIgnoreCase(token)) { | ||
try { | ||
this.antiCSRF(); | ||
} catch (IOException e) { | ||
logger.error(e.toString()); | ||
} | ||
Log.SetLog("", "", "antiCSRF token doesnt match! Failed attempt", "", "NULL"); | ||
logger.info("antiCSRF token doesnt match! Failed attempt"); | ||
ConfigurableNavigationHandler nav = (ConfigurableNavigationHandler) fc.getApplication().getNavigationHandler(); | ||
nav.performNavigation("UserLogin"); | ||
} | ||
} | ||
/* | ||
the following function used to encode the viewstate with the html tag into a jsf component | ||
*/ | ||
@Override public void encodeEnd(FacesContext context) throws IOException | ||
{ | ||
//generate new token in every request | ||
this.generateToken(); | ||
// get the session (don't create a new one!) | ||
HttpSession session = (HttpSession) context.getExternalContext().getSession(false); | ||
// get the token from the session | ||
String token = (String) session.getAttribute("CSRF"); | ||
// write the component HTML to the response | ||
ResponseWriter responseWriter = context.getResponseWriter(); | ||
responseWriter.startElement("input", null); | ||
responseWriter.writeAttribute("type", "hidden", null); | ||
responseWriter.writeAttribute("name", "_CSRFToken", ""); | ||
responseWriter.writeAttribute("value", token, "CSRF"); | ||
responseWriter.endElement("input"); | ||
} | ||
*/ | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
46 changes: 46 additions & 0 deletions
46
skf/markdown/code_examples/java/10-code_example--encoder--.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
|
||
Encoder (SQL - ESAPI) | ||
----------- | ||
|
||
***Example:*** | ||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
package com.edw; | ||
import java.time.LocalDateTime; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
import org.owasp.esapi.ESAPI; | ||
import org.owasp.esapi.codecs.MySQLCodec; | ||
public final class Encoding { | ||
AuditLog Log = new AuditLog(); | ||
public String encoder(String input , String allowed, String user_id) | ||
{ | ||
/* | ||
We can specify also special characters which allowed in order to keep | ||
track of any unwanted special characters | ||
Example : | ||
To keep malicious inputs contained, any inputs written to the database need to be encoded. | ||
SQL encoding: ' OR 1=1 --' is encoded to \' OR 1\=1 \-\-\' | ||
*/ | ||
String pattern = "^[a-zA-Z0-9" + allowed + "]+$"; | ||
// Create a Pattern object | ||
Pattern reg = Pattern.compile(pattern); | ||
// Now create matcher object. | ||
Matcher match = reg.matcher(input); | ||
if (!match.find()) { | ||
Log.SetLog(user_id, "Illegal characters", "FAIL", LocalDateTime.now(), "HIGH"); | ||
} | ||
//We return the user input encoded | ||
return ESAPI.encoder().encodeForSQL(new MySQLCodec(MySQLCodec.MYSQL_MODE), input); | ||
} | ||
} | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Oops, something went wrong.