Cookies, HTTP GET, and Query Strings - browser

The United States District Court for the Southern District of New York in re Doubleclick Inc. stated:
"GET information is submitted as part of a Web site's address or "URL," in what is known as a "query string." For example, a request for a hypothetical online record store's selection of Bon Jovi albums might read: http://recordstore.hypothetical.com/search?terms=bonjovi. The URL query string begins with the "?" character meaning the cookie would record that the user requested information about Bon Jovi.
Is it true that a URL query string with a "?" would have the cookie record the user requested information? If so, what RFC/standard includes this?
Edit: I understand the United States District Court doesn't define standards, but I would like to have something concrete to note that they were incorrect.

If you read the whole document, you'll note that they say
DoubleClick's cookies only collect
information from one step of the above
process: Step One. The cookies capture
certain parts of the communications
that users send to
DoubleClick-affiliated Web sites. They
collect this information in three
ways: (1) "GET" submissions, (2)
"POST" submissions, and (3) "GIF"
submissions.
They are describing a process used by DoubleClick, not an internet standard.
You (and anyone else, including DoubleClick) can take information that is available to you (including information that might be sent as part of a GET submission) and store it in a cookie.
You should interpret the sentence in question (in context) like this:
DoubleClick stores information from the query string in a cookie.
The URL query string is the portion of a URL that begins with the "?" character.
The query string portion of the hypothetical URL is "Bon Jovi".
DoubleClick's process would use a cookie to record that the user requested information about Bon Jovi
Supported Conclusion:
DoubleClick takes/took information from a URL query string (which is the part of the URL that begins with a "?") and uses a cookie to record information that the user requested.
Unsupported Conclusion:
A URL query string with a "?" would have the cookie record the user requested information. There exists some RFC that describes this behavior.

It's certainly possible to store the query string in a cookie, but there is no technical standard that forces that to occur.
They are likely referencing something specific to the code on that specific website, which is presumably storing the query string in a cookie.

Cookies get set and submitted seperately from the URL, so in the HTTP-header it would look like this:
GET /search?terms=bonjovi
Cookie: $Version=1; UserId=JohnDoe
The only way the query string would be stored in a cookie would be if a cookie path is used in conjunction with rewritten URLS or if the server explicitely sets a cookie with some sort of id or the query string.

Last time I checked, the US District Court for the Southern District of New York didn't define Internet standards.
The query string does not affect the cookies, they are using technical language in a sloppy way.

That text may be just an example and you shouldn't stick to that.
Including any text in the query string does not imply a cookie is created with that information, although some sites may contain additional code to do so.

Related

How to pass a unique user ID to a page with user-specific, personal data

I'm sending a mass email though Emma (3rd party vendor) that will contain a link to a landing page. The landing page will be personalized and display some of the user's identifying info (name, title, email). Additionally, there will be a form collecting a few of the user's preferences that will be saved back to that user's record in Emma's database.
The user ID column in the 3rd party's database is incremental so I obviously can't just append that value through the query string otherwise user 522, for example, would get a link such as www.example.com?landing/?uid=522 allowing him (or anyone with the link)cto take a wild guess at other values for uid (such as 523... or 444) and change other users' preferences as well as view their personal data quite easily.
Bottom line is that I'm trying to find a secure way to pass an ID (or other unique value) that I can look up via API and use to dynamically display and then resubmit personal info/data on this landing page on a user-to-user basis.
I had an idea to add a custom column to my list in Emma for a unique identifier. I would then write a script (accessing Emma's API) to BASE64 Encode the ID (or possibly email address, as that would be unique as well) and add that to the list for each user. In my email, I could then pass that to the landing page in for the form of ?xy=ZGF2ZUBidWRvbmsuY29t, but I know this is encoding and not encrypting so not all that secure... or secure at all for that matter.
To my knowledge, there's no remote risk of anyone receiving the mailing having the ability and/or inclination to know what those extra characters in the link are, BASE64 Decode, BASE64 ENCODE another email address or integer an make a request with the newly BASE64 encoded value in order to manipulate my system in an an unintended way.
BUT for the purpose of this question, I'd like to know the "right" way to do this or what levels of security are currently being taken in similar circumstances. I've read about JWT tokens and some OOth stuff, but I'm not quite sure that's possible given that I've got the Emma API to deal with as well... and/or if that is overkill.
What is appropriate/standard for passing values to a page that are in turn used for a form to be resubmitted along with other user-supplied values when giving the user the ability to submit a "compromised" (intentionally or not) form could, at worst, could cause one of their competitors to have bad preference and opt-in saved data in our Emma mailing list?
Security on the web is all about "acceptable risk". You can reduce risk in various ways, but ultimately there's always some risk exposure you must be willing to accept.
Your very best option would be to force users to be logged-in to view the page, and to avoid using any querystring parameters. That way the backend for the page can pull the ID (or whatever it might need) out of the server's session.
Your next best option still involves forcing the user to be logged in, but leave the uid in the URL -- just be sure to validate that the user has access to the uid (i.e. don't let a user access another user's info).
If you can't do that... then you could create random keys/ids that you store in a database, and use those values (rather than uid or email or real data) in the URL. BUT let's be clear: this isn't secure, as it's technically possible to guess/deduce the scheme.
Absolutely DO NOT try passing the info in the URL as base64 encoded data, that's likely to be the first thing a hacker will figure out.
Keep in mind that any unsecured API that returns PII of any kind will be abused by automated tools... not just a user farting around with your form.
To my knowledge, there's no remote risk of anyone receiving the
mailing having the ability and/or inclination to know
^ That's always always always a bad assumption. Even if the result is at worst something you think is trivial, it opens the door for escalation attacks and literally exposes the company to risks it likely doesn't want to accept.
If you're stuck between bad options, my professional advice is to have a meeting where you record the minutes (either video, or in a document) and have someone with "authority" approve the approach you take.
In case anyone needs a working example, I found this at https://bhoover.com/using-php-openssl_encrypt-openssl_decrypt-encrypt-decrypt-data/. It uses PHP's openssl_encrypt and openssl_decrypt, and it seems to work perfectly for my purposes
<?php
$key = base64_encode(openssl_random_pseudo_bytes(32));
function my_encrypt($data, $key) {
// Remove the base64 encoding from our key
$encryption_key = base64_decode($key);
// Generate an initialization vector
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
// Encrypt the data using AES 256 encryption in CBC mode using our encryption key and initialization vector.
$encrypted = openssl_encrypt($data, 'aes-256-cbc', $encryption_key, 0, $iv);
// The $iv is just as important as the key for decrypting, so save it with our encrypted data using a unique separator (::)
return base64_encode($encrypted . '::' . $iv);
}
function my_decrypt($data, $key) {
// Remove the base64 encoding from our key
$encryption_key = base64_decode($key);
// To decrypt, split the encrypted data from our IV - our unique separator used was "::"
list($encrypted_data, $iv) = explode('::', base64_decode($data), 2);
return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
}
I first ran my_encrypt in a loop to encrypt the uid of each member in the list.
$members[$uid] = array('unique-identifier' => my_encrypt($uid, $key));
Next, through the API, I modified each member's record with the new value.
$ret = update_members_batch($members);
That only had to be done once.
Now in my email, I can pass the uid through the query string like this www.example.com/landing/?UID=<% unique-identifier %>, which will look something like www.example.com/landing/?UID= XXXXX2ovR2xrVmorbjlMMklYd0RNSDNPMUp0dmVLNVBaZmd3TDYyTjBFMjRkejVHRjVkSEhEQmlYaXVIcGxVczo6Dm3HmE3IxGRO1HkLijQTNg==
And in my page, I'll decrypt the query string value and use it via the API to get the email address with something like:
$member_email = get_member(my_decrypt($_GET['UID']))['email'];
and display it in the appropriate location(s) on my page.
I think this covers all my bases, but I am going to have a stakeholder meeting to get sign-off. What potential vulnerabilities does this expose that I should warn them about?

solution for: select input, dropdown tampering prevention

for hidden field tampering protection: Id, RowVersion, I use a version of Adam Tuliper AntiModelInjection.
I'm currently investigating a way to prevent tampering of valid options found in select lists/drop downs. Consider a multitenant shared database solution where fk isn't safe enough and options are dynamic filtered in cascading dropdowns.
In the old days of ASP.NET webforms, there was viewstate that added tampering prevention for free. How is select list tampering prevention accomplished in ajax era? Is there a general solution by comparing hashes rather than re-fetching option values from database and comparing manually?
Is ViewState relevant in ASP.NET MVC?
If you can, the single solution here is to filter by the current user ids permission to that data, and then those permissions are validated once again on the save.
If this isn't possible (and there are multiple ways server side to accomplish this via things like a CustomerId fk in your records, to adding to a temporary security cache on the server side, etc) , then a client side value can provide an additional option.
If a client side option is provided like was done with Web Forms, then consider encrypting based on their
a.) User id plus another key
b.) SessionId (session must be established ahead of time though or session ids can change per request until session is established by a value stored in the session object.
c.) Some other distinct value
HTTPS is extremely important here so these values aren't sniffed. In addition ideally you want to make them unique per page. That could be the second key in A above. Why? We don't want an attacker to figure out a way to create new records elsewhere in your web app and be able to figure out what the hashes or encrypted values are for 1,2,3,4,5,6,etc and create essentially a rainbow table of values to fake.
Leblanc, in my experience, client side validation has been used mostly for user convenience. Not having to POST, to only then find out that something is wrong.
Final validation needs to occurs in the server side, away from the ability to manipulate HTML. Common users will not go on to temper with select lists and drop downs. This is done by people trying to break your page or get illegal access to data. I guess my point is final security needs to exist in the server, instead of the client side.
I think a global solution could be created given a few assumptions. Before i build anything I'll like to propose an open solution to see if anyone can find flaws or potential problems.
Given all dropdowns retrieve their data remotely. - in an ajax era and with cascading boxes this is now more common. (We are using kendo dropdowns.)
public SelectList GetLocations(int dependantarg);
The SelectList will be returned back as json - but not before having newtonsoft serialization converter automatically inject: (done at global level)
EncryptedAndSigned property to the json. This property will contain a Serialized version of the full SelectList containing all valid values that is also encrypted.
EncryptedName property to the json. This property will have the controller actionname - For this example the EncryptedName value would be "GetLocations"
When the http post is made EncryptedName : EncryptedAndSigned must be sent in the post also. For this JSON POST example it would be:
{
Location_Id: 4,
GetLocations: 'EncryptedAndSigned value'
}
On the server side:
[ValidateOptionInjection("GetLocations","Location_Id")
public ActionResult Update(Case case)
{
//access case.Location_Id safety knowing that this was a valid option available to the user.
}

Look for unique ID pattern which easy indexed by search engines

Like from Microsoft - "KB2756872" or from National Vulnerability
Database - "CVE-2010-1428" or from Red Hat - "RHSA-2010:0376" or
from OIDs - "1.3.6.1.4.1.311" or from UUID/GUID
- "550e8400-e29b-41d4-a716-446655440000".
I want to put several jobs to UIDs. See next...
I develop blog software and have idea to put unique ID in body of
each post so can easily identify that copy from local storage is
correspond to remote published copy.
Also I want to post to many different blogging services so if one
is down articles will be accessible from another. So link can
dead but if I add UID - anyone can try web-search to find post on
another service!
Also this allow to gather some article spreading
statistics. Many sites just replicate content (copy-writing and
rewriting bots and people) to broke search engines. With UID I
easily can identify such sites...
So my question how is to make UIDs (in which form) so it would be
easily indexed by search engines (web, like Google/Yahoo, and
corporate, like Lucene/Solr/Sphinx/Xapian/etc).
I know about some limitation of search engine like:
only >= 3 chars for each search part
it was not indexed dust like gfh6wytrh6wu56he5gahj763
so this task s not easy...
Any advice is appreciated (books/blog articles/etc).
You could use Tag URIs, as defined by RFC 4151.
They are globally unique, and everyone who owned a domain name or an email address for at least a day can mint them.
Note that these URIs only identify, they don’t locate. So a Tag URI doesn’t say anything about where something is published.
Let’s say your site’s domain is "example.com". If you create a blog post, you could create the following Tag URI:
tag:example.com,2012-12:cute-cat
Note that the date in this URI is not a publication date! It must be a (past) date on which you owned the domain (resp. email address). If you registered your domain in 2003, you could always use Tag URIs starting with tag:example.com,2004: (not "2003", because "2003" would mean "2003-01-01", which might be a time where you didn’t own the domain yet), followed by a (unique) string under your control. However, if you like you could always use the publication date, of course. But don’t use future dates.
You can use year and number based article identifier just like CVE identifiers. Since you need revisions as well, you can append dot after the identifier to clarify the version. For example, for an AWesome Blog Service, AWBS-2012-1.0 would refer to original document, AWBS-2012-1.1 would refer to first revision etc.
However, you need to make sure that AWBSs are unique before you use them. CVEs are assigned manually from the pool. You would probably need some kind of service that assigns AWBS from pool. It could be a simple database query.

How do I get the foursquare venue ID from the new pretty url

The new venue urls are prettier but the ID isn't there and there is no mechanism to look up the ID from the pretty url.
For example, this particular url:
https://foursquare.com/felice_83
How can I look up the venueID?
In the righthand sidebar, there is a link to Claim the location. In the URL for that claim link, the "vid" parameter is the venue ID.
When searching a Place on foursquare.com, or expanding a 4sq.com short link, the ID will be appended automatically to the pretty URL, e.g.
https://foursquare.com/v/sim-lim-square/4b058815f964a520aab022e3
Where 4b058815f964a520aab022e3 is the Venue ID. This will save you time on manual lookups compared to reverse engineering the vid query string param from the "Claim it now." links.

SEF url without passing id

Client need SEF URL for e-commerce site (ISS 6). We tried IonicIsapiRewriter and it works good.
Now consider the below url,
www.store.com/product/12345/men_tshirt.html
This works fine. I write the rule to pass the id as query string (product.action?prt_id=12345)
But client wants the URL to be
www.store.com/product/men_tshirt.html
How to do this? Without passing product id how to identify the product?
In order to get this working as expected, the men_tshirt part needs to be the new ID to identify the resource that was formerly identified by 12345. So men_tshirt needs to be a unique value in that context.
Then you just need a mapping of those textual IDs onto numeric ID.

Resources