Avoid URL parameter Manipulation - javascript

So in my case, after a user chooses a certain room, the number of nights he will stay and the number of guests, the price gets calculated (depending on certain factors) and then they are redirected to the payment page where they will see the total price, which the user can change by manipulating the price parameter in the url.
on the booking page :
<Link to={"/book?pricetotal="+total_prices+"&title="+title+"&img="+img+"&price="+price+"&checkin="+checkkin+"&checkout="+checkkout+"&idr="+idroom} >
and on the paiment page i am using
const windowUrl = window.location.search;
const params = new URLSearchParams(windowUrl);
and then i get the parameter using
params.get('price')
The solution i found is to encrypt the content of the Url parameter and then decrypt it.
Is the solution effective enough or are there other ways to implement it?

Anything on the client can potentially be intercepted and manipulated by someone interested enough. Encryption likely isn't enough if you're really worried about security because the user could examine the code that generates the link and perhaps reverse-engineer it.
You can't trust anything done on the client. Instead, when the user makes their choices:
after a user chooses a certain room, the number of nights he will stay and the number of guests
Save this data server-side, and give the user a session ID if they don't already have one. Then when it comes time for them to check out, you can calculate the total server-side, and then show it to the user somehow. Yeah, don't put it in URL parameters, because that's too easy for someone to mess up, even unintentionally - but putting it, for example, in response to a fetch request, or in a data element on the page would work.
When the user enters their payment info and submits it, use their session ID to determine what the price for what they chose was. Using this approach, even if someone decides to mess with the client-side script to display something else, it won't affect the final price - they'll only be messing up their view (and if they do that, any confusion that results is on them).

That isn't going to work, since you are encrypting and decrypting on the frontend.
A viable solution would be to send the products instead of the price of the products. Then, when you send the request to the backend for payment, also send the products, and in the backend calculate how much to charge the user.

My solution was to pass props in link react-router
<Link to={{pathname:`/book`,state: { total_prices,title,img,price,checkkin,checkkout,idroom },}} >
and access them in my other function component using
const location = useLocation()
console.log(location.state)

Related

Securing PHP scripts - Shopify

Basically my question is similar to this one:
How to secure php scripts?
with one slight difference, the other side is Shopify.
Background info:
Shopify user bought some credits (Audible style), and wants to know how many he has available. He logs in into his account, and it says there that he has X credits.
That number comes from AJAX call to my server (I have full control), where there is a simple php script which checks the value in db (which is updated using webhooks from Shopify, each of which needs to be verified so they are secure, I think).
The script uses customers ID for a look up, and that value needs to be passed to the script somehow, and that allows someone external to just keep running it until he has all IDs and corresponding credits values.
So, my questions is, how do I stop that? How do I ensure that only authenticated users can check it, and only for their IDs.
There is plenty of info on Shopify docs about securing the connections the other way, i.e. to make sure only correct scripts have access to the Shopify db, but nothing about my problem.
As far as I know I only I only have access to JS on Shopify, which creates the problem, because everything I send to my server is visible to all.
Thanks
EDIT: I just read up on CSRF. I can easily implement checks for origin and headers, but these can be faked, right?
EDIT 2: I got around this problem by using metafields. So, instead of storing all that info on my server's db, I just use Customer Metafields to store the available credits. Webhooks are secure so that's brilliant. It still doesn't solve a problem with the next stage though. Customers will still need to be able to use their credits and get digital products, which are generated by my server. So I still need to verify the requests.
EDIT 3: Comment by #deceze and answer by #Jilu got me thinking. Yes, you are correct, I need to do that, but I don't have access to back-end on Shopify, so I cannot create session. However, what I could do (if I figure out how in js) is hash it. PHP login scripts operate on password_hash. That way you do not store a password in the db. Password get's verified again hash (or whatever you call) in the db, and it's either true or false. If true, you are logged in. So I could try to generate a token using a specific string (make it very long) and user id. Send it with the request, and using password_verify or what not, check it against the users. The one that pops positive is logged in user who requested the information. That is assuming I can hide the string in the Shopify...
Step1: Do a session login system.
Step2: Before the Ajax, generate a random token in your form or request page, put it into a input display none, send it with POST.
Verify each time if the token is set and is the same that you got.
You have now verified if the user is really logged in with session.
And you checked that he is from the right page.
You create a token out of shared secret (both Shopify and server have it), and client ID.
On Shopify:
{% assign my_secret_string = "ShopifyIsAwesome!" | hmac_sha256: "secret_key" %}
My encoded string is: {{ my_secret_string }}
On server:
We gonna be checking received hash value against values in our db, so we need to hash local client IDs using the same algo and key (that probably should be done on receiving the Customer Creation webhook).
Hash IDs using: http://php.net/manual/en/function.hash-hmac.php
$hashed_id = hash_hmac('sha256', '$client_id', 'secret_key');
Compare hash using: http://php.net/manual/en/function.hash-equals.php
$check = hash_equals($hashed_id, $received_id);
Then all that's requires is to loop through the db until you find a match. There may be quicker ways of doing it.

How to create a new page on form submit?

I'm attempting to create a new page every time a form is submitted. It'll be an order status page- one that'll be updated periodically. Basically, I want the user to see a form confirmation page, and I want it to be permanent link (that they can visit later).
My first thought was using variables in the URL, like so:
http://www.example.org/member.php?id=123
And then calling the id using GET
echo $_GET['id'];
http://www.example.org/member.php would be a template, just waiting for the few details which are specific to the user.
Once I have this in place, I could use a simple if statement to check their order status.
For example,
if ($id === "user_id") {
echo "Your order is: Pending";
}
However, this seems like a bad idea, just for the security aspect of it. If someone else guesses a user ID, they can view their order status. Going off of that, here's my first question.
If the user ID is long enough, is this a secure practice?
Otherwise, what are some other methods of doing this? Creating a new page every time the form is submitted feels like a bad practice- people could spam it, and there's a possibility that someone could exploit this to create malicious pages on the site.
Any suggestions? Most major retail sites have order confirmation pages (think ebay.com)- how do they do it? Also, is my suggested URL format secure?
The most ideal scenario is you force users to login prior to submitting the form then provide them with a list of their past orders of which they can check the status providing the user_id of the order matches the id from the session of the logged in user. Give each order in the list a link like yoursite.com/orders/1 then query for an order with an id of one with a user_id matching the logged in users id to ensure they're the only ones that can view it.
If you don't want to have to do any of that and just provide a permanent link to the status page I'd save a long randomly generated string against the order and provide it to the user to check in the future, e.g
yoursite.com/orders/wUk1DhfxMh if you're using a framework with some routing
or yoursite.com/orders.php?code=wUk1DhfxMh if you're not.
Query the database to select the order with the matching code, ensure you prevent MySQL injection and sanitize the $_GET input.
Are you sure you need to make a new page?
You could just have a basic "confirm" page (ex. http://yoursite.com/order/confirm) which uses PHP sessions to create a customized confirm page–
Other than that, IF you make a new page, you should use ID's in the URL and ALSO check the session id. (ex. http://yoursite.com/order/confirm/ABsisnEALnsoSK?yyyy=xxxx) and then ALSO check if the user is logged in.
Lastly, cymath has a good example of async page-creation; although it isn't exactly what you are looking for.
EDIT: It is not page creation, it's like what I said before: one page with extra parameters in the url: a permanent link, just using PHP.
I understood that you are having some doubts about how to make the algorithm of your app, here's what i thought to this case:
Insert the order at your database, get the id of the insertion and give it to the user.
Set the page where the user will check the status to receive a $_GET['id'], check (SELECT) if this id exists in the database.
(if the user exists): get the information you need from the table
you store them. (FETCH_ASSOC or FETCH_OBJECT)
(if the user don't exist):show an error.
If you are experiencing some doubts about how to code CodeSchool is offering free trial on all courses this weekend.
If the user ID is long enough, is this a secure practice?
R: To improve the security of the transactions, try to understand/learn about PDO Class, i think it will get your code to next level if you aggregate some Good Practices and Design Patterns.
For more information, visit PHP's Documentation.

How to paginate a search result using same query with different skip and limit values

Some of you might argue that this is a question for programmers.stackexchange.com but, having read through Help Center of Stack Overflow I believe this is a specific programming problem and I am more likely to get a response here.
I have a webapp that uses ExpressJS with Neo4j database as backend. I have a search screen, where I would like to use the power of Neo4j's relationships. The search screen accepts one or more values (i.e. manufacture year, fuel type, gearbox, etc etc) and then make a post request to ExpressJS where I construct a cypher query using the parameters of POST request as shown below as an example:
MATCH
(v:VEHICLE),(v)-[:VGEARBOX_IS]->(:VGBOX{type:'MANUAL'}),
(v)-[:VCONDITION_IS]->(:VCONDITION{condition:'USED'})
WITH DISTINCT v
WHERE v.manufacture_year = 1990
MATCH (v)-[r]->(info)
RETURN v AS vehicle, COLLECT({type:type(r), data:info}) AS details
Let's say that running above query, returns the following three vehicles and its properties
If more than 20 vehicles in result then I want to paginate the result and I know how that works, we make use of SKIP and LIMIT as shown below:
MATCH
(v:VEHICLE)
OPTIONAL MATCH (v)-[r:VFUEL_TYPE|:VGEARBOX_IS|:VHAVING_COLOR|...]->(info)
RETURN
v.vehicle_id AS vehicle_id,
v.engine_size AS engine_size,
v.published_date AS published_date,
COUNT(v) AS count,
COLLECT({type:type(r), data:info}) as data
ORDER BY v.published_date DESC
SKIP 20
LIMIT 16
Here is the workflow,
User navigates to search screen which is a form with POST method and various input fields.
User selects some options based on which he/she wish to search.
User then submits the form, which makes a post request to the server.
This request is handled by a ROUTE which uses the parameters of the request to construct a cypher query shown above. It runs the cypher against the Neo4j database and receive the result.
Let's assume, there are 200 vehicles that match the search result. I then want to display only 20 of those results and provide a next/previous button.
When user is done seeing the first 20, he/she wants to see the next 20, that is when I have to re-run the same query that user submitted initially but, with SKIP value of 20 (SKIP value keeps incrementing 20 as user navigates to next page, and decrement 20 as your moves to previous page).
My question is, what is the best approach to save search request (or the cypher generated by original request) so that when user clicks next/previous page, I re-run the original search cypher query with different SKIP value? I don't want to make a fresh POST request every time the user goes to next/previous page. This problem can be resolved in the following manner but, not sure which is more performance-friendly?
Every time the user clicks next or previous page, I make a new POST request with preserved values of original request and rebuild the cypher query (POSTs can be costly - I want to avoid this, please suggest why this is better option)
I store the original cypher query in Redis and whenever the user clicks next or previous, I retrieve the query specific to that user (need to handle this either via cookie, session or some sort of hidden uuid) from Redis, supply the new value for SKIP and re-run it (somehow I have to handle when I should delete this entry from Redis - deletion should happen when user change his search or abandon the page/site).
I store the query in session (user does not have to be logged in) or some other temporary storage (than Redis) that provide fast access (not sure if that is safe and efficient)
I am sure somebody came across this issue and it in an efficient manner which is why I post the question here. Please advise how I can best resolve this problem.
As far as performance goes, the first thing that you should absolutely do is to use Cypher parameters. This is a way to separate your query string from your dynamic data. This has the advantage that you are guarded against injection attacks, but it also is more performance because if your query string doesn't change, Neo4j can cache a query plan for your query and use it over and over again. With parameters your first query would look like this:
MATCH
(v:VEHICLE),(v)-[:VGEARBOX_IS]->(:VGBOX{type: {vgearbox_type}}),
(v)-[:VCONDITION_IS]->(:VCONDITION{condition: {vcondition}})
WITH DISTINCT v
WHERE v.manufacture_year = {manufacture_year}
MATCH (v)-[r]->(info)
RETURN v AS vehicle, COLLECT({type:type(r), data:info}) AS details
SKIP ({page} - 1) * {per_page}
LIMIT {per_page}
Your javascript library for Neo4j should allow you to pass down a separate object. Here is what the object would look like represented in json:
{
"vgearbox_type": "MANUAL",
"vcondition": "USED",
"manufacture_year": 1990,
"page": 1,
"per_page": 20
}
I don't really see much of a problem with making a fresh query to the database from Node each time. You should benchmark how long it actually takes to see if it really is a problem.
If it is something that you want to address with caching, it depends on your server setup. If the Node app and the DB are on the same machine or very close to each other, probably it's not important. Otherwise you could use redis to cache based on a key which is a composite of the values that you are querying for. If you are thinking of caching on a per-user basis, you could even use the browser's local storage, but are users often re-visiting the same pages over and over? How static is your data and does the data vary from user to user?

Ways to Encrypt and decrypt array in jquery

I am completly new to jquery and client side programing. I am trying to figure out a way of achiving this:
On the client side I have a hidden user id/profile id, which I wanna to encrypt, but while manipulating the hidden value, I have to decrypt and perform some operation on it.
I have a global array of arrays like below:
var users=[{"u_id":"1234", "u_name":"Test"},{"u_id":"12345", "u_name":"Test1"}];
this array is used by various other compoenets, e.g. when user mouse-over on the profile-id, it will get the details from the above array and display the result to him.
In short, I want to encrypt/decrypt all my global variables inside the script.
any plugin or ways to do will be highly appricated.
Encryption/decryption on the client side is entirely pointless. Encryption is used to hide something from somebody. For that you need a secret (password etc.) that you're not giving to that somebody.
If you want to encrypt and decrypt something on the client, the client will need the secret in order to do the encryption. Therefore, the client has everything it needs to decrypt any encrypted secret. That means any user has everything he needs to decrypt data and can in fact see the process happening (try breakpoints in your browser's Javascript debugger). Therefore, the entire exercise is by definition pointless. It may deter some very unskilled poker-arounder, but anyone with the skill to actually do something with the decrypted data can get it easily.
#deceze: Yes exactly, the example you have posted, lets say user 42, trying to update his age, basicaly user will see 42 as his profile id when he logsin, and then subsequent call he will make for changes he need to pass sessionkey/apikey along with profile id and data, so basically if you will suggest me how I can manage these sessionkey/apikey, so that user/hacker from outside can't missuse.. – Jayaram Pradhan 1 min ago
It's pretty simple:
Require users to be logged in via a regular login mechanism, typically involving a session id. This session identifies the user as securely as it's feasible to do anything securely over the web. Your security focus must be here.
Knowing who the user is, you can validate any and all of his actions. If the user requests to change the profile information of some user, check whether he's allowed to do that or not. No API key or anything needed. The server receives a request for change, the server knows who the requesting user is by the session, the server can decide to accept or reject the request.
In the concrete case of updating one's own profile, if the user is only allowed to update his profile and his profile alone: there needs to be only one action/URL, when a user POSTs data to that action, the server knows who the user is and updates that user's profile. The user doesn't need to submit a user id of the profile he wants to update, in fact he can't submit a user id, only his profile will ever get updated. There's no publicly accessible action that allows him to update anyone else's profile.
There is no 3.
i know no way to perform this on client side, you can serialize and obfuscate the data (like using base 64 encoding on json string).

Shall I use javascript for page submission?

I am working on a big site, and in the site there is a search module. Searching is done by using a a lot of user submitted values, so in pagination I must pass all these data to the next page, appending the values to url make the url very big.
Sso how can I solve this issue? I am planning to use a javascript based page submission (POST) with all the values in hidden fields to the next page the read all the values from the next page.
Will it cause any problems? Or should I use database to keep the search criterias?
I would create a server side object, possibly with a database backend which is updated by the different pages.
It is at my opinion the most clear and easy solution. Giving parameters from page to page, either by post or javascript or cookie will work too but it's more of a quirk in my experience.
Also if a search query is so complex that it needs multiple pages to create it, it might be helpfull for the user to have all the data stored on the server so he can change it more easily by switching back and forth between the different pages.
I would store all the search criterias in some kind of session-store on the server when the initial search is being triggered.
For pagination I would retrieve the criterias from the session-store and then just show the appropriate results. Also I would append some kind of key to the pagination links (so this would be the only hidden post-field) under which the search criterieas can be found.
Even though the session is per user, you might have several search windows open within the same session, and you don't want to mess them up with the pagination.
In order to make a reliable search with pagination, we need to do a bit more than normal.
We need to handle the following cases.
Once search is done, user may choose to do browser back and forward. Here, if you are doing form submission on every page, it would be an overload. Also, if user presses browser refresh button, it will unnecessarily warn him that data is being submitted.
Searching on a large database with lots of criteria is costly. Hence, optimization is important.
So you should NOT do the following:
Submit data on every page change
Not store data in cookie. (This is not secure and not even reliable.)
For large database with complex query, cache the result in session.
In case, you need very up-to-date and real-time result, ignore point (3) and try doing partial search for every page.
Thus, for your case, you can do the following:
When user searches first time, make the form POST data to a search page.
This search page will store the search query in session and generate a unique id for it.
Now render the result page. The result page will be passed the search id (generated in point 2) and the page number. Example result.aspx?searchId=5372947645&page=2
The result page will puck up the query from session using the searchId and then provide result based on the page number sent.
Using hidden fields and POST method should be fine too unless you are able to get them on the next page right.
To supplement Sarfraz's answer...
It's not necessary to use Javascript to make a POST.
<form action="destination_url" method="POST">
...
</form>

Categories