Fortify Sql Injection for Oracle - sql

When I scan my project with fortify static code analyzer it finds Sql Injection results.
At Recommendations window fortify says : "The root cause of a SQL injection vulnerability is the ability of an attacker to change context in the SQL query, causing a value that the programmer intended to be interpreted as data to be interpreted as a command instead. When a SQL query is constructed, the programmer knows what should be interpreted as part of the command and what should be interpreted as data. Parameterized SQL statements can enforce this behavior by disallowing data-directed context changes and preventing nearly all SQL injection attacks. Parameterized SQL statements are constructed using strings of regular SQL, but when user-supplied data needs to be included, they create bind parameters, which are placeholders for data that is subsequently inserted. Bind parameters allow the program to explicitly specify to the database what should be treated as a command and what should be treated as data. When the program is ready to execute a statement, it specifies to the database the runtime values to use for the value of each of the bind parameters, without the risk of the data being interpreted as commands."
Look my code please. I am already using Parameterized SQL statements. So what is the problem? What am I missing?
Summary of my code;
Dim stateid As String = HttpContext.Current.Request.QueryString.Item("stateid"))
Dim colArgs As COLLECTIONS.ParamterCollection
colArgs = New COLLECTIONS.ParamterCollection
colArgs.Add(DATA.DataPreps.PrepStringForDB(stateid ))
Dim sSQL As String = "SELECT * FROM STATE WHERE N_STATE_ID = :P"
PrepareSQL(sSQL, colArgs, objDBConfigObject)
Dim objCommand As OracleCommand = new OracleCommand(sSQL, connection)
objCommand.CommandTimeout = m_nConnectionTimeout
For Each objArgument In colArgs
objParam = New Oracle.DataAccess.Client.OracleParameter(":P" & CStr(nInArgIndex), objArgument.enOracleType)
objParam.Value = objArgument.varValue
objCommand.Parameters.Add(objParam)
nInArgIndex += 1
objArgument = Nothing
objParam = Nothing
Next
objCommand.CommandType = CommandType.Text
objDataAdapter = New Oracle.DataAccess.Client.OracleDataAdapter(objCommand)
nRecordsAffected = objDataAdapter.Fill(objDataSet)

You can use DBMS_ASSERT to validate all user inputs.Read this
http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_assert.htm#BABIEIFE

Parameterized queries are not a magic bullet. I would add a few things:
objParam.OracleDbType = Oracle.DataAccess.Client.OracleDbType.VarChar (this is the db column data type)
Ensure you are doing input validation to defang any dangerous SQLi characters.
Perform some sanity checking on arguments being passed. For example, how many max characters should the string stateid be?

Related

How do I add parameters to my queries when using clr/c++ for multiple variables

I want to be able to add parameters to my queries to make my statements less vunerable to sql injections
My code (Key parts are surrounded by ** as I cannot make code bold)
OleDbConnection^ existingSqlConnection = nullptr;
existingSqlConnection = gcnew OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0;" +
"Data Source =" + "myDatabaseV3.accdb");
**String^ sqlText = "SELECT * FROM #tableName WHERE #fieldName = #fieldEntityName";
OleDbCommand^ dbCommand = gcnew OleDbCommand(sqlText, existingSqlConnection);
OleDbParameterCollection^ paramCollection = dbCommand->Parameters;
dbCommand->Parameters->Add(gcnew OleDbParameter("#tableName", tableName->ToString()));
dbCommand->Parameters->AddWithValue("#fieldName", field);**
dbCommand->Parameters->AddWithValue("#fieldEntityName", fieldEntity);
**Console::WriteLine(dbCommand->CommandText);
Console::WriteLine(paramCollection->Count);**
existingSqlConnection->Open();
OleDbDataReader^ reader = dbCommand->ExecuteReader(System::Data::CommandBehavior::CloseConnection);
return reader;
The output for this is
SELECT * FROM #tableName WHERE #fieldName = #fieldEntityName
3
Which clearly shows that there are 3 parameters but they are not being added to my query which is the problem I want to be solved
This is not how parameters work. They are not replacement values for text templates. Parameters are a mechanism to pass in a value to the variable in the query, just like passing a parameter to a stored procedure will pass that value in to be used as a variable in the query.
Along these lines, parameters can only be used where variables can be used in queries. And, variables cannot be used for object names, which is why people resort to using SQL Injection when the table and/or column name(s) need to change. In your example code:
#tableName could never be a variable in a query, hence it cannot be a parameter
#fieldName could never be a variable in a query, hence it cannot be a parameter
#fieldEntityName if it is supposed to be a value and not a column name, can be a parameter, in which case it will remain as #fieldEntityName in the query, and it will have a value of fieldEntity.
Please see the second option of my answer on your related question for how to prevent SQL Injection (short answer: sanitize inputs).
Also, using AddWithValue() is a bad practice. Create the parameter with the intended max size, then give that a value, and finally add it to the parameters collection. You do not want it to auto-detect the max size for the parameter as it will use the first value it gets, and any subsequent value that is longer will be silently truncated.

How do I prevent my SQL statements from SQL injection when using CLR/C++ with multiple variables?

I am having a major problem where I do not know how to prevent SQL injection when writing SQL statements in CLR/C++
Below is the code
String^ sqlstr = "SELECT * FROM ";
sqlstr += tableName + " WHERE " + field + " = " + fieldEntity;
I need to be able to input correct SQL Injection preventions to this statement.
Background code
class database
{
protected:
string fieldEntity;
string tableName;
string field;
...
____
OleDbDataReader^ openData(String^ fieldEntity, String^ field, String^ tableName)
{
String^ sqlstr = "SELECT * FROM ";
sqlstr += tableName + " WHERE " + field + " = " + fieldEntity;
...
___
OleDbDataReader^ reader2 = testData.openData(effectID, "effectID", "effectOnUser");
while (reader2->Read())
{
Object^ dHealthptr = reader2["effectOnHealth"];
Object^ dTirednessptr = reader2["effectOnTiredness"];
Object^ dHappinessptr = reader2["effectOnHappiness"];
...
There are two ways to prevent SQL Injection and the environment of SQLCLR does not change this:
The preferred mechanism is by using parameterized queries. Different languages and libraries go about this in different ways, but at the very least you should be able to use prepared statements. Please note that this does not apply to scenarios that could not accept a variable, such as with tableName and field in your code.
Please see:
Issuing a Parameterized Query
Using Stored Procedures
Sanitize the inputs:
Bare minimum, and by far the most common, requirement is to escape single quotes by doubling them (i.e. ' becomes '')
Additionally (below is a quote from a related answer of mine on DBA.StackExchange):
There is a lesser known type of attack in which the attacker tries to fill up the input field with apostrophes such that a string inside of the Stored Procedure that would be used to construct the Dynamic SQL but which is declared too small can't fit everything and pushes out the ending apostrophe and somehow ends up with the correct number of apostrophes so as to no longer be "escaped" within the string. This is called SQL Truncation and was talked about in an MSDN magazine article titled "New SQL Truncation Attacks And How To Avoid Them", by Bala Neerumalla, but the article is no longer online. The issue containing this article — the November, 2006 edition of MSDN Magazine — is only available as a Windows Help file (in .chm format). If you download it, it might not open due to default security settings. If this happens, then right-click on the MSDNMagazineNovember2006en-us.chm file and select "Properties". In one of those tabs there will be an option for "Trust this type of file" (or something like that) which needs to be checked / enabled. Click the "OK" button and then try opening the .chm file again.
So, be sure to properly size the string input parameters. You don't need VARCHAR(500) for a column that is declared as VARCHAR(25). Please see my answer on DBA.StackExchange for more details and examples:
Why does SQL Injection not happen on this query inside a stored procedure?
For tableName and field variables, those are being used as SQL identifiers in your query. You can't use either common method of query parameters or escaping. You just have to make sure to whitelist the values for those variables. In other words, check them against known identifiers of tables and columns in your database.
For the other variable fieldEntity, I suppose this should be used like a constant value in your SQL query. You can protect this from SQL injection by using a query parameter.
I don't know CLR, but there are lots of examples of using SQL query parameters in C++ or C#.
https://owasp.org/www-project-cheat-sheets/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html

Sql exception was unhandled

I have this code in C# (Visual Studio 2012), it was retriving the data perfectly before now it randomly says 'Sql exception was unhandled' 'Incorrect syntax near the keyword 'FROM'
It says it from the line that reads.... ads.Fill(dt)
This is my code....
SqlConnection ssl = new SqlConnection();
ssl.ConnectionString = #"Data Source=Jhon;Initial Catalog=Training;Integrated Security=True";
ssl.Open();
SqlDataAdapter ads= new SqlDataAdapter("SELECT order, price, FROM table WHERE order < 100", ssl);
DataTable dt = new DataTable();
ads.Fill(dt);
dataGridView1.DataSource = dt;
Your syntax is wrong due to the comma after price. Change your query to SELECT order, price FROM ... to resolve the issue.
EDIT: As a general good practice, you should wrap this code in a try/catch block and properly handle the exceptions e.g. by logging to a file. Also, as another answer points out, you should avoid using reserved words for your own tables/columns, and if you do use them, you should escape them by putting them inside square brackets e.g. [table]
Is your table really named "table"? That seems a rather poor choice. I would think that that would be a reserved word so would need to be escaped, i.e. [table]. The best option is to not use reserved words as identifiers though.

How can this SQL query code be broken/exploited by user input? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Can I protect against SQL Injection by escaping single-quote and surrounding user input with single-quotes?
We have a legacy app that doesn't do queries using positional parameters, and there's SQL everywhere. It was decided (before I started here) that since user input can contain apostrophes, every string input should be manually escaped for those apostrophes.
Here is the essential original code (not written by me), translated into C# for easier consumption:
private string _Escape(string input)
{
return input.Replace("'", "''");
}
private bool _IsValidLogin(string userName, string password)
{
string sql =
string.Format
(
#"SELECT COUNT(*) FROM UserAccounts
WHERE UserName = '{0}' AND Password = '{1}'",
_Escape(userName),
_Escape(password)
);
// ...
}
This really seems like it can be broken in some way, but I'm at a loss as to how it could be exploited by user input. Assume user input is unfiltered until it hits _IsValidLogin, and forget that passwords appear to be stored in plain text.
The solution to shore it up for good is obvious -- use positional parameters -- but I need some ammunition to demonstrate to management why/how this code is insecure so time/$ can be allocated for it to get fixed.
Note: I'm assuming this can be broken, but that may not actually be the case. I'm not a SQL superstar.
Note 2: I've expressed this question as database-agnostic, but if you can exploit this code for a certain engine, I welcome your contribution.
It could be exlpoited by backslashes.
password = foo\' OR 1=1 --
becomes:
password = foo\'' OR 1=1 --
the query:
"SELECT COUNT(*) FROM UserAccounts
WHERE UserName = '{0}' AND Password = 'foo\'' OR 1=1 --'"
-- Is the comment mark in this example.
The solution assumes the program only filters (duplicates) apostrophes.
Well, I can't see a way it's vulnerable. So, let's argue a different reason why it should be changed --- it's rather ineffiecent. In MSSQL (and, I think, most other high end SQL servers), queries are parsed, and execution plan is devised, and then the query and plan are stored. If an exact copy of the query is requested again, the saved execution plan is used. Parameter don't affect this, so if you use parameters, it will reuse the plans; if you embed the text, it never will.

SQL CASE Statement Versus Conditional Statements In Programming Language

I'm going through some old stored procedures at work and constantly come across
CASE MyColumn WHEN 'Y' THEN 'Yes' WHEN 'N' THEN 'No' ELSE 'Unknown' END
It gets even worse when this is tied not to a word, but instead a colour.
CASE MyColumn WHEN 'Y' THEN 'style="background-color:pink"' ELSE '' END
The reason this was done was for older ASP 1 pages where everything had to be done inline, but as it's such a large system it's impossible to keep up with updating all the pages.
Can anyone give any valid evidence that using a SQL query for conditional statements surpasses that in other languages such as C# or Java? Is this good practice for speed? Should the plain value be returned and the presentation layer decide what should be done?
When speed is of the essence, the SQL case statements might even be the fastest (I'll run a test) but for maintainability, returning the plain values to the presentation layer (or some business layer thingy) is the best option.
[update] ran some quick and dirty tests (code below) and found the C# code variant slightly faster than the SQL case variant. Conclusion: returning the 'raw' data and manipulating it in the presentation layer is both quicker and more maintainable.
-Edoode
I retrieved 196288 rows with queries below.
StringBuilder result = new StringBuilder();
using (SqlConnection conn = new SqlConnection(Settings.Default.Conn))
{
conn.Open();
string cmd = "select [state], case [state] when 'ca' then 'california' else [state] end from member";
SqlCommand command = new SqlCommand(cmd, conn);
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
while (reader.Read())
{
result.AppendLine(reader.GetString(1));
}
}
}
C# variant:
StringBuilder result = new StringBuilder();
using (SqlConnection conn = new SqlConnection(Settings.Default.Conn))
{
conn.Open();
string cmd = "select [state] from member";
SqlCommand command = new SqlCommand(cmd, conn);
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
while (reader.Read())
{
result.AppendLine(reader.GetString(0) == "ca" ? "california" : reader.GetString(0));
}
}
}
I would be concerned putting this kind of logic in SQL statements. What happens if your database engine changes? Will you have to update every SQL statement to Oracle SQL? What if the repository itself changes, when you move to a message bus, XML files, or web service call...
It looks like you're storing display information. In which case, it's part of the data model. Let the controller (in a typical MVC pattern) perform the conditional logic. The presentation layer doesn't need to know what happened and the repository can be happy just holding data.
Can anyone give any valid evidence that using a SQL query for conditional statements surpasses that in other languages such as C# or Java? Is this good practice for speed? Should the plain value be returned and the presentation layer decide what should be done?
Sometimes (sometimes) it just helps to avoid extra coding in the presentation layer.
As a rule, if both database and presentation are developed by one person, it doesn't matter. Problems begin when the work becames shared. In this case you, obviously, need a well stated contract on what the database emits and what ASP accepts.
Sure, CSS belongs to presentation layer's domain and it should be parsed by ASP rather than hardcoded in SQL.
That is old style code, I don't believe people code like this anymore (we use CSS now)
Your are probably looking at some soon to be legacy stuff which will be rewritten or abandoned
In terms of SQL Performance, if you are only returning a few rows (or one by the looks of it), this has minimal impact as the WHERE part of the statement is evaluated before the case (The case is only performed on rows which match the where).
From a best practises point of view, display information should not really be determined in SQL. Perhaps returning a theme type, but certainly not discreet style information.
Agree 100% on refactoring to put display decisions up to the presentation layer (or as near as possible).
CASE ... END in SQL still can have its uses, though, for example, say I want to calculate the percentage of the total value of all orders that is for domestic customers. I think I'd be happy with
SELECT
SUM(CASE domestic WHEN 'Y' THEN order_value ELSE 0 END) / SUM(order_value) AS pctg
FROM orders
as a query. Unless someone knows better, of course.