Allowed approaches for addressing SQL Injection in Fortify - sql-injection

I have the following code for implementing a drop down menu. The user selects two values, and, based on the input, the query selects the relevant columns to be shown to the user:
String sql = "SELECT :first, :second from <table>";
sql = sql.replace(":first", <first_user_input>);
sql = sql.replace(":second", <second_user_input>);
Now, Fortify catches these lines as allowing SQL Injection. My question is, will Fortify accept a RegEx based whitelisting approach as a solution?
I was thinking of adopting the following approach:
if(isValidSQL(<first_user_input>) && isValidSQL(<second_user_input>))
{
sql = sql.replace(...);
}
else
throw new IllegalSQLInputException
and
public boolean isValidSQL(String param)
{
Pattern p = Pattern.compile([[A-Z]_]+); //RegEx for matching column names like "FIRST_NAME", "LNAME" etc. but NOT "DROP<space>TABLE"
Matcher m = p.matcher(param);
return m.matches(param);
}
So, would Fortify accept this as a valid whitelisting method? If Fortify works on the below grammar:
valid_sql := <immutable_string_literal> //Something like "SELECT * FROM <table> WHERE x = ?" or //SELECT * FROM <table>
valid_sql := valid_sql + valid_sql //"SELECT * FROM <table>" + "WHERE x = ?"
then I don't suppose RegEx-based whitelisting would work. In that case, only this example would work, since it appends strings that are fixed at run time. I would not prefer this approach since it would result in a massive amount of switch-case statements.
Thank You

So, after trying the above mentioned approach, I found that Fortify is still catching the line as a potential threat. However, after reading about how Fortify works, I'm not sure if the "strictness" comes from Fortify itself, or the corporate rules defined in the XML configuration file for the same. I think that, if one's corporate rules allow regular expression-based whitelisting to work, then that should do the trick.

Related

How do you pass variables into Mirth Database Reader Channels for SQL expressions?

I can't find any documentation on how to manager parameters into Database Reader SQL statements?
-> this is a simplified example: I am not looking for scripting a variable to "yesterday" which is easy to express in SQL. That's not the point. I have have more complex variables in the actual SQL statement I'm trying to martial in. I just want to know how to get variables into the SQL form if possible.
-> "you can just do that in JavaScript": the actual queries I need to run are about a hundred lines long, I don't want to maintain and debug a query build by concatenating strings and then deal with escaping 'quoted' things everywhere in the SQL. I really prefer to maintain an actual SQL statement that copy/paste works in a SQL IDE.
How do we pass in parameters into the SQL block at the bottom of the Database Reader form?
SELECT patientsex, visitnumber, samplereceived_dt, sr_d, sr_t, orderpriority, orderrequestcode, orderrequestname
FROM mydata.somedata
WHERE sr_d = (${DateUtil.getCurrentDate('yyyyMMdd')})::integer;
JavaScript is the feasible way to achieve this, with SQL statements defined inside Mirth connect or have the SQL statements bundled in a stored procedure then use SQL server's Exec command within Mirth connect to call the stored procedure while passing the parameters (interestingly using JavaScript).
For example
var dbConn;
try {
dbConn = DatabaseConnectionFactory.createDatabaseConnection('','DB:Port\instance','user','pass');
var paramList = new java.util.ArrayList();
paramList.add($('patientId'));
paramList.add($('lastName'));
paramList.add($('firstName'));
var result = dbConn.executeCachedQuery("SELECT * FROM patients WHERE patientid = ? AND lastname = ? AND firstname = ?) ",paramList);
while (result.next()) {
//you can reference by column index like so...
//result.getString(1);
}
} finally {
if (dbConn) {
dbConn.close();
}
}
Should be noted that the parameters you add to the list MUST be in order.

EF Core raw query with Like clause

I want to create queries using EF FromSqlInterpolated or FromSqlRaw that allows me to use Like clauses, but I don't know what is the right way to do it without opening the application to SqlInjection attacks.
One first approach has took me to the following code
var results = _context.Categories.FromSqlInterpolated(
$"Select * from Category where name like {"%" + partialName + "%"}");
First test worked fine, it returns results when providing expected strings, and returns nothing when i provide something like ';select * from Category Where name='Notes'--%';
Still I don't know much about SqlInjection, at least not enough to feel safe with the query shown before.
Does someone know if the query is safe, or if there is a right way to do it?
Thanks
From this document
The FromSqlInterpolated and ExecuteSqlInterpolated methods allow using
string interpolation syntax in a way that protects against SQL injection attacks.
var results = _context.Categories.FromSqlInterpolated(
$"Select * from Category where name like {"%" + partialName + "%"}");
Or you can also change your query to Linq-to-Entity like this way
var results = _context.Categories.Where(p => p.name.Contains(partialName ));

How to insert similar value into multiple locations of a psycopg2 query statement using dict? [duplicate]

I have a Python script that runs a pgSQL file through SQLAlchemy's connection.execute function. Here's the block of code in Python:
results = pg_conn.execute(sql_cmd, beg_date = datetime.date(2015,4,1), end_date = datetime.date(2015,4,30))
And here's one of the areas where the variable gets inputted in my SQL:
WHERE
( dv.date >= %(beg_date)s AND
dv.date <= %(end_date)s)
When I run this, I get a cryptic python error:
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) argument formats can't be mixed
…followed by a huge dump of the offending SQL query. I've run this exact code with the same variable convention before. Why isn't it working this time?
I encountered a similar issue as Nikhil. I have a query with LIKE clauses which worked until I modified it to include a bind variable, at which point I received the following error:
DatabaseError: Execution failed on sql '...': argument formats can't be mixed
The solution is not to give up on the LIKE clause. That would be pretty crazy if psycopg2 simply didn't permit LIKE clauses. Rather, we can escape the literal % with %%. For example, the following query:
SELECT *
FROM people
WHERE start_date > %(beg_date)s
AND name LIKE 'John%';
would need to be modified to:
SELECT *
FROM people
WHERE start_date > %(beg_date)s
AND name LIKE 'John%%';
More details in the pscopg2 docs: http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries
As it turned out, I had used a SQL LIKE operator in the new SQL query, and the % operand was messing with Python's escaping capability. For instance:
dv.device LIKE 'iPhone%' or
dv.device LIKE '%Phone'
Another answer offered a way to un-escape and re-escape, which I felt would add unnecessary complexity to otherwise simple code. Instead, I used pgSQL's ability to handle regex to modify the SQL query itself. This changed the above portion of the query to:
dv.device ~ E'iPhone.*' or
dv.device ~ E'.*Phone$'
So for others: you may need to change your LIKE operators to regex '~' to get it to work. Just remember that it'll be WAY slower for large queries. (More info here.)
For me it's turn out I have % in sql comment
/* Any future change in the testing size will not require
a change here... even if we do a 100% test
*/
This works fine:
/* Any future change in the testing size will not require
a change here... even if we do a 100pct test
*/

Is this kind of code prone to SQL injection?

I am doing a project for my school and I am task to debug all of the issues found using the application call HPE Fortify. The report generated by the application only indicates the code below prone to SQL injection:
String sql = " select Distinct p1.desc1,p2.desc2 from parameter p1"
+" inner join parameter p2"
+" on p1.ParaCode1='CR_DERIVE' and p1.ParaCode2=p2.Desc2"
+" inner join parameter p3"
+ " on p2.ParaCode3=p3.ParaCode1 and p3.ParaCode3=p2.Desc2"
+" where p2.paracode1='ATTRIBUTE'"
+ " and p2.ParaCode2='" + ddl_attribute.SelectedValue + "'";
But not the codes below:
strSQL = "SELECT Paracode2 FROM Parameter WHERE Paracode1 = 'PROGMGR' AND Desc1 = '" + login + "' AND Status = 'A' ";
I would like to know the reason why as I am unclear regarding SQL injection and I am new to this. Thanks for the response
You're concatenating some application variables into your SQL query string, so the safety depends on how those variables' values were set. Did they come from some untrusted input? Or were they set from some safe application data?
If HPE Fortify has analyzed your code and knows how your login variable was assigned its value, it may be able to tell that it's safe to use in an SQL expression. Whereas it may not be able to make that conclusion about the SelectedValue variable, so it assumes it's unsafe and therefore could cause an SQL vulnerability.
The Perl language does something similar, without the use of a tool like HPE Fortify. Every Perl variable is either "tainted" or "untainted" depending on where it got its value. So you can tell whether a variable is safe to use in SQL, or in eval() or other possible code-injection situations. It's a pity more languages don't support something similar.
But I agree with other commenters that you should learn to use query parameters. It's easy and it's safe. And you can stop getting eyestrain figuring out if you've balanced your quotes-within-quotes correctly.
Your code sample looks like it might be Java. Here's an example in Java:
strSQL = "SELECT Paracode2 FROM Parameter"
+ " WHERE Paracode1 = 'PROGMGR' AND Desc1 = ? AND Status = 'A' ";
Notice the ? placeholder for the parameter has no single-quotes around it within the SQL string. You must not put SQL quotes around the placeholder.
PreparedStatement stmt = con.PreparedStatement(sql);
stmt.setString(1, login);
ResultSet rs = stmt.executeQuery();
For more information to help you understand SQL injection, you might like my presentation SQL Injection Myths and Fallacies, or the video of me delivering that talk: https://www.youtube.com/watch?v=VldxqTejybk

Subsonic - query with optional parameters

Using C# 3.5 through VS 2008 and subsonic 2.2.
Anyone know if it's possible to create a subsonic query that essentially has an 'IF' in the middle of it, depending on whether a passed parameter was, for example, greater than zero.
For example, a delete method that has two passed parameters - A and B.
I want something like (pseudo code)
DELETE from Products
Where productId = A
if(B > 0)
{
AND ProductAttributeId = B
}
Obviously it wouldn't need the actual 'IF' clause in there but that's the essence of what I'm trying to do with subsonic. I know I can just have two different queries depending on whether the parameter is there or not but I was wondering if there's a cleaner way of doing it.
Thanks.
That's how I usually do it - it's not two queries, but one SqlQuery with optionally added constraints:
SqlSquery q = DAL.DB.Delete()
.From<DAL.Product()
.Where(DAL.Product.ProductIdColumn).IsEqualTo(A);
if (B > 0)
{
q.And(DAL.Product.ProductAttributeIdColumn).IsEqualTo(B);
}
q.Execute();
There may be a typo, I can't test this right now.