So I just noticed one of my table have been dropped/deleted, I am using MySQL anyway I can trace or see logs of this?
I have no idea where to start look.
If you have binary logging enabled, you could probably see the DROP TABLE command in the binlog. However, that won't help you get the table back, of course. You would need to restore your data from a backup.
I hope you are keeping regular backups.
The next question is, why has this happened? Is your site vulnerable to SQL injection? Building SQL queries/statements with 'literals' from an external source, is inherently vulnerable.
For example: "select * from CUSTOMER where name='".cust_name."'", and all queries/statements like it, are vulnerable to attack.
Calling from the web such that cust_name=test';drop table CUSTOMER; supplies the closing apostrophe, issues a semicolon to complete the statement and then issues malicious commands which will be executed.
You should use parameterized queries and bind parameters explicitly.
See: http://en.wikipedia.org/wiki/SQL_injection
Related
I'm a java dev who uses Mysql Workbench as a database client and IntelliJ IDEA as an IDE. Every day I do SQL queries to the database from 5 up to 50 times a day.
Is there a convenient way to save and re-run frequently used queries in Mysql Workbench/IntelliJ IDEA so that I can:
avoid typing a full query which has already been used again
smoothly access a list of queries I've already used (e.g by auto-completion)
If there is no way to do it using Mysql Workbench / IDEA, could you please advise any good tools providing this functionality?
Thanks!
Create Stored Procedures, one per query (or sequence of queries). Give them short names (to avoid needing auto-completion).
For example, to find out how many rows in table foo (SELECT COUNT(*) FROM foo;).
One-time setup:
DELIMITER //
CREATE PROCEDURE foo_ct
BEGIN;
SELECT COUNT(*) FROM foo;
END //
DELIMITER ;
Usage:
CALL foo_ct();
You can pass arguments in in order to make minor variations. Passing in a table name is somewhat complex, but numbers of dates, etc, are practical and probably easy.
If you have installed SQLyog for your mysql then you can use Favorites menu option in which you can save your query and in one click it will automatically writes the saved query on Query Editor.
The previous answers are correct - depending on the version of the Query Browser they are either called Favorites or Snippets - the problem being you can't create sub-folders to group them. And keeping tabs open is an option - but sometimes the browser 'dies' - and you're back to ground 0. So the obvious solution I came up with - create a database table! I have a few 'metadata' fields for descriptions - the project a query is associated to; problem the query solves; and the actual query.
You could keep your query library in an SQL file and load that when WB opens (it's automatically opened when you restart WB and that file was open on last close). When you want to run a specific query place the caret in it's text and press Ctrl+Enter (Cmd+Enter on Mac) to run only this query. The organization of that SQL file is totally up to you. You have more freedom than any "favorites" solution can give you. You can even have more than one file with grouped statements.
Additionally, MySQL Workbench has a query history (see the Output Tab), which is saved to disk, so you can return to a query even month's after you wrote it.
I need to convince someone that he needs to sanitize the user input in addition to the user of stored procedures. well I know I sound crazy but I do not feel comfortable enough with store procedures only. My first reason is that I am able to cause errors in the stored procedure but because of the fact that the application itself handles errors such that error messages are coded it is difficult for outside to understand the what there are. but I still think that this is not secure.
Does any one has a suggestion ? or am I wrong to doubt stored procedures?
No it's not safe on it's own. You can also do in a stored procedure something like this:
SET #sql = 'Select * from products where name like ''' +#spinput+''' ';
exec(#sql);
With the wrong value in #spinput you can inject code.
However you can write stored procedures that are safe against sql injection.
Even if you use proper parameters, you can still mess with the database. You could insert a script that goes in as a parameter, but when it's displayed on a web page starts doing something it shouldn't. Use parameters to ensure your database is used as intended, but also sanitize the output later - never trust user-entered data.
Using stored procedures normally protects against SQL injection, but is not the only solution to prevent SQL injections, and it doesn't protect against all forms of SQL injection.
It's not the stored procedure itself that makes the big difference, but parameterised queries, which is the most common way to call a stored procedure. By putting the values used by the query in parameters, you let the database library handle them instead of having to escape them correctly yourself.
It's possible to write code that is safe against SQL injections without using parameterised queries, but it's difficult. You have to know exactly what characters you need to escape in a string for the specific database that you are using, and if you get it wrong you are pretty much as unprotected as if you didn't know about SQL injections at all.
If you use parameterised queries, then the step of sending the values into the database is safe from SQL injection, but the query itself might not be. If the query generates and executes SQL code itself, you have the same problem with escaping strings correctly. It's however not so usual to create SQL code in the SQL code, and if you do it you are very aware of that you are doing it.
My program restores a MySQL database from SQL file. If I wanted to display progress of SQL execution in my program, I would need to know the number of SQL statements in the file. How can I do this in MySQL? (The queries may consist of mysql specific multi-row insert statements)
I could use either MySQL command line tools or the Python API. You're welcome to post solutions for other DBMS too.
The simple (and easy) way: Add PRINT statements to your SQL script file, displaying progess messages.
The advantage (apart from the obvious 'it's hard to parse multi-statement constructs') is that you get precise control over the progress. For example, some statements might take much longer to run than others so you would need to weight them.
I wouldn't think of progress in terms of number of statements executed. What I do is print out feedback that specific tasks have been started and completed, such as 'Synchronising Table 'blah'', 'Updating Stored Procedure X' etc
The naive solution is to count the number of semicolons in the file (or any other character used as delimited in the file).
It usually works pretty well, except when the data you are inserting has many semicolons and then you have to start dealing with actual parsing of the SQLs, which is a headache.
I've got one easy question: say there is a site with a query like:
SELECT id, name, message FROM messages WHERE id = $_GET['q'].
Is there any way to get something updated/deleted in the database (MySQL)? Until now I've never seen an injection that was able to delete/update using a SELECT query, so, is it even possible?
Before directly answering the question, it's worth noting that even if all an attacker can do is read data that he shouldn't be able to, that's usually still really bad. Consider that by using JOINs and SELECTing from system tables (like mysql.innodb_table_stats), an attacker who starts with a SELECT injection and no other knowledge of your database can map your schema and then exfiltrate the entirety of the data that you have in MySQL. For the vast majority of databases and applications, that already represents a catastrophic security hole.
But to answer the question directly: there are a few ways that I know of by which injection into a MySQL SELECT can be used to modify data. Fortunately, they all require reasonably unusual circumstances to be possible. All example injections below are given relative to the example injectable query from the question:
SELECT id, name, message FROM messages WHERE id = $_GET['q']
1. "Stacked" or "batched" queries.
The classic injection technique of just putting an entire other statement after the one being injected into. As suggested in another answer here, you could set $_GET['q'] to 1; DELETE FROM users; -- so that the query forms two statements which get executed consecutively, the second of which deletes everything in the users table.
In mitigation
Most MySQL connectors - notably including PHP's (deprecated) mysql_* and (non-deprecated) mysqli_* functions - don't support stacked or batched queries at all, so this kind of attack just plain doesn't work. However, some do - notably including PHP's PDO connector (although the support can be disabled to increase security).
2. Exploiting user-defined functions
Functions can be called from a SELECT, and can alter data. If a data-altering function has been created in the database, you could make the SELECT call it, for instance by passing 0 OR SOME_FUNCTION_NAME() as the value of $_GET['q'].
In mitigation
Most databases don't contain any user-defined functions - let alone data-altering ones - and so offer no opportunity at all to perform this sort of exploit.
3. Writing to files
As described in Muhaimin Dzulfakar's (somewhat presumptuously named) paper Advanced MySQL Exploitation, you can use INTO OUTFILE or INTO DUMPFILE clauses on a MySQL select to dump the result into a file. Since, by using a UNION, any arbitrary result can be SELECTed, this allows writing new files with arbitrary content at any location that the user running mysqld can access. Conceivably this can be exploited not merely to modify data in the MySQL database, but to get shell access to the server on which it is running - for instance, by writing a PHP script to the webroot and then making a request to it, if the MySQL server is co-hosted with a PHP server.
In mitigation
Lots of factors reduce the practical exploitability of this otherwise impressive-sounding attack:
MySQL will never let you use INTO OUTFILE or INTO DUMPFILE to overwrite an existing file, nor write to a folder that doesn't exist. This prevents attacks like creating a .ssh folder with a private key in the mysql user's home directory and then SSHing in, or overwriting the mysqld binary itself with a malicious version and waiting for a server restart.
Any halfway decent installation package will set up a special user (typically named mysql) to run mysqld, and give that user only very limited permissions. As such, it shouldn't be able to write to most locations on the file system - and certainly shouldn't ordinarily be able to do things like write to a web application's webroot.
Modern installations of MySQL come with --secure-file-priv set by default, preventing MySQL from writing to anywhere other than a designated data import/export directory and thereby rendering this attack almost completely impotent... unless the owner of the server has deliberately disabled it. Fortunately, nobody would ever just completely disable a security feature like that since that would obviously be - oh wait never mind.
4. Calling the sys_exec() function from lib_mysqludf_sys to run arbitrary shell commands
There's a MySQL extension called lib_mysqludf_sys that - judging from its stars on GitHub and a quick Stack Overflow search - has at least a few hundred users. It adds a function called sys_exec that runs shell commands. As noted in #2, functions can be called from within a SELECT; the implications are hopefully obvious. To quote from the source, this function "can be a security hazard".
In mitigation
Most systems don't have this extension installed.
If you say you use mysql_query that doesn't support multiple queries, you cannot directly add DELETE/UPDATE/INSERT, but it's possible to modify data under some circumstances. For example, let's say you have the following function
DELIMITER //
CREATE DEFINER=`root`#`localhost` FUNCTION `testP`()
RETURNS int(11)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DELETE FROM test2;
return 1;
END //
Now you can call this function in SELECT :
SELECT id, name, message FROM messages WHERE id = NULL OR testP()
(id = NULL - always NULL(FALSE), so testP() always gets executed.
It depends on the DBMS connector you are using. Most of the time your scenario should not be possible, but under certain circumstances it could work. For further details you should take a look at chapter 4 and 5 from the Blackhat-Paper Advanced MySQL Exploitation.
Yes it's possible.
$_GET['q'] would hold 1; DELETE FROM users; --
SELECT id, name, message FROM messages WHERE id = 1; DELETE FROM users; -- whatever here');
Does anyone know of a way to embed comments in MySQL statements? When I search for mysql and comments I get only ways to put comments in tables, etc
The idea, if I implement this the way my boss wants it, is to prepend the user id to the statement apparently so that when MySQL is analyzed later (via the binary log) we know who did what.
Example:
SELECT id
FROM customer
WHERE handle='JBH'
Would now show up as:
-- user:jwilkie
SELECT id
FROM customer
WHERE handle='JBH'
(or similar)
EDIT FOR CLARITY: The reason for this is that we have perl modules that are interfacing with MySQL and we are retrieving the user id by reading $ENV{USER} (which in this case is "jwilkie"). It is a situation where we have one MySQL user defined but multiple people running the perl mod.
Does anyone have experience with this? Many many thanks! Jane
Normally, comments are stripped before the SQL statement is recorded in the binary log. However, a nasty workaround is to pretend that ypur comment contains syntax for some future version of MySQL - eg. 9.99.99:
/*!99999 user:jwilkie */ insert into tbl values (yyy);
These comments will then be passed through into the binary log.
If you have control over the SQL queries being generated, then you should be able to embed comments in them programatically in your query builder.
Select queries don't go in the binary log, but the comments may make it into the slow query log, general query log, etc.
Here's a blog post from Percona that touches on the subject a bit, specifically in the context of mk-query-digest. It might help:
http://www.mysqlperformanceblog.com/2010/07/05/mk-query-digest-query-comments-and-the-query-cache/