java servlets : passing url variable values with spaces - java

I'm building a simple java Servlet which passes categories using a URL variable into another Servlet.
For example, in the following code
ResultSet rs = qw.DBquery("select distinct manufacturer from Products order by manufacturer asc");
try {
while (rs.next()) {
table+= "<tr><td><a href=\"getItems?manufacturer="
+ rs.getString("Manufacturer") + "\">"
+ rs.getString("Manufacturer") + "</a></td></tr>\n";
}
}
its output includes:
Adobe
Adobe Acrobat
IBM
IBM - Workstations
IF I click on one, the link gets to the URL as:
http://localhost/getItems?getItems?manufacturer=Adobe%20Acrobat
However, when I get the manufacturer variable and its value
String manufacturer = request.getParameter( "manufacturer" );
ResultSet rs1 = qw.DBquery("select * from products where Manufacturer like '"
+ manufacturer + "'");
the query output fails and doesn't produce anything if there are spaces in the value of manufacturer. Any ideas or workarounds on how to convert this back? Do I need to do some kind of urldecode?
thanks in advance

The encoding of space in a URL as %20 is correct, and the web application container takes care of URL decoding.
String manufacturer = request.getParameter( "manufacturer" );
The String manufacturer in your program should therefore contain 'Adobe Acrobat' (with a space). Can you verify that (by logging it to somewhere)?
"select * from products where Manufacturer like '"+ manufacturer + "'"
Also, please use bind variables.
Directly interpolating query parameters (without any validation, too!) into SQL leaves you totally open to SQL injection attacks. It is bad for performance, too.
"select * from products where Manufacturer like ? "

Related

BLOCKER - Change this code to not construct SQL queries directly from user-controlled data

Sonarqube is giving me this error:
[BLOCKER] Change this code to not construct SQL queries directly from user-controlled data
Here is my code:
String countSQL;
countSQL = (String.format("SELECT count(*) as total FROM ltid_owner.enty %s",additionalWhereClauses));
jdbcTemplateTMI.queryForObject(countSQL, Integer.class);
In the above code additionalWhereClauses could be something like this shown below which I am building on the fly when the user clicks on the grid to perform filtering on different columns:
additionalWhereClauses = where UPPER(enty_num) like '003%'
Can you please let me know how to resolve this issue?
Your code combines strings into SQL statements. If any of these strings contains user provided input, an attacker can sneak in code to trigger an SQL injection attack and possibly run arbitrary code on your computer (obligatory Bobby Tables reference).
Simple example:
String sql = "SELECT * FROM users WHERE name = '" + name + "' AND password = '" + password + "'";
If I enter ' OR 1=1 -- for the name (and "..." for the password, but that doesn't really matter anymore) the code becomes a valid SQL statement:
SELECT *
FROM users
WHERE name = '' OR 1=1 -- ' AND password = '...'
but the user name / password check is completely disabled.
To avoid this, use prepared statements. They build the SQL command in a way that SQL injection is impossible.
Maybe this never happens in your code as you don't accept user input, but Sonar doesn't know this (and human reviewers won't either). I'd always use prepared statements. Just because your code only passed column headers from a frontend, doesn't mean an attacker cannot manually call your web service endpoints and pass whatever they want, it your code runs as an HTTP endpoint.

JAVA - Possible SQL Injection

So I have this snippet of code:
String username = props.getProperty("jdbc.username");
try {
String username = parts[1];
// Check procedure
System.out.println("Checking user");
// Check database user table for username
conn = getSQLConnection();
Statement stat = conn.createStatement();
ResultSet user = stat.executeQuery( "SELECT * FROM USER WHERE log_id='" + username + "';" );
// Check given password against user entry
if(user.next()){
System.out.println("User Exists: " + username);
sendMessage("true");
return;
}
else{
System.out.println("User Does Not Exist: " + username);
sendMessage("false user");
return;
}
For educational purposes, is the SQL statement protected from an SQL injection even though I know where the input is coming from?
ResultSet user = stat.executeQuery( "SELECT * FROM USER WHERE log_id='" + username + "';" );
This is subject to SQL injection.
Imagine what happens if username has this value:
John'; delete from user where 'a' = 'a
And yes, a s*load of Java JDBC SQL tutorials get this wrong. Basically, always use PreparedStatements.
Not only because this makes it safe ot use even if username has malicious values as the above, but also, and more importantly, because the same query can be reused by the RDBMS engine for all further invocations.
In short, there is no reason at all not to use them. And tutorials demonstrating SQL using string concatenation should die a painful, SQL injection death.
As explained in this post, one rogue attacker can do the following to yoour application:
call a sleep function so that all your database connections will be busy, therefore making your application unavailable
extracting sensitive data from the DB
bypassing the user authentication
And it's not just SQL that can be affected. Even JPQL can be compromised if you are not using bind parameters.
Bottom line, you should never use string concatenation when building SQL statements. Use a dedicated API for that purpose:
JPA Criteria API
jOOQ

Why does this SQL-Statement lead to an error?

I am getting quite angry with this, so I seek help from the crowd ;)
What I want to do: We have a Unity learning game which shall implement a login window. The entered credentials are then hashed (the pw is) and sent to the server, who then should check this against a database.
I have the following table:
xy.users_confirms with the following colums:
id username email password hashcode created
Why does my code
String sql = "SELECT " + "xy.users_confirms.password as pwhash, "
+"FROM xy.users_confirms " +"WHERE xy.users_confirms.username = " +"\"userNameToGetHashFor\"";
lead me to the SQLException "Parameter index out of range (1 > number of parameters, which is 0)"
?
Thanks, any input is much appreciated!
Try this:
String parameter = "'"+ strNameToGetHashFor + "'";
String sql = "SELECT " + "xy.users_confirms.password as pwhash, "
+"FROM xy.users_confirms "
+"WHERE xy.users_confirms.username ="+ parameter;
You are using varchar value as a parameter so it's need to be quot like this.'username'. or you can use Stored Procedure.
Personally, I would try getting a working query using the custom query box directly in phpmyadmin. Once you have a working query you can re-write it in java.
And I would try writing the syntax like this into the phpmyadmin query box:
SELECT password as pwhash
FROM xy.users_confirms
WHERE username ='userNameToGetHashFor'
Using the above syntax I don't see anyway your error could persist.
Phpmyadmin screen cap showing custom query box: http://screencast.com/t/9h8anH0Aj
(the 2 empty text boxes in screen cap are just me hiding my database info)
The comma after pwhash is one potential cause:
+ "xy.users_confirms.password as pwhash*!*,*!* "
Depending on the DBMS, you may also need to use single quotes instead of double quotes like this:
+ "'userNameToGetHashFor'";
Also this code is potentially vulnerable to a SQL Injection attack so you may want to make the userNameToGetHashFor a parameter rather than concatenating the string into the SQL statement.

String formatting prob for making database value inside a file

I have a bean class which does maintain user data:
soppose I have created a postgresql DB table like this:
StringBuffer sqlStr = new StringBuffer();
sqlStr.append("CREATE TABLE Users ("
user_id bigint,
username character varying NOT NULL,
biography character varying NOT NULL
);
& I want to make a query command and inject my String data inside it:
sqlStr.append("INSERT INTO users(" +
"user_id, username, biography)" +
"\n\tVALUES (" + user.getID()+ "," + user.getUsername() + "," + user.getBiography()+");";
my problem is for example if the data coming from my method has quote or double quote or "," my command will become wrong suppose that the user biography is something like this :
hello, I'm Mr X an "IT Pro" ...
If I run my application and save the output inside a file called query.sql I can't use it because my query command is wrong because of quote & double quote, something like this:
INSERT INTO users(userid, username, biography)
VALUES(2, 'Mehdi', 'hello, I'm Mr X an "IT Pro" ..');
how Can I fix this problem ?
You should never ever use the above method for constructing SQL queries.
"Why not?" you ask, well; where to start. The classic example is Bobby Tables, the more general problem is SQL injection. This leaves your program open to attack but also to random failure - like the situation you describe.
Now, the solution. Always use PreparedStatement to construct your query. In your example
final String query = "INSERT INTO users(user_id, username, biography) VALUES (?,?,?)";
final PreparedStatement ps = con.prepareStatement(query);
ps.setInt(1, user.getID());
ps.setString(2, user.getUsername());
ps.setString(3, user.getBiography());
ps.executeUpdate();
A much nicer syntax to use with is the the SET syntax rather than the traditional VALUES syntax. The query would then look like
final String query = "INSERT INTO users SET user_id = ?, username = ?, biography = ?";
EDIT
The OP is building a query for a script file, not executing a query in the code.
There is a utility class in Apache Commons Lang, StringEscapeUtils. This has an escapeSql method. Looking at the source code, all this does is escape single quotes with another single quote.
This works if you build your queries with single quotes:
VALUES (" + user.getID()+ ",'" + user.getUsername() + "'...
So the query, once the example value is inserted will go from:
VALUES (10 ,'hello, I'm Mr X an "IT Pro"'...
Will become
VALUES (10 ,'hello, I''m Mr X an "IT Pro"'...
The apostrophe in "I'm" is now escaped and harmless.
Note that you obviously need to escape the values and not the query, so (assuming you have a static import for the class)
VALUES (" + user.getID()+ ",'" + escapeSql(user.getUsername()) + "'...
But does not escape other sql characters, percent signs for example.
This is really a stop-gap measure to make the code work while you come up with a more robust solution. And you should come up with a more robust solution.
Why dont you use PreparedStatement? That will also give you better performance as the SQL will be pre-compiled on DB side.
Or
You can escape the quotes using
String.replaceAll http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#replaceAll(java.lang.String, java.lang.String)

Communication between jsp and java application

My project requirement is to develop a website which interacts with a mysql database and a java application which continuously runs on the server. user is on some remote computer he sends a request to the java application by executing a jsp code on the server, the jsp code waits for the application to send the information back. once the jsp recives the info. it sends a request to database. The is a special type of database built just because of limitations of a database and my project requirements. Please tell me how the request are sent i.e. what part of java will help me do this.
some link that have the same info but not exact Communication between two separate Java desktop applications.
EDIT: my question is.... what should i use in a jsp page such that i will be able to get info. from the application which stores data in a special form of datastructure. For now I dont want to talk to database. I just want to interact with a running application.
for example there is a program on the server which returns sum of two numbers which waits for someone to give it input. now my jsp sends two numbers to the application which adds the two numbers and gives back the sum to the jsp page. now jsp page code can do anything which is not my concern for now.
Database access through the Website is one of the essential components for any web-based development. JDBC, a mechanism that allows Java to talk to databases.
Java Database Connectivity (JDBC) is a standard Application Programming Interface (API) that is used to access databases, irrespective of the application driver and database product. In other words, JDBC presents a uniform interface to databases, however, if you change the database management system and your applications, you only need to change their driver. JDBC provides cross-DBMS connectivity to a wide range of SQL databases, and other tabular data sources, such as spreadsheets or flat files.
Here is the sample example:
import java.sql.*;
class DBQuery1{
public static void main(String args[]) throws SQLException
{
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
}catch(ClassNotFoundException e){};
Connection cnn;
Statement mystmt;
ResultSet myrs;
String op = "jdbc:odbc:JavaTest";
cnn = DriverManager.getConnection(op,
"Admin", "");
mystmt = cnn.createStatement();
String sql;
sql = "SELECT * FROM SupplierMaster " +
"WHERE SupplierCode IN ( " +
"SELECT SCode " +
"FROM Relation " +
"WHERE PCode IN ( " +
"SELECT ProductCode " +
"FROM ProductMaster " +
"WHERE ProdCatg IN ( " +
"SELECT CatgID " +
"FROM CategoryMaster " +
"WHERE CategoryName = 'Eatables')))";
myrs = mystmt.executeQuery(sql);
System.out.println(" "+"Sup Code" + " " +"Sup Name" + " " + "Sup Address ");
System.out.println("--------------------------------------------------------------------");
String name, add;
int code;
while (myrs.next())
{
code = myrs.getInt("SupplierCode");
name = myrs.getString("SupplierName");
add = myrs.getString("SupplierAddress");
System.out.println(" " + code +" " + name+" " + add);
}
}
}
More information you can find on this link:
http://webserver.ignou.ac.in/virtualcampus/adit/course/cst302/block2/cst302-bl2-u3.htm
Java applications most often communicate with a relational database through the use of a JDBC driver. The driver tells the application how to communicate with a specific database. Each database vendor often provides a driver for their particular database. In your case you will need the MySql Connecter/J driver, which you will include within your project as a jar file.
The JDBC drivers provided by database vendors implement an interface so connecting to different databases is pretty much the same except for a few syntax differences between parameters. There is a ton of information that can be found about how to connect to a database through a Java application.

Categories