I have made a form, where that if a value is missing the redirect to error page.
<?php
if (empty($_POST['submit']) && empty($_POST['email']))
{
header('Location: empty.php');
exit;
}
?>
Now, Lets say that i have a password that i need my users to type in to proceed, how do i do that, and if its wrong, then how do i redirect them to empty.php?
My problem is that i dont know how to make a "PHP" tag that redirects if not specific value.
Solution (please, read whole post, as there are security holes..., even black holes in the code ;) ):
<?php
if (isset($_POST['password']) && $_POST['password'] == 'yourpasshere')) {
// Password OK, continue
}
else {
// Password not ok, redirect
header('Location: empty.php');
exit;
}
?>
Few words about solution: if $_POST['password'] is not set, the second condition is even not checked, and it go to else. If the $_POST['password'] is set, second condition check if the password is as you want (read security warnings below). If and only if it is OK, the if passed.
There are few important messages however:
1) Never store password in plain text, anywhere! Read this: http://php.net/manual/en/function.password-hash.php. My example is storing password in plain text, but it is only to sketch the possible solution. Every possible leak of your file gain access to your site.
In that case, my answer sketch the logical part (in which you have a problem) of solution, but NEED TO BE CORRECTED IN SENSE OF SAFETY.
2) Always validate form data (minimal solution is to use http://php.net/manual/en/function.htmlspecialchars.php, but this is not perfect, and it is much more better to use preg_match, or even preg_replace for special characters, to remove them
2*) You can validate email using: var_dump(filter_var('bob#example.com', FILTER_VALIDATE_EMAIL)); (doc: http://php.net/manual/en/function.filter-var.php). This is a great function that will try to validate if entered email is really OK.
3) In your code it will redirect to empty page only if BOTH of the POST values are empty. If You want to redirect if any of them is empty use logical OR (||) not AND (&&).
Related
Very strange problem and I'm scratching my head. If anyone can help it would be much appreciated, thanks.
I have a Search Location result page that should only appear if either 1) the form on the previous page has been submitted; or 2) they are searching via a url, e.g.
www.mywebsite.com?use_url=on&zipcode=UB95BX&radius=50.
So, at the top of the page I have the following code:
// Validate input and sanitize
if (empty($_POST['submit']) || empty($_GET['use_url']))
{
header('Location: index1.php');
exit;
}
Problem is, it's not working and it's redirecting EVERY request. Does anyone know how I can get it to work, so that if there is no submit post, or if there is no get request (basically, if the user types in www.mywebsite.com/locations.php directly into the url bar), the user is redirected.
Strange thing is this, if I leave out the empty($_GET) command and make it therefore
// Validate input and sanitize
if (empty($_POST['submit']))
{
header('Location: index1.php');
exit;
}
It works fine on an empty submit, the problems only occurs when I specify two criteria for a redirect.
Thanks everyone / Luke
|| is logical OR. Currently your code reads "if either post or get are empty, redirect"
What im sure you mean is "if both post and get are empty, redirect".
You should use logical AND (&&):
if (empty($_POST['submit']) && empty($_GET['use_url']))
{
header('Location: index1.php');
exit;
}
Try this:
if (empty($_REQUEST['submit'])
or if (!isset($_REQUEST['submit'])
I am trying to make a simple redirect php plugin, and i cant get to the bottom, i would really appreciate some help.
Inside a folder i have the php script that will handle the redirect, for ex: /redirect/a.php
Scenario 1:
call /redirect/a.php?key=firstkey the redirect to http://www.url1.com
Scenario 2:
call redirect/a.php?key=secondkey then redirect to http://www.url2.com
General rule:
If a.php is called without key, or with wrong key then display Error.
Thank you!
Use global variable $_GET["key"] to get value of "?key=value", then use header() to redirect.
Note that there cannot be any output before calling header(), that applies even for whitespaces (such as space, or tab).
It could look something like this:
// checking whether the key is sent by user who visits the page
if(!isset($_GET["key]))
{
die("Key is required");
}
// checking whether the key is empty
if(empty($key)
{
die("Key shouldn't be empty");
}
if($_GET["key"] == "firstkey")
{
header("location: http://www.url1.com");
}
It would be better to use array() to list keys that should be accepted by script, you could easily look for them by using in_array().
I have a login form on my website that checks submitted usernames/passwords. If there's no match, the user is sent back to the login page and an appropriate error message is displayed. The call for this redirect is this:
header("location:../login.php?error_message=$error_message");
This works fine, but it does look messy in the browser's address bar (especially with descriptive error messages). Is there any way to do this automatic redirect without using the $_GET variable? I had considered using the $_SESSION variable, but that doesn't seem like the best coding practice.
Thanks for reading.
What about having a simpler GET variable?
// something.php
header ("Location: foo.php?err=1");
And then in the page handling the errors:
// foo.php
$errors = array (
1 => "Hello, world!",
2 => "My house is on fire!"
);
$error_id = isset($_GET['err']) ? (int)$_GET['err'] : 0;
if ($error_id != 0 && in_array($error_id, $errors)) {
echo $errors[$error_id];
}
Hope this helps.
If you don't wish to use sessions, you could use error codes instead:
header('Location: ../login.php?error=' . urlencode($error_code));
Then, inside login.php:
if (isset($_GET['error'])) {
switch ($_GET['error']) {
case 123: // ...
break;
}
}
Instead of a bulky switch, you could use a lookup array for error messages instead (can be language dependent).
Btw, using relative URIs in your header redirects is not recommended, an absolute (e.g. /login.php) or fully qualified URI (e.g. http://example.org/login.php) is preferred.
For the form validation you have 3 options:
Use AJAX to validate - so, there will be no need to redirect at all.
Use redirect and session to store the error message along with entered data.
Use redirect as a part of the POST/Redirect/GET patterm
Personally I would implement (1) and (3) for my forms. (1) for the convenience of ordinary user and (3) for backward compatibility with paranoids like myself.
Using sessions is indeed a cleanest way for the redirec-based validations, as it will leave no POSTed page in the history under any circumstances. However, in a presence of AJAX-based validation it seems a bit overkill
You can use session based flash messages.
Look at this example : http://mikeeverhart.net/php/session-based-flash-messages/
Using session is a good option. You can clear session value as soon as you display error. But if you don't want to use session you can modified your url like following.
// login failed
header("location:../login.php?status=0");
I prefer to use session.
My profile.php displays all the user's postings,comments,pictures. If the user wants to delete, it sends the posting's id to the remove.php so it's like remove.php?action=removeposting&posting_id=2. If they want to remove a picture, it's remove.php?action=removepicture&picture_id=1.
Using the get data, I do a query to the database to display the info they want to delete and if they want to delete it, they click "yes". So the data is deleted via $POST NOT $GET to prevent cross-site request forgery.
My question is how do I make sure the GETs are not some javascript code, sql injection that will mess me up.
here is my remove.php
//how do I make $action safe?
//should I use mysqli_real_escape_string?
//use strip_tags()?
$action=trim($_GET['action']);
if (($action != 'removeposting') && ($action != 'removefriend')
&& ($action != 'removecomment'))
{
header("Location: index.php");
exit();
}
if ($action == 'removeposting')
{
//get the info and display it in a form. if user clicks "yes", deletes
}
if ($action =='removepicture')
{
//remove pic
}
I know I can't be 100% safe, but what are some common defenses I can use.
EDIT
Do this to prevent xss
$oldaction=trim($_GET['action']);
$action=strip_tags($oldaction);
Then when I am 'recalling' the data back via POST, I would use
$posting_id = mysqli_real_escape_string($dbc, trim($_POST['posting_id']));
if ($action == 'removeposting')
{
//get the posting id from the user
$getposting_id = htmlspecialchars(trim($_GET['posting_id']));
//basic checks for the posting id
if (empty($getposting_id)){
//header ("Location: index.php");
echo '<p>Sorry, no posting was specified for removal.</p>';
exit();
}
if (!is_numeric($getposting_id))
{
echo "Not an integer";
exit();
}
//Also have check to see if the posting_id is the user's. If so, can delete
Because you aren't storing $action and only using it in your conditional, it's not necessary to do all the trimming/stripping/escaping. The simple string comparisons is enough in terms of "safety," though I recommend using === instead of ==.
Alternatively, if you were storing a $_GET or $_POST value into an integer column of a MySQL database, for example, you could simply pass the value into intval() before storing it in the database. If you need to store plain text, just pass it through mysql_real_escape_string() before storing it. You can also use preg_match() or preg_replace() to make sure you are only storing valid values (different patterns for different uses, e.g. /^\d{5}(?:-?\d{4})?$/ for zip codes).
To prevent against any SQL injection you should use mysqli_real_escape_string OR you can use Prepared Statements that accomplish the same thing.
To prevent any javascript, you could use strip_tags in concert with htmlspecialchars.
I know I can't be 100% safe
ahahahaha :)
if your question regarding only action, and it is used only to determine the code to run, it IS safe by any means.
But some info for you:
POST doesn't prevent cross-site request forgery. unique token does.
You didn't post actual action code, so just to be sure - I hope you check user's id whan perform these actions
Use the mysqli_real_escape_string as noted elsewhere. Also, of course this does nothing to prevent XSRF. You'll need tokens containing some entropy for that.
See also: http://www.owasp.org/index.php/Main_Page
$_GET is completely safe until you try to glue (concatenate) it to the other things in your program like:
SQL to be executed (in which case you should use mysqli_real_escape_string() or another escaping technique that is advised with the database that you are using)
HTML to be outputted (in which case you should pass it through htmlspecialchars() before concatenation or printing/echoing)
URL to be navigated to by the user (in which case you most likely should pass it through urlencode())
JavaScript to be executed by the browser (in which case you should pass it through json_encode())
If you want to have an url in javascript embedded in html that you want to be inserted in database then you should pass value that you receive from $_GET (also $_POST, $_COOKIE and other similar outside sources) through all those functions in order appropriate to this scenario, namely
mysql_real_escape_string(htmlspecialchars(json_encode(urlencode($_GET['val']))));
If the only thing you do is compare your $_GET['action'] to some strings then you are perfectly safe without doing any escaping at all.
I've got this code on my page:
header("Location: $page");
$page is passed to the script as a GET variable, do I need any security? (if so what)
I was going to just use addslashes() but that would stuff up the URL...
I could forward your users anywhere I like if I get them to click a link, which is definitely a big security flaw (Please login on www.yoursite.com?page=badsite.com). Now think of a scenario where badsite.com looks exactly like your site, except that it catches your user's credentials.
You're better off defining a $urls array in your code and passing only the index to an entry in that array, for example:
$urls = array(
'pageName1' => '/link/to/page/number/1',
'pageNumber2' => '/link/to/page/number/2',
'fancyPageName3' => '/link/to/page/number/3',
);
# Now your URL can look like this:
# www.yoursite.com?page=pageName1
This is a code injection vulnerability by the book. The user can enter any value he wants and your script will obey without any complaints.
But one of the most important rules – if even not the most important rule – is:
Never trust the user data!
So you should check what value has been passed and validate it. Even though a header injection vulnerability was fixed with PHP 4.4.2 and 5.1.2 respectivly, you can still enter any valid URI and the user who calls it would be redirected to it. Even such cryptic like ?page=%68%74%74%70%3a%2f%2f%65%76%69%6c%2e%65%78%61%6d%70%6c%65%2e%63%6f%6d%2f what’s URL encoded for ?page=http://evil.example.com/.
Yes, you do. Just because you or I can't immediately think of a way to take advantage of that little bit of code doesn't mean a more clever person can't. What you want to do is make sure that the redirect is going to a page that you deem accessible. Even this simple validation could work:
$safe_pages = array('index.php', 'login.php', 'signup.php');
if (in_array($page, $safe_pages)) {
header("Location: $page");
}
else {
echo 'That page is not accessible.';
}
Or, at the very least, define a whitelist of allowed URLs, and only forward the user if the URL they supplied is in the GET variable is in the list.