I've searched around and found a way to do exactly this. But I'm hesitant because I occasionally read that its a "security risk". Unfortunately, nobody ever elaborates on why. I, personally, can't think of any security risk that wouldn't involve an attacker already having permissions they shouldn't. The MySQL/PHP servers are running on the same machine. so there's no public requests between the MySQL and PHP.
The PHP script triggered, will make an API call to a web service on a third-party CRM/ESP that keeps a simplified version of certain tables on a their server. Our marketing team could then log into the CRM's GUI and send emails, gather information, and plan marketing campaigns without the need to bother the dev team.
The tables on this server do not mirror ours, they contain only information they would need. The reason I want to use triggers is to keep their information as up-to-date as possible and have that logic in one place, instead of scattered throughout the project.
UPDATE:
I always sanitize/validate any Forms that touch MySQL. I never store PHP in my tables. I never use FTP (SFTP using a .pem instead of a password).
The script that will be executing will be a single file I created that won't change which is going through the same framework I'm using (zend). The only variables passed to the script will be the row's id (which will be validated as an INT).
I'm thinking of not doing this because of performance. And making PHP execute Asynchronously is possible, but difficult and not worth my time to implement. But I'm still curious, Other than the performance penalty, how would the security concerns be any different than say a web service? I mean you definitely have to sanitize/validate just like you would a web service, so given that, what concerns would there be?
There are different ways your app can be compromised, such as SQL injection, a sniffed FTP password, or a vulnerability in the code itself. It is generally a good idea to keep these things as localized as possible to prevent a breach in one area from cascading.
For example, say that you are storing sensitive data in your database. Typically, you would encrypt this data somehow, using a salt and key that is not stored in the database itself. Then, if your database is compromised by SQL injection, the attackers may cause damage, but they will not be able to steal the sensitive information. However, if you are executing PHP stored as text in your database, the attacker will certainly realize this and update it to execute his code, from whence he can figure out how you are encrypting the sensitive data and unencrypt it.
In short, SQL injection is very common (even if you are following best practices, nobody says the intern who walks in next year will) and it is therefore not safe to execute code stored in a database.
EDIT: after reading your link more closely, I need to restate some things. I don't see a particular security risk in this, but this seems to really contravene the separation of data and logic. Further, mysql is not async and there is no way that this can possibly scale under load...
Related
I wanted to know why isn't easier and more secure to have one database service, dedicated only to user authentication (withholding usernames and passwords) which would be well secured (inputs well sanitized etc.)
And another database service for all the other data in the website which would be possibly less secured and available for serving web content.
Wouldn't it be a good way to prevent a lot of the SQL injections happening these days?
No. There is a difference between sanitizing inputs and protecting passwords. SQL injection can happen in any query, and allows someone not only to steal, but also to destroy data. This should be prevented at all times.
Regarding usernames and passwords, there are additional measures to take. For one, don't store passwords at all, but always store hashed versions, hashed with a salt. Furthermore, you might put the authentication in a different database or even some authentication service if you like, but like I said, that's extra.
Of course, if you got a big bunch of data that is read-only from a website perspective, you might store that in a different database, or at least make the website connect using a database user that doesn't have any rights to modify the data. That way, the data is better protected against destruction, because errors on the website, SQL injection and even leaking of the username and password will not lead to destruction of the data. But this also goes for both the user credentials as the 'less important' data.
You seem to miss two points :
the rest of your data also should be secure (or else there's no point in securing the application)
you don't store passwords. Never. You only store a hash built from the password, the username (optionally) and a record specific salt. So it's not so important to secure that base, it only is done to prevent impersonation
As there's no reason to secure in a greater manner that part of the DB, just ensure the whole is correctly secured, it's so much easier to manage one DB than two TB. Trying to keep different types of data in different RDBMS and to maintain their coherency is a nightmare.
Lastly, note that this shouldn't change anything regarding to mysql injections. Just don't allow those injections by using prepared statements.
This is a tough quesiton. Indeed you can have two databases one for sensible data, the other for "furnishing".
Let's put it this way: even if you use a database only for "furnishing", what happens if that database get hacked ? Will your users have to see "THIS SITE WAS HACKED" in the section or...? :)
EDIT: What is protection? Protection is when you buy a coffee and you don't want your friend or someone to drink it. Then what if you buy a coffee and a muffin. Would you protect only one ? Would you protect both ? Which one is more important for you ? If you're like me and most people you would say both. What you made me understand by commening is that muffin (users) is more important than something else (furnishing).
Why would you need protection, if you don't care about the coffee ? Probably because you don't really value coffee enough to protect it. Then let me say this: the money you used to buy your coffee were worth when they were still money, but now they're coffee, what's changed apart from their shape ? Nothing.
Now let's get back to our case: if you have a simple database which contains only "furnishing" texts like "TITLE", "DESCRIPTION" etc. Having them lost isn't bad ? Won't you have to go there and fix them ? Won't you have to WORK to get everything pretty ?
Not to speak that most vulnerabilities related to a database might get pretty worse than just losing only ONE database. Having a sql injection issue might get all database destroyed, that's the danger you're trying to avoid. So, it's almost pointless to try to secure a database more than another. Try to secure everything instead, you'll be sure that everywhere you go, nothing could happen.
So you fear a special inmate, and you secure him A LOT, and trascurate that old cell. You look away, the inmate in the old cell is now out of his cell! And worse, he freed the special inmate (and everyone else). That's the kind of security hole a sql injection imply.
I think you need to look deeper into your RDBMS protection layers to get a better picture why they are better in the same instance.
Let's take for example your MySQL database:
an instance is made out of 3 + databases (mysql, information_schema, and all others you create).
so you already have a separate database repo that is handling the auth + user + pass - and that is your MySQL database.
There are ways to develop applications that are hacker free - when working with MySQL most of the coders use open SQL code (inline SQL) - and this is the problem - hackers will take advantage of this! To fix this use stored procedures (encapsulated).
Inside database privileges are a problem as well - lazy developers or stupid DBA will give extra rights for application users. Your idea is redundant from many points of view. More instances will cost you more money, more resources, etc.
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 :)
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 :)
Everything I find on the net tells me to provide the database user and password to connect to the database.
Being paranoid as usual, I don't like this because it means anybody that has the php source can now log into the database and screw with the data. Is this the only way to access the database?
context: http://www.cyberciti.biz/tips/facebook-source-code.html
Yes, it is the only way. Also, as a paranoid you should know that knowledge of login and password is not enough, but you have to login from the right host (which is permitted to log in with this credentials).
Also, as a paranoid, why are you afraid of stealing your sources and not afraid of having vulnerabilities in your code that will allow a hacker to steal data even without login and password? In this case it is better for paranoid to never program at all.
Since PHP will be parsed by the interpreter and only HTML will be output, you need not fear as there will be no way to get hold of the PHP source (guessing that you have set appropriate measures so that the PHP source cannot be downloaded).
Block all traffic to the MySQL server from outside. Only allow localhost to use it.
It's not the only way, but its the way most of the world (like 99.999%) does it, and as far as I can tell, 100% of web programmers.
Consider this: if the password is hardcoded into the source somewhere, why bother? Why not make the account password-less and just limit its access to the web server? Some might say, "oh noooooes!! Don't do that!" But again I ask, what's the difference? What security hole is opened that is not there anyway?
The real security issue is actually protecting yourself from SQL injection. That wide-open account makes you vulnerable if:
1) You have a glitch in code that can be exploited to do something a user is not supposed to do, or
2) They can trick your db server into executing code via SQL injection.
So SQL injection is your big bugaboo to protect against.
There are secondary protections as well. For instance, most people are paranoid about their "users" table that contains users and (unfortunately most of the time) plain text passwords, which are required if you are going to email a user their password.
You can put in a second level of protection on this table (in case they get past your SQL injection protection or find an exploit to make your program do something you thought it would not do) by locking it down so users cannot see it at all or write to it. Then you write two stored procedures, "addUser(username,password)" and "checkPassword(username,password)". This is an example of "security in depth" where you have multiple levels of security around the more sensitive data.
not a lot better but you an specify it in the php.ini
http://www.php.net/manual/en/mysql.configuration.php#ini.mysql.default-password
You need to provide the connection information somehow, but you can mitigate the risk by setting up your MySQL user to have as limited privileges as possible. So grant read/insert access only where needed, and you can set the user host to only allow connections from 127.0.0.1 too.
There are also commercial obfuscation products like http://www.zend.com/en/products/guard/, which might be of interest. I'm not sure if they include string encryption or not though.