SQL Injection DROP TABLE not working - mysql

I need to demonstrate SQL Inject using PHP/MySQL. I want to inject a DROP TABLE query in a login form but it never works. (TRUNCATE table works fine OTOH).
After I input '; drop table users; # as field input; query turns out to be
SELECT * FROM `users` WHERE `email` = ''; DROP TABLE users; #' AND `password` LIKE '3232';
But it never works using mysql_query() function. When I copy/paste this query in PHPmyAdmin directly, it works perfectly and table gets dropped. What can be the issue?

MULTIPLE SQL Execution is not enabled by defaults.
So SQL Injection like ;drop table won't work. please enable multiple sql execution. this could be enabled like http://php.net/manual/en/mysqli.quickstart.multiple-statement.php if you are using mysqli.
useful SQL Injection is :
SELECT COUNT(*) FROM users
WHERE user_id = '$user_id' AND passwd = '$passwd'
and user inserts passwd to ' || '1' = '1.

This is not possible in php/MySQL as php does not support stacked queries. The moment you inject semicolon (;) it will fail.
You can do many other much more creative exploits using sql injection in a php-mysql application though.
Enumerate all databases
Table Names and Column Names
Values stored in tables
Upload a php backdoor
Check Out for SQL-Map as well.

Related

My SQL Syntax error for multiple commands in one query, working for each command running separately

I'm trying to run the following MySQL command:
USE database_name;
DROP TEMPORARY TABLE IF EXISTS only_with_balance;
DROP TEMPORARY TABLE IF EXISTS keys_to_match;
CREATE TEMPORARY TABLE only_with_balance as (
SELECT
*
FROM
transactions t
WHERE
t.balance is not NULL
and (t.transaction_status_id = 4 or t.transaction_status_id = 5)
and (t.date between "2022-05-01" and "2022-08-24" )
);
But I'm getting a syntax error while trying to run the all the commands at once.
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DROP TEMPORARY TABLE IF EXISTS only_with_balance;
DROP TEMPORARY TABLE IF EXIST' at line 2
When I run each command separately, the result is the expected.
Can someone help me here?
What am I forgetting?
In MySQL, by default the query interface only allows one SQL statement per call.
There's an option to enable multi-query per call, but it must be set at connect time. Some MySQL connectors do this by default, or allow it as an option, but some do not. You didn't say if you're writing code or if you're submitting this set of queries through a client (though you tag the question 'dbeaver' you don't say anything else about that). So I can't guess what interface you're using for these queries.
Anyway, there's no advantage to using multi-query. The default mode is one SQL statement per call. That's what I do.
Using the default mode of a single SQL statement per call has some advantages:
Supports prepared statements and bound parameters (you can't run multiple statements in a single prepare call, even if you enable multi-query).
Simplifies processing errors and warnings.
Simplifies processing result sets.

How can we prevent SQL-Injection from MySQL?

We all know that we can prevent SQL-Injection in PHP by Prepared Statement of query or mysqli_real_escape_string() function. But if i want to prevent it from MySQL side ? Do you have any idea? How can i achieve it ?
You can use stored procedure to query the database. The stored procedure checks the data type and parameters supplied, if there is a mismatch a query is not executed.
Here is a sample of stored procedure you can use to insert a record in mysql -
DELIMITER $$
CREATE PROCEDURE book_Insert (
in title varchar(30),
in isbn varchar(30),
out bookID tinyint(3) unsigned
)
BEGIN
insert into books (title, isbn)
values(title, isbn);
set bookID =last_insert_id();
END $$
As the comment from #Ferrybig says, on the MySQL side there's no way to be sure that an SQL query is legitimate or the result of SQL injection.
Suppose the database server receives this query:
SELECT col1, col2, col3 FROM MyTable WHERE account_id = 1
UNION SELECT user, password, NULL FROM mysql.user
This looks pretty suspicious. Why would the app want to read all passwords, and append it to the query we expect to see? There's a strong chance this is an attempt at hacking.
Another example:
SELECT col1, col2, col3 FROM MyTable WHERE account_id = 1
OR account_id = 473
Is this legitimate? Or is it illicit? Is the query executed for a user who should have privileges to read data for account 473? How can you know? On the MySQL side, the query looks exactly the same whether it was the result of SQL injection or not.
It might have been code like the following PHP, which is vulnerable to SQL injection (this is not a failing of PHP, because similar vulnerable code can be written in any programming language):
$sql = "SELECT col1, col2, col3 FROM MyTable WHERE account_id = " . $_GET['id'];
If the attacker caused the input parameter to be: "1 OR account_id = 473"
The point is, once the query is formatted in the app and submitted to MySQL, MySQL can't tell how it was formatted. MySQL can only trust that the developer of the code did format the query in a safe way.
One method of blocking illicit queries is by using a type of Web Application Firewall (WAF) that you design to recognize legitimate inputs and block requests that are not legitimate. In other words, you need to program the WAF with a whitelist or set of patterns to recognize safe requests. This list will be unique for each app, so you need to be very familiar with the app. Any modification to the app may require you to update the WAF's whitelist.
The WAF is typically a proxy at the http layer, to prevent illicit request from reaching the web app. There are also proxy solutions to protect the request between the app and the database. You program the proxy to recognize which SQL queries are expected, and it blocks any queries that have unexpected terms. It would
An example of a database firewall is https://www.oracle.com/database/technologies/security/audit-vault-firewall.html
They aren't perfect. They may block queries you want to allow. And they don't work for dynamic queries run in stored procedures.
Ultimately, you should just establish safe programming standards in your application code. Use query parameters whenever you combine unsafe data with your SQL queries.
You can use
assuming that you input a parameter $bookID
DELIMITER $$
CREATE PROCEDURE `spGetBook`(
in bookID int)
BEGIN
SELECT *
FROM categories
where bookID=bookID;
END $$

what sql injection can do to harm you

The following is a textbook sql injection example:
SELECT id FROM table WHERE username = '$username' AND password = '$password'
if your site doesn't protect against sql injection you can simply send in password = anything' OR 'x'='x as the input and login without a password. easy.
attacker can also pass in '; DROP TABLE table; to drop the table from the db. And of course if the sql connection does have DROP permission than it will not work. Also attackers probably want to get more benefits by doing something other than simply dropping your table.
So the question is can the attackers carry out attacks to do UPDATE on table, get the structure on all tables, list tables or db by only attacking this vulnerability?
p.s: not that I want to use it to attack people but I am kinda curious what could happen at worst on my db..
Potentially, sure. If you can inject a DROP TABLE table; into the SQL statement that is executed, you could just as easily inject an UPDATE statement that modified whatever rows of whatever tables you'd like. You can also frequently add or modify a SELECT statement to show you information that you're interested in. For example, if you have a query like
select name
from people
where person_id = '$person'
you could inject something like
anything` union all select table_name from information_schema.tables
to produce a statement like
select name
from people
where person_id = 'anything'
union all
select table_name
from information_schema.tables
to show you all the tables. You can do the same sort of thing to get a list of columns in the tables and then start running queries to see what data is in the various tables.

Need readable pure SQL equivalent of SQL Closures code

Have you heard of SQL Closures or any library that implements them ?
They allow to execute this script in SQL command window (or put it into SP):
exec closure,"
rec{select db=name from sys.databases where name like 'corp_'},{
use |db|
rec{select tbl=name from sys.tables where name like 'user_'},{
for{col},{Created,Modified},{
def_col {
|tbl|.|col| datetime not null default(getdate()) ix
}
}
def_col {|tbl|.deleted datetime ix}
}
}
"
This script will make sure that Created not null, Modified not null and Deleted indexed columns exist in all tables with prefix user_ in all databases with prefix corp_.
def_col will create new column or alter existing column to match desired definition. It will also create/recreate non-unique ascending index for each of these columns.
def_col will drop and recreate dependencies as needed (constraints, indexes, foreign keys, schema bound views and functions).
rec and for and def_col will catch errors and log them into error table or raise immediately depending on context options for easy debugging and tracking of errors during script execution should they happen.
As you can see, the script can be executed many times without failures, it's just second time it will not change anything.
Is there a more readable, supportable and compact way to achieve the same functionality in MS-SQL ?
If yes - please post example in your answer.
Is more readable, supportable and compact way available in MySql, Oracle or other major flavors of SQL language ?
I do not see any reason you could not create simple SQL Server Groups in SSMS, and register your servers against those groups and run your DDL from there. You could also do it with SQLCMD, or Powershell.

sql developer mysql to oracle migration

I successfuly migrate mysql to oracle. But the only problem is case sensitive on table name and fieldname.Some pages in web said go to tools and option in sql developer and tick the ansi but i cannot find it.
On oracle website forum said it part of migration .
Anybody had new version of sql developer and migrate from mysql ?
E.g
calendarColor become CALENDARCOLOR
I really don't see how this is a problem. Since Oracle's objects are case-insensitive by default, you can continue to query them using SELECT * FROM calendarColor.
If you need them to be case sensitive, use quotes, like:
CREATE TABLE "calendarColor" ( ... );
SELECT * FROM TABLE "calendarColor";
See also: Schema Object Names and Qualifiers
If the table was created using
CREATE TABLE calendarcolor ( calendarColorId NUMBER(10,0) NOT NULL );
then the table name is stored in uppercase internally. When you run a statement like this:
select * from "calendarColor"
then you are telling Oracle: The table name should be treated case-sensitive but as there is not table named calenderColor, only one named CALENDARCOLOR your statement fails.
The fix is very easy: remove the quotes and change the select to
select * from calendarColor