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:
parent
0149a699a3
commit
cb2a3784b6
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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,22 +133,24 @@ 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();
|
||||
|
||||
int rows = statement.getInt(1);
|
||||
if (rows > 0) {
|
||||
setSessionAttribute(s,
|
||||
getLessonName() + ".isAuthenticated", Boolean.TRUE);
|
||||
setSessionAttribute(s, getLessonName() + "."
|
||||
@ -158,26 +161,33 @@ public class Login extends DefaultLessonAction
|
||||
{
|
||||
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)
|
||||
|
@ -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;
|
||||
/
|
||||
|
||||
|
@ -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;
|
||||
/
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user