Let's not go so far as to say that I'm paranoid, but I've been spending hour after hour learning how to prevent SQL injections (and XSS for what it's worth).
What I'm wondering is that a SQL injection doesn't seem like it would do permanent harm to my database if I've made daily backups. Doesn't importing yesterday's copy of my tables just restore them and then I can be on my merry way?
As far as actual loss of data goes, you're mostly correct - you'd lose any changes made in the past day, but aside from that you'd be back to a functional database.
However, there are other things that, just because they aren't "lost", doesn't mean it isn't bad that they got compromised. These kinds of things are stuff like user account info (and especially password hashes) - things that people use to protect their accounts and, if discovered by the wrong people, can lead to malicious usage of their information and resources.
That's why you have to work to avoid security breaches in the first place rather than simply rolling back any changes.
This is a very dangerous way to think. Yes, SQL injection attacks will usually trash the database and thus instantly crash your web app, after which you (somewhat) merrily restore from backup and go on your (somewhat) merry way.
On the other hand, they may simply blow away or alter a few records at random, so that it takes you weeks or even months to discover that your data have been getting slowly corrupted over a long period of time. Good luck recovering from that.
Worse still, the SQL injection attack might be designed to steal data rather than damage it. An attacker might figure how to get your web site to deliver a bunch of credit card numbers in response to a nominal request to edit their profile.
Yes, unless the table contains user-sensitive and/or XSS-injected data. Then you've another problem to fix. Always sanitize on SQL injections during constructing SQL queries and always sanitize on XSS injections during displaying client-controlled data in HTML output.
Other people have noted that you've partially addressed the issue of data loss (restore from hopefully recent backup) but missed the issue of data theft.
There's another potential issue. Many SQL servers allow you to execute arbitrary system commands (e.g. MS SQL). Others (e.g. MySQL) let you write arbitrary files (see also this article on exploiting MySQL injections). The bottom line is that an SQL injection attack can compromise the whole system, and thence onward. Of course, there are configuration options to disable some of these, but they're real concerns.
If you want recommendations, I suggest PDO with prepared statements.
Related
I am going to get into database designing and PHP. But when I do I am very worried about SQL-Injecting. Is there anyway to reverse this when it happens. Like auto reset it, or delete the account thats hacked, or close the databases. Also is there a way that it can be Auto-Tested for intruders?
This is an immensely complex question.
Short answer is: No, if no backups exist
The long answer:
You should mainly focus on how to prevent sql injection, for example using prepared statements is a good method to prevent these attacks. Regardless of potential sql-injection vulnearbilities regular backups should be made and stored at a different physical location. The datacenter of the server with the database might burn down and your data is gone. Though this is very unlikely to happen it is not impossible.
Depending on the importance of the data in your database there are ways (for example cron jobs) to do backups weekly, dayly, every hour and so on. If you have a second server you can write a script that sends the backup to the seconds server or you log in from time to time and download them.
You could also log all interaction and changes in the database but reversing the damage done in this way is not practical.
This link might be interesting for you: Prevent SQL Injection in PHP
If you get a SQL injection the attacker gets the same privileges as your application, they can delete or change whatever they want so basically you're out of luck. You can restore your database from a backup but then you'd lose whatever changes happened between the backup and the attack.
Instead of trying to detect and revert SQL injection you'd better avoid allowing them in the first place, a good way to avoid SQL injections is to use PDO's prepared statements.
To put it simply, if it happens, you pretty much already lost. Disconnect the database from the internet and assess the damage, dump the damaged version for later analysis or whatnot, and restore to the closest non-broken backup, is probably the best course of action in most situations.
But what you should do is prevent it in the first place.
While it is possible to do escaping and/or pattern checks, it is much better to solve it with prepared/parameterized statements and/or object-relational mapping.
A lot of the major frameworks comes with some form of ORM, and unless you are either super-confident about covering all security holes or in a situation where security is completely optional, I seriously recommend you to use something like that.
Aside from SQL injection, this will also protect you from a variety of other security risks, and help you in other ways.
For example, have a look at FuelPHP.
I Just noticed that my mysql_real_escape_string function is not inside a '' in some of my php scripts and it was vulnerable to injections and things like sleep(30) executed on my production site.
I am going the PDO route and implementing the prepared statements after lots of reading here. but this is not implemented yet.
Few questions, I see in my logs that lots of injections where done by people online but I can not see any damages. the user that the site runs to do sql queries has update/select/delete/insert only privileges.
But I am woried things like sleep(30) and what not works and if they did any damages I am not seeing?
Can you tell me where to check for damages or was I safe for at least major damages?
Can they have changed hidden mysql settings or system settings?
By the way, I tried to run latest updates on centos 6+ linux and php.
Thanks
edit:
just to clarify, the database is empty almost and i am not worried about the data being there and the passwords are hashed sh512. so the data inside is not important since this is a new application i am writing. but i am worried if they changed anything on the system or the db i should be worried about. some of the injections i see have java etc but the log is huge and its going to take time to go over it. i also see some schema strings in the injections.
now the question is can they have read my schema info or modified them? why does functions like sleep are working if it is a restricted user? what other functions could they have run?
note i have other DBs in the same MySQL. should i be woried about those?
by '' i mean:
select * from dbname where id=scaped_string
i should have put it in quotes
Checking for damage done to your data is dependent on the kind of data you have in your database. If after careful inspection you don't see anything wrong, then there is probably nothing wrong. If your data is of any decent size, this will be difficult or impossible.
There are many automated bots roaming the internet looking for code vulnerable to SQL injection attacks. Their attempts are probably what you are seeing in your logs. Just because an attempt was made does not necessarily mean an intrusion occurred.
Also keep in mind that you won't necessarily have evidence of data being stolen. The best way to determine this would be to take your server logs and replay them on a copy of your current server, checking to see if you get any data back.
Without any further information, we have to assume the worst case: An attacker is able to read, write, and delete arbitrary data in your database, and possibly even files on your file system, which may lead to compromise of your whole server (e.g. command execution via PHP file, privilege escalation, etc.).
Now let’s have a closer look at the possible impact:
Since PHP’s MySQL extension does not allow multiple statements, so called stacked statement attacks are not possible. So the remaining possibilities depend on the actual statement verb and the context, i.e. the clause inside the statement:
SELECT statement:
Reading any accessible data (e.g. sub-queries, unions, boolean-based blind, etc.)
Reading files (LOAD_FILE())
Writing files (… INTO OUTFILE …)
UPDATE statement:
Obviously updating any accessible data, possibly not just in the current table
Reading any accessible data (e.g. sub-queries, boolean-based blind)
DELETE statement:
Obviously deleting any accessible data, possibly not just from the in the current table
Reading any accessible data (e.g. sub-queries, boolean-based blind)
INSERT statement:
Obviously inserting arbitrary data
Reading any accessible data (e.g. sub-queries)
Some of these may not have a direct impact but may be used to exploit other vulnerabilities. In the end, it depends on the actual vulnerable statement.
As far as I know, there is not hidden mysql setting other than sanitizing your inputs to protect your data from being injected.
You said, you saw lots of injections done by people into the site, and yet you can not see any damage, maybe they were just injecting a plain HTML tags, or trying XXS attacks, because the real mysql injection, can delete your tables, update, reset every data subjected to mysql injection, so if I were you, I would implement PDO right away.
If you have anything like admin panel you should check for webshells and other backdoor-like tools on your server, because attacker could easily read your credentials from appropriate table. And, ofcourse, look for any changes in your pages (look for iframes and suspicious JS code).
Worst case scenario is executing INTO OUTFILE in writeable directory and then accesing it via local include or directly.
But, first of all, before worrying you should consider this as most common automated sql-injection checkers (bots you might say) and if you don't see any damage - mose probably there was no intrusion. But be careful - most intruders nowadays don't look for any visible damage, most probably they will inject some malicious code in your pages (like iframes with their exploits).
So, don't be too paranoid, but still cautious :)
As we know as usual sites use functions like mysqli_query() and mysql's PHP driver does NOT allow multiple queries in a single->query() call (But you can do as many in phpmyadmin SQL running section) so we cannot directly add DELETE/UPDATE/INSERT but abusing of possibilities to modify data under some circumstances. The 1st thing is that in that case I think 80% of potentially being at risk (maybe lost of data) is gone! & the 2nd one is, rely on this knowledge, why most of injecting tutorials are based and focused on multiple queries?
80% of potentially being at risk (maybe lost of data) is gone!
This assumption is wrong.
why most of injecting tutorials are based on multiple queries?
Because it's just a simple understandable example, a proof of concept. Just like one "If John have 2 apples and Mike five...". If real Mike doesn't feel like to spare his apples, it doesn't mean that arithmetics is all wrong.
SQL Injection Concudrum
There are NO conundrum in injections.
There is no point in musings on injections.
There is no percents of risk to be calculated but just a dichotomy: either you have your application compromised or not.
There is just one simple rule - always format your data properly, and you will forget of injections forever.
PHP for a long while has disallowed multiple queries running for a single query() statement. This is just part of preventing sql injection. You must also escape your inputs, use prepared statements, make your table names and columns hard to guess and such.
The simplest example of an sql injection attack does involve a query that's tricked into executing more than one query, but obviously php prevents a lot of such attacks by the limitation already mentioned. However, things like subqueries are still possible, so it's not fool proof. I don't think it's possible to make sql injections altogether impossible as people keep finding new ways to trick scripts.
The best you can do is know how such attacks are done and write your code according to currently accepted best practices to prevent such attacks. If you've done all this and still get hacked, then probably (but not certainly) it wasn't your sql that was the weakest link in your security. From what I understand, more often hackers succeed using social engineering techniques.
Making an un-hackable system is nigh impossible, so the best you can do is make it difficult to hack and thus, not be the 'low hanging fruit' or, in other words, don't be an easy target.
I'm finishing up my first "real" PHP application and I am trying to make sure it is secure. I'm kind of afraid that since I'm not an "expert" PHP programmer that I might be missing something huge, so I would like to give you some information about my application and hopefully you can tell me whether or not that is the case. So here we go:
I'm using a CMS to handle user authentication, so I don't have to
worry about that.
After discovering PDO shortly after starting work
on my application, I ported all of my code over to using prepared
statements with PDO.
I am escaping all form and database data (even stuff I think is safe) which is being output with htmlentities().
My application does use a session variable and cookie variable, but the function of both is very unimportant.
I have designed my form processing functions in such a way that it doesn't matter if the form were somehow altered, or submitted from off-server (i.e. I always check the data submitted to ensure it's valid).
I have done my best to make all error messages and exception messages polite but very obscure.
I'm forcing pages with sensitive information (such as the login page) to be served over https.
When I first starting writing my application, I didn't know about prepared statements, which is kind of a huge deal. Have I missed anything else?
OWASP maintains a list of the Top 10 Most Critical Web Application Security Risks (warning, PDF download). This is from 2010, but I think it still applies, perhaps even moreso now.
Injection and XSS are the top two, but you should certainly be aware of the other 8. If you are using an existing CMS, many of these may already be considered, but the more popular the CMS the more you risk running into vulnerabilities because of black hats trying to find holes in it.
If you are not storing critical data like credit cards, order history, addresses, and even emails, then I wouldn't worry too much about your site being affected as long as you are taking the basic precautionary measures (and it sounds like you are).
If you are concerned about security issues, a good resource is the OWASP - Top 10 Application Security Risks
The most important thing to take care in web applications(specially PHPs') is Data Validation of all the inputs taken from the user which are further saved in your database.
For a secure application, all the transactions should be done on HTTPS. For a secure cookie management Secure and HTTPOnly cookie should be implemented.
Some more points I don't see mentioned yet. Most of these are not related to code - I am not sure if you only wished for things related to code, but I'll mention them anyway.
Backups (user data). should be self-evident
Version control. If you have a big bug, you want to have access to the previous version.
Audit trail, alarms and logging. If you do get into trouble, how will you find out? Are you able to track down what happened? if you know something is wrong but don't fully know what, are you able to diagnoze the issue?
Hosting. Where are you hosting? Do you have adequade bandwidth and monitoring? What happens if you get DOSed? Are you able to block out unwanted traffic?
Caching. Can you change it if needed?
There's always one thing left. Availability :) There are three aspects of security:
Confidentiality (Noone can read what they don't have access to)
Integrity (Noone can change any data what they should have to and you have to be able to detect if it happened even so)
Availability (The data, application whatever has to be available)
You pretty much did a nice job and took care of the first two (credentials, prepared statements, htmlentities...) but none of them will help against a DoS attack. You should be able to detect if someone slaps your site and ban the attackers ip from your server. Although this can be done in PHP (still much better to kick the attacker at the first line of php than let them initialize the framework, database connections etv.) it can be done mre effectively in lower layers (for example: nginx/apache, iptables, snort).
However what you're asking for that usually comes to the matter of risk management. In a real application you're not able to be prepared for all the possible attacks, edge cases etc. What you need to do is classify all the risks by the probability and the impact ( http://www.jiscinfonet.ac.uk/InfoKits/infokit-related-files/Resources/Images/risk-matrix ). With this you can focus on the most important (highest) risks first and probably you can completely ignore the lower bottom part.
SQL Injection and XSS are the most prominent Hacking methods.
You are covered from SQL Injections if you use prepared statements.
Also, if htmlentities() on everywhere you display HTML you should be safe.
More of a risk assessment question than technical.
So i have been reading a lot about protecting against SQL Injection. Lets assume i have a large web application that is mostly unprotected and i need to make some improvements to protect against this problem. Read large as lots of SQL interaction using dynamic queries but on few (less than 100 registered users).
My question is... If i have already secured the main login script (the only publicly available user input) using parameterized queries, is it really that necessary to do the same work for the rest of the site? I mean if a potential attacker can't log in, how much other damage can he do?
Assuming of course none of my registered users have malicious intent.
Assuming of course none of my registered users have malicious intent.
Never assume that :) If your users have different rights, one with almost no right could find the way to get admin access... And so on.
Also, protecting against SQL injection does not make your login bulletproof and someone could bruteforce through it or simply have sniffed packets from your trusted users. Make sure you protect your whole application, do not assume that the entry point you planned (login script) is the only one available...
And please use SSL if your website contains or requires any sensitive data from your users.
What makes you sure that none of the legitimate users won't attempt to attack your system?
I'm glad my bank don't think that. Some-one would have emptied my account by now, just by using sql injection attacks.
And even then you should be careful about accidents. If you use parameterised queries, someone using a ' in a value won't cause problems.
It allows type safety in your parameters.
It engenders better programming habits.
It allows execution plan caching. (Without it, every query with a different parameter will look like a completely different query. Not only preventing caching of plans for those queries, but over-filling the cache so plans that really can be re-used get discarded.)
Not only is it more secure, it's more reliable. Other than experimentation and throw-away code, I can think of no project where I would have condoned not using parameterised queries.
Never trust your users!
Even if you do (and nobody can sign up either), there's always the potential of CSRF for instance; an attacker would lead users of that system to a seemingly harmless page with an image. That image would have the following code:
<img src="http://yourserver.com/profile?user_id='; DROP TABLE users" />
My hacking skills are practically zilch, but you can imagine what would happen :)