Embedded iframe - Verify source/origin of GET request - php

I'm seeking to utilize an iframe to embed some html in customers websites that will list some information from my database using a simple GET request like so:
// customer would copy/paste this code onto their site
// value of key would be unique key for that customer
<iframe src='http://mydomain.php/api?key=1234j1lj1hj124kh' ></iframe>
Now I want to be able to verify that the request is coming from customer that owns the key, and not just anybody who copy/pasted that code onto their page.
I've done some research and found that $_SERVER['HTTP_REFERRER'] can give me this information, but with mostly mixed reviews saying it isn't always reliable (and most of the questions I came across were a couple years old).
QUESTIONS
1.) Is this method of using an iframe/GET request the standard way of achieving this functionality?
2.) Is there a standard, SECURE and RELIABLE way to verify the origin of the GET request?

Unfortunately this is not possible in a secure way.
To answer your questions: In fact this is not a standard functionality itself. I mean, there is no standard secure way of allowing content to be loaded only through iframes from allowed websites.
There are three parties in this communication:
1) Your website
2) Customer website that loads your website's data in an iframe
3) End user visiting customer website
When an end user visits customer web site, he will perform a GET request to your website through the iframe. At this connection, 2nd party above (customer website) is not involved. In this case, there is no reliable way for your website to know whether this request is coming through the iframe or not. Only favor that party 2 does here is adding HTTP_REFERER header to end-user's request. But this header cannot be trusted.
For example, if I want to abuse this and show that content on my website, I can create a proxy page on my application, where I perform a back-end call to your app (adding a valid HTTP_REFERER header) and display results back.

Personally I would never use iFrames for this functionality. I am assuming that this has to be reasonably secure, which is why only your specified customer can view it? If for whatever reason you can't use PHP to embed the content you need to display (through the use of an "included" file for example), I would instead use AJAX which would still use any PHP user verification you have in place to dynamically load content into a secure webpage.
This is because your PHP user verification will (should!) use cookie/session information to determine which customer is viewing the page and therefore decide whether the content should be delivered, since Session variables are determined by a single unique code stored client-side, which match up to as much information as you want to collect about a user server-side (Which could include the last page they visited, which is what the "HTTP_REFERRER" variable would give you, if they came from another page on your website).
'$_SERVER' variables aren't reliable because they rely on the information given to them by the web browser when the request is made, and such information can easily be forged, by most people who have a basic understanding about how headers are sent.

In summary, use a NONCE (cookied), validate IP and user agent.
Steps:
When you deliver the outer frame, generate a unique identifier
(totally random, long string) and return that in a cookie with the
HTML content.
At the same time, note the IP and the user agent string you have
sent that unique identifier to, and store in a DB with the time.
When requesting the inner frame, assuming the same domain, the
cookie will come too. (If a different domain, you'll need to attach
the unique identifier as a visible string, but that's not really of
concern, just uglier)
If the user agent or IP do not match those you stored against the
unique string, or the request is too long (i.e. after an hour, or
whatever is reasonable for your application) or the unique string is used more than once
(or whatever other restrictions you place on it) then reject the
request and invalidate (delete) the unique identifier.
Not 100% foolproof, but just combine more options to make it less and less likely to be abused.

Related

How to hide a piece of text in header ("Location:") using php

HTMLCODE IMG
PHPCODE IMG
I used the HTML file to redirect to the php file and from there i want to redirect to address below
header( "Location: https://csp-thanhhung123213.c9users.io/FINAL/HOME.php?username = thanhhung" );
My only question is that is there any way I can hide "username = thanhhung" from the link when redirect to the address above
THKS for helping me, have a nice day
There's no way you can hide any information that goes through the client. You're trying to redirect the client to another site, and make it carry some information with it. That means in one way or another, the client will need to know about the information to carry it to the other site.
The only way to not expose information to the client is to… well, not expose it. If you control both the origin and the target server, you store the information in a session server-side instead of transporting it client-side. If the two servers are separate, you could encrypt the information you give the client so the client can transport, but not read it. Another option is to give the client a meaningless token, and exchange the actual information associated with that token directly server-to-server behind the scenes.
You want a POST field, you should not use GET variables for sensitive information.
https://www.w3schools.com/tags/ref_httpmethods.asp
Edit:This question wasn't as clear when I initially posted, so here's the revised solution.
Solution 1:Nonce
What you want here is a nonce, a nonce is a value held on your server that represents a hidden value. It stands for number-once. A one time value. that way the sensitive information never leaves the server.
Before rewriting the location, store a map from nonce->username on the server, then rewrite with the nonce instead of the username. In the receiving script map the nonce back to the username, and proceed as usual.
Solution 2: Less secure
You could encrypt the string by XORing it with a secret hardcoded into each script, but since that's constant, an attacker could easily recover the key if they are able to manipulate username.

Is it safe to use variable session data?

I have a (hopefully) quick question regarding sessions. Whilst I have used sessions extensively, I have not used them in a situation whereby the values change depending on a users actions.
After logging in to my application, a user can select a company area, which has many levels of pages and folders. All of these pages will need this 'company_id'. At the moment I send the company_id via GET, but as I get deeper into the application this is becoming increasingly hard to maintain, with various other data being stored in the URL.
Therefore, when a user selects their company, I could set their company_id in $_SESSION array. However, when a user changes company, I would then need to change $_SESSION['company_id'] to the new value.
Is this a good use of sessions? I could potentially clean up my urls by using session data rather than always using GET, but I am unsure if this is a recommended way of using sessions.
Thanks in advance
This is a bad implementation of the HTTP design philosophy. All HTTP requests should be self contained, RESTful. All information needed to get a specific page should be present in the request itself (URL, headers and body), not dependent on hidden state.
Super trivial example: you can't copy a URL to someplace or someone else and have them see the same page. The content of the page is dependent on session state, which has been laboriously set through the visit history of several previous pages. To return to this same page, you need to retrace the same steps, recreating some hidden server-side state to arrive at the same page.
This gets even more complex and messier if you take into account that a visitor may want to open pages requiring different states in two or more simultaneous tabs/windows.
All this isn't to say that it can't work, only that it's hideously complex and will break the usual expected behaviour of browsers, unless you really bend over backwards to somehow prevent that.
If the many levels of pages and levels are per-company, you can put the company_id in a specific include file - this part of the site being dedicated to a given company.
However if they're shared by multiple companies, and this is probably what you want, this is potentially misleading, or even dangerous depending on the user actions, since the user may jump to a given page (link...) and access a page with unexpected data linked to a company which ID is provided by the session or cookie.
You could dynamically build the links on a page, based on IDs, to ensure consistency during the navigation from that page. Any direct "jump" to another part of the site will not carry the ID with it (and the page may offer to select a company).
Depending on your web server and if you have control over it you could build the URL having "company ID" as an element of the URL path, not the GET parameters
Eg
http://example.com/invoicing/company382/listprices.php
using a rewrite (web server configuration) to change the URL to be actually used to
http://example.com/invoicing/listprices.php?compid=company382
(URL not visible to the user) that informs of the company ID via the GET parameters.

php security & marking mysql records for deletion using a html link (GET)

Just wondering if people think it is safe for a website to use a html link to allow users to mark their documents for deletion from their secure account page?
I have a website where users can create documents once they have registered and logged in to the website. To delete a document I include links on their account page for each document to be marked for deletion as follows :
http://www.examplewebsitename.com/delete_document.php?docid=5
The delete_document script makes sure the docid parameter is numeric, then checks using a session variable of their user id set when they logged in, wether this person actually created this document by looking up the user id of the creator of the document. If they where the creator, then it marks the document for deletion, otherwise if the current logged in person wasnt the creator then it doesnt mark the document for deletion and returns an error page.
Do you think this is a valid and safe way to mark documents for deletion, or should I be using a form and Post to do this more securely?
Three main concerns I can think of about using GET as a delete operation for your app.
Semantic reason, GET, according to http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html, should be an idempotent method
the side-effects of N > 0 identical requests is the same as for a single request.
More prone to CSRF, someone could post a link to http://www.examplewebsitename.com/delete_document.php?docid=5 and wrap the link into a harmless looking anchor
Click here for free puppy!
If by any chance the user is logged in and clicked on that link on his trusted website, it would inadvertently get the user to delete the document.
Browser addon / plugin that crawls web pages and cache links might accidentally crawl the link, opens it and again, delete the document without your user knowing.
Generally I advice against using GET requests to manipulate data because that's not what GET is designed to do if you stick to the HTTP Spec. If you would go completely restful you should be using a DELETE request but in most cases i use a confirmation page with a form that performs a POST request to delete the record.
Read Why should you delete using an HTTP POST or DELETE, rather than GET? for the reasoning behind this. It's been asked before in some other contexts.
The main reason is because GET is meant to be a safe method that is used for retrieval only:
In particular, the convention has been established that the GET and
HEAD methods SHOULD NOT have the significance of taking an action
other than retrieval. These methods ought to be considered "safe".
This allows user agents to represent other methods, such as POST, PUT
and DELETE, in a special way, so that the user is made aware of the
fact that a possibly unsafe action is being requested.
User agents expect this method to have no side-effects:
Naturally, it is not possible to ensure that the server does not
generate side-effects as a result of performing a GET request; in
fact, some dynamic resources consider that a feature. The important
distinction here is that the user did not request the side-effects,
so therefore cannot be held accountable for them.
This means GET should no cause any server-side state change.
Another reason, but rather a minor one, is that GET is easier to exploit that POST as there are more ways to trigger GET request than to trigger POST request. But no matter which method, both are vulnerable to CSRF attacks.
So if you make sure you’re protected against CSRF, you could even use GET for state changing requests.

PHP Guest Access to Website

I have a PHP project is essentially an order processing website for a company. Each user in the company has access to this website and is given certain credentials to the application that control access to pages and functionality throughout.
Now I have a request to allow a guest access to a single page. The complexity of this request is that the guest will be different each time as well as the page will be different. Basically it is a portal to allow customers, who don't have accounts within the system as there is no live ordering on this site, to be able to access and verify the order and shipping information.
My thought to accomplish this is to have a database table setup as a guest relationship table that will be used to store UIDs, MD5 Hash Keys and the destination page that the record is referring to. Also included would be a visit counter and expiration date. When the user receives an email they would have a link provided in the email to somewhere like http://website.com/verify/?HASH-KEY.
When this link is clicked I expect that the verify index.php page takes in the HASH, verifies it in the database and displays the page reference in the database within this location instead of redirecting into the application. This would allow guest access to the single page without the need to expose the structure of the website or a rework of the user authorization already setup.
Am I approaching this solution in the proper manner?
How do I grab the contents of one page and display it in another?
1. Am I approaching this solution in the proper manner?
Yep, more or less.
Some pointers:
Make sure you seed hash generation randomly. For example, DON'T simply MD5 a customer ID or some other small/sequential number, as that would make it easy for a malicious use to hunt down other pages.
Expire the hashed links after a set time out.
2. How do I grab the contents of one page and display it in another?
If you want people to "access and verify the order and shipping information" you should probably create a page specifically for it, instead of trying to pass through normally secure pages to insecure guests. Ie, a 'shipping confirmation page' that populates details according the data keyed by the supplied hash.
I'm trying to a follow this as well as I can.
It seems to be you should use your hash method, and just have a stand alone page that will generate the content you want, totally separate from the rest of the system. Just put enough data in your hash URL to determine what is needed.
Something else to do is use a timestamp in your hash string URL and have that timestamp part of the random bits that you generate your hash on. This will allow you to make a URL essentially "expire" after a certain point.
Example: url.com/in/123456789865/hash-here
You can compare "123456789865" in this example to the current server time and determine if its expired. Of course you need to make "123456789865" part of your hash encryption to still validate
If I understand you correctly (and I think I do), than I think you're approaching this correctly.
To include another page's contents, you usually use include.
include "/path/to/page.php";

remote user name

Is it possible to get remote username when I get a referral link without involving any server side code from the referral link?
Do you mean like if I clicked a link to your site on Stack Overflow, you would want to be able to see that my username is "Agent Conundrum"? No, you can't do that without the help of the referring site. The only information you should be able to get is the (permanently misspelled) HTTP_REFERER in the $_SERVER superglobal array, which tells you the page the user came from. Even then, there are ways to block or change this so you shouldn't count on it being set (especially since it wouldn't be set if the user navigated directly to your page via the address bar).
Frankly, I wouldn't want to use a site that leaked personal information (and for some sites, even the username qualifies as personal information), and I wouldn't want to use a site that tries to harvest such leaked information without my knowledge.
Generally, any site where you have a legitimate reason to broadcast this information would have some sort of API built in, like FacebookConnect. Even then, it should be strictly opt-in for the user.
As a general thing: no. The HTTP protocol does not involve the transmission of a remote user name.
Hey, it could help to answer if you would be a little more specific on which kind of service are you trying to fetch the data from.
Large/Public services tend to have somekind of an accessible API that you can fork on your referrer, but other than that its mostly that you need to regexp the site and know the structure of the HTML pretty much.

Categories