zap tool showing security vulnerability but we can't find those vulnerability in our source code? - sql-injection

vulnerability showing as:-
SQL Injection - SQLite
Method: GET
Parameter: query
Attack: ' | case randomblob(10000000) when not null then "" else "" end --
Evidence: The query time is controllable using parameter value [' | case randomblob(10000000) when not null then "" else "" end --], which caused the request to take [542] milliseconds, parameter value [' | case randomblob(100000000) when not null then "" else "" end --], which caused the request to take [900] milliseconds, when the original unmodified query with value [query] took [167] milliseconds.
SQL Injection - Oracle - Time Based
Method: GET
Parameter: query
Attack: field: [query], value [query and exists (SELECT UTL_INADDR.get_host_name('10.0.0.1') from dual union SELECT UTL_INADDR.get_host_name('10.0.0.2') from dual union SELECT UTL_INADDR.get_host_name('10.0.0.3') from dual union SELECT UTL_INADDR.get_host_name('10.0.0.4') from dual union SELECT UTL_INADDR.get_host_name('10.0.0.5') from dual) -- ]
Advanced SQL Injection - Oracle AND time-based blind
Method: GET
Parameter: query
Attack: query AND 2972=DBMS_PIPE.RECEIVE_MESSAGE(CHR(113)||CHR(65)||CHR(80)||CHR(114),5)
SQL Injection - MsSQL
Method: GET
Parameter: query
Attack: query WAITFOR DELAY '0:0:15' --
SQL Injection - Hypersonic SQL - Time Based
Method: GET
Parameter: query
Attack: field: [query], value ["; select "java.lang.Thread.sleep"(15000) from INFORMATION_SCHEMA.SYSTEM_COLUMNS where TABLE_NAME = 'SYSTEM_COLUMNS' and COLUMN_NAME = 'TABLE_NAME' -- ]
SQL Injection - PostgreSQL - Time Based
Method: GET
Parameter: query
Attack: field: [query], value [case when cast(pg_sleep(15) as varchar) > '' then 0 else 1 end]
SQL Injection - MySQL
Method: GET
Parameter: query
Attack: query / sleep(15)
Advanced SQL Injection - PostgreSQL > 8.1 stacked queries (comment)
Method: GET
Parameter: query
Attack: query;SELECT PG_SLEEP(5)--
Advanced SQL Injection - Oracle stacked queries (DBMS_PIPE.RECEIVE_MESSAGE - comment)
Method: GET
Parameter: query
Attack: Feb 2018;SELECT DBMS_PIPE.RECEIVE_MESSAGE(CHR(105)||CHR(122)||CHR(102)||CHR(108),5) FROM DUAL--
Advanced SQL Injection - Microsoft SQL Server/Sybase time-based blind.
Method: GET
Parameter: query
Attack: query) WAITFOR DELAY CHAR(48)+CHAR(58)+CHAR(48)+CHAR(58)+CHAR(91)+CHAR(83)+CHAR(76)+CHAR(69)+CHAR(69)+CHAR(80)+CHAR(84)+CHAR(73)+CHAR(77)+CHAR(69)+CHAR(93) AND (1972=1972
All of our source code following the given Example:-
public interface UserRepository extends JpaRepository<User, Long> {
#Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
User findByLastnameOrFirstname(#Param("lastname") String lastname,
#Param("firstname") String firstname);
}

Pick one of the timebased attacks and rerun it - you can do that by rightclicking on the alert in ZAP and selecting 'Open/Resend with Request Editor'.
Check to see how long the request took (its shown at the bottom of the dialog) - was it the same time (or a bit more) than the delay that the attack is using?
If so try increasing the delay and resending - is it now taking the longer period of time?
If the time is being affected by the time specified in the attack then you will have an SQL injection vulnerability.
Why havnt I said anything about the source code you posted? Thats because I have no idea if thats all of the relevant code :)
You might also want to try using a static analyser on your code - it will probably show loads of false positives, but you can just focus on any SQL injection vulnerabilities it reports.

Related

Is it possible to have hibernate generate update from values statements for postgresql?

Given a postgresql table
Table "public.test"
Column | Type | Modifiers
----------+-----------------------------+-----------
id | integer | not null
info | text |
And the following values :
# select * from test;
id | info
----+--------------
3 | value3
4 | value4
5 | value5
As you may know with postgresql you can use this kind of statements to update multiples rows with different values :
update test set info=tmp.info from (values (3,'newvalue3'),(4,'newvalue4'),(5,'newvalue5')) as tmp (id,info) where test.id=tmp.id;
And it results in the table being updated in a single queries to :
# select * from test;
id | info
----+--------------
3 | newvalue3
4 | newvalue4
5 | newvalue5
I have been looking around everywhere as to how to make hibernate generate this kind of statements for update queries. I know how to make it work for insert queries (with reWriteBatchedInserts jdbc option and hibernate batch config options).
But is it possible for update queries or do I have to write the native query myself ?
No matter what I do, hibernate always sends separate update queries to the database (I'm looking to the postgresql server statements logs for this affirmation).
2020-06-18 08:19:48.895 UTC [1642] LOG: execute S_6: BEGIN
2020-06-18 08:19:48.895 UTC [1642] LOG: execute S_8: update test set info = $1 where id = $2
2020-06-18 08:19:48.895 UTC [1642] DETAIL: parameters: $1 = 'newvalue3', $2 = '3'
2020-06-18 08:19:48.896 UTC [1642] LOG: execute S_8: update test set info = $1 where id = $2
2020-06-18 08:19:48.896 UTC [1642] DETAIL: parameters: $1 = 'newvalue4', $2 = '4'
2020-06-18 08:19:48.896 UTC [1642] LOG: execute S_8: update test set info = $1 where id = $2
2020-06-18 08:19:48.896 UTC [1642] DETAIL: parameters: $1 = 'newvalue4', $2 = '5'
2020-06-18 08:19:48.896 UTC [1642] LOG: execute S_1: COMMIT
I always find it many times faster to issue a single massive update query than many separate update targeting single rows. With many seperate update queries, even though they are sent in a batch by the jdbc driver, they still need to be processed sequentially by the server, so it is not as efficient as a single update query targeting multiples rows. So if anyone has a solution that wouldn't involve writing native queries for my entities, I would be very glad !
Update
To further refine my question I want to add a clarification. I'm looking for a solution that wouldn't abandon Hibernate dirty checking feature for entities updates. I'm trying to avoid to write batch update queries by hand for the general case of having to updating a few basic fields with different values on an entity list. I'm currently looking into the SPI of hibernate to see it if it's doable. org.hibernate.engine.jdbc.batch.spi.Batch seems to be the proper place but I'm not quite sure yet because I've never done anything with hibernate SPI). Any insights would be welcomed !
You can use Blaze-Persistence for this which is a query builder on top of JPA which supports many of the advanced DBMS features on top of the JPA model.
It does not yet support the FROM clause in DML, but that is about to land in the next release: https://github.com/Blazebit/blaze-persistence/issues/693
Meanwhile you could use CTEs for this. First you need to define a CTE entity(a concept of Blaze-Persistence):
#CTE
#Entity
public class InfoCte {
#Id Integer id;
String info;
}
I'm assuming your entity model looks roughly like this
#Entity
public class Test {
#Id Integer id;
String info;
}
Then you can use Blaze-Persistence like this:
criteriaBuilderFactory.update(entityManager, Test.class, "test")
.with(InfoCte.class, false)
.fromValues(Test.class, "newInfos", newInfosCollection)
.bind("id").select("newInfos.id")
.bind("info").select("newInfos.info")
.end()
.set("info")
.from(InfoCte.class, "cte")
.select("cte.info")
.where("cte.id").eqExpression("test.id")
.end()
.whereExists()
.from(InfoCte.class, "cte")
.where("cte.id").eqExpression("test.id")
.end()
.executeUpdate();
This will create an SQL query similar to the following
WITH InfoCte(id, info) AS(
SELECT t.id, t.info
FROM (VALUES(1, 'newValue', ...)) t(id, info)
)
UPDATE test
SET info = (SELECT cte.info FROM InfoCte cte WHERE cte.id = test.id)
WHERE EXISTS (SELECT 1 FROM InfoCte cte WHERE cte.id = test.id)

How to change Postgres JDBC driver properties to change return class on count function?

I am running a Jasper report (via an jrxml), I am connecting / reading from a Postgres database.
The Sql returns a value from a count function, this then causes java.lang.ClassCastException when writing this value to the Jasper report (via an xml), can I amend the JDBC driver properties to handle this (rather than amend the sql).
The line in the SQL that caused the error was
COALESCE(B.GP_COUNT,0) as GP_COUNT
If I amend the line that populates GP_COUNT using a CAST statement then this works OK in the xml:-
CAST(COUNT(DISTINCT PD_CDE) AS INT4) AS GP_COUNT
I am looking for a solution that avoids changes to the xml’s & jrxml’s (as we have hundreds of reports to convert to Postgres from DB2)
Any help appreciated, I am not a java person so I apologise in advance.
The PostgreSQL JDBC Driver does not return a string, but a BIGINT as result of the count aggregate function.
This Java code:
Class.forName("org.postgresql.Driver");
java.sql.Connection conn = java.sql.DriverManager.getConnection(
"jdbc:postgresql://127.0.0.1/mydb?user=myuser"
);
java.sql.Statement stmt = conn.createStatement();
java.sql.ResultSet rs = stmt.executeQuery("SELECT count(*) FROM pg_class");
System.out.println("Type of count(*) is a BIGINT: "
+ (rs.getMetaData().getColumnType(1) == java.sql.Types.BIGINT)
);
rs.close();
stmt.close();
conn.close();
produces:
Type of count(*) is a BIGINT: true

NHibernate Formula based property + PostgreSQL interval

I'm using NHibernate with Mapping by Code and I have a property that is created by this formula.
Property(x => x.IsInOverdue,
mapper => mapper
.Formula("(SELECT (state_ <> 3 AND invoice_uniqueAlias.duedate_ < NOW()) " +
" FROM _invoice AS invoice_uniqueAlias "+
" WHERE invoice_uniqueAlias.invoice_id = issuedinvoice_key)"));
It works perfectly, this sql is inserted as subselect in all queries...
But I would need to add 1 day to invoice_uniqueAlias.duedate_ value. We are using PostgreSQL where the syntax for it is: invoice_uniqueAlias.duedate_ + interval '1 day'
But when I put it in mapper.Formula, NHibernate thinks that interval is a name of column and in all queries tries to add table prefix before interval keyword. The generated SQL then looks like:
... (SELECT (issuedinvo0_.state_ <> 3
AND (invoice_uniqueAlias.duedate_ + (issuedinvo0_.interval '1 day')) < NOW()) ...
I tried to put interval keyword in [, `, put statement interval + '1 day' to brackets, but it didn't help. Any suggestions how to handle it correctly in NHibernate or how it is possible to write it in Postgres without using + interval syntax?
In case, we need NHibernate to treat some words (key words) as part of the underlying DB engine dialect, we have to just extend it.
One way would be the create custom dialect:
public class CustomPostgreDialect : PostgreSQL82Dialect
{
public CustomPostgreDialect()
{
RegisterKeyword("interval");
}
}
And now just use it:
<property name="dialect">My.Namespace.CustomPostgreDialect,My.Data</property>
Some similar issue - Using SQL CONVERT function through nHibernate Criterion (with the similar solution in this answer)

intersystem cache C# query with datetime

When I use cache sql query in C# I'm getting an error:
SQLtext1 = "SELECT top 10 * FROM dbo.DAPPLICATIONSTAT where TIMESTAMP = '2015-02-01 00:00:00'"
I would like to use a where clause with a datetime filter.
I am using InterSystems.Data.CacheClient.dll to execute the query.
Error Messge :
[SQLCODE: <-4>:<A term expected, beginning with one of the following: identifier, constant, aggregate, %ALPHAUP, %EXACT, %MVR, %SQLSTRING, %SQLUPPER, %STRING, %UPPER, $$, :, +, -, (, NOT, EXISTS, or FOR>]
[Cache Error: <<SYNTAX>errdone+2^%qaqqt>] [Details: <Prepare>]
[%msg: < SQL ERROR #4: A term expected, beginning with either of: (, NOT, EXISTS, or FOR^SELECT top :%qpar(1) * FROM dbo . DAPPLICATIONSTAT where TIMESTAMP>
I think that you have reserved word TIMESTAMP and so, you have that error
Try this SQL query, where filedname TIMESTAMP in dobled quotas
SELECT top 10 * FROM dbo.DAPPLICATIONSTAT where "TIMESTAMP" = '2015-02-01 00:00:00'

Prevent sql injection, Activerecord #where, with multiple AND/OR clause

I am fairly new to rails. I have a rails Model 'Message' with: 'belongs_to :sender' and 'belongs_to :receiver' relations.
I am trying to create a message thread between two users: 'current_user' and 'params'.
In the show controller action of the MessagesController, I want to use the equivalent of this sql query:
Message.find_by_sql(
"SELECT *
FROM messages
WHERE
(sender_id = #{current_user.id} OR sender_id = #{params[:id]})
AND
(receiver_id = #{current_user.id} OR receiver_id = #{params[:id]});"
)
If I where looking for one Message I would use this Activerecord queryto prevent SQL injection:
Message.where('sender_id = ? OR receiver_id = ?', current_user.id, current_user.id).find(params[:id])
My current query is:
Message.where(sender_id: [current_user.id, params[:id]], receiver_id: [current_user.id, params[:id]])
Is this query currently guarded against SQL injection?
it's safe. the final query would be something like sender_id IN (1, 2) AND receiver_id IN (3, 4) and all integer values are sanitized. You can simply run tests:
Message.where(sender_id: [current_user.id, "' is dangerous"], receiver_id: [current_user.id, params[:id]])
and see raw SQL output in console. illegal integers should be converted to 0.