doc
java
org
owasp
webgoat
lessons
ClientSideFiltering
CrossSiteScripting
DBCrossSiteScripting
DBSQLInjection
GoatHillsFinancial
RoleBasedAccessControl
SQLInjection
admin
instructor
model
AbstractLesson.java
AccessControlMatrix.java
BackDoors.java
BasicAuthentication.java
BlindNumericSqlInjection.java
BlindScript.java
BlindStringSqlInjection.java
BypassHtmlFieldRestrictions.java
CSRF.java
Category.java
Challenge2Screen.java
ClientSideValidation.java
CommandInjection.java
ConcurrencyCart.java
CsrfPromptByPass.java
CsrfTokenByPass.java
DOMInjection.java
DOMXSS.java
DOS_Login.java
DangerousEval.java
Encoding.java
FailOpenAuthentication.java
ForcedBrowsing.java
ForgotPassword.java
HiddenFieldTampering.java
HowToWork.java
HtmlClues.java
HttpBasics.java
HttpBasicsController.java
HttpOnly.java
HttpSplitting.java
InsecureLogin.java
JSONInjection.java
JavaScriptValidation.java
LessonAdapter.java
LogSpoofing.java
MaliciousFileExecution.java
MultiLevelLogin1.java
MultiLevelLogin2.java
NewLesson.java
OffByOne.java
PasswordStrength.java
PathBasedAccessControl.java
Phishing.java
RandomLessonAdapter.java
ReflectedXSS.java
RemoteAdminFlaw.java
SameOriginPolicyProtection.java
SequentialLessonAdapter.java
SessionFixation.java
SilentTransactions.java
SoapRequest.java
SqlAddData.java
SqlModifyData.java
SqlNumericInjection.java
SqlStringInjection.java
StoredXss.java
ThreadSafetyProblem.java
TomcatSetup.java
TraceXSS.java
UncheckedEmail.java
UsefulTools.java
WSDLScanning.java
WeakAuthenticationCookie.java
WeakSessionID.java
WelcomeScreen.java
WsSAXInjection.java
WsSqlInjection.java
XMLInjection.java
XPATHInjection.java
servlets
session
util
Catcher.java
HammerHead.java
LessonSource.java
resources
scripts
tomcatconf
webapp
.classpath
.project
README.txt
build.xml
pom.xml
webgoat for SQL Server.bat
webgoat.bat
webgoat.sh
webgoat_8080.bat
webscarab.bat
git-svn-id: http://webgoat.googlecode.com/svn/branches/webgoat-6.0@485 4033779f-a91e-0410-96ef-6bf7bf53c507
517 lines
13 KiB
Java
517 lines
13 KiB
Java
|
|
package org.owasp.webgoat.lessons;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
import java.security.MessageDigest;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
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.Form;
|
|
import org.apache.ecs.html.IMG;
|
|
import org.apache.ecs.html.Input;
|
|
import org.apache.ecs.html.TD;
|
|
import org.apache.ecs.html.TR;
|
|
import org.apache.ecs.html.Table;
|
|
import org.owasp.webgoat.session.WebSession;
|
|
import sun.misc.BASE64Encoder;
|
|
|
|
|
|
/***************************************************************************************************
|
|
*
|
|
*
|
|
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
|
* please see http://www.owasp.org/
|
|
*
|
|
* Copyright (c) 2002 - 2007 Bruce Mayhew
|
|
*
|
|
* 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/
|
|
*/
|
|
public class HttpOnly extends LessonAdapter
|
|
{
|
|
|
|
public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com")
|
|
.addElement(
|
|
new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0)
|
|
.setVspace(0));
|
|
|
|
private final static Integer DEFAULT_RANKING = new Integer(125);
|
|
|
|
private final static String UNIQUE2U = "unique2u";
|
|
|
|
private final static String HTTPONLY = "httponly";
|
|
|
|
private final static String ACTION = "action";
|
|
|
|
private final static String READ = "Read Cookie";
|
|
|
|
private final static String WRITE = "Write Cookie";
|
|
|
|
private final static String READ_RESULT = "read_result";
|
|
|
|
private boolean httpOnly = false;
|
|
|
|
private boolean readSuccess = false;
|
|
|
|
private boolean writeSuccess = false;
|
|
|
|
private String original = "undefined";
|
|
|
|
/**
|
|
* Gets the title attribute of the EmailScreen object
|
|
*
|
|
* @return The title value
|
|
*/
|
|
public String getTitle()
|
|
{
|
|
return ("HTTPOnly Test");
|
|
}
|
|
|
|
protected Integer getDefaultRanking()
|
|
{
|
|
return DEFAULT_RANKING;
|
|
}
|
|
|
|
/**
|
|
* Description of the Method
|
|
*
|
|
* @param s
|
|
* Description of the Parameter
|
|
* @return Description of the Return Value
|
|
*/
|
|
|
|
protected Element createContent(WebSession s)
|
|
{
|
|
ElementContainer ec = new ElementContainer();
|
|
String action = null;
|
|
String http = null;
|
|
|
|
http = s.getRequest().getParameter(HTTPONLY);
|
|
action = s.getRequest().getParameter(ACTION);
|
|
|
|
if (http != null)
|
|
{
|
|
httpOnly = Boolean.parseBoolean(http);
|
|
}
|
|
|
|
if (httpOnly)
|
|
{
|
|
// System.out.println("HttpOnly: Setting HttpOnly for cookie");
|
|
setHttpOnly(s);
|
|
}
|
|
else
|
|
{
|
|
// System.out.println("HttpOnly: Removing HttpOnly for cookie");
|
|
removeHttpOnly(s);
|
|
}
|
|
|
|
if (action != null)
|
|
{
|
|
if (action.equals(READ))
|
|
{
|
|
handleReadAction(s);
|
|
}
|
|
else if (action.equals(WRITE))
|
|
{
|
|
handleWriteAction(s);
|
|
}
|
|
else
|
|
{
|
|
// s.setMessage("Invalid Request. Please try again.");
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
ec.addElement(makeContent(s));
|
|
} catch (Exception e)
|
|
{
|
|
s.setMessage("Error generating " + this.getClass().getName());
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return (ec);
|
|
}
|
|
|
|
/**
|
|
* DOCUMENT ME!
|
|
*
|
|
* @return DOCUMENT ME!
|
|
*/
|
|
protected Category getDefaultCategory()
|
|
{
|
|
return Category.XSS;
|
|
}
|
|
|
|
/**
|
|
* Gets the hints attribute of the EmailScreen object
|
|
*
|
|
* @return The hints value
|
|
*/
|
|
protected List<String> getHints(WebSession s)
|
|
{
|
|
List<String> hints = new ArrayList<String>();
|
|
hints.add("Read the directions and try out the buttons.");
|
|
return hints;
|
|
}
|
|
|
|
private String createCustomCookieValue()
|
|
{
|
|
String value = null;
|
|
byte[] buffer = null;
|
|
MessageDigest md = null;
|
|
BASE64Encoder encoder = new BASE64Encoder();
|
|
|
|
try
|
|
{
|
|
md = MessageDigest.getInstance("SHA");
|
|
buffer = new Date().toString().getBytes();
|
|
|
|
md.update(buffer);
|
|
value = encoder.encode(md.digest());
|
|
original = value;
|
|
|
|
} catch (Exception e)
|
|
{
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
private void setHttpOnly(WebSession s)
|
|
{
|
|
String value = createCustomCookieValue();
|
|
HttpServletResponse response = s.getResponse();
|
|
String cookie = s.getCookie(UNIQUE2U);
|
|
|
|
if (cookie == null || cookie.equals("HACKED"))
|
|
{
|
|
response.setHeader("Set-Cookie", UNIQUE2U + "=" + value + "; HttpOnly");
|
|
original = value;
|
|
}
|
|
else
|
|
{
|
|
response.setHeader("Set-Cookie", UNIQUE2U + "=" + cookie + "; HttpOnly");
|
|
original = cookie;
|
|
}
|
|
}
|
|
|
|
private void removeHttpOnly(WebSession s)
|
|
{
|
|
String value = createCustomCookieValue();
|
|
HttpServletResponse response = s.getResponse();
|
|
String cookie = s.getCookie(UNIQUE2U);
|
|
|
|
if (cookie == null || cookie.equals("HACKED"))
|
|
{
|
|
response.setHeader("Set-Cookie", UNIQUE2U + "=" + value + ";");
|
|
original = value;
|
|
}
|
|
else
|
|
{
|
|
response.setHeader("Set-Cookie", UNIQUE2U + "=" + cookie + ";");
|
|
original = cookie;
|
|
}
|
|
}
|
|
|
|
private ElementContainer makeContent(WebSession s)
|
|
{
|
|
ElementContainer ec = new ElementContainer();
|
|
Element r = null;
|
|
Table t = null;
|
|
TR tr = null;
|
|
Form f = null;
|
|
|
|
ec.addElement(new StringElement(getJavaScript()));
|
|
|
|
f = new Form();
|
|
|
|
t = new Table();
|
|
t.setWidth(500);
|
|
|
|
tr = new TR();
|
|
|
|
tr.addElement(new TD(new StringElement("Your browser appears to be: " + getBrowserType(s))));
|
|
t.addElement(tr);
|
|
|
|
tr = new TR();
|
|
t.addElement(tr);
|
|
|
|
tr = new TR();
|
|
|
|
tr.addElement(new TD(new StringElement("Do you wish to turn HTTPOnly on?")));
|
|
|
|
tr.addElement(new TD(new StringElement("Yes")));
|
|
|
|
if (httpOnly == true)
|
|
{
|
|
r = new Input(Input.RADIO, HTTPONLY, "True").addAttribute("Checked", "true");
|
|
}
|
|
else
|
|
{
|
|
r = new Input(Input.RADIO, HTTPONLY, "True").addAttribute("onClick", "document.form.submit()");
|
|
}
|
|
|
|
tr.addElement(new TD(r));
|
|
|
|
tr.addElement(new TD(new StringElement("No")));
|
|
|
|
if (httpOnly == false)
|
|
{
|
|
r = new Input(Input.RADIO, HTTPONLY, "False").addAttribute("Checked", "True");
|
|
}
|
|
else
|
|
{
|
|
r = new Input(Input.RADIO, HTTPONLY, "False").addAttribute("onClick", "document.form.submit()");
|
|
}
|
|
|
|
tr.addElement(new TD(r));
|
|
|
|
r = new Input(Input.HIDDEN, READ_RESULT, "");
|
|
tr.addElement(r);
|
|
|
|
t.addElement(tr);
|
|
|
|
/*
|
|
* tr.addElement(new TD(new StringElement("<strong>Status:</strong> " ))); t.addElement(tr);
|
|
* if(httpOnly == true) { tr.addElement(new TD(new StringElement("<div
|
|
* id=\"status\">On</div>"))); } else { tr.addElement(new TD(new StringElement ("<div
|
|
* id=\"status\">Off</div>"))); } t.addElement(tr); t.addElement(new TR(new TD(new
|
|
* StringElement("<br/>"))));
|
|
*/f.addElement(t);
|
|
|
|
t = new Table();
|
|
tr = new TR();
|
|
|
|
r = new Input(Input.SUBMIT, ACTION, READ).addAttribute("onclick", "myAlert();");
|
|
tr.addElement(new TD(r));
|
|
|
|
r = new Input(Input.SUBMIT, ACTION, WRITE).addAttribute("onclick", "modifyAlert();");
|
|
tr.addElement(new TD(r));
|
|
t.addElement(tr);
|
|
|
|
f.addElement(t);
|
|
ec.addElement(f);
|
|
|
|
return ec;
|
|
}
|
|
|
|
private void handleReadAction(WebSession s)
|
|
{
|
|
|
|
String displayed = s.getRequest().getParameter(READ_RESULT);
|
|
|
|
if (httpOnly == true)
|
|
{
|
|
if (displayed.indexOf(UNIQUE2U) != -1)
|
|
{
|
|
s.setMessage("FAILURE: Your browser did not enforce the HTTPOnly flag properly for the '" + UNIQUE2U
|
|
+ "' cookie. It allowed direct client side read access to this cookie.");
|
|
}
|
|
else
|
|
{
|
|
s.setMessage("SUCCESS: Your browser enforced the HTTPOnly flag properly for the '" + UNIQUE2U
|
|
+ "' cookie by preventing direct client side read access to this cookie.");
|
|
if (writeSuccess)
|
|
{
|
|
if (!this.isCompleted(s))
|
|
{
|
|
makeSuccess(s);
|
|
readSuccess = false;
|
|
writeSuccess = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!this.isCompleted(s))
|
|
{
|
|
s.setMessage("Now try to see if your browser protects write access to this cookie.");
|
|
readSuccess = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (displayed.indexOf(UNIQUE2U) != -1)
|
|
{
|
|
s.setMessage("Since HTTPOnly was not enabled, the '" + UNIQUE2U
|
|
+ "' cookie was displayed in the alert dialog.");
|
|
}
|
|
else
|
|
{
|
|
s.setMessage("Since HTTPOnly was not enabled, the '" + UNIQUE2U
|
|
+ "' cookie should have been displayed in the alert dialog, but was not for some reason. "
|
|
+ "(This shouldn't happen)");
|
|
}
|
|
}
|
|
|
|
private void handleWriteAction(WebSession s)
|
|
{
|
|
String hacked = s.getCookie(UNIQUE2U);
|
|
|
|
if (httpOnly == true)
|
|
{
|
|
if (!original.equals(hacked))
|
|
{
|
|
s
|
|
.setMessage("FAILURE: Your browser did not enforce the write protection property of the HTTPOnly flag for the '"
|
|
+ UNIQUE2U + "' cookie.");
|
|
s.setMessage("The " + UNIQUE2U + " cookie was successfully modified to " + hacked
|
|
+ " on the client side.");
|
|
}
|
|
else
|
|
{
|
|
s
|
|
.setMessage("SUCCESS: Your browser enforced the write protection property of the HTTPOnly flag for the '"
|
|
+ UNIQUE2U + "' cookie by preventing client side modification.");
|
|
if (readSuccess)
|
|
{
|
|
if (!this.isCompleted(s))
|
|
{
|
|
makeSuccess(s);
|
|
readSuccess = false;
|
|
writeSuccess = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!this.isCompleted(s))
|
|
{
|
|
s.setMessage("Now try to see if your browser protects read access to this cookie.");
|
|
writeSuccess = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (!original.equals(hacked))
|
|
{
|
|
s.setMessage("Since HTTPOnly was not enabled, the browser allowed the '" + UNIQUE2U
|
|
+ "' cookie to be modified on the client side.");
|
|
}
|
|
else
|
|
{
|
|
s.setMessage("Since HTTPOnly was not enabled, the browser should have allowed the '" + UNIQUE2U
|
|
+ "' cookie to be modified on the client side, but it was not for some reason. "
|
|
+ "(This shouldn't happen)");
|
|
}
|
|
}
|
|
|
|
private String getJavaScript()
|
|
{
|
|
StringBuffer buffer = new StringBuffer();
|
|
|
|
buffer.append("<script language=\"javascript\">\n");
|
|
buffer.append("function myAlert() {\n");
|
|
buffer.append("alert(document.cookie);\n");
|
|
buffer.append("document.form.read_result.value=document.cookie;\n");
|
|
buffer.append("return true;\n");
|
|
buffer.append("}\n");
|
|
buffer.append("function modifyAlert() {\n");
|
|
buffer.append("document.cookie='" + UNIQUE2U + "=HACKED;\';\n");
|
|
buffer.append("alert(document.cookie);\n");
|
|
buffer.append("return true;\n");
|
|
buffer.append("}\n");
|
|
buffer.append("</script>\n");
|
|
|
|
return buffer.toString();
|
|
}
|
|
|
|
private String getBrowserType(WebSession s)
|
|
{
|
|
int offset = -1;
|
|
String result = "unknown";
|
|
String browser = s.getHeader("user-agent").toLowerCase();
|
|
|
|
if (browser != null)
|
|
{
|
|
if (browser.indexOf("firefox") != -1)
|
|
{
|
|
browser = browser.substring(browser.indexOf("firefox"));
|
|
|
|
offset = getOffset(browser);
|
|
|
|
result = browser.substring(0, offset);
|
|
}
|
|
else if (browser.indexOf("msie 6") != -1)
|
|
{
|
|
result = "Internet Explorer 6";
|
|
}
|
|
else if (browser.indexOf("msie 7") != -1)
|
|
{
|
|
result = "Internet Explorer 7";
|
|
}
|
|
else if (browser.indexOf("msie") != -1)
|
|
{
|
|
result = "Internet Explorer";
|
|
}
|
|
else if (browser.indexOf("opera") != -1)
|
|
{
|
|
result = "Opera";
|
|
}
|
|
else if (browser.indexOf("safari") != -1)
|
|
{
|
|
result = "Safari";
|
|
}
|
|
else if (browser.indexOf("netscape") != -1)
|
|
{
|
|
browser = browser.substring(browser.indexOf("netscape"));
|
|
|
|
offset = getOffset(browser);
|
|
|
|
result = browser.substring(0, offset);
|
|
}
|
|
else if (browser.indexOf("konqueror") != -1)
|
|
{
|
|
result = "Konqueror";
|
|
}
|
|
else if (browser.indexOf("mozilla") != -1)
|
|
{
|
|
result = "Mozilla";
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private int getOffset(String s)
|
|
{
|
|
int result = s.length();
|
|
|
|
for (int i = 0; i < s.length(); i++)
|
|
{
|
|
if (s.charAt(i) < 33 || s.charAt(i) > 126)
|
|
{
|
|
result = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public Element getCredits()
|
|
{
|
|
return super.getCustomCredits("", ASPECT_LOGO);
|
|
}
|
|
}
|