HMAC verification API in javascript - javascript

I am successfully implemented HMAC verification from the backend but would like to offer JSONP support. Since I dont want the client to know about the secret key, what is the best way to take advantage of HMAC and make calls from the client?

If the attacker knows the secret key then he will always be able to generate a valid HMAC. An attacker will be able to obtain this HMAC value by looking at the traffic or by modifying the JavaScript. A JavaScript debugger like firebug could also be used.
In short, this security feature doesn't exist anywhere because its completely and totally worthless. It sounds like you are very carefully implementing a CWE-602 violation.
Trusting the client is the worst mistake you could make. The very foundation of modern web application security is about defending the server from the client. I think you have a lot to learn.

Related

How to restrict the web client to a certain domain?

I have a problem that people are cloning my website front and imitate calls to my API from their own domains to abuse my service. The solution I came up with is for Angular client to check the URL it works on, encrypt it and add as a header to API call. Obfuscate the JS code to prevent reverse engineering. This way API will receive an encrypted header and make sure that the domain is the proper one.
So on the client side
headers.append(`CustomHeader`, this.encryptDomain());
and on the server side
var domainEncrypted = Request.Content?.Headers?.GetValues("CustomHeader").FirstOrDefault();
var domainPlain = Decrypt(domainEncrypted);
if (domainPlain != myDomain)
{
return BadRequest();
}
Can you please help me with code samples to match JS and C# encrypt and decrypt algorithms? So that encryptDomain works on JS side and Decrypt works on the C# side. I am aware that this is not a perfect solution, but I want to try. And if anyone has a better idea, you are welcome.
Edit: apparently what I want to do is similar to JScrambler domain lock feature
TLDR
It is not possible to prevent communicate with your API through different (cloned) clients guaranteed way in cases when white-lists of IP addresses can't/shouldn't be used.
Why
Think about it that way. You have a server that has some identification rule - client should have some identifier that marks it as trusted. In your question it is a domain.
Domain is a public information that could be passed in HTTP header or in the body of your request, it is easy, but also it will be easy for clients to replace this information on their side.
And if you use any type of cryptography to provide more secured identification mechanism - you just making it harder to hack it and again pretend as trusted client, because every mechanism you use on the client side could be reverse-engineered by a hacker. Just look at this question.
One think you can use to guaranteed access restriction is to use white-list of IP addresses on server-side, because IP address is a part of TCP/IP transport level protocol and it has "handshake" process to identify communicated points to each other, and it is kind of hard to replace it. Check this question for details.
So what can you do?
CORS
Setup CORS policy is a first step to create a trusted client-server communication. Most of browsers are support CORS policies, but of course client may be not a browser. And the questions was not about browser-server communication, but I should mention that because browser is a client too.
Client-side encryption
You can use encryption, but I don't see any reason to do that because any request to server could be read through your legal client (website). So even if you encrypted it - any person has a key and a crypto algorithm on their side to pretend as trusted client. But if you want to...
You need to create unique key every your request to make life of pretenders little harder. To make it you need few ingredients:
Public key for key generation (encrypted) on the client side
Obfuscated key generation JS code
Private key for decrypt generated key on the server side
JS-side RSA crypto libraries could be googled easily (for example)
Obfuscation libraries could be found just using google too (like this)
Server-side decryption could be done with System.Security.Cryptography namespace if you use C# backend.
Basically, more complex key-generation algorithm you make and more obfuscated code you make - more hard for hacker to pretend himself as a trusted client. But as I said there is no guaranteed way to completely identify trusted client.
You cannot prevent people from copying your website's FE assets... They are supposed to be publicly available. You could try to make it a little harder by spliting your built app in more chunks (with angular's lazzy-loading or by manipulating webpack's config). Still, Browsers require code in plain text, so although this makes it a little harder it does not prevent copying.
When we build angular for production it already does code obfuscation through its optimizations (minification, tree-shaking and so on).
To mitigate the problem of people misusing your Server resources, you need to implement robust practices on Back-End request authorization and some miss-usage detection.
Configuring CORS would not work, as you reported attackers are using BE proxies.
Make sure your request's authentication is solid. A market standard approach is the use of a JWT payload embedded in the Authorization Header of each request. It is simple, reliable and resource-inexpensive.
I would also recommend the implementation of request throttling. But this is a separated question.
If your authentication is already solid, you would need to detect when your real users are misusing your system. There are many tools to monitor traffic (like azure's) but there is no umbrella definition for "unusual traffic". Detection of "unusual traffic" is what you would need to custom built for the specifics of your system. Once you have a network traffic tool in place that should help you getting started.
Couple of solutions for you. Firstly you can block by applying a CORS policy on server. If you still want to do from code then you can block on this basis of hostname in c# like this.
var hostname = requestContext.HttpContext.Request.Url.Host;
if (hostname != myDomain)
{
return BadRequest();
}

How to develop secure Dropbox browser client?

A Dropbox browser client with application API key and secret stored in its source code is a bad idea as anyone could impersonate the application using them.
But what about the Dropbox API key encoder, if used, can a
third-party obtain the original key/secret?
If an attacker obtain the key/secret pair, what is the worst case
scenario that can happen to users of the compromised application?
What are the best practices dealing with Dropbox security in a
browser only client in order to have a perfectly secure
implementation (if possible)?
I think that the application stored on the client can never be completely secure, but I still would like to hear from developers more experienced than me.
Thank you in advance for your help
Caveat: I'm not a security expert.
Using the encoder might discourage a casual "attacker" from picking up your app key and secret, but it doesn't provide any true security. Here's a line of code using the JS library that converts an encoded key back into the unencoded key/secret pair:
Dropbox.Util.atob(Dropbox.Util.encodeKey(encodedSecret).split('|')[1]).split('?')
That said, the security risk here is that someone else uses your app key and secret, which is arguably not the end of the world. Pretty much all client apps that use OAuth (in the browser, on the desktop, and on mobile platforms) suffer from this problem. For example, here's one article discussing Twitter's leaked consumer key/secret: https://news.ycombinator.com/item?id=5337099.
I think the most likely consequence of exposing your app key and secret is that someone will copy/paste your code and use your credentials. This would be misleading to users (who will see the name of your app when they authorize via OAuth), and if another app takes your key and uses it in a malicious app, your legitimate app might end up being collateral damage.

Is there a way to securely send information in Ajax?

I'm currently developing an application in HTML+JS based almost entirely in ajax connections (using the jQuery.ajax() call to ease the process).
I was thinking about the best practice to make secure calls without using HTTPS (at least at this time. I can't afford paying for a certificate right now).
At this point, the only thing that concerns me is the registration and login steps. Maybe the login is a bit easier. I thought of sending the username and a timestamp, and then encrypt them using the user's password. So, by doing this, I wouldn't be sending any password (keeping as a secret like in OAuth). The server should check the user, decrypt using the password and pairing the recieved timestamp with the decrypted result. The server should keep the nonce-like number into a database (to avoid repetition attacks) and then give back to the user another unique id (encrypted with the user's password). At that point the user should start using that key to encrypt all his information (and probably another nonce) and send it to the server. Please correct me if you find any mistake or leak.
The very big problem to me is the registration. I can't encrypt with a regular password the information, because if I do that in the javascript, any could know the password. If I serve temporary generated passwords to encrypt and I send it from the server to the client, any sniffer could get it and use to decrypt the info.
I know HTTPS could save my life at this point (and maybe that's the only solution), but at this point I'm not able to use it.
Is there any other solution, or should I wait until I can use HTTPS? Bear in mind that if I could skip the wait, it would be better. Thanks mates!
Short answer: You can't do it without HTTPS
Longer answer: If you try to do it without HTTPS, you will find yourself trying to reproduce everything that HTTPS was designed to do. You could reach at some point, but it is unrealistic to believe that you will succeed in implementing even the 1% that HTTPS offers. The only benefit you will have would be an obscure security mechanism (security through obscurity), which may be OK for not critical systems, but would fail miserably in a real critical situation.
You could create your own certificate you know and then work with Ajax the same way as with regular HTTP calls. The only drawback is that the users will get a warning message.
Using an SSL Certificate is the only way really, if you encrypt it in javascript anyone can read the code and decrypt it.
http://www.startssl.com/
Generate a public/private key pair on the server, along with a randomly-generated salt.
Attach the key pair and salt to the user session object.
Send the public key and the salt to the client-side code.
Use the public key and salt to encrypt the AJAX requests.
This would not be a trivial task. You'll probably find that it's cheaper and more effective to just buy a certificate.
EDIT: This also means that all the regular HTTP traffic (HTML, images, CSS, etc) is sent in the clear. That could be a problem, since it might allow an eavesdropper to indirectly figure out what the user is doing.
I think you should have a look at :
http://assl.sullof.com/assl/
Here is the description of the project :
aSSL is a library distributed under MIT License thats implements a technology similar to SSL without HTTPS.
aSSL enables the client to negotiate a secret random 128-bit key with the server using the RSA algorithm. Once the connection has been established, the data will be sent and received using AES algorithm.
aSSL is composed of some Javascript files and a server side component. Because I have recently changed the negotiation algoritm from RC4 to RSA, only a pure Javascript (ASP) server component is currently available. I will do a porting for the main web languages (PHP, Java, Perl, Python, TKL, etc.) as soon as possible once the library has passed the beta phase.

How do I encode passwords in web forms without javascript?

It's not that I don't have access to javascript, of course. In most of my CS Web Development courses, we are taught a little bit about server-side validation, and then as soon as javascript is introduced, server-side validation is thrown out the window.
I choose not to just rely on javascript, as the client-side is never a secure place. I have gotten into the habit of writing both the client and server-side code for such things. However, for a web application that I am writing that has optional AJAX, I do not want the password to be send plaintext over the wire if someone has javascript turned off.
I realize I may be asking a catch-22 situation, so let me just ask this: how do we know our users' passwords will be secure (enough) from malicious users on the same network when all we can rely on is server-side scripting. On that first request from the login page, is there any way to have the browser encrypt a data field?
SSL Solves this problem. For the record, passwords should never be "encrypted" or "encoded", this employs that there is a method of "Decoding" or "Decrypting" which is a clear violation if CWE-257. Passwords must be hashed, SHA-256 is a great choice, but this is not meant for transmission, only storage. When you transit secrets there is a long list of things that can go wrong, SSL is by far the best choice for solving these issues.
If the attacker can sniff the traffic then they will be able to see the session id and use it immediately, so its a moot point. You have to use SSL to protect the authenticated session anyway.
The easy solution is SSL.
I think you're mixing up a couple of concepts. The browser does not encrypt individual fields. Client-side scripting, server-side scripting and AJAX are not means to defend against eavesdropping.
As others have said, SSL is the technology that encrypts the data. The entire request and response, including the fields and scripts are contained within the SSL session.
You can also use Digest HTTP Authentication.

JavaScript Code Signing

How can a user, using one of the major modern browsers, know for sure that he is running my unmodified javascript code even over an untrusted network?
Here is some more info about my situation:
I have a web application that deals with private information.
The login process is an implementation of a password-authenticated key agreement in JavaScript. Basically during login, a shared secret key is established between the client and the server. Once the user logs in all communication with the server is encrypted using the shared key. The system must be safe against ACTIVE man-in-the-middle attacks.
Assuming that my implementation is correct and the user is smart enough not to fall victim to a phishing attack there remains just one large hole in the system: an attacker can tamper with my application as it is being downloaded and inject code that steals the password. Basically the entire system relies on the fact that the user can trust the code running on his machine.
I want something similar to signed applets but I would prefer a pure javascript solution, if possible.
Maybe I am misunderstanding your problem, but my first thought is to use SSL. It is designed to ensure that you're talking to the server you think you are, and that no one has modified the content midstream. You do not even have to trust the network in this case, because of the nature of SSL.
The good thing about this approach is that you can fairly easily drop it into your existing web application. In most cases, you can basically configure your HTTP server to use SSL, and change your http:// requests to https://.
This is an old, open question but the answers seemed to not do this justice.
https:// provides integrity, not true identification nor non-repudiation.
I direct you to http://www.matasano.com/articles/javascript-cryptography/
Don't do crypto in JS, because a malicious injected script can easily grab passwords or alter the library. SJCL is neat, but it offer a blatantly false sense of security (their quote, and quoted by above)
Unfortunately, this is not as great as in desktop applications
because it is not feasible to completely protect against code
injection, malicious servers and side-channel attacks.
The long-term issue is that JavaScript lacks:
Uniformly working const
The ability to make objects deeply const and not reprototypable.
Code-signing
// codesign: cert:(hex fingerprint) signature:(hex MAC)
Certs would be managed similar to CA certs. MAC would be used with appropriate sign/verify constructions.
Crypto, clipboard stuff are reasons to have JavaScript native plugins (signed, of course)
Getting JavaScript engines to all implement a standard is another thing, but it's doable an it's absolutely necessary to end a large swath of malware.
You could have an external Javascript file which takes an MD5 hash of your login JS, and sends an Ajax request to the server to verify that it is correct and up-to-date. Use basic security or encryption practices here - public/private keys or some other method to be sure that the response came from your server.
You can then confidently display to the user that the client-side scripts are verified, and allow the login script to proceed.

Categories