Restructured the baseline to remove extra src/main directory structure. Added eclipes project file

git-svn-id: http://webgoat.googlecode.com/svn/branches/webgoat-6.0@485 4033779f-a91e-0410-96ef-6bf7bf53c507
This commit is contained in:
mayhew64@gmail.com
2012-11-19 23:57:51 +00:00
parent fb938e0933
commit 6a96547ef0
1204 changed files with 85 additions and 2 deletions

View File

@ -0,0 +1,53 @@
package org.owasp.webgoat.lessons.instructor.RoleBasedAccessControl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial;
import org.owasp.webgoat.lessons.GoatHillsFinancial.LessonAction;
import org.owasp.webgoat.lessons.RoleBasedAccessControl.DeleteProfile;
import org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl;
import org.owasp.webgoat.session.UnauthorizedException;
import org.owasp.webgoat.session.WebSession;
public class DeleteProfile_i extends DeleteProfile
{
public DeleteProfile_i(GoatHillsFinancial lesson, String lessonName, String actionName, LessonAction chainedAction)
{
super(lesson, lessonName, actionName, chainedAction);
}
public void doDeleteEmployeeProfile(WebSession s, int userId, int employeeId) throws UnauthorizedException
{
if (s.isAuthorizedInLesson(userId, RoleBasedAccessControl.DELETEPROFILE_ACTION)) // FIX
{
try
{
String query = "DELETE FROM employee WHERE userid = " + employeeId;
// System.out.println("Query: " + query);
try
{
Statement statement = WebSession.getConnection(s)
.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
statement.executeUpdate(query);
} catch (SQLException sqle)
{
s.setMessage("Error deleting employee profile");
sqle.printStackTrace();
}
} catch (Exception e)
{
s.setMessage("Error deleting employee profile");
e.printStackTrace();
}
}
else
{
throw new UnauthorizedException(); // FIX
}
}
}

View File

@ -0,0 +1,101 @@
package org.owasp.webgoat.lessons.instructor.RoleBasedAccessControl;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial;
import org.owasp.webgoat.lessons.RoleBasedAccessControl.EditProfile;
import org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl;
import org.owasp.webgoat.session.Employee;
import org.owasp.webgoat.session.UnauthorizedException;
import org.owasp.webgoat.session.WebSession;
/**
* Copyright (c) 2006 Free Software Foundation developed under the custody of the Open Web
* Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is
* published by OWASP under the GPL. You should read and accept the LICENSE before you use, modify
* and/or redistribute this software.
*
*/
/*************************************************/
/* */
/* This file is not currently used in the course */
/* */
/*************************************************/
public class EditProfile_i extends EditProfile
{
public EditProfile_i(GoatHillsFinancial lesson, String lessonName, String actionName)
{
super(lesson, lessonName, actionName);
}
public Employee getEmployeeProfile(WebSession s, int userId, int subjectUserId) throws UnauthorizedException
{
// Query the database to determine if this employee has access to this function
// Query the database for the profile data of the given employee if "owned" by the given
// user
Employee profile = null;
if (s.isAuthorizedInLesson(userId, RoleBasedAccessControl.EDITPROFILE_ACTION)) // FIX
{
// Query the database for the profile data of the given employee
try
{
String query = "SELECT * FROM employee WHERE userid = ?";
try
{
PreparedStatement answer_statement = WebSession.getConnection(s)
.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
answer_statement.setInt(1, subjectUserId);
ResultSet answer_results = answer_statement.executeQuery();
if (answer_results.next())
{
// Note: Do NOT get the password field.
profile = new Employee(
answer_results.getInt("userid"),
answer_results.getString("first_name"),
answer_results.getString("last_name"),
answer_results.getString("ssn"),
answer_results.getString("title"),
answer_results.getString("phone"),
answer_results.getString("address1"),
answer_results.getString("address2"),
answer_results.getInt("manager"),
answer_results.getString("start_date"),
answer_results.getInt("salary"),
answer_results.getString("ccn"),
answer_results.getInt("ccn_limit"),
answer_results.getString("disciplined_date"),
answer_results.getString("disciplined_notes"),
answer_results.getString("personal_description"));
/*
* System.out.println("Retrieved employee from db: " +
* profile.getFirstName() + " " + profile.getLastName() + " (" +
* profile.getId() + ")");
*/}
} catch (SQLException sqle)
{
s.setMessage("Error getting employee profile");
sqle.printStackTrace();
}
} catch (Exception e)
{
s.setMessage("Error getting employee profile");
e.printStackTrace();
}
}
else
{
throw new UnauthorizedException(); // FIX
}
return profile;
}
}

View File

@ -0,0 +1,176 @@
package org.owasp.webgoat.lessons.instructor.RoleBasedAccessControl;
import org.apache.ecs.ElementContainer;
import org.owasp.webgoat.lessons.GoatHillsFinancial.DefaultLessonAction;
import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial;
import org.owasp.webgoat.lessons.GoatHillsFinancial.LessonAction;
import org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl;
import org.owasp.webgoat.session.ParameterNotFoundException;
import org.owasp.webgoat.session.UnauthenticatedException;
import org.owasp.webgoat.session.UnauthorizedException;
import org.owasp.webgoat.session.ValidationException;
import org.owasp.webgoat.session.WebSession;
/**
* Copyright (c) 2006 Free Software Foundation developed under the custody of the Open Web
* Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is
* published by OWASP under the GPL. You should read and accept the LICENSE before you use, modify
* and/or redistribute this software.
*
*/
/* STAGE 2 FIXES
Solution Summary: Edit RoleBasedAccessControl.java and change handleRequest().
Modify handleRequest() with lines denoted by // STAGE 2 - FIX.
Solution Steps:
1. This solution adds an access control check in the controller.
Point out that their architecture may require the check to occur in the business function.
2. Look at the RoleBasedAccessControl class identify where execution happens of an action.
a. action.handleRequest(s); is not protected by an access control check.
b. look at handleRequest(s) to determine where access control check should occur.
c. add protection by a programmatic authorization check before dispatching to the action:
1. Add an isAuthorized() call before dispatching to the action,
and throw an unauthorized exception. Tell student this exception exists.
Use eclipse command completion to find the isAuthorized() call on the action.
From command completion - determine calling arguments of isAuthorized()
int userId = action.getUserId(s);
if (action.isAuthorized(s, userId, action.getActionName()))
{
action.handleRequest(s);
}
else
throw new UnauthorizedException();
Repeat stage 1 and note that the function fails with a "Not authorized" message.
Tom will be in the list again, because the DB is reset when lesson restarts.
Adding the access check in the RoleBasedAccessControl:handleRequest() is putting the check in the <20>Controller<65>
The access check can also be added to DeleteProfile.deleteEmployeeProfile(), which is putting the check in the <20>Business Function<6F>
*/
public class RoleBasedAccessControl_i extends RoleBasedAccessControl
{
public void handleRequest(WebSession s)
{
// System.out.println("RoleBasedAccessControl.handleRequest()");
if (s.getLessonSession(this) == null) s.openLessonSession(this);
String requestedActionName = null;
try
{
requestedActionName = s.getParser().getStringParameter("action");
} catch (ParameterNotFoundException pnfe)
{
// Missing the action - send them back to login.
requestedActionName = LOGIN_ACTION;
}
try
{
LessonAction action = getAction(requestedActionName);
if (action != null)
{
// FIXME: This code has gotten much uglier
// System.out.println("RoleBasedAccessControl.handleRequest() dispatching to: " +
// action.getActionName());
if (!action.requiresAuthentication())
{
// Access to Login does not require authentication.
action.handleRequest(s);
}
else
{
if (action.isAuthenticated(s))
{
int userId = action.getUserId(s); // STAGE 2 - FIX
// action.getActionName() returns the user requested function which
// is tied to the button click from the listStaff jsp
//
// Checking isAuthorized() for the requested action
if (action.isAuthorized(s, userId, action.getActionName())) // STAGE 2 - FIX
{
// Calling the handleRequest() method for the requested action
action.handleRequest(s);
}
else
throw new UnauthorizedException(); // STAGE 2 - FIX
}
else
throw new UnauthenticatedException();
}
}
else
setCurrentAction(s, ERROR_ACTION);
} catch (ParameterNotFoundException pnfe)
{
// System.out.println("Missing parameter");
pnfe.printStackTrace();
setCurrentAction(s, ERROR_ACTION);
} catch (ValidationException ve)
{
// System.out.println("Validation failed");
ve.printStackTrace();
setCurrentAction(s, ERROR_ACTION);
} catch (UnauthenticatedException ue)
{
s.setMessage("Login failed");
// System.out.println("Authentication failure");
ue.printStackTrace();
} catch (UnauthorizedException ue2)
{
String stage = getStage(s);
// Update lesson status if necessary.
if (STAGE2.equals(stage))
{
try
{
if (GoatHillsFinancial.DELETEPROFILE_ACTION.equals(requestedActionName)
&& !isAuthorized(s, getUserId(s), GoatHillsFinancial.DELETEPROFILE_ACTION))
{
setStageComplete(s, STAGE2);
}
} catch (ParameterNotFoundException pnfe)
{
pnfe.printStackTrace();
}
}
// System.out.println("isAuthorized() exit stage: " + getStage(s));
// Update lesson status if necessary.
if (STAGE4.equals(stage))
{
try
{
// System.out.println("Checking for stage 4 completion");
DefaultLessonAction action = (DefaultLessonAction) getAction(getCurrentAction(s));
int userId = Integer.parseInt((String) s.getRequest().getSession()
.getAttribute(getLessonName() + "." + GoatHillsFinancial.USER_ID));
int employeeId = s.getParser().getIntParameter(GoatHillsFinancial.EMPLOYEE_ID);
if (!action.isAuthorizedForEmployee(s, userId, employeeId))
{
setStageComplete(s, STAGE4);
}
} catch (Exception e)
{
// swallow this - shouldn't happen inthe normal course
// e.printStackTrace();
}
}
s.setMessage("You are not authorized to perform this function");
// System.out.println("Authorization failure");
setCurrentAction(s, ERROR_ACTION);
ue2.printStackTrace();
}
// All this does for this lesson is ensure that a non-null content exists.
setContent(new ElementContainer());
}
}

View File

@ -0,0 +1,135 @@
package org.owasp.webgoat.lessons.instructor.RoleBasedAccessControl;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial;
import org.owasp.webgoat.lessons.GoatHillsFinancial.LessonAction;
import org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl;
import org.owasp.webgoat.lessons.RoleBasedAccessControl.UpdateProfile;
import org.owasp.webgoat.session.Employee;
import org.owasp.webgoat.session.UnauthorizedException;
import org.owasp.webgoat.session.WebSession;
/**
* Copyright (c) 2006 Free Software Foundation developed under the custody of the Open Web
* Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is
* published by OWASP under the GPL. You should read and accept the LICENSE before you use, modify
* and/or redistribute this software.
*
*/
/*************************************************/
/* */
/* This file is not currently used in the course */
/* */
/*************************************************/
public class UpdateProfile_i extends UpdateProfile
{
public UpdateProfile_i(GoatHillsFinancial lesson, String lessonName, String actionName, LessonAction chainedAction)
{
super(lesson, lessonName, actionName, chainedAction);
}
public void changeEmployeeProfile(WebSession s, int userId, int subjectId, Employee employee)
throws UnauthorizedException
{
if (s.isAuthorizedInLesson(userId, RoleBasedAccessControl.UPDATEPROFILE_ACTION)) // FIX
{
try
{
// Note: The password field is ONLY set by ChangePassword
String query = "UPDATE employee SET first_name = ?, last_name = ?, ssn = ?, title = ?, phone = ?, address1 = ?, address2 = ?,"
+ " manager = ?, start_date = ?, ccn = ?, ccn_limit = ?,"
+ " personal_description = ? WHERE userid = ?;";
try
{
PreparedStatement ps = WebSession.getConnection(s)
.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ps.setString(1, employee.getFirstName());
ps.setString(2, employee.getLastName());
ps.setString(3, employee.getSsn());
ps.setString(4, employee.getTitle());
ps.setString(5, employee.getPhoneNumber());
ps.setString(6, employee.getAddress1());
ps.setString(7, employee.getAddress2());
ps.setInt(8, employee.getManager());
ps.setString(9, employee.getStartDate());
ps.setString(10, employee.getCcn());
ps.setInt(11, employee.getCcnLimit());
ps.setString(12, employee.getPersonalDescription());
ps.setInt(13, subjectId);
ps.execute();
} catch (SQLException sqle)
{
s.setMessage("Error updating employee profile");
sqle.printStackTrace();
}
} catch (Exception e)
{
s.setMessage("Error updating employee profile");
e.printStackTrace();
}
}
else
{
throw new UnauthorizedException(); // FIX
}
}
public void createEmployeeProfile(WebSession s, int userId, Employee employee) throws UnauthorizedException
{
if (s.isAuthorizedInLesson(userId, RoleBasedAccessControl.UPDATEPROFILE_ACTION)) // FIX
{
try
{
// FIXME: Cannot choose the id because we cannot guarantee uniqueness
int nextId = getNextUID(s);
String query = "INSERT INTO employee VALUES ( " + nextId + ", ?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
// System.out.println("Query: " + query);
try
{
PreparedStatement ps = WebSession.getConnection(s).prepareStatement(query);
ps.setString(1, employee.getFirstName().toLowerCase());
ps.setString(2, employee.getLastName());
ps.setString(3, employee.getSsn());
ps.setString(4, employee.getTitle());
ps.setString(5, employee.getPhoneNumber());
ps.setString(6, employee.getAddress1());
ps.setString(7, employee.getAddress2());
ps.setInt(8, employee.getManager());
ps.setString(9, employee.getStartDate());
ps.setString(10, employee.getCcn());
ps.setInt(11, employee.getCcnLimit());
ps.setString(12, employee.getDisciplinaryActionDate());
ps.setString(13, employee.getDisciplinaryActionNotes());
ps.setString(14, employee.getPersonalDescription());
ps.execute();
} catch (SQLException sqle)
{
s.setMessage("Error updating employee profile");
sqle.printStackTrace();
}
} catch (Exception e)
{
s.setMessage("Error updating employee profile");
e.printStackTrace();
}
}
else
{
throw new UnauthorizedException(); // FIX
}
}
}

View File

@ -0,0 +1,133 @@
package org.owasp.webgoat.lessons.instructor.RoleBasedAccessControl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial;
import org.owasp.webgoat.lessons.RoleBasedAccessControl.ViewProfile;
import org.owasp.webgoat.session.Employee;
import org.owasp.webgoat.session.UnauthorizedException;
import org.owasp.webgoat.session.WebSession;
/* STAGE 4 FIXES
1. Find the code location where this flaw of directly retrieving the profile without data-level access control checking exists:
public void handleRequest( WebSession s )
{ <09>
Employee employee = getEmployeeProfile(s, userId, employeeId);
<09> }
public Employee getEmployeeProfile(WebSession s, int employeeId, int subjectUserId) throws UnauthorizedException { <09>
return getEmployeeProfile(s, employeeId, subjectUserId);
<09> }
2. The solution requires a data-level access control check to ensure the user has the rights to access the data they are requesting.
a. There is a common method you can take advantage of:
isAuthorizedForEmployee(s, userId, subjectUserId)
Either tell the student this exists or have them look in DefaultLessonAction.
Note that this is not required to implement data access control but is for detection of violations.
b. Uncomment the modified query retrieving the user data to have data access control
String query = "SELECT * FROM employee,ownership WHERE employee.userid = ownership.employee_id and " +
"ownership.employer_id = " + userId + " and ownership.employee_id = " + subjectUserId;
3. Bundle the entire logic with this call and throw an unauthorized exception
if (isAuthorizedForEmployee(s, userId, subjectUserId))
{ ...
//String query = "SELECT * FROM employee WHERE userid = " + subjectUserId;
String query = "SELECT * FROM employee,ownership WHERE employee.userid = ownership.employee_id and " +
"ownership.employer_id = " + userId + " and ownership.employee_id = " + subjectUserId; // STAGE 4 - FIX
...
}
else
{
throw new UnauthorizedException();
}
4. Repeat stage 3 and note that the function fails with a "Not authorized" message.
Adding the access check in the query is providing data-level access control.
The access check from isAuthorizedForEmployee is used to detect a violation.
The same logic could've been applied after the query but isAuthorizedForEmployee provides a nice centralized abstraction of that logic.
*/
public class ViewProfile_i extends ViewProfile
{
public ViewProfile_i(GoatHillsFinancial lesson, String lessonName, String actionName)
{
super(lesson, lessonName, actionName);
}
public Employee getEmployeeProfile(WebSession s, int userId, int subjectUserId) throws UnauthorizedException
{
// Query the database to determine if the given employee is owned by the given user
// Query the database for the profile data of the given employee
Employee profile = null;
// isAuthorizedForEmployee() allows us to determine authorization violations
if (isAuthorizedForEmployee(s, userId, subjectUserId)) // STAGE 4 - (ALTERNATE) FIX
{
// Query the database for the profile data of the given employee
try
{
// STAGE 4 - FIX
// String query = "SELECT * FROM employee WHERE userid = " + subjectUserId;
// Switch to this query to add Data Access Control
//
// Join employee and ownership to get all valid record combinations
// - qualify on ownership.employer_id to see only the current userId records
// - qualify on ownership.employee_id to see the current selected employee profile
// STAGE 4 - FIX
String query = "SELECT * FROM employee,ownership WHERE employee.userid = ownership.employee_id and "
+ "ownership.employer_id = " + userId + " and ownership.employee_id = " + subjectUserId;
try
{
Statement answer_statement = WebSession.getConnection(s)
.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet answer_results = answer_statement.executeQuery(query);
if (answer_results.next())
{
// Note: Do NOT get the password field.
profile = new Employee(
answer_results.getInt("userid"),
answer_results.getString("first_name"),
answer_results.getString("last_name"),
answer_results.getString("ssn"),
answer_results.getString("title"),
answer_results.getString("phone"),
answer_results.getString("address1"),
answer_results.getString("address2"),
answer_results.getInt("manager"),
answer_results.getString("start_date"),
answer_results.getInt("salary"),
answer_results.getString("ccn"),
answer_results.getInt("ccn_limit"),
answer_results.getString("disciplined_date"),
answer_results.getString("disciplined_notes"),
answer_results.getString("personal_description"));
/* System.out.println("Retrieved employee from db: " +
profile.getFirstName() + " " + profile.getLastName() +
" (" + profile.getId() + ")");
*/ }
}
catch ( SQLException sqle )
{
s.setMessage("Error getting employee profile");
sqle.printStackTrace();
}
} catch (Exception e)
{
s.setMessage("Error getting employee profile");
e.printStackTrace();
}
}
else
{
throw new UnauthorizedException(); // STAGE 4 - ALTERNATE FIX
}
return profile;
}
}