Hello my dears you always help me go further.
I have a problem with a form.
How can I protect it from user manipulation after being submitted?
FORM
<form method="post" action="/selling.php" />
<input type="hidden" name="user" value="{$_SESSION['session_username']}" />
<input type="hidden" name="price" value="$price" />
<input type="hidden" name="nick" value="$nick" />
<input type="hidden" name="class" value="$class" />
<input type="hidden" name="amount" value="$amount" />
<input type="submit" name="reset" class="input_submit" value="Submit" />
</form>";
How does it work?
The user logs in on my website, then based on his "$username", I retrieve his info from DB (nickname,class) and based on some conditions I create a "$amount" and "$price" for it.
Everything goes automatically, all the user has to do is to click the "Submit" button.
But I found out that he can manipulate the whole form and change for example the "$price" to 0...
What should I do and how?
Wherever you might derive $amount and $price from, it seems to be calculated before outputting the form. This means you can also just store those two values in a session like
$_SESSION['amount'] = $amount;
$_SESSION['price'] = $price;
and get rid of them in the form completely. You will be able to access these sessions in selling.php so long as you start the session before trying to access it by doing:
session_start();
Through this, none of the sensitive information will be shown in the form/source code, but it will still be available in selling.php.
Remember to always do validations in the backend, i.e. php code, never in the front end.
Related
I am trying to send passthrough data in a paypal paynow button and have paypal return that data to my php page when user clicks “return to merchant” button after paying.
For this I am using the “return” facility in the paypal button, together with rm=2 to send all the data back as post. However, I cannot get it to work. Here is my paypal button html:
<form name="paypal2" action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="xxx">
<input type="hidden" name="invoice" value="testinvoice_fromcode2">
<input type="hidden" name="custom" value="testcustom_fromcode1">
<input type="hidden" name="on0" value="yes"><!--agreetc-->
<input type="hidden" name="os0" value="<?php echo $aid; ?>">
<input type="hidden" name="on1" value="<?php echo $id; ?>">
<input type="hidden" name="os1" value="<?php echo $agent; ?>">
<input type="hidden" name="return" value=http://www.example.com/Admin/conpanel/privat/phpvendorpaidad.php>
<input type="hidden" name="rm" value="2">
<input id="submit" type="image" src="https://www.paypalobjects.com/en_GB/i/btn/btn_paynowCC_LG.gif" border="0" name="submit" alt="PayPal – The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypalobjects.com/en_GB/i/scr/pixel.gif" width="1" height="1">
</form>
In the IPN notification, paypal renders:
os0 as option_selection1,
os1 as option_selection2,
on0 as option_name1,
on1 as option_name2,
I know that on0 and os0 are supposed to be used as name value pairs but way back in 2009 when I first wrote this script there were only 2 sets allowed and therefore I used all 4 to carry values and it worked then.
But essentially, I cannot understand why
<input type="hidden" name="return" value=http://www.example.com/Admin/conpanel/privat/phpvendorpaidad.php>
<input type="hidden" name="rm" value="2">
is not working.
I cannot pick up these values in the receiving script, phpvendorpaidad.php, either as
$aid=$_REQUEST['option_selection1'];
or as
$aid=$_REQUEST['os0'];
for example.
Can anyone see what I am doing wrong? Much appreciated.
I also have an IPN listener page that is working normally. Could another way be to build this in to the IPN listener page using javascript to send the form data automatically on page onload?
Is paypal actually POSTing to your return script or using GET? In the latter case, you can see the txn_id and some other info in the query string, but you will NOT get the whole payment detail data.
If you have Auto Return set to On (meaning the user get automatically redirected back to your site, without having to click a button), then paypal with send a GET request and will include only a few items.
var_dump($_REQUEST) and var_dump($_POST) in your script to see what you are getting.
Actually the problem lay in defective if/else logic in my return code, which was set up in 2009 to handle the GET variables that Paypal was sending to the return script in those days. This logic had to differentiate between the POSTed data received from a preceeding form on my server and the GET data received from Paypal. Paypal appears to have chenged since 2009 and no longer sends GET data to the return script but POST data via
<input type="hidden" name="return" value=http://www.example.com/Admin/conpanel/privat/phpvendorpaidad.php>
<input type="hidden" name="rm" value="2">
Once this was corrected the program worked.
However, I was only able to discover the problem thanks to the brilliant suggestion from JBart to var_dump($_REQUEST) (or the more easily read print_r($_REQUEST)). Without this I would still have been floundering. So cheers JBart, would love to buy you a drink if you are in the neighbourhood (NW London)!
And no, I didn't need to extract any variables from the received POSTed array (see my last comment above), just normal '$payment_status = $_POST['payment_status'];'. In this I had misinterpreted another thread on the subject in "How can I get posted data passed along when the user is first redirected through Paypal?"
Let's say I have a form that looks like this:
<form action="/script.php" method="post">
<input name="my_input" length="80" />
<input type="submit" value="submit" />
</form>
Now I also want to include a numeric identifier - call it a ticket id. "Here's the ticket history, do you want to add something?" The user can't modify that.
My question is...what is the safest way to get that ticket id in the form submission?
No problem accomplishing it, but my question is around security. So here are the ways to get a variable back that I can think of:
<form action="/script.php" method="post">
<input name="my_input" length="80" />
<input type="hidden" name="ticket_id" value="12345" />
<input type="submit" value="submit" />
</form>
or
<form action="/script.php?ticket_id=12345" method="post">
<input name="my_input" length="80" />
<input type="submit" value="submit" />
</form>
I'm concerned that someone could craft a malicious POST and submit it and append their comments to a different ticket. i.e., compose a POST from their own server/browser/tool. If I was doing this with GET then they certainly could do that just by changing the url vars - it's possible to do that also with POST too, right?
I can check that the user owns that ticket of course and do some other validation, but fundamentally, how do you present data to a user and safely get it back again in an HTML form?
Is there something other than creating a unique serial number ("FORM 12345 should present ticket id 6789") record on the server side and then checking it back?
I'm using PHP & MySQL on the backend though I'm not sure my question is specific to those technologies.
use session
form.php
<?
session_start();
$_SESSION['ticket_id'] = '1234';
?>
script.php
<?
session_start();
$ticket_id = $_SESSION['ticket_id'];
?>
On page1.php I have a form which sends vars via POST to page2.php.
However, I only want to process the form if it is called from page1.php.
How do I check for this?
Kind regards!
EDIT:
It's a kind of security measure. If i'm a hacker and I copy the form code from the source of the page and run it, I can change crucial vars.
EDIT2:
Ok here is the actual problem:
Users can edit credit to their account. They can choose values from 5EUR to 50EUR.
Eventually they come on a page 'deposit.php' where the final form is sent to a page 'payments.php' which then sends the var to Paypal.
Deposit.php:
<form class="paypal" action="paypal/payments.php" method="post" id="paypal_form" target="_blank">
<input type="hidden" name="cmd" value="_xclick" />
<input type="hidden" name="no_note" value="1" />
<input type="hidden" name="lc" value="BE" />
<input type="hidden" name="currency_code" value="EUR" />
<input type="hidden" name="bn" value="PP-BuyNowBF:btn_buynow_LG.gif:NonHostedGuest" />
<input type="hidden" name="item_number" value="50" / >
<input type="hidden" name="price" value="47.50" / >
<input type="submit" class="uibutton " value="Betaal met Paypal" style="width: 100%; font-size:120%;">
(BTW they get a discount if they add 50EUR)
Well, first of all you have to understand that there is no security measure the way you put it.
And, of course, no method provided by other participants can protect your "crucial vars". They were actually answering other question, one is more familiar to them.
Forms are intended to be filled by client party. So, you can't expect whatever variable be untouched. Everything coming from the client side can be spoofed, no matter what measures you took.
So, whatever "crucial vars" should remain on the server.
While all the data coming from the form should be considered unsafe and treated accordingly.
Depending on the application, you could use $_SERVER['HTTP_REFERER'] and do a check but the problem with it is that not all browsers send it, and it is modifiable by the user. So if this is just for a few people that you know it probably won't be a problem. If this is for the world it isn't recommended.
What I usually do is set a session on page 1, then check for that session on page 2. Every time page 1 loads you need to reset the session.
page1.php
<?php
session_start();
$hash = $_SESSION['hash'] = md5(time().rand(0,100));
?>
<form action="page2.php" meethod="post">
<input type="hidden" name="h" value="<?php echo $hash; ?>" />
Your Name: <input type="text" name="name" />
</form>
page2.php
<?php
session_start();
if($_SESSION['hash'] != $_POST['h']){
header("Location: page1.php");
exit;
}
// process data
I think Adam D response is too weak (Anyone can change that just using firebug). what you want to prevent is users to skip some step or avoid XSRF.
In that case I would say use sessions.
Create a session
Save the current step
Retrieve and validate the current step and halt or continue according to the value
In your form, include a hidden field that you then check for on page2.php. See below:
<form action="post.php" method="POST">
<input type="text" name="fname" id="fname" />
<input type="hidden" name="cameFromPageOne" value="true" />
</form>
Then, on the top of page2.php, check that the hidden variable is set, and if not, redirect back to page1.php
<?php
if(!isset($_POST['cameFromPageOne']) || $_POST['cameFromPageOne'] != 'true') {
header('location: http://www.example.com/page1.php');
exit();
} else {
// ... code to process if they DID come from page1.php
}
?>
There's no reason to overcomplicate it, there's a global variable in PHP which tell's you the url your current script was requested from:
echo $_SERVER["HTTP_REFERER"];
I have very simple form (the file is called message.php):
<?php
print_r($_POST);
?>
<form method="post" target="_top" action="<?php echo CANVAS_URL;?>message.php">
<input type="text" name="your_name" />
<input type="hidden" name="signed_request" value="<?php echo $_REQUEST['signed_request'];?>" />
<input type="submit" name="send" />
</form>
I found one solution of this issue - put into the form hidden input with the signed_request - I did it but unfortunately I am still facing with this problem -- I cannot retrieve sent POST data.
If I change the method to method="get", everything is working well, but I would need to data from POST.
Could anyone help me, how to solve this problem? Thanks!
Try this. I don't believe you need to use target in FB canvas aps anymore. Also a form ID would be good.
<form method="POST" id="my_form" action="message.php">
<input type="text" name="your_name" />
<input type="hidden" value="<?php print $_POST["signed_request"] ?>" name="signed_request" />
<input type="submit" name="submit" />
</form>
POSTing to Canvas URLs (as in http://apps.facebook.com/namespace) is simply not supported.
But why post to the top window instead of simply staying within the iframe? It's way better as it doesn't require the entire page to be reloaded, only the iframe.
Another lame question
So, I have a site that displays several students' requests to change advisors, with an Approve and Deny button for each student. Then I have a Javascript pop-up that confirms the decision when clicked on either button, and it will also e-mail the student about this decision. This should all be on one page as well.
How do I specify which student I will update and e-mail to? I know the query will be like $query = "UPDATE student set current_advisor = ".$requested_advisor." where SID = ".$sid, but how do I specify which student I'm doing this for?
I have only worked with php forms, where you have the user type in the information, but in this case, all the data is there already...
$sid is the id of the student you want to update... It depends how you're building the page. You can either insert a form for each student, as follows:
// for each student
<form method="post">
<input type="hidden" value="the-sid" name="SID"/>
<input type="submit" value="confirm" name="type" onclick="return confirm('Sure?');"/>
<input type="submit" value="deny" name="type" onclick="return confirm('Sure?');"/>
</form>
// end for each
Then when the user clicks either approve or deny, you're $_POST array in PHP will be filled with:
array("SID"=> $theSID, "type" => "confirm or deny");
You have a couple options for doing something like this.
If you want to do it with actual <form>s, then you'd do this by putting the information you need in "hidden" form fields. For example, you can have something like this in each form:
<input type="hidden" name="SID" value="4" />
And use PHP to fill in the value for each hidden field when you're generating the HTML.
Another option is to just have the buttons open a link, instead of submitting a form. In that case, you can pass the values you need as "GET" parameters on the URL, like this:
http://yoursite.com/change_advisor.php?SID=4&new_advisor=18
And then have the change_advisor.php file use the variables $_GET['SID'] and $_GET['new_advisor'] to do the query you need.
i'm not sure if this is what you want exactly, but if you wanted a list of advisors and the option to approve or deny each you could do for each advisor
<?php foreach($advisors as $advisor): ?>
<form method="post" action="somewhere">
<input type="hidden" name="id" value="<?php echo $advisor['id']; ?>" />
<input type="submit" name="result" value="Approve" onclick="return confirm('Are you sure you want to approve this advisor?')" />
<input type="submit" name="result" value="Deny" onclick="return confirm('Are you sure you wish to deny this advisor?')" />
</form>
<?php endforeach; ?>
Then that sends to your script a post array which should contain whether it was approved or denied, then you can handle it from there using the id variable to identify your record against your primary key.
Hope this helps :)