Does Hibernate's Query.setParameter make SQL injection possible [duplicate] - java

This question already has answers here:
How to prevent SQL Injection with JPA and Hibernate?
(5 answers)
Closed 5 years ago.
I'm Using Struts2 Framework and Hibernate, I'm Enhancing a System that I didn't started, I enhanced some features of the system and implement it on the prod. But when they scan it using Acunetix, Somewhere in Login Module, there are some threats(alerts) that are detected in the System wherein the alert says:
Alert: SQL injection
Severity: High
Description: This script is possibly vulnerable to SQL Injection attacks.
Recommendation: Your script should filter metacharacters from user input. Check detailed information for more information about fixing
this vulnerability.
And then, I checked the Script that would be the fault on that alert. The Old Developer uses Hibernate to create a query.
List<UserBean> users = session.createQuery("from UserBean where username =?")
.setParameter(0,username)
.list();
My Question is:
-Is this Query using Hibernate can't Avoid SQL Injection?
-Is .setParameter should be .setString to be more specific to avoid SQL Injection?
or None of the Above ?
Thanks for the time.

If you use the Hibernate query parameter binding like this you are safe from SQL injection attacks.
In opposite to string concatenation, setParameter will fill the placeholders of the query after creating the prepared statement and before execution of the query, and the query processing engine knows which (probably malicious) chars should be escaped.
This is the common way to go.
setString is the non-generic pendant to setParameter. setParameter detects the datatype automatically.
A small improvement would be to use named parameter binding, e.g.:
List<UserBean> users = session.createQuery("from UserBean where username = :username")
.setParameter("username", username)
.list();
This way you will not get more problems with more parameters in the future.

Related

Checkmarx report sql injection JpaRepository

im running Checkmarx on my code and im getting an sql injection vulnerability.
this is the simplified method im using
public String assignRole(String userId, String roleId) {
Optional<RoleEntity> roleEntity = roleRepository.findById(roleId)
if (roleEntity.isPresent()) {
UserEntity user = UserEntity.builder().userId(userId).role(roleEntity.get()).build();
userRepository.save(user);
return "SUCCESS";
} else {
throw new ServiceException("ERROR");
}}
and the analysis of checkmax says:
The application's assignRole method executes an SQL query with save, at line xx of
src/Service.java. The application
constructs this SQL query by embedding an untrusted string into the query without proper sanitization. The
concatenated string is submitted to the database, where it is parsed and executed accordingly.
An attacker would be able to inject arbitrary syntax and data into the SQL query, by crafting a malicious
payload and providing it via the input roleId;
This may enable an SQL Injection attack.
im a little bit confused because im not building a native query or concatenating strings in a query, or maybe im missing something.
any ideas for fix this? or maybe is a false positive.
This sounds like a false positive.
If your Java code uses Spring, I recommend configuring your scan (Settings > Scan Settings > Preset Manager) with the SQL_Injection and Second_Order_SQL_Injection items under the Java section disabled (unchecked) to avoid false positives from these items.
If your code persists data to the database exclusively via the Spring save action, it is not at risk of SQL injection exploitation. That’s because Spring saves (inserts or updates) to the database using an object mapped to your db (the ORM approach) which does not allow additional sql to be maliciously forced in.
Nonetheless, from what I’ve seen, Checkmarx marks Spring save actions, falsely, as high severity SQL Injection vulnerabilities (SQL_Injection and/or Second_Order_SQL_Injection). Given this, disabling those rules seems to me valid and in fact the only viable way around this.
But if you do take this approach, make sure your code does not for some reason also use some other some other sql approach such as a String containing SQL that’s not sanitized via the use of PreparedStatement. Those statements are vulnerable to sql injection exploits and I believe are what the Checkmarx SQL injection rules are intending to identify.

How to select schema at runtime using Hibernate?

I already have an existing code base, where schema(like db_1, db_2..) are created at run time.
We are currently using JdbcTemplate, using that its quite easy to append schema in the native SQL queries some thing like :-
sql = " Select * from "+schema+".user";
jdbcTemplate.query(sql, new UserMapper());
Now I want to know is how to provide schema to hibernate at runtime like I did with the jdbcTemplate?
What connection url should I provide in hibernate.cfg.xml so that it doesn't connects to a single schema rather whole database?
Any suggestions will be helpfull.
P.S: I am new to hibernate (So I might have missed something stupid)
I know of two options:
Use native SQL query binding results to JPA entities. Details here.
Use Hibernate multi-tenancy. Details here and here.
Although I haven't tried either.

How to prevent SQL second order injections in java (Spring Application)

I have been facing the second order SQL injection in this following code
if(subjectId!=null){Query query= sessionFactory
.getCurrentSession()
.createSQLQuery(HubQueryConstants.GET_QUERY)
.setParameter(MyConstants.SUBJECT_ID, subjectId)
.setFirstResult(offset)
.setMaxResults(limit)
.setResultTransformer(
Transformers.aliasToBean(MyClass.class));}
My Constant file is :
Constant file is Final class
GET_QUERY="Select * from MyClass where id=:id ";
though it is in static query by default still my security report is giving it as Second order SQL injection
Should we declare constants in interface? to avoid Security issue?
A SQL injection occurs, when a placeholder is replaced with a SQL term that alters the original SQL string so that the SQL does something different than intened.
You can find more details at SQL_injection
SQL injection happens when the placeholder of the parameters are replaced. So declaring constants instead of reading the SQL from a properties file does not help. The injection happens later, independently from where the SQL string was obtained.
The easiest way to prevent SQL injection is by using prepared statements.
When a prepared statement is executed, the SQL string and the parameters are handled completely seperate by the SQL server, making SQL injection impossible.
With JPA you can use the annotation javax.persistence.NamedNativeQuery; to declare a SQL query that will be executed as prepared statement.
You find a tutorial using NamedNativeQuers at the end of jpa-native-queries

Query with dynamic schema without using string concatenation

I have a system that uses a Oracle database, with a schema that is different from the application user. The schema name itself is not known in advance, so we can't just hardcode it. It's a system property.
Most of the data access is through Hibernate, which can specify the default schema on connection so this is not a problem in those cases.
However, there are a few places where plain SQL queries are used (using spring jdbcTemplate). So right now we have something that boils down to:
Map<String,Object> result = jdbcTemplate.queryForMap("SELECT A, B, C FROM "+schema+".TABLE WHERE blablablah");
And this, of course, is an open SQL injection vulnerability. We're planning security audits and this will be flagged for sure.
So the question is: How do I specify the schema on the query, be it with jdbcTemplate, another Sprint data access utility, or even plain jdbc?
Thank you,
JGN
You can use Connection.setSchema to specify the schema for a JDBC connection. This should be done before you create the Statement to execute a SQL command.

How does Hibernate generate sql string from session.get queries

I am using Hibernate 4.2.4 and I am interested to know how Hibernate translate a session.get call to an equivalent sql query that is eventually used to retrieve rows from database. I do not want to log the generated sql in console. I want to use the same sql query in my application. Something like below.
...
SessionFactory sessionFactory = configuration.buildSessionFactory(builder.buildServiceRegistry());
// I want the query string here
String query = sessionFactory.someUnknownMethod(Some Paramters);
Session session = sessionFactory.openSession();
// actual session.get query
Comment comment = (Comment) session.get(Comment.class, new Integer(1));
...
I have seen this thread for Criteria query -> How to get SQL from Hibernate Criteria API (*not* for logging).
I would like to know if similar procedure exists for session.get type queries.
I have also seen this thread -> get SQL from hibernate get
where the question is exactly same as mine, but the accepted solution talks about fetching statistics which, to my understanding, only accounts for the queries that have already been executed. Plus, from statistics I was able to catch hql/sql queries but not session.get queries.
I want to know if there is a way for a user to generate and use the sql even before the actual session.get gets executed (possibly by following the same path as hibernate).

Categories

Resources