diff --git a/.gitignore b/.gitignore index 40c64083..85cfca11 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,14 @@ # Project Files # ################# *.userprefs -WebGoat/WebGoat.NET.pidb -WebGoat/bin -WebGoat/obj +*.pidb +*swp +bin +obj WebGoat/App_Data/*.txt -WebGoat/App_Data/.DS_Store -WebGoat/App_Data/*.sqlite +*.sqlite* WebGoat/Configuration/*.config # Trash Files # ############### .DS_Store -DB/.DS_Store -WebGoat/DB_Scripts/.DS_Store diff --git a/README b/README index 9c86601e..a5ce616c 100644 --- a/README +++ b/README @@ -1,22 +1,64 @@ - - From the prompt, cd into the WebGoat.NET DB directory +***************************** Webgoat.NET ********************************** +* Source Code: https://github.com/jerryhoff/WebGoat.NET +* Download zip: https://github.com/jerryhoff/WebGoat.NET/zipball/master +**************************************************************************** - % cd /WebGoat.NET/DB +This web application is a learning platform that attempts to teach about +common web security flaws. It contains generic security flaws that apply to +most web applications. It also contains lessons that specifically pertain to +the .NET framework. The excercises in this app are intented to teach about +web security attacks and how developers can overcome them. - Start the mysql utility, giving the name (and password, if needed) of a user permission to create databases. For example, to use the default root user: +WARNING: THIS WEB APPLICATION CONTAINS NUMEROUS SECURITY VULNERABILITIES +WHICH WILL RENDER YOUR COMPUTER VERY INSECURURE WHILE RUNNING! IT IS HIGHLY +RECOMMENDED TO COMPLETELY DISCONNECT YOUR COMPUTER FROM ALL NETWORKS WHILE +RUNNING! - % mysql --user=root +Notes: + - Google Chrome performs filtering for reflected XSS attacks. These attacks + will not work unless chrome is run with the argument + --disable-xss-auditor. +- Some (but not all!) of the lessons require a working SQL database. Setup + guidelines are shown below. - Create the webgoat_coins database and load the schema. (Loading the schema the schema the first time will give error messages as it attemps to empty any existing tables, just ignore these.) +How To Build And Run under Mac OS X and Linux: + 1. Prerequisites + a. Mono framework for your respective OS. It can be downloaded at + http://www.go-mono.com/mono-downloads/download.html. Make sure + that ALL components get installed, including GTK and xsp. + b. A DB for some of the lessions. Sqlite3 is recommended as it's + faster and easier to use for the purposes of these lessions. + Binaries can be found here: http://www.sqlite.org/download.html + 2. Install the mono framework and sqlite3 binaries. + 3. IMPORTANT: Make sure that the the mono executable is in your PATH. + 4. Grab WebGoat.NET and cd into the root dir. + 5. Run 'xbuild'. There may be a few warnings but there should be no + errors! If there are please let us know. + 6. cd into the WebGoat project and run 'xsp4'. Then open your favorite + browser and go to http://localhost:8080 (or whatever port your + xsp4 is using if you're not using the default). Note: The first run + may take take some time as it's compiling everything on the fly. + 7. If you see the WebGoat.NET page that means you're almost there! Next + step is to click on 'Set Up Database!' + 8. You should see a form with a bunch of setup information for the + database. For 'Data Provider' choose Sqlite. For 'Data File Path' put + in 'db.sqlite3' and for 'Client Executable' put in the sqlite3 + executable of your OS (usually /usr/bin/sqlite3). + 9. Click on 'Test Configuration', followed by 'Rebuild Database' and + hopefully you should be good go! Enjoy your hackathon! - mysql> create database webgoat_coins; - mysql> use webgoat_coins; - mysql> source create_webgoatcoins.sql; - - Load the table contents: - - mysql> source load_webgoatcoins.sql; - - Exit from mysql: - - mysql> quit; +How to build and run under Windows: + 1. Prerequisites: + a. Visual Studio 2010 and above. + b. Mysql database that's up and running with at least one user + aleady setup with full permissions. + 2. Open WebGoat.sln file via Visual Studio, and click on debug. + 3. You should see the WebGoat.NET page at which point click on + 'Set Up Database'. + 3. You should see a form with a bunch of setup information for the + database. For 'Data Provider' choose MySql. You'll need to fill in + the respective data entries for your mysql db. 'Client Executable' + and 'Data File Path' are not necessary for MySql so you can leave + them empty. + 4. Click on 'Test Configuration', followed by 'Rebuild Database' and + hopefully you should be good go! Enjoy your hackathon! diff --git a/WebGoat/App_Code/CustomerLoginData.cs b/WebGoat/App_Code/CustomerLoginData.cs index 9d4a5e13..fa431889 100644 --- a/WebGoat/App_Code/CustomerLoginData.cs +++ b/WebGoat/App_Code/CustomerLoginData.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Web; namespace OWASP.WebGoat.NET @@ -31,4 +30,4 @@ public String Message } } -} \ No newline at end of file +} diff --git a/WebGoat/App_Code/DB/DbConstants.cs b/WebGoat/App_Code/DB/DbConstants.cs index 85351d09..69e86efb 100644 --- a/WebGoat/App_Code/DB/DbConstants.cs +++ b/WebGoat/App_Code/DB/DbConstants.cs @@ -1,4 +1,5 @@ -using System; +using System; +using System.IO; namespace OWASP.WebGoat.NET.App_Code.DB { @@ -18,10 +19,12 @@ public class DbConstants public const string DB_TYPE_MYSQL = "MySql"; public const string DB_TYPE_SQLITE = "Sqlite"; public const string CONFIG_EXT = "config"; - + //DB Scripts - public const string DB_CREATE_SCRIPT = "DB_Scripts/create_webgoatcoins.sql"; - public const string DB_LOAD_MYSQL_SCRIPT = "DB_Scripts/load_webgoatcoins.sql"; - public const string DB_LOAD_SQLITE_SCRIPT = "DB_Scripts/load_webgoatcoins_sqlite3.sql"; + private const string SCRIPT_DIR = "DB_Scripts"; + public static readonly string DB_CREATE_MYSQL_SCRIPT = Path.Combine(SCRIPT_DIR, "create_webgoatcoins.sql"); + public static readonly string DB_CREATE_SQLITE_SCRIPT = Path.Combine(SCRIPT_DIR, "create_webgoatcoins_sqlite3.sql"); + public static readonly string DB_LOAD_MYSQL_SCRIPT = Path.Combine(SCRIPT_DIR, "load_webgoatcoins.sql"); + public static readonly string DB_LOAD_SQLITE_SCRIPT = Path.Combine(SCRIPT_DIR, "load_webgoatcoins_sqlite3.sql"); } } diff --git a/WebGoat/App_Code/DB/MySqlDbProvider.cs b/WebGoat/App_Code/DB/MySqlDbProvider.cs index 6d4307e3..0bc79812 100644 --- a/WebGoat/App_Code/DB/MySqlDbProvider.cs +++ b/WebGoat/App_Code/DB/MySqlDbProvider.cs @@ -103,7 +103,7 @@ public bool RecreateGoatDb() log.Info("Running recreate"); - int retVal1 = Math.Abs(Util.RunProcessWithInput(_clientExec, args, DbConstants.DB_CREATE_SCRIPT)); + int retVal1 = Math.Abs(Util.RunProcessWithInput(_clientExec, args, DbConstants.DB_CREATE_MYSQL_SCRIPT)); int retVal2 = Math.Abs(Util.RunProcessWithInput(_clientExec, args, DbConstants.DB_LOAD_MYSQL_SCRIPT)); return Math.Abs(retVal1) + Math.Abs(retVal2) == 0; diff --git a/WebGoat/App_Code/DB/SqliteDbProvider.cs b/WebGoat/App_Code/DB/SqliteDbProvider.cs index ee3e6e41..0e88a6d8 100644 --- a/WebGoat/App_Code/DB/SqliteDbProvider.cs +++ b/WebGoat/App_Code/DB/SqliteDbProvider.cs @@ -1,6 +1,6 @@ using System; using System.Data; -using System.Data.SQLite; +using Mono.Data.Sqlite; using log4net; using System.Reflection; using System.IO; @@ -25,17 +25,20 @@ public SqliteDbProvider(ConfigFile configFile) _clientExec = configFile.Get(DbConstants.KEY_CLIENT_EXEC); _dbFileName = configFile.Get(DbConstants.KEY_FILE_NAME); + + if (!File.Exists(_dbFileName)) + SqliteConnection.CreateFile(_dbFileName); } public bool TestConnection() { try { - using (SQLiteConnection conn = new SQLiteConnection(_connectionString)) + using (SqliteConnection conn = new SqliteConnection(_connectionString)) { conn.Open(); - using (SQLiteCommand cmd = conn.CreateCommand()) + using (SqliteCommand cmd = conn.CreateCommand()) { cmd.CommandText = "SELECT date('now')"; @@ -54,9 +57,11 @@ public bool TestConnection() public DataSet GetCatalogData() { - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { - SQLiteDataAdapter da = new SQLiteDataAdapter("select * from Products", connection); + connection.Open(); + + SqliteDataAdapter da = new SqliteDataAdapter("select * from Products", connection); DataSet ds = new DataSet(); da.Fill(ds); @@ -67,16 +72,18 @@ public DataSet GetCatalogData() public bool IsValidCustomerLogin(string email, string password) { - //encode password + //encode password string encoded_password = Encoder.Encode(password); //check email/password string sql = "select * from CustomerLogin where email = '" + email + "' and password = '" + encoded_password + "';"; - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + connection.Open(); + + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); //TODO: User reader instead (for all calls) DataSet ds = new DataSet(); @@ -98,13 +105,24 @@ public bool IsValidCustomerLogin(string email, string password) } public bool RecreateGoatDb() - { - log.Info("Running recreate"); - - int retVal1 = Math.Abs(Util.RunProcessWithInput(_clientExec, _dbFileName, DbConstants.DB_CREATE_SCRIPT)); - int retVal2 = Math.Abs(Util.RunProcessWithInput(_clientExec, _dbFileName, DbConstants.DB_LOAD_SQLITE_SCRIPT)); - - return Math.Abs(retVal1) + Math.Abs(retVal2) == 0; + { + try + { + log.Info("Running recreate"); + string args = string.Format("\"{0}\"", _dbFileName); + string script = Path.Combine(Settings.RootDir, DbConstants.DB_CREATE_SQLITE_SCRIPT); + int retVal1 = Math.Abs(Util.RunProcessWithInput(_clientExec, args, script)); + + script = Path.Combine(Settings.RootDir, DbConstants.DB_LOAD_SQLITE_SCRIPT); + int retVal2 = Math.Abs(Util.RunProcessWithInput(_clientExec, args, script)); + + return Math.Abs(retVal1) + Math.Abs(retVal2) == 0; + } + catch (Exception ex) + { + log.Error("Error rebulding DB", ex); + return false; + } } //Find the bugs! @@ -116,9 +134,11 @@ public string CustomCustomerLogin(string email, string password) //get data string sql = "select * from CustomerLogin where email = '" + email + "';"; - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + connection.Open(); + + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); DataSet ds = new DataSet(); da.Fill(ds); @@ -144,7 +164,7 @@ public string CustomCustomerLogin(string email, string password) } } - catch (SQLiteException ex) + catch (SqliteException ex) { log.Error("Error with custom customer login", ex); error_message = ex.Message; @@ -163,10 +183,12 @@ public string GetCustomerEmail(string customerNumber) try { - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { + connection.Open(); + string sql = "select email from CustomerLogin where customerNumber = " + customerNumber; - SQLiteCommand command = new SQLiteCommand(sql, connection); + SqliteCommand command = new SqliteCommand(sql, connection); output = command.ExecuteScalar().ToString(); } } @@ -188,9 +210,11 @@ public DataSet GetCustomerDetails(string customerNumber) try { - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + connection.Open(); + + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); da.Fill(ds); } @@ -208,10 +232,12 @@ public DataSet GetCustomerDetails(string customerNumber) public DataSet GetOffice(string city) { - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { + connection.Open(); + string sql = "select * from Offices where city = @city"; - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); da.SelectCommand.Parameters.AddWithValue("@city", city); DataSet ds = new DataSet(); da.Fill(ds); @@ -221,10 +247,12 @@ public DataSet GetOffice(string city) public DataSet GetComments(string productCode) { - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { + connection.Open(); + string sql = "select * from Comments where productCode = @productCode"; - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); da.SelectCommand.Parameters.AddWithValue("@productCode", productCode); DataSet ds = new DataSet(); da.Fill(ds); @@ -240,9 +268,10 @@ public string AddComment(string productCode, string email, string comment) try { - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { - SQLiteCommand command = new SQLiteCommand(sql, connection); + connection.Open(); + SqliteCommand command = new SqliteCommand(sql, connection); command.ExecuteNonQuery(); } } @@ -262,9 +291,11 @@ public string UpdateCustomerPassword(int customerNumber, string password) try { - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { - SQLiteCommand command = new SQLiteCommand(sql, connection); + connection.Open(); + + SqliteCommand command = new SqliteCommand(sql, connection); int rows_added = command.ExecuteNonQuery(); @@ -287,9 +318,11 @@ public string[] GetSecurityQuestionAndAnswer(string email) string[] qAndA = new string[2]; - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + connection.Open(); + + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); DataSet ds = new DataSet(); da.Fill(ds); @@ -311,11 +344,13 @@ public string GetPasswordByEmail(string email) try { - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { + connection.Open(); + //get data string sql = "select * from CustomerLogin where email = '" + email + "';"; - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); DataSet ds = new DataSet(); da.Fill(ds); @@ -339,10 +374,12 @@ public string GetPasswordByEmail(string email) public DataSet GetUsers() { - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { + connection.Open(); + string sql = "select * from CustomerLogin;"; - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); DataSet ds = new DataSet(); da.Fill(ds); return ds; @@ -352,10 +389,12 @@ public DataSet GetUsers() public DataSet GetOrders(int customerID) { - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { + connection.Open(); + string sql = "select * from Orders where customerNumber = " + customerID; - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); DataSet ds = new DataSet(); da.Fill(ds); @@ -369,18 +408,20 @@ public DataSet GetOrders(int customerID) public DataSet GetProductDetails(string productCode) { string sql = string.Empty; - SQLiteDataAdapter da; + SqliteDataAdapter da; DataSet ds = new DataSet(); - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { + connection.Open(); + sql = "select * from Products where productCode = '" + productCode + "'"; - da = new SQLiteDataAdapter(sql, connection); + da = new SqliteDataAdapter(sql, connection); da.Fill(ds, "products"); sql = "select * from Comments where productCode = '" + productCode + "'"; - da = new SQLiteDataAdapter(sql, connection); + da = new SqliteDataAdapter(sql, connection); da.Fill(ds, "comments"); DataRelation dr = new DataRelation("prod_comments", @@ -405,9 +446,11 @@ public DataSet GetOrderDetails(int orderNumber) "and OrderDetails.orderNumber = " + orderNumber; - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + connection.Open(); + + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); DataSet ds = new DataSet(); da.Fill(ds); @@ -420,10 +463,12 @@ public DataSet GetOrderDetails(int orderNumber) public DataSet GetPayments(int customerNumber) { - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { + connection.Open(); + string sql = "select * from Payments where customerNumber = " + customerNumber; - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); DataSet ds = new DataSet(); da.Fill(ds); @@ -443,7 +488,7 @@ public DataSet GetProductsAndCategories(int catNumber) { //TODO: Rerun the database script. string sql = string.Empty; - SQLiteDataAdapter da; + SqliteDataAdapter da; DataSet ds = new DataSet(); //catNumber is optional. If it is greater than 0, add the clause to both statements. @@ -452,15 +497,16 @@ public DataSet GetProductsAndCategories(int catNumber) catClause += " where catNumber = " + catNumber; - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { + connection.Open(); sql = "select * from Categories" + catClause; - da = new SQLiteDataAdapter(sql, connection); + da = new SqliteDataAdapter(sql, connection); da.Fill(ds, "categories"); sql = "select * from Products" + catClause; - da = new SQLiteDataAdapter(sql, connection); + da = new SqliteDataAdapter(sql, connection); da.Fill(ds, "products"); @@ -480,9 +526,11 @@ public DataSet GetEmailByName(string name) string sql = "select firstName, lastName, email from Employees where firstName like '" + name + "%' or lastName like '" + name + "%'"; - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + connection.Open(); + + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); DataSet ds = new DataSet(); da.Fill(ds); @@ -499,10 +547,12 @@ public string GetEmailByCustomerNumber(string num) try { - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { + connection.Open(); + string sql = "select email from CustomerLogin where customerNumber = " + num; - SQLiteCommand cmd = new SQLiteCommand(sql, connection); + SqliteCommand cmd = new SqliteCommand(sql, connection); output = (string)cmd.ExecuteScalar(); } @@ -521,9 +571,11 @@ public DataSet GetCustomerEmails(string email) string sql = "select email from CustomerLogin where email like '" + email + "%'"; - using (SQLiteConnection connection = new SQLiteConnection(_connectionString)) + using (SqliteConnection connection = new SqliteConnection(_connectionString)) { - SQLiteDataAdapter da = new SQLiteDataAdapter(sql, connection); + connection.Open(); + + SqliteDataAdapter da = new SqliteDataAdapter(sql, connection); DataSet ds = new DataSet(); da.Fill(ds); diff --git a/WebGoat/App_Code/Encoder.cs b/WebGoat/App_Code/Encoder.cs index 5d792c51..99bb022e 100644 --- a/WebGoat/App_Code/Encoder.cs +++ b/WebGoat/App_Code/Encoder.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Web; using System.IO; using System.Text; @@ -242,4 +241,4 @@ public string EncodeTicket(string token) } } -} \ No newline at end of file +} diff --git a/WebGoat/App_Code/Settings.cs b/WebGoat/App_Code/Settings.cs index c72eb0de..b0873633 100644 --- a/WebGoat/App_Code/Settings.cs +++ b/WebGoat/App_Code/Settings.cs @@ -2,6 +2,12 @@ using OWASP.WebGoat.NET.App_Code.DB; using System.IO; using System.Web; +using log4net; +using System.Reflection; +using System.Diagnostics; +using log4net.Config; +using log4net.Appender; +using log4net.Layout; namespace OWASP.WebGoat.NET.App_Code { @@ -10,43 +16,66 @@ public class Settings public static readonly string DefaultConfigName = string.Format("Default.{0}", DbConstants.CONFIG_EXT); private const string PARENT_CONFIG_PATH = "Configuration"; private const string DATA_FOLDER = "App_Data"; - private const string DEFAULT_SQLITE_NAME = "webgoat_coins.sqlite"; + private const string DEFAULT_SQLITE_NAME = "webgoat_coins.sqlite"; + + private static object _lock = new object(); + private static bool _inited = false; + private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public static void Init(HttpServerUtility server) - { - string configPath = Path.Combine(PARENT_CONFIG_PATH, DefaultConfigName); - DefaultConfigPath = server.MapPath(configPath); - - //By default if there's no config let's create a sqlite db. - string defaultConfigPath = DefaultConfigPath; - - string sqlitePath = Path.Combine(DATA_FOLDER, DEFAULT_SQLITE_NAME); - sqlitePath = server.MapPath(sqlitePath); - - if (!File.Exists(defaultConfigPath)) - { - ConfigFile file = new ConfigFile(defaultConfigPath); - - file.Set(DbConstants.KEY_DB_TYPE, DbConstants.DB_TYPE_SQLITE); - file.Set(DbConstants.KEY_FILE_NAME, sqlitePath); - file.Save(); - - CurrentConfigFile = file; - } - else - { - CurrentConfigFile = new ConfigFile(defaultConfigPath); - CurrentConfigFile.Load(); + { + lock (_lock) + { + if (Debugger.IsAttached) + BasicConfigurator.Configure(); + else + XmlConfigurator.Configure(); + + string configPath = Path.Combine(PARENT_CONFIG_PATH, DefaultConfigName); + DefaultConfigPath = server.MapPath(configPath); + + RootDir = server.MapPath("."); + + log.Debug("DYLD_FALLBACK_LIBRARY_PATH: " + Environment.GetEnvironmentVariable("DYLD_FALLBACK_LIBRARY_PATH")); + log.Debug("PWD: " + Environment.CurrentDirectory); + + //By default if there's no config let's create a sqlite db. + string defaultConfigPath = DefaultConfigPath; + + string sqlitePath = Path.Combine(DATA_FOLDER, DEFAULT_SQLITE_NAME); + sqlitePath = server.MapPath(sqlitePath); + + if (!File.Exists(defaultConfigPath)) + { + ConfigFile file = new ConfigFile(defaultConfigPath); + + file.Set(DbConstants.KEY_DB_TYPE, DbConstants.DB_TYPE_SQLITE); + file.Set(DbConstants.KEY_FILE_NAME, sqlitePath); + file.Save(); + + CurrentConfigFile = file; + } + else + { + CurrentConfigFile = new ConfigFile(defaultConfigPath); + CurrentConfigFile.Load(); + } + + CurrentDbProvider = DbProviderFactory.Create(CurrentConfigFile); + _inited = true; } - CurrentDbProvider = DbProviderFactory.Create(CurrentConfigFile); - } - + } + + public static string RootDir { get; private set; } + public static IDbProvider CurrentDbProvider { get; set; } public static string DefaultConfigPath { get; private set; } - public static ConfigFile CurrentConfigFile { get; set; } + public static ConfigFile CurrentConfigFile { get; set; } + + public static bool Inited { get { lock (_lock) { return _inited; } } } } } \ No newline at end of file diff --git a/WebGoat/App_Code/Util.cs b/WebGoat/App_Code/Util.cs index a074d7ef..a88fa9ff 100644 --- a/WebGoat/App_Code/Util.cs +++ b/WebGoat/App_Code/Util.cs @@ -15,6 +15,7 @@ public static int RunProcessWithInput(string cmd, string args, string input) { ProcessStartInfo startInfo = new ProcessStartInfo { + WorkingDirectory = Settings.RootDir, FileName = cmd, Arguments = args, UseShellExecute = false, @@ -27,7 +28,6 @@ public static int RunProcessWithInput(string cmd, string args, string input) { process.EnableRaisingEvents = true; process.StartInfo = startInfo; - process.Start(); process.OutputDataReceived += (sender, e) => { if (e.Data != null) @@ -47,16 +47,26 @@ public static int RunProcessWithInput(string cmd, string args, string input) Thread.Sleep(1000); are.Set(); log.Info("Process exited"); - }; - process.Start(); + }; - using (StreamReader reader = new StreamReader(new FileStream(input, FileMode.Open))) - { - string line; - - while ((line = reader.ReadLine()) != null) - process.StandardInput.WriteLine(line); + process.Start(); + + using (StreamReader reader = new StreamReader(new FileStream(input, FileMode.Open))) + { + string line; + string replaced; + while ((line = reader.ReadLine()) != null) + { + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + replaced = line.Replace("DB_Scripts/datafiles/", "DB_Scripts\\\\datafiles\\\\"); + else + replaced = line; + + log.Debug("Line: " + replaced); + + process.StandardInput.WriteLine(replaced); + } } process.StandardInput.Close(); diff --git a/WebGoat/App_Code/VeryWeakRandom.cs b/WebGoat/App_Code/VeryWeakRandom.cs new file mode 100644 index 00000000..ed70a3ce --- /dev/null +++ b/WebGoat/App_Code/VeryWeakRandom.cs @@ -0,0 +1,38 @@ +using System; + +namespace OWASP.WebGoat.NET.App_Code +{ + public class VeryWeakRandom + { + private uint _seed = 7; + private uint _helper = 1; + + public VeryWeakRandom() {} + + public VeryWeakRandom(uint seed) + { + _seed = seed; + } + + public uint Next(uint min, uint max) + { + _seed = Peek(min, max); + _helper++; + + return _seed; + } + + public uint Peek(uint min, uint max) + { + if (min >= max) + throw new Exception("Min must be smaller than max"); + + var seed = _seed + _helper; + + if (seed > max) + seed = min; + + return seed; + } + } +} diff --git a/WebGoat/App_Code/WeakRandom.cs b/WebGoat/App_Code/WeakRandom.cs new file mode 100644 index 00000000..f0b4ae2f --- /dev/null +++ b/WebGoat/App_Code/WeakRandom.cs @@ -0,0 +1,42 @@ +using System; + +namespace OWASP.WebGoat.NET.App_Code +{ + public class WeakRandom + { + private uint _seed = 7; + + public WeakRandom() {} + + public WeakRandom(uint seed) + { + _seed = seed; + } + + public uint Next(uint min, uint max) + { + if (min >= max) + throw new Exception("Min must be smaller than max"); + + unchecked //Just use next number from overflow + { + _seed = _seed * _seed + _seed; + } + + return _seed % (max - min) + min; + } + + public uint Peek(uint min, uint max) + { + if (min >= max) + throw new Exception("Min must be smaller than max"); + + unchecked //Just use next number from overflow + { + var seed = _seed * _seed + _seed; + + return seed % (max - min) + min; + } + } + } +} \ No newline at end of file diff --git a/WebGoat/App_Themes/.DS_Store b/WebGoat/App_Themes/.DS_Store deleted file mode 100644 index 73b840f1..00000000 Binary files a/WebGoat/App_Themes/.DS_Store and /dev/null differ diff --git a/WebGoat/Content/.DS_Store b/WebGoat/Content/.DS_Store deleted file mode 100644 index 5008ddfc..00000000 Binary files a/WebGoat/Content/.DS_Store and /dev/null differ diff --git a/WebGoat/Content/EncryptVSEncode.aspx.cs b/WebGoat/Content/EncryptVSEncode.aspx.cs index 16bdb328..aac8a197 100644 --- a/WebGoat/Content/EncryptVSEncode.aspx.cs +++ b/WebGoat/Content/EncryptVSEncode.aspx.cs @@ -13,54 +13,62 @@ namespace OWASP.WebGoat.NET { public partial class EncryptVSEncode : System.Web.UI.Page { - enum WG_Hash {Sha1=1, Sha256}; - - private string password = "123456"; + public string Password { get; set; } + + enum WG_Hash + { + Sha1=1, + Sha256 + }; + private string hardCodedKey = "key"; protected void Page_Load(object sender, EventArgs e) { - + Password = "123456"; } + protected void btnGO_Click(object sender, EventArgs e) { - //url encoded - //base64 - //sha1 - //encryption with password - - string secret = txtString.Text; - string key = String.IsNullOrEmpty(txtPassword.Text) ? hardCodedKey : txtPassword.Text; - - Table t = new Table(); - t.Width = new Unit("100%"); - + //url encoded + //base64 + //sha1 + //encryption with password + + string secret = txtString.Text; + string key = String.IsNullOrEmpty(txtPassword.Text) ? hardCodedKey : txtPassword.Text; + + Table t = new Table(); + t.Width = new Unit("100%"); + t.Rows.Add(MakeRow("Custom Crypto", CustomCryptoEncrypt(secret))); - t.Rows.Add(MakeRow("URL Encoded:", Server.UrlEncode(secret))); - t.Rows.Add(MakeRow("Base64 Encoded:", Base64(secret))); - t.Rows.Add(MakeRow("SHA1 Hashed:", SHA(secret, WG_Hash.Sha1))); - t.Rows.Add(MakeRow("SHA256 Hashed:", SHA(secret, WG_Hash.Sha256))); - t.Rows.Add(MakeRow("Rijndael Encrypted: ", Encypt(secret, key), Color.LightGreen)); + t.Rows.Add(MakeRow("URL Encoded:", Server.UrlEncode(secret))); + t.Rows.Add(MakeRow("Base64 Encoded:", Base64(secret))); + t.Rows.Add(MakeRow("SHA1 Hashed:", SHA(secret, WG_Hash.Sha1))); + t.Rows.Add(MakeRow("SHA256 Hashed:", SHA(secret, WG_Hash.Sha256))); + t.Rows.Add(MakeRow("Rijndael Encrypted: ", Encypt(secret, key), Color.LightGreen)); + + ContentPlaceHolder cph = (ContentPlaceHolder)this.Master.FindControl("BodyContentPlaceholder"); + cph.Controls.Add(new LiteralControl("
")); + cph.Controls.Add(t); - ContentPlaceHolder cph = (ContentPlaceHolder)this.Master.FindControl("BodyContentPlaceholder"); - cph.Controls.Add(new LiteralControl("")); - cph.Controls.Add(t); - } + private TableRow MakeRow(string label, string val) { - TableRow row = new TableRow(); - - TableCell t1 = new TableCell(); - t1.Text = label; - row.Cells.Add(t1); - - TableCell t2 = new TableCell(); - t2.Text = val; - row.Cells.Add(t2); - return row; + TableRow row = new TableRow(); + + TableCell t1 = new TableCell(); + t1.Text = label; + row.Cells.Add(t1); + + TableCell t2 = new TableCell(); + t2.Text = val; + row.Cells.Add(t2); + return row; } + private TableRow MakeRow(string label, string val, Color color) { TableRow row = new TableRow(); @@ -76,29 +84,30 @@ private TableRow MakeRow(string label, string val, Color color) return row; } - private string Base64(string s) - { - byte[] bytes = System.Text.ASCIIEncoding.ASCII.GetBytes(s); - return System.Convert.ToBase64String(bytes); - } - - private string SHA(string s, WG_Hash hash) - { - byte[] bytes = System.Text.ASCIIEncoding.ASCII.GetBytes(s); - byte[] result; - HashAlgorithm sha; - switch(hash){ - case WG_Hash.Sha1: - sha = new SHA1Managed(); - break; - case WG_Hash.Sha256: - sha = new SHA256Managed(); - break; - } - result = sha.ComputeHash(bytes); - return System.Convert.ToBase64String(result); - } + { + byte[] bytes = System.Text.ASCIIEncoding.ASCII.GetBytes(s); + return System.Convert.ToBase64String(bytes); + } + + private string SHA(string s, WG_Hash hash) + { + byte[] bytes = System.Text.ASCIIEncoding.ASCII.GetBytes(s); + byte[] result; + HashAlgorithm sha = null; + + switch (hash) + { + case WG_Hash.Sha1: + sha = new SHA1Managed(); + break; + case WG_Hash.Sha256: + sha = new SHA256Managed(); + break; + } + result = sha.ComputeHash(bytes); + return System.Convert.ToBase64String(result); + } private string Encypt(string s, string key) { @@ -112,13 +121,13 @@ private string CustomCryptoEncrypt(String s) // needs work but you get the point for (int i = 0; i < bytes.Length; i++) { - if (i % 2 == 0) + if (i % 2 == 0) { - bytes[i] = (byte) (bytes[i] | 2); + bytes[i] = (byte)(bytes[i] | 2); } else { - bytes[i] = (byte) (bytes[i] & 2); + bytes[i] = (byte)(bytes[i] & 2); } } diff --git a/WebGoat/Content/HeaderInjection.aspx.cs b/WebGoat/Content/HeaderInjection.aspx.cs index ed691602..47b665ea 100644 --- a/WebGoat/Content/HeaderInjection.aspx.cs +++ b/WebGoat/Content/HeaderInjection.aspx.cs @@ -5,6 +5,7 @@ using System.Web.UI; using System.Web.UI.WebControls; using System.Collections; +using System.Collections.Specialized; namespace OWASP.WebGoat.NET { @@ -12,8 +13,24 @@ public partial class HeaderInjection : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { + if (Request.QueryString["Cookie"] != null) + { + HttpCookie cookie = new HttpCookie("UserAddedCookie"); + cookie.Value = Request.QueryString["Cookie"]; + + Response.Cookies.Add(cookie); + } + else if (Request.QueryString["Header"] != null) + { + NameValueCollection newHeader = new NameValueCollection(); + newHeader.Add("newHeader", Request.QueryString["Header"]); + Response.Headers.Add(newHeader); + } + + + //Headers - lblHeaders.Text = Request.Headers.ToString().Replace("&", "A weak number generator can be the source of a system break-in, as it is used in many important situations + such as password salts, SSL handshakes etc.
+ +In the following example, try to predict the next number in the sequence:
+ +The next number is:
In this lesson we'll take a look at .NET's unsafe block and how it can be exploited through user input. + When typing a string in the textbox below, the server will read it and compute its reverse. Try to exploit the + server by typing in a 'bad' input.
+ +Result: