Change DBSQLInjection lesson to count the matched rows

This is an improvement over expecting the stored proc
to throw an exception, and is more portable


git-svn-id: http://webgoat.googlecode.com/svn/trunk@238 4033779f-a91e-0410-96ef-6bf7bf53c507
This commit is contained in:
rogan.dawes 2008-01-10 10:13:13 +00:00
parent 0149a699a3
commit cb2a3784b6
5 changed files with 68 additions and 52 deletions

View File

@ -251,7 +251,9 @@ public class DBCrossSiteScripting extends GoatHillsFinancial
@Override
protected boolean getDefaultHidden() {
return ! getWebgoatContext().getDatabaseDriver().contains("oracle");
String driver = getWebgoatContext().getDatabaseDriver();
boolean hidden = ! (driver.contains("oracle") || driver.contains("jtds"));
return hidden;
}
}

View File

@ -252,8 +252,9 @@ public class DBSQLInjection extends GoatHillsFinancial
@Override
protected boolean getDefaultHidden() {
return ! getWebgoatContext().getDatabaseDriver().contains("oracle");
String driver = getWebgoatContext().getDatabaseDriver();
boolean hidden = ! (driver.contains("oracle") || driver.contains("jtds"));
return hidden;
}
}

View File

@ -4,6 +4,7 @@ import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.List;
import java.util.Vector;
@ -132,52 +133,61 @@ public class Login extends DefaultLessonAction
public boolean login(WebSession s, String userId, String password)
{
System.out.println("Using \"" + password + "\"");
boolean authenticated = false;
try
{
String call = "{ CALL EMPLOYEE_LOGIN(?,?) }";
String call = "{ ? = call EMPLOYEE_LOGIN(?,?) }"; // NB: "call", not "CALL"! Doh!
try
{
CallableStatement statement = WebSession.getConnection(s)
.prepareCall(call, ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
statement.setInt(1, Integer.parseInt(userId));
statement.setString(2, password);
// if this executes successfully, we are authenticated
statement.registerOutParameter(1, Types.INTEGER);
statement.setInt(2, Integer.parseInt(userId));
statement.setString(3, password);
statement.execute();
setSessionAttribute(s,
getLessonName() + ".isAuthenticated", Boolean.TRUE);
setSessionAttribute(s, getLessonName() + "."
+ DBSQLInjection.USER_ID, userId);
authenticated = true;
if (DBSQLInjection.STAGE1.equals(getStage(s)) &&
DBSQLInjection.PRIZE_EMPLOYEE_ID == Integer.parseInt(userId))
{
setStageComplete(s, DBSQLInjection.STAGE1);
}
int rows = statement.getInt(1);
if (rows > 0) {
setSessionAttribute(s,
getLessonName() + ".isAuthenticated", Boolean.TRUE);
setSessionAttribute(s, getLessonName() + "."
+ DBSQLInjection.USER_ID, userId);
authenticated = true;
if (DBSQLInjection.STAGE1.equals(getStage(s)) &&
DBSQLInjection.PRIZE_EMPLOYEE_ID == Integer.parseInt(userId))
{
setStageComplete(s, DBSQLInjection.STAGE1);
}
} else {
if (DBSQLInjection.STAGE2.equals(getStage(s)))
{
try
{
String call2 = "{ ? = call EMPLOYEE_LOGIN_BACKUP(?,?) }";
statement = WebSession.getConnection(s)
.prepareCall(call2, ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
statement.registerOutParameter(1, Types.INTEGER);
statement.setInt(2, Integer.parseInt(userId));
statement.setString(3, password);
statement.execute();
rows = statement.getInt(1);
if (rows > 0)
setStageComplete(s, DBSQLInjection.STAGE2);
}
catch (SQLException sqle2){}
}
}
}
catch (SQLException sqle)
{
s.setMessage("Error logging in: " + sqle.getLocalizedMessage());
sqle.printStackTrace();
if (DBSQLInjection.STAGE2.equals(getStage(s)))
{
try
{
String call2 = "{ CALL EMPLOYEE_LOGIN_BACKUP(?,?) }";
CallableStatement statement = WebSession.getConnection(s)
.prepareCall(call2, ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
statement.setInt(1, Integer.parseInt(userId));
statement.setString(2, password);
statement.execute();
setStageComplete(s, DBSQLInjection.STAGE2);
}
catch (SQLException sqle2){}
}
}
}
catch (Exception e)

View File

@ -2,27 +2,28 @@ package org.owasp.webgoat.lessons.instructor.DBSQLInjection;
/*
* The solution is to choose Neville's userid, and enter a password like:
* ' OR userid=112 OR password='
* ' OR '1'='1
* Modify the Stored procedure LOGIN_EMPLOYEE to use fixed statements or bind variables
*
*
CREATE OR REPLACE PROCEDURE EMPLOYEE_LOGIN(v_id NUMBER, v_password VARCHAR) AS
v_userid NUMBER;
CREATE OR REPLACE FUNCTION WEBGOAT_guest.EMPLOYEE_LOGIN(v_id NUMBER, v_password VARCHAR) RETURN NUMBER AS
cnt NUMBER;
BEGIN
SELECT USERID INTO v_userid FROM EMPLOYEE
SELECT COUNT(*) INTO cnt FROM EMPLOYEE
WHERE USERID = v_id
AND PASSWORD = v_password;
RETURN cnt;
END;
/
* OR
CREATE OR REPLACE PROCEDURE EMPLOYEE_LOGIN(v_id NUMBER, v_password VARCHAR) AS
stmt VARCHAR(1000);
v_userid NUMBER;
CREATE OR REPLACE FUNCTION WEBGOAT_guest.EMPLOYEE_LOGIN(v_id NUMBER, v_password VARCHAR) RETURN NUMBER AS
stmt VARCHAR(32767); cnt NUMBER;
BEGIN
stmt := 'SELECT USERID FROM EMPLOYEE WHERE USERID = :1 AND PASSWORD = :2';
EXECUTE IMMEDIATE stmt INTO v_userid USING v_id, v_password;
stmt := 'SELECT COUNT (*) FROM EMPLOYEE WHERE USERID = :1 AND PASSWORD = :2';
EXECUTE IMMEDIATE stmt INTO cnt USING v_id, v_password;
RETURN cnt;
END;
/

View File

@ -24,19 +24,21 @@ CREATE TABLE WEBGOAT_guest.EMPLOYEE (
);
CREATE OR REPLACE PROCEDURE WEBGOAT_guest.EMPLOYEE_LOGIN(v_id NUMBER, v_password VARCHAR) AS
stmt VARCHAR(32767);v_userid NUMBER;
CREATE OR REPLACE FUNCTION WEBGOAT_guest.EMPLOYEE_LOGIN(v_id NUMBER, v_password VARCHAR) RETURN NUMBER AS
stmt VARCHAR(32767);cnt NUMBER;
BEGIN
stmt := 'SELECT USERID FROM EMPLOYEE WHERE USERID = ' || v_id || ' AND PASSWORD = ''' || v_password || '''';
EXECUTE IMMEDIATE stmt INTO v_userid;
stmt := 'SELECT COUNT (*) FROM EMPLOYEE WHERE USERID = ' || v_id || ' AND PASSWORD = ''' || v_password || '''';
EXECUTE IMMEDIATE stmt INTO cnt;
RETURN cnt;
END;
/
CREATE OR REPLACE PROCEDURE WEBGOAT_guest.EMPLOYEE_LOGIN_BACKUP(v_id NUMBER, v_password VARCHAR) AS
stmt VARCHAR(32767);v_userid NUMBER;
CREATE OR REPLACE FUNCTION WEBGOAT_guest.EMPLOYEE_LOGIN_BACKUP(v_id NUMBER, v_password VARCHAR) RETURN NUMBER AS
stmt VARCHAR(32767);cnt NUMBER;
BEGIN
stmt := 'SELECT USERID FROM EMPLOYEE WHERE USERID = ' || v_id || ' AND PASSWORD = ''' || v_password || '''';
EXECUTE IMMEDIATE stmt INTO v_userid;
stmt := 'SELECT COUNT (*) FROM EMPLOYEE WHERE USERID = ' || v_id || ' AND PASSWORD = ''' || v_password || '''';
EXECUTE IMMEDIATE stmt INTO cnt;
RETURN cnt;
END;
/