I have angularjs application. I have edit form where url in routing is app/edit/:id. When I go to app/edit/5 then I can edit object where id = 5. But when I change manually url link to app/edit/6 then app loads object where id = 6. And it's my problem because my user can't edit this object. How to detect this situation? How to block it? Any options? Solution can be from other js framework.
The technique you are looking for is tamper-proofing your query string.
The idea is that you generate your query string on a server, calculate its hash value, add that hash to the query string and then check the hash on the server when user clicks on or somehow uses that link. However, it may still be prone to attacks.
Anyway, tamper-proofing query strings is not a common practice across the web, and should not be used as a replacement for authorization and authentication, so you should ask yourself, do you really need that?
Related
I am a graphic designer working on a website for my employer. At last minute, they have asked if it is possible to hide/reveal certain parts of a page dependent on whether the user types a specific email domain. After some research—given I am not an expert web developer—I figure out this bit of Javascript:
function validate()
{
var text = document.getElementById("email_input").value;
var formslist = document.getElementById ("forms");
var regx = /^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]{3,20})+#(email1.com||email2.com)$/;
if (regx.test(text))
{
forms.style.display = "block";
document.getElementById("errortext").style.visibility="hidden";
}
else
{
forms.style.display = "hidden";
document.getElementById("errortext").innerHTML="Our forms section requires an approved email address.";
document.getElementById("errortext").style.visibility="visible";
document.getElementById("errortext").style.color="gray";
}
}
And it works! But common sense tells me this seems too simple to be secure... How can I hide/hash/mask "email1.com" or "email2.com"? How could I decrease the of odds of someone just going into the browser's developer view and seeing the accepted values?
(Sorry if I am repeating this question. I just can't figure out the correct search terms for what I want to do!)
you can use digest method of Crypto API, and check the hashed input against the hashed email values
What you want is probably not possible using only a client-side approach, or else a robust client-side approach is probably overkill.
A one-way hash function is a cryptographically sound approach to allow the client to check input without revealing what the desired input is. You can send a hashed value H(v1) without leaking information about v1 itself, and then have the client verify if the user's input v2 satisfies H(v1) == H(v2).
However, what is the client then to do after verifying a match? If it's going to display information to the user, that same information must be sent to the client before displaying it. Though the page may be cryptographically sound in it's decision of when to show the information on the page, any modestly savvy user may find that information using debug tools in the browser without making the page's script render it properly.
One actually cryptographically sound approach is to only grant the client access to the secret display-information in a form that has been encrypted with a symmetric-key cipher using the output of a key derivation function (KDF) like Encrypt(secretData, KDF(v1)), and attempt to perform the corresponding Decrypt(secretData, KDF(v2)) to decrypt the data using the user's input v2. It would probably be simpler to just send the input to the server and have it decide whether to send the secret data at all, but if you have no server (or no server that you trust with your secrets, or no server you believe will stay online for the useful life of your client application) then this is a viable approach.
If you want this to be completely hidden from a "clever" user - you need to implement a backend validation. I don't see other good ways of doing this.
Javascript that runs in browser can be easily read by a user and translated into a more human readable form. So, even if you encode your strings with btoa() - it can be decoded with atob(). Example - https://www.w3schools.com/jsref/met_win_atob.asp
I'm working on a web application where a large set of data can be filtered using JavaScript. When a user selects filters, I want to update the URL of the page to reflect the selected filters so that the user can share that URL with someone else, and that person can load the page and my app will apply the same filters. I don't have a need for the back buttons in the browser to cycle thru the previous filters that were selected.
I think I have two approaches here:
I can create a representation of the filters and add them to the fragment of the current page via window.location.hash. I can parse them on page load to see if there are any already set.
I can create a representation of the filters as query string params, and manipulate the URL using the history API. I would use the replaceState method.
Is there a reason to chose one over the other? Again, I want to emphasize that I'm not concerned with any routing or browser history manipulation. I just want to provide a way for someone to put certain params in the URL that my JS code will parse and apply as the filters.
Using the Vue router and may be also vuex for state management should help you save some time. There is also a little helper library for url encoding / decoding --> qs.
To your question "history vs hash": that depends on your application, the system which hosts the application (e.g. part of a content management system with its own url handling) and the meaning of the params.
History mode generates better looking paths and features some more control, as long as you stay in your application. But: as your path segments have no identifiers, the sort order matters.
Scenario: You have an application which can have three params:
/value1/value2/value3 means something else as /value1/value3/value2
With a query string you don't need to take care about sort order, as every value has its key:
key1=value1&key2=value2&key3=value3 is the same as key1=value1&key3=value3&key2=value2
In my react based single page application, my page is divided in two panes.
Left Pane: Filter Panel.
Right Pane: Grid (table containing data that passes through applied filters)
In summary, I have an application that looks very similar to amazon.com. By default, when user hits an application's root endpoint (/) in the browser, I fetch last 7 days of data from the server and show it inside the grid.
Filter panel has couple of filters (e.g. time filter to fetch data that falls inside specified time interval, Ids to search data with specific id etc.) and a search button attached in the header of filter panel. Hitting search button makes a post call to a server by giving selected filters inside post form body, server returns back data that matches filters passed and my frontend application displays this data returned back from the server inside grid.
Now, when someone hits search button in the filter panel I want to reflect selected filters in the query parameter of the URL, because it will help me to share these URLs with other users of my website, so that they can see filters I applied and see data inside the grid matching these filters only.
Problem here is, if on search button click, I use http get with query parameters, I will endup breaking application because of limit imposed on URL length by different browsers.
Please suggest me correct solution to create such URLs that will help me to set the selected filters in the filter panel without causing any side effect in my application.
Possible solution: Considering the fact that we cannot directly add plain strings in query parameter because of URL length limitation from different browsers (Note: Specification does not limit the length of an HTTP Get request but different browsers implement their own limitations), we can use something like message digest or hash (convert input of arbitrary length into an output of fixed length) and save it in DB for server to understand the request and serve content back. This is just a thought, I am not sure whether this is an ideal solution to this problem.
Behavior of other heavily used websites:
amazon.com, newegg.com -> uses hashed urls.
kayak.com -> since they have very well defined keywords, they use
short forms like IN for INDIA, BLR for Bangalore etc. and combine
this with negation logic to further optimize maximum url length. Not
checked but this will ideally break after large selection of filters.
flipkart.com -> appends strings directly to query parameters and breaks
after limit is breached. verified this.
In response to #cauchy's answer, we need to make a distinction between hashing and encryption.
Hashing
Hashes are by necessity irreversible. In order to map the hash to the specific filter combination, you would either need to
hash each permutation of filters on the server for every request to try matching the requested hash (computationally intensive) or
store a map of hash to filter combination on the server (memory intensive).
For the vast majority of cases, option 1 is going to be too slow. Depending on the number of filters and options, option B may require a sizable map, but it's still your best option.
Encryption
In this scheme, the server would send its public key to the client, then the client could use that to encrypt its filter options. The server would then decrypt the encrypted data with its private key. This is good, but your encrypted data will not be fixed length. So, as more options are selected, you run into the same problem of indeterminate parameter length.
Thus, in order to ensure your URL is short for any number of filters and options, you will need to maintain a mapping of hash->selection on the server.
How should we handle permanent vs temporary links?
You mentioned in your comment above
If we use some persistent store to save the mapping between this hash to actual filters, we would ideally want to segregate long-lived "permalinks" from short-lived ephemeral URLs, and use that understanding to efficiently expire the short-lived hashes.
You likely have a service on the server that handles all of the filters that you support in your application. The trick here is letting that service also manage the hashmap. As more filters and options are added/removed, the service will need to re-hash each permutation of filter selections.
If you need strong support for permalinks, then whenever you remove filters or options, you'll want to maintain the "expired" hashes and change their mapping to point to a reasonable alternative hash.
When do we update hashes in our DB?
There are lots of options, but I would generally prefer build time. If you're using a CI solution like Jenkins, Travis, AWS CodePipeline, etc., then you can add a build step to update your DB. Basically, you're going to...
Keep a persistent record of all the existing supported filters.
On build, check to see if there are any new filters. If so...
Add those filters to the record from step 1.
Hash all new filter permutations (just those that include your new filters) and store those in the hash DB
Check to see if any filters have been removed. If so...
Remove those filters from the record from step 1.
Find all the hashes for permutations that include those filters and either...
remove those hashes from the DB (weak permalinks), or
Point that hash to a reasonable alternative hash in the DB (strong permalinks)
Lets analyse your problem and the solution possible.
Problem : You want a URL which has information about the filter applied so that when you share that URL user doesn't land on arbitrary page.
Solutions:
1) Append filter applied with URL. To achieve this you will need to shorten the key of type of filter and the value of filter so that Length of URL don't exceed much for each filter.
Drawback: This is not most reliable solution as the number of filter increase URL length has to increase no other option.
2) Append a unique key of filter applied(hash) with URL. To achieve this you will need to do some changes on server and client both. On client side you will need a encoding algorithm which convert filter applied to unique hash. On server side you will need decoding algorithm which convert unique hash to filter applied. SO now client whenever a URL like this is hit you can make a POST api call which take this hash give you the array of filter applied or on client side only put the logic to convert this hash.
Do all this in componentWillMount to avoid any side effect.
I think 2nd solution is scalable and efficient in almost all cases.
In an ASP.NET MVC application, there is Request.Url to access the url in Global.asax.
But for an Angular application where an url is like http://domain/#/home. The Request.Url we obtained from Application_BeginRequest or Application_EndRequest are http://domain/. The Angular routes are not included.
It is reasonable because those routes are added at the client side. But is it possible to get the value of the true url in the MVC server side?
Update:
Just picked Matteo's answer as the correct one. Let me clarify a bit.
I have been trying this for one purpose: rewrite my url.
In the past, I used to check Request.ApplicationPath and manipulate url with string functions or built-in tools like VirtualPathUtility.
The need for the hash part is valid because the query string parameters are appended there. For example, I have a url like this:
http://[domain]/#/pay/cancel?paymentId=[some guid]
The conventional wisdom brought me to Global.asax to access those query parameters. I find none. Everything behind the hash tag is conveniently ignored.
So the correct way is to handle that part of url in the client side code. I am using ui-router. So for url rewrite/redirect, use stateProvider.when(oldUrl, newUrl);. To access query parameters, use $state.params.
Lesson learned: think clearly and approach different problem with different mindset.
There is no way, as the "hash" part of an url is not really part of the url. Have you ever used anchors in a page to create an index? The concept is the same.
Anyway I can't possibly imagine how the hash part could be useful server side. My guess is that you think it's useful because you're approaching a problem the wrong way.
If you complement your question with more details, like what you're trying to achieve, it's very possible we can provide you with an appropriate solution.
I am building a webapp and have a few arrays that I would like to pass through the URL in order to make the results of my application easily sharable.
Is there an efficient way to do this? I know a lot of websites (like youtube) use some sort of encoding to make their URLs shorter, would that be an option here?
Thanks in advance!
What I suspect you're asking is you have some page where the user can alter information, etc, and you want a way to create a URL on the fly with that information so it can easily be accessed again. I've listed two approaches here:
Use the query string. On your page you can have a button saying "save" that produces a URL with info about what the user did. For example, if I have a webpage where all I do is put my name in and select a color, I can encode that as http://my-website.com/page?name=John_Doe&color=red. Then, if I visit that link, your page could access the query object in JavaScript and load a page with the name and color field already set.
An approach for the "YouTube-style" URLs would be to create a hash of the relevant information corresponding to the page. For example, if I were creating a service for users to store plaintext files. These files are to have the following attributes: title, date, name, and body. We can create a hash of the string hash_string = someHashFunction(title+date+name).
Of course, this is a very naive hashing scheme, but something like this may be what you are looking for. Following this, your URL would be something like http://my-website.com/hash_string. The key here is not only creating these URLs, but having a means to route requests on the server side to the page corresponding to the hash_string.