Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
How much important is it to secure the URL parameters naming? Is ?user_id=3 less secure then ?uid=3 or ?u=3 or just /user/3? Should I really consider making parameters hard to guess?
Obscurity is no security at all. The only reasonable factors to consider are readability/prettiness of links. If you have 200-character links, they are not memorable, and are kind of hard to paste, and consume a lot of space (e.g. can't send through SMS, and they're hard to type on a mobile); on the other hand, it's easier to have confidence in a link if you can understand its semantics.
The userid should be a session variable, and the session id should be in a cookie.
Some security information says to avoid all URL variables, but that is just security through obscurity. The point is, if it comes through to the user from any source $_GET, $_POST, $_COOKIE, $_SERVER, $_REQUEST, $_FILE... You need to sanitize it. By:
Using a white list wherever possible
Using RegEx and type checking all input before used
If it will be displayed, remove HTML
using strip_tags() [if there are some allowed tags]
or htmlentities() [prefered]
Use prepared statements (mysqli or PDO are common libraries that can do prepared statements for MySQL databases) for all database queries to prevent SQL injection
Use nounce to prevent XSFR attack and accident form resubmission
If its a file check mime type (not just the mime type in the $FILE array) before moving it
TL;DR: Using mod_rewrite is hide variable's real names might not be a terrible idea, and may make your urls "prettier" to the user -- but it is not a huge security gain.
In general, I have found that consideration of implementation is critical. Is this going to be used by you and a couple friends? It's probably less important, in that case, to worry about what you're naming URL variables.
If the data is sensitive, don't put it in the URL at all - this includes information specific to users, like passwords (which you shouldn't have in plain text anyway), password hashes, email addresses, private information, etc. I don't worry too much about usernames. If the info is important/sensitive, POST it rather than GET.
Using the .htaccess with some rewriteRules can make URLs much easier to remember - for example, website.com/page/1 is considerably more user-friendly than website.com?page=1, particularly when you get more than 1 variable in there. .htaccess rewriterules are not difficult to make, and can help your website look considerably more professional.
In terms of variable NAMES in the url, it again depends on usage. For example, "user=username" would be fine, or even "u=uname" or "uid=username" are acceptable, but if you're worried the user might easily find and change something, that's a big indicator that there's a problem: Not because the user could change something there, (even POST isn't secure, users can POST anything they want) but because your backend should be built to handle it, even IF your users change things in the POST/GET.
TL;DR: Putting GET variables in the URL bar is a courtesy to users. If they will appreciate or make use of it, do it - it's a nice touch. Users don't want you to put sensitive information there, and users don't want it to be too long. Any and all security should be done in the backend, where the user can't tamper with it.
It's a very good question. I do not think it needs to be - or can be - really secure to be honest.
And both have advantages. eg
Make it short and the url will be short. (too long urls can be a problem if you put urls together dynamically)
Make it long and its easier to debug things later.
:)
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have a very limited understanding of PHP, as well as the internet for that matter. I'm wondering if someone could simply send a POST request to my PHP script (assuming its public). Wouldn't that have the potential to mess up my entire script?
Answer: YES.
The end.
I think this question comes from some security concerns that are not being worded.
First off, know you can check the request method (a.k.a HTTP verb) with $_SERVER['REQUEST_METHOD'].
Second, you can send HTTP request from the browser, or from other software with whatever request method, to whatever public server (read: reachable on the network). And yes, you can handle other things aside from GET and POST in PHP.
I have found the browser extension "Requestly" useful for testing.
You might be interested in Cross-Site Request Forgery and Cross-Site Scripting.
Let us talk mitigation...
It should be evident... but: validate all input. Do not trust that the input comes from a well intended user of your own site.
After validation, it could be necesary to have a sanitation step. For example, if you are going to display the values you got from a request to your users, sanitize the input so it does not contain HTML code. By doing so, you are preventing the attacker to inject potentially dangerous code in your page (being the classic example, injecting javascript).
You probably know this already also, however: Use prepared statements. If you are sending the data you got from a request to the database, using prepared statements will protect you from SQL injection.
Yes, I know the question is not about javascript or SQL injection. However Injection reminds the most common vulnerability according to OWASP TOP 10 and people who wonder if third party can make requests to their page is the kind of people who needs to be told this.
Alright, next up, you need to know if the request comes from an authenticated user. Again, you are probably doing this already, use sessions. What you might not know is that PHP session cookie is not HTTP only by default, meaning that it could be stolen on the client (see Session Hijacking). To fix that use ini_set('session.cookie_httponly', 1);.
Now, of course, the cookie could be stolen from a Man In the Middle attack, which brings me to: use HTTPS. You can get an free SSL certificate to set up HTTPS in your hosting from Let's Encrypt, if you are new to this, I suggest using ZeroSSL which will make it easy to get a certificate and uses Let's Encrypt behind the scenes.
Finally, there are scenarios where you need to make sure the request does not come from a malicius party and you cannot depend on a session being open. In this situation you need to issue a token associated with an specific action, and only allow the action to proceed if the token is presented... for example, if the user wants to recover access (forgot password) you can send a link with a token to their email account, and if the email is presented (and optionally if a captcha is resolved) you allow the user to set a new password.
I hope I do not need to tell you How NOT to Store Passwords!.
For more information see OWASP Cross-Site Request Forgery Prevention Cheat Sheet.
I'm wondering if someone could simply send a POST request to my PHP script (assuming its public).
Yes, though not via XHR/fetch from a modern browser if you haven't allowed CORS. (This doesn't stop a regular form on another web page posting to your script.)
Wouldn't that have the potential to mess up my entire script?
How so? You're responsible for properly handling anything posted to you.
I've been working with PHP for some time and I began asking myself if I'm developing good habits.
One of these is what I belive consists of overusing PHP sanitizing methods, for example, one user registers through a form, and I get the following post variables:
$_POST['name'], $_POST['email'] and $_POST['captcha']. Now, what I usually do is obviously sanitize the data I am going to place into MySQL, but when comparing the captcha, I also sanitize it.
Therefore I belive I misunderstood PHP sanitizing, I'm curious, are there any other cases when you need to sanitize data except when using it to place something in MySQL (note I know sanitizing is also needed to prevent XSS attacks). And moreover, is my habit to sanitize almost every variable coming from user-input, a bad one ?
Whenever you store your data someplace, and if that data will be read/available to (unsuspecting) users, then you have to sanitize it. So something that could possibly change the user experience (not necessarily only the database) should be taken care of. Generally, all user input is considered unsafe, but you'll see in the next paragraph that some things might still be ignored, although I don't recommend it whatsoever.
Stuff that happens on the client only is sanitized just for a better UX (user experience, think about JS validation of the form - from the security standpoint it's useless because it's easily avoidable, but it helps non-malicious users to have a better interaction with the website) but basically, it can't do any harm because that data (good or bad) is lost as soon as the session is closed. You can always destroy a webpage for yourself (on your machine), but the problem is when someone can do it for others.
To answer your question more directly - never worry about overdoing it. It's always better to be safe than sorry, and the cost is usually not more than a couple of milliseconds.
The term you need to search for is FIEO. Filter Input, Escape Output.
You can easily confound yourself if you do not understand this basic principle.
Imagine PHP is the man in the middle, it receives with the left hand and doles out with the right.
A user uses your form and fills in a date form, so it should only accept digits and maybe, dashes. e.g. nnnnn-nn-nn. if you get something which does not match that, then reject it.
That is an example of filtering.
Next PHP, does something with it, lets say storing it in a Mysql database.
What Mysql needs is to be protected from SQL injection, so you use PDO, or Mysqli's prepared statements to make sure that EVEN IF your filter failed you cannot permit an attack on your database. This is an example of Escaping, in this case escaping for SQL storage.
Later, PHP gets the data from your db and displays it onto a HTML page. So you need to Escape the data for the next medium, HTML (this is where you can permit XSS attacks).
In your head you have to divide each of the PHP 'protective' functions into one or other of these two families, Filtering or Escaping.
Freetext fields are of course more complex than filtering for a date, but never mind, stick to the principles and you will be OK.
Hoping this helps http://phpsec.org/projects/guide/
I'm in the early phases of working on a web application, and I've reached a point where I want to make the best choice about a particular security concern. At the moment, all fields found within HTML forms are named after the database column that they are representing. So, for example, if in the database I have a field named "email", then the form field will be called "email" as well. This makes it easier for my generic code to handle forms, but I naturally see one major problem with such names: They can give potential hackers insight into how my database is structured, just from viewing the source.
The main solution I've thought of involves encrypting field names so that client never has the real ones. A server-side key would be used to do the encryption. I am, however, concerned that this approach may complicate things too much. For example:
I may find myself having to use POSTs more often, as the encrypted text might be longer than the original - pushing the limits of GET when many fields and their data are present.
Frequent encrypt/decrypt calls might lead to performance issues down the line. I did not test this yet, so it could end up being negligible.
Non-AJAX GETs can't use this approach without looking really cryptic.
So, I'm wondering what you guys think about this. Am I over-thinking it, or am I on the right track? Is there a better way to handle it?
By the way, I'm also aware that a field name like "email" doesn't offer much information to the developer (why not txtEmail, or something like that?). I'm looking to see if there's a good naming convention that I can adopt, as it might help with the above problem.
If anyone can gain access to your DB via SQL injection or any other method, your schema can be revealed with one query so there is no point in trying to obscure it. If you feel you have to do security by obscurity, you're not doing something else right.
If your application is secured, then it doesn't matter if a potential attacker thinks they know your schema or not. They can't do anything with the information.
I'd spend less time trying to obscure your database (which will only frustrate you and your developers) and more time trying to lock down your application against potential injection attacks.
I am making a CMS which can be extended by third-party developers. In the past I have had problems with newbie developers ignoring security all together. When they put their modules on my website, they are potentially compromising users websites.
I want to create a globals object. This will overwrite all globals with a sanitized copy. This could cause issues, so this object will also provide an option to get unsanitized data.
This way, by default, developers could theoretically do something like this and it's effect wouldn't be as bad as it usually would be. (Obviously this would still potentially cause problems however tables won't be dropped and data won't be exposed.)
mysql_query("INSERT INTO users (`name`) VALUES ('{$_POST['name']}')");
This doesn't protect against developers who intentionally try to break things. However, it will help eliminate basic mistakes.
The end object would be accessed as follows.
$_POST['key']; // Provides Sanitized version of the post key.
$obj->post('key'); // Provides Sanitized version of the post key.
$obj->post_raw('key'); // Provide unsanitized version of the post key.
What do people think about this approach? Is there a proven 'escape all' function floating around that would achieve this?
You're basically talking about reimplementing magic_quotes_gpc. It didn't go that well when Zend did it.
The largest problems are 1) different forms of data protection are necessary for different contexts, and 2) if somebody is too much of a noob to do elementary data security, they're definitely too much of a noob to understand what data your auto-protection mechanism has been applied to and which it hasn't. (They will source data from places your mechanism does not and cannot touch; take this as a given.)
No, it's really difficult to have a generic sanitizing function. It's always use-specific. And let me thus recommend something else:
http://sourceforge.net/p/php7framework/wiki/input/
It basically overwrites the superglobals $_GET, $_POST with objects. This prevents raw access, and you get either notices or log errors if no appropriate filter is used. You still have to think about which filter to use, but at least this method can be used to coerce co-developers on spending a few seconds to give it a thought. Also it's really easy to apply:
$_GET->text["comment"]
mysql_query("SELECT '{$_REQUEST->sql[field]}'");
$_POST->nocontrol->utf7->xss->text["text"];
It's also possible to predefine filter lists for specific input variable names. Or set a filter for all old array accesses with $_POST->xss->nocontrol->always(); It needs some getting used to, but it's really the simplest API possible and meant just for cases like you describe.
You may want to check out http://code.google.com/p/inspekt/ , which pretty much already does what you describe.
Security is a very complicate and delicate subject IMHO.
I'm not sure if you should even allow unsafe access to data. I'd make access only to sanitized contents, and also enforce use of prepared statements.
I just wanted to know what are some basic PHP security techniques I should use when creating a web page that accepts articles?
I'm fairly new to PHP and was wondering what will hold the fort down until I'm a security expert?
There are two fronts to consider when accepting user-generated text that will later be displayed.
First off, you need to protect your database from injection attacks. There's a simple PHP function for this: mysql_real_escape_string() will usually suffice to protect your database from injection when passing this string in to store as a field value.
From there, you have to be careful about your display, as a user who is allowed to upload HTML code can do nasty things to other users when that code gets displayed. If you're doing plaintext articles, you can simply htmlspecialchars() the resulting text. (you'll also probably want to convert newlines to tags.) If you're using a formatting solution, such as the Markdown engine used on this site, those solutions will usually provide HTML sanitization as a function of the engine, but be sure to read the documentation and make sure.
Oh, make sure you're also verifying your GET/POST variables used to submit the articles. That goes without saying, and the verification performed is going to need to be tailored to what your site is doing with its logic.
This is to broad, maybe you should try to narrow it a bit.
What kind of security?
For passwords?
Do you want to restrict some stuff?
SQL Injection?
HTML Injection?
Cross domain security?
Well, as mentioned in the other answers, there are a number of different fronts in which your PHP scripts can be compromised.
Here are just a couple:
SQL Injection
Cross site scripting
There are a number of ways to deal with each. Here are some things to look at:
Suhosin
eval()
There is a lot to know, and you should start as soon as you can.
For one, if you accept articles (and probably use a WYSIWYG and are accepting HTML), use something to parse the content and strip out things that could leave you vulnerable to XSS and the like.
An example is HTML Purifier.
It might be wise to start by using a framework like Drupal or CakePHP. That way you can both learn from the way they've implemented security and take advantage of the fact that it's already been done. The learning curve is steep enough without having to roll your own authentication mechanisms etc.
maybe two tips could help you get more secure websites
create two users in your database, read only account to make only selects and counts, and write account when you have to do updates, inserts or deletes.
when you have to insert into database or delete, sanitize inputs, use mysql prepared statements or assert values that arrive via post or get this way :
if(!empty($_GET["integer_like_id_value"]){
$integer_id_value = (int)$_GET["integer_like_id_value"];
}else{
// that stuff seems not to be legit, die application, log error ? whatever
die();
}
Top 7 PHP Security Blunders
When your project is ready for public usage, it is generally a good idea to set error_reporting(0);
It won't provide more security, but it makes it lot harder (usually) for bad guys to find possible security problems with your site.