Let's consider i have this line of code
$result = $mysqli->query("SELECT * from myTable where field='".$_GET['var']."');
IMHO this is vulnerable to SQL injections.
So I'd like to prove it trying by sending via Get / URL a "var" param that will inject the query, with potential malicious code.
I actually tryed this:
var = "1'; TRUNCATE myTable; ";
I tryed to print out the SQL string query before executing it and it's actually 2 SQL valid statements.
SELECT * from myTable where field='1'; TRUNCATE myTable;
1st problem
But actually itseems that mysqli->query will not execute 2 statements at once. Isn't it?
2nd problem
I see that a common technique to Inject queries is to per form injection then add comment chars to get rid of the tail of the SQL.
Example:
"SELECT * from myTable where field='".$_GET['var']."' AND field2 IS NOT NULL"
Can be injected with :
var = "1'; TRUNCATE myTable; # ";
But this problem arise and I'm missing the trick to get rid of it
if the SQL string in the code have new lines e.g. :
"SELECT * from myTable where field='".$_GET['var']."'
AND field2 IS NOT NULL"
If i use the above "var" the final result is
SELECT * from myTable where field='1'; TRUNCATE myTable; #
AND field2 IS NOT NULL
Second line won't be commented
How to test injection on this?
Many thanks.
1st problem But actually it seems that mysqli->query will not execute 2
statements at once. Isn't it?
That's right, if you want to execute multiple statements you need to use mysqli->multi_query. You can find a good explanation about multiple statements here: http://www.php.net/manual/en/mysqli.quickstart.multiple-statement.php
But this problem arise and I'm missing the trick to get rid of it
The problem arises because you are using multiple statements, and mysqli->query does not support them.
About your queries:
$result = $mysqli->query("SELECT * from myTable where field='".$_GET['var']."');
You can inject this using for example 1' OR 1=1; that would return all entries of myTable on the query result.
"SELECT * from myTable where field='".$_GET['var']."' AND field2 IS NOT NULL"
Here you could use 1' OR 1=1 UNION ALL SELECT * FROM myTable WHERE '1'='1
Nowadays there are tools that can automatically check SQL injection for you, take a look at SQL Inject Me (Firefox Addon) for example.
Related
Following this syntax:
Here is generic SQL syntax of UPDATE command to modify data into MySQL table −
UPDATE table_name SET field1 = new-value1, field2 = new-value2 [WHERE Clause]
from https://www.tutorialspoint.com/mysqli/mysqli_update_query.htm
I made this:
$query = mysqli_query($MYSQL_CONNECT, "UPDATE forum_topics SET player_userid = ".$player_userid.", titulo = ".$titulo.", msg = ".$msg.", data = ".$data." WHERE UserID=".$inTopic."");
mysqli_query($MYSQL_CONNECT,$query);
But on line:
mysqli_query($MYSQL_CONNECT,$query);
Is showing:
mysqli_query(): Empty query in /var/www/html/ucp/php_func/edit_topic.php on line 30
The main problem is that you're trying to execute your query twice. And the second attempt is invalid because, where it expects a string query, you're either passing it a result object or a boolean (if the first query failed).
Just execute your query once:
$query = mysqli_query($MYSQL_CONNECT, "...");
Then the value in $query will be the result.
Additionally, you have the problem that your code is open to SQL injection and you're not checking for errors. If mysqli_query() returns false you'd need to examine what went wrong by using mysqli_error($MYSQL_CONNECT), which returns the error as a string.
For the SQL injection problem, what you should be doing is treating values as values (query parameters) instead of as executable code (by concatenating them directly into the query). This is a great place to learn more about that. Note that SQL injection is not just a security concern but is also a very common source of errors and bugs. Since you're currently having exactly that problem, it's worth correcting.
You should wrap your variables in single quotes, try:
$query = mysqli_query($MYSQL_CONNECT, "UPDATE forum_topics SET player_userid = '".$player_userid."', titulo = '".$titulo."', msg = '".$msg."', data = '".$data."' WHERE UserID='".$inTopic."'");
I am trying to select exact json value in mysql query condition, currently i am using LIKE and it work but like returns false positive.
my code is::
$id='1';
json data example:: ["1","12","38"]
$sql="SELECT * FROM `posts` WHERE `json_column` LIKE '%".$id."%' ";
with this query, it returns both 1 and 12. how can i get just 1?
Note the extra quotes:
$sql="SELECT * FROM posts WHERE json_column LIKE '%\"$id\"%'";
However, this is wide open to SQL inject if $id comes from user input. Be careful.
The more secure method would be to use parameterised queries with PHPs prepared statements as follows:
$stmt = $dbh->prepare("SELECT * FROM posts WHERE json_column LIKE '%\"?\"%'");
$stmt->bindParam(1, $id);
I am having this piece of code:
$result = mysqli_query($con , 'SELECT * FROM messages WHERE group = "'.$_POST['group'].'" ORDER BY date '.$_POST['order'].'');
I don't understand why it is always returning me false. The variables $_POST['group'] and $_POST['order'] aren't empty .
$_POST['group']='PHP'
$_POST['order']='DESC'
The conecction to the database is corect too.
GROUP is a mysql reserved word and needs to be quoted using backticks;
SELECT * FROM messages WHERE `group` = ...
You're also wide open to SQL injection, you should never add un-validated/un-escaped POST data in string format to your SQL. The safest way to do queries with user data is using prepared statements, or - as a less secure alternative - escape the data using mysqli_real_escape_string.
$result = mysqli_query($con , "SELECT * FROM messages WHERE group = '".mysqli_real_escape_string($_POST['group'])."' ORDER BY date '".mysqli_real_escape_string($_POST['order'])."'";
Try formatting the query like this and see if it helps your result. I also added mysqli_real_escape_string() to escape your input, as your query was wide open to SQL injection.
http://php.net/manual/en/mysqli.real-escape-string.php
I'm trying to do a SELECT * from a table, where the name of that table is itself taken from another query. I think I'm tying myself in knots. Here's what I've got:
SELECT options_table INTO #tableName FROM registrant_fields WHERE id = 9;
SET #sql_text_1 = concat('CREATE TABLE tmp_options LIKE ', #tableName);
PREPARE stmt_1 FROM #sql_text_1 ;
EXECUTE stmt_1;
SET #sql_text_2 = concat('INSERT tmp_options SELECT * FROM ', #tableName);
PREPARE stmt_2 FROM #sql_text_2;
EXECUTE stmt_2;
SELECT * FROM tmp_options;
DEALLOCATE PREPARE stmt_1;
DEALLOCATE PREPARE stmt_2;
So... when I paste that lot into PHPMyAdmin and run it, I get the results of each statement appended respectively, and learn that yep, my "SELECT * FROM tmp_options;" has indeed got some rows. But how do I GET them??
All I want to do is drop that query into a PHP string and run it with mysqli_query(). Is that not going to work?
I have no clue about PHP, but I happen to know that mysqli_query() works with one SQL statement only (for security reasons).
I'd suggest you do (pseudo code, except SQL parts)
somePHPvariableForTableName = ("SELECT options_table FROM registrant_fields WHERE id = 9;");
query("CREATE TABLE whyDoIneedAtmpTable AS SELECT * FROM $somePHPvariableForTableName");
query("SELECT * FROM whyDoIneedAtmpTable;");
and that's it. No need for that extra INSERT step. And it's not clear, why and if you really need a temp table.
Simple question: how can I protect so that when the user inputs "union select" in a field and then sends it as a parameter to a query mysql won't give an error.
Should I simply check if "union select" is inputed or there are also other keywords that could result in a mysql error?
Here's the SQL protection function I use now:
function sql_protect(&$n){
$n=stripslashes($n);
$n=mysql_real_escape_string($n);
$dntwant = array("\'","\\", "/","\"",")","(","<",">","\\r\\n",";","*","%");
$n = str_replace($dntwant,"", $n);
}
The query has something similar in it:
where column1 like '%$user_input%'
You need two things
Either use PDO, no checking needed PDO does everything.
Or use :
$var = mysql_real_escape_string($_POST['var']);
$query = "SELECT * FROM test WHERE var = '$var' ";
// ^ ^ These single quotes are vital!!
This is all you need to do, forget about stripslashes, and str_replace.
If you want to use dynamic database/table/column names, or you want to inject numbers for the limit clause, be warned mysql_real_escape_string will not work. Neither will PDO.
Nothing will work except for checking the input you are about to inject against a pre-approved whitelist.
See this question on how to do that: How to prevent SQL injection with dynamic tablenames?
Try to prepare and execute the query:
$stmt = $db->prepare("SELECT * FROM test WHERE column1 LIKE ?");
$stmt->execute(array("%{$user_input}%"));