SQL injection with no spaces - mysql

I'm trying to exploit an SQL injection on a website (in the name of Science, of course). After some tests I found how the back-end works. The SQL query is formed like this:
$query = 'SELECT * FROM TABLE WHERE ID ='.$segment
where $segment is the second path segment from the URL. In case of http://vict.im/menu/10 it equals 10. Symbols /, # and everything after them is ignored, so the previous link, http://vict.im/menu/10/blah-blah and http://vict.im/menu/10#blah-blah give the same result.
The problem here is that the segment-parser doesn't URLdecode() the segment. If I send .../menu/30 ; it will be encoded to .../menu/30%20;, and MySQL will interpret it as remainder of division, returning us result where ID = 10. By the same reason + is not replaced for whitespace, it works as an operator.
So, it's needed to make an injection that doesn't contain any symbols usually encoded by web browsers. For example, .../menu/(10)or(1=1), boolean-based injection .../menu/9+(USER()='Smith') and .../menu/CONCAT('1','0') work fine.
How can I explain this situation to Sqlmap? Is there a tamper script for this? Are there any other ways to bypass this "protection"?
P.S. It seems following symbols can be used: ! $ & ' ( ) * + , : ; = ? # [ ] plus mixalpha-numeric.

Related

How to update a database using textfields values in JDBC?

I'm trying to update a database in JavaFX using JDBC and Textfields ,
The first textfields, but I keep getting SQL syntax errors.
It's a simple update syntax , but I have to use the textfield.getText() in order to fill up the data.
I tried this as the query I'll execute:
UPDATE intervention
set "+update_textfield2.getText()+" = "+update_textfield3.getText()+"
WHERE ( Numdemande ="+update_textfield.getText()+"
To explain the code above : set the database field the user entered (update_textfield2) as the value the user entered (update_textfield3) where the "Numdemande" number is x (update_textfield)
While your code is unsafe, as explained in the comments, I'll answer on the assumption that your class has not yet covered SQL injection attacks.
As for your SQL statement itself, there are several problems.
First of all, you are using double quotes " instead of single quotes '. It is unclear which dialect of SQL you are using, but most, if not all, require single quotes when passing through Strings like this.
Secondly, you are wrapping your calls to the textField.getText()
methods in quotes, meaning you're telling SQL to use that text
literally.
You have not added a closing parentheses ()) at the end of your WHERE clause. The parentheses in this case, however, are not necessary.
In essence, you're trying to pass the following statement to SQL:
UPDATE intervention
set +update_textfield2.getText()+ = '+update_textfield3.getText()+'
WHERE ( Numdemande = '+update_textfield.getText()+'
Unless you have a field called +update_textfield2.getText()+ in your table, this statement will fail.
The following String would produce the correct statement:
String statement = "UPDATE intervention " +
"SET " + update_textfield2.getText() + " = " + update_textfield3.getText() +
"WHERE Numdemande = " + update_textfield.getText() + ";";
Side Note: Please learn the Java Naming Conventions and stick to them. In your code, you've used Snake Case when naming your TextField, but should be using Camel Case instead. An appropriate name for your TextField might be something like this instead: updateTextField1

Could this string concatenation in my query result in injection attacks?

This comment made me worried that the way I am searching my databases may result in an injection attack. Bellow is the query I'm currently using:
return db.query("SELECT * FROM customers
WHERE ( num LIKE ? AND name LIKE ? )",
[customer.num + "%", customer.name + "%"], callback)
Should I be adding the % symbol in my call to the API, or how would this be properly implemented?
The comment you're referring to uses string concatenation, whereas you are using prepared statements
This means that the intention is that the db.query function should be applying filtering and escaping to the inputs you provide, and hopefully they would be fairly extensive, and protecting you well.
It doesn't mean that you're immune to SQLI attacks, because there are just so many of them, but you have followed good practices in using prepared statements.
To check and/or improve your security against SQLI attacks, you could:
Audit the database connector library you are using to see whether it has known issues. npm audit is your friend here
Consider using another system for the queries, like an ORM like Sequelize, which tend to use querying systems even further separated from the actual SQL.
No, you misunderstood it. The problem comes when you concatenate a string with the SQL Query . e.g db.query("SELECT * FROM customers WHERE ( num LIKE "+ var +"AND name LIKE "+ var2+" )". You are safe here because you are using placeholders that will escape them.

Django raw SQL query trouble with format characters and string interpolation

In my Django app, I need to generate a MySQL query like this:
SELECT * FROM player WHERE (myapp_player.sport_id = 4 AND (myapp_player.last_name LIKE 'smi%'))
UNION
SELECT * FROM player WHERE (myapp_player.sport_id = 4 AND (myapp_player.first_name LIKE 'smi%'));
I can't use Q objects to OR together the __istartswith filters because the query generated by the Django ORM does not use UNION and it runs at least 40 times slower than the UNION query above. For my application, this performance is unacceptable.
So I'm trying stuff like this:
Player.objects.raw("SELECT * FROM myapp_player WHERE (sport_id = %%s AND (last_name LIKE '%%s%')) UNION SELECT * FROM sports_player WHERE (sport_id = %%s AND (first_name LIKE '%%s%'))", (sport.id, qword, sport.id, qword))
I apologize for the long one-liner, but I wanted to avoid using a triple-quoted string while trying to debug this type of issue.
When I execute or repr this queryset object, I get exceptions like this:
*** ValueError: unsupported format character ''' (0x27) at index 133
That's a single-quote in single quotes, not a triple-quote. If I get rid of the single-quotes around the LIKE clauses, then I get a similar exception about the close-paren ) character that follows the LIKE clause.
Apparently Django and MySQL disagree on the correct syntax for this query, but is there a syntax that will work for both?
Finally, I'm not sure that my %%s syntax for string interpolation is correct, either. The Django docs suggest that I should be able to use the regular %s syntax in the arguments for raw(), but several online resources suggest using %%s or ? as the placeholder for string interpolation in raw SQL.
My sincere thanks for just a little bit of clarity on this issue!
I got it to work like this:
qword = word + '%'
Player.objects.raw("SELECT * FROM myapp_player WHERE (sport_id = %s AND (last_name LIKE %s)) UNION SELECT * FROM myapp_player WHERE (sport_id = %s AND (first_name LIKE %s))", (sport.id, qword, sport.id, qword))
Besides the fact that %s seems to be the correct way to parameterize the raw query, the key here was to add the % wildcard to the LIKE clause before calling raw() and to exclude the single quotes from around the LIKE clause. Even though there are no quotes around the LIKE clause, quotes appear in the query ultimately sent to the MySQL sever.

odd sql error, variable not being recognized correctly

I'm currently in hour two of this issue, I can't explain it so I will simply show what is going on. I don't know if this matters at all, but I am using the linkedIN API to retrieve a user's linkedIn unique ID.
In English, what I'm doing:
User Signs in with LinkedIn
I read-in user's LinkedIn ID (returned from the API)
If ID exists in database, say "hello", if not, show them a form to register
The issue I am having:
The following line works and properly returns the 1 user I have in the database with a linkedIn ID of OtOgMaJ2NM
$company_data = "SELECT * FROM s_user WHERE `LI_id` = 'OtOgMaJ2NM'";
The following query returns no results - using the same database with the same record in the table s_user:
$linkedIn_id = "<?js= id ?>";
echo $linkedIn_id;
The following code outputs OtOgMaJ2NM with no trailing spaces.
So far so good ... expcept when I run the query this time using the variable, no records are returned!
$company_data = "SELECT * FROM s_user WHERE `LI_id` = '$linkedIn_id'";
Further notes:
When I echo $company_data the same query is displayed when I use the variable as did when I used the plain text version of the query.
Anyone have ANY ideas?
Thanks,
Evan
I can only assume that when echoing variables it strips the tags, so when you're using it with the query you're actually saying:
$company_data = "SELECT * FROM s_user WHERE `LI_id` = '<?js= OtOgMaJ2NM ?>'";
I could be wrong, but have you tried stripping the tags from the variable?
If you send the variable between the "", the MySQL engine will search for $linkedIn_id literally and not for its content.
Seems you are using php, but I'm not sure about the right syntax. Take a look in the docs.

Why does my INSERT sometimes fail with "no such field"?

I've been using the following snippet in developements for years. Now all of a sudden I get a DB Error: no such field warning
$process = "process";
$create = $connection->query
(
"INSERT INTO summery (process) VALUES($process)"
);
if (DB::isError($create)) die($create->getMessage($create));
but it's fine if I use numerics
$process = "12345";
$create = $connection->query
(
"INSERT INTO summery (process) VALUES($process)"
);
if (DB::isError($create)) die($create->getMessage($create));
or write the value directly into the expression
$create = $connection->query
(
"INSERT INTO summery (process) VALUES('process')"
);
if (DB::isError($create)) die($create->getMessage($create));
I'm really confused ... any suggestions?
It's always better to use prepared queries and parameter placeholders. Like this in Perl DBI:
my $process=1234;
my $ins_process = $dbh->prepare("INSERT INTO summary (process) values(?)");
$ins_process->execute($process);
For best performance, prepare all your often-used queries right after opening the database connection. Many database engines will store them on the server during the session, much like small temporary stored procedures.
Its also very good for security. Writing the value into an insert string yourself means that you must write the correct escape code at each SQL statement. Using a prepare and execute style means that only one place (execute) needs to know about escaping, if escaping is even necessary.
Ditto what Zan Lynx said about placeholders. But you may still be wondering why your code failed.
It appears that you forgot a crucial detail from the previous code that worked for you for years: quotes.
This (tested) code works fine:
my $thing = 'abcde';
my $sth = $dbh->prepare("INSERT INTO table1 (id,field1)
VALUES (3,'$thing')");
$sth->execute;
But this next code (lacking the quotation marks in the VALUES field just as your first example does) produces the error you report because VALUES (3,$thing) resolves to VALUES (3,abcde) causing your SQL server to look for a field called abcde and there is no field by that name.
my $thing = 'abcde';
my $sth = $dbh->prepare("INSERT INTO table1 (id,field1)
VALUES (3,$thing)");
$sth->execute;
All of this assumes that your first example is not a direct quote of code that failed as you describe and therefore not what you intended. It resolves to:
"INSERT INTO summery (process) VALUES(process)"
which, as mentioned above causes your SQL server to read the item in the VALUES set as another field name. As given, this actually runs on MySQL without complaint and will fill the field called 'process' with NULL because that's what the field called 'process' contained when MySQL looked there for a value as it created the new record.
I do use this style for quick throw-away hacks involving known, secure data (e.g. a value supplied within the program itself). But for anything involving data that comes from outside the program or that might possibly contain other than [0-9a-zA-Z] it will save you grief to use placeholders.