SAML private key leak - php

I have encountered a data leak recently and it turns out source code got leaked.
I'm analysing everything that might come back to bite me and of the things is SAML private key.
Could a private key be used with malicious intent? I understand it gives the ability to decrypt SAML requests and the possibility to create some aswell, but I am far from knowledgable on the subject.
Thanks!
Z

First just as a note. Never store any secrets in source code. There are many good solutions available for secrets management.
Next, as with any leakage of keys. Change the key immediately so that it can not be used by anyone anymore.
One idea could be to try and monitor any usage of the old key to get a understanding of if anyone is trying to use it. If you have any good logs at the other party on the SAML communication you could try to see if there have been request from other IPs than yours.
As for risks. Take this as advice, real risk will depend on context.
If you are the SP the private key is user to authenticate and sign when sending messages to the IdP and decrypting message from the IdP. Signing and auth probably includes AuthnRequest, possibly Single Logout messages and Artifact binding artifact exchange.
In a AuthnRequest there is generally not much that is sensitive to modification.
Creation or modification of SLO message could lead to signing out users with they requesting it. Not good but not the worst
Compromizing the exchange in the artifact binding could let the attacker get a hold of the Artifact, but this is generally no worst than most cases where another binding is used.
As for decryption. It depends on the sensitivity of what your encrypting. The basic information inside a Assertion of response should not be sensetive by default, but you can include attributes by your own that can be sensitive, for example personal information. If a attacker gets a hold of a Assertion , which is sent over the user browser, they can read that information with you private key.
If you are a IdP, this one of the worst cases. If the attacker can redirect IdPs to talk to their server instead of the real IdP, they can issue SAML responses and Assertion and pretend to be any user they want into any of the connected SPs.
In this case you must really start a thorough investigation on the SPs to understand the impact.
Hope this helps. Summing up, if you are a SP there is not very much worry about. If your a IdP your in for a ride.

Related

Session integration, is this approach secure?

A user logs in using default Laravel authentication, which puts an encrypted cookie in the browser, and saves the session in the database.
The user moves to a classic asp page, where I check the cookie value, get the hash, and call the laravel app back passing the session id hash.
Then I use that in laravel to see if there's an active session for that id, and if so I return true, so the user can be logged in, in classic asp.
On each page request in the classic app, I check the last_updated_time in the db and update it on each page. All logging in and out is done in laravel, and classic relies on the database to see if a session is active.
I would also call a public url to get sessions variables and add session variables using laravel, since it's all encrypted and using classic asp for this would be hard.
The only risk I see is session highjacking, but I don't think it's a higher risk than usual.
Is it important to lockdown the laravel URL I call to check if it's a valid session?
Am I missing a security hole here?
Is this method secure?
From what you've stated you probably haven't opened up any security holes. The session cookie is not itself encrypted on the users machine, but you are making sure it is encrypted between their machines and yours, as well as between each of your machines. You should make sure you've set the Secure Flag to help prevent the cookie being accidentally sent over traditional unencrypted transport (HTTP), but as stated, this doesn't effect storing the cookie itself.
That being said, you are essentially hijacking your own users sessions. While a hole might not be introduced now, you are potentially weakening the overall system, which could lead to hole in the future.
Is there a better way to do it?
This might well be a dumb question, but are you sure you need the session? If you're juggling credentials between servers, it sounds more like you want to use Access Tokens and scrap the session.
Using Access Tokens is similar to using sessions, but you need to make your services stateless. This means your no longer storing information about the logged in user any specific machine so you'll need to pull anything you need from the database every time they hit a server requiring that information.
This is a good thing in the long run as it's much easier to scale your services when you don't need to worry so much about where the session is and what's inside it.
OAuth 2.0 is widely used standard (Facebook, Twitter, Google), and was specifically designed to be easy to use. The RFC is complex, but there's a log of good guides out there don't worry.
The one slight down side (if you can call it that) to OAuth 2, is that it MUST happen over an encrypted connection. If your use case can not guarantee encryption over SSL or (preferably) TLS, then you should use OAuth 1.0 (WITH revision A) instead.
This is due to the fact that OAuth 2.0 exposes it's "secret" token in requests, where as OAuth 1.0 only ever uses it to provide a signature hash. If you take this route it's advisable to use someone else's library as the hash is very, specific.
Further Improvement
(Note: This section added after the answer was accepted)
One system I've been exploring recently is Json Web Tokens. These store information about the user to save each machine repeatedly looking it up in a database. Because the token is hashed with a secret, you can be sure that, so long as your secret isn't exposed, a valid token represents a successfully logged in user, without having to touch the database.
You should avoid putting anything too personal in the tokens if possible. If you must store private or secret information in the token, you can encrypt it, or you can use a reverse caching proxy to exchange the JWT for a traditional security token. This may initially seem to defeat the purpose, but it means some of your services may not need database access at all.
I'm no security expert but I don't see an issue with this. The packaged Laravel database session handler works the same way. The cookie contains a hash that references a record in the database. The session data is base64 encoded but that's neither here nor there. I think you could actually avoid rolling your own and just use Laravel's DatabaseSessionHandler.
Illuminate/Session/DatabaseSessionHandler
... I just read a little deeper into your question and noticed the part about the public URL to set and retrieve session data. I think this is a really bad idea. Mostly because it will provide an open door to the end user allowing them to read and write session data. This can only end badly.
Like I said above, the data is only base64 encoded so I believe you'll be able to parse, read and write that to your hearts content within asp.
Edit
Ok... I think this is the last edit. The data is php serialized and then base64 encoded. This question looks like it may help you to that end. If it doesn't and an API endpoint is the only way, find some way to block the end user from accessing it.
Aside from session-hijacking, no. This is the standard way applications interact on a internal basis. Of course there might be a better way to get at the data if you choose a different type of session store other than your database, Memcached for instance.
There are couple of things that can be done.
Make the channel HTTPS. It will make almost impossible to sniff on your transport layer.
Rather than making interactions with your cookie, you could use a JWT to get this task done. Which will help you to use the existing functionality in your system while connecting with ASP system as well. You can write a small REST web service which allows ASP to connect. You could use this lib. You can refer this article which will give you an idea how it should be done.
Please let me know if you need more information.

PHP-Javascript Encrypt and Decrypt using the same secret key

I am working on an application who's front end is in javascript (backbone) and backend in codeigniter(php). I want a way where I can encrypt a message in backend using a secret key and decrypt that message from javascript using same secret key. Basically I need this flow for user authentication.
Its turning out to be a hard luck as I am not able to find such a combination over internet. What way can be used for this workflow?
Thanks
using HTTPS is pretty much the only answer that makes sense. Relying on Javascript cryptography is bad because malicious users can do all sorts of nasty stuff to inject scripts to make your front end instead send passwords out in plaintext, or send them to a server controlled by the attackers.
HTTPS and SSL/TLS has it's problems, but it is the standard mechanism for securing web application communication channels. It has been reviewed extensively by experts in the field, and has been secured against various failure modes and attack scenarios.
For instance: It sounds like in your comment that you are going to use a single static key for your encryption. Since you need to send the key to the client, how are you going to do this securely? What prevents a user from getting the key legitimately by visiting your login page, then using it to decrypt the communications of any other users? What about when enough messages have been sent with one key, what is your mechanism for moving to a new key?
These sorts of scenarios are covered by HTTPS. You might have to pay a few bucks for a certificate if you are doing something "real" with your webapp (and it really is just a few bucks these days), but it is really the way to go.

Authentication system - Return information that have to change every time

I have a application (made in Delphi) that contains a Authentication system (login & password).
This system is in PHP, and the application get results from PHP using HTTP GET method.
The system returns 'OK' if login and password are correct, and 'NO' if not correct.
Like this...
procedure Check;
var
x: string;
begin
x:=Get('www.mywebsite.com/auth.php?user=xxxxxx&pass=zzzzzz');
if x='OK' then
UnlockFeatures
else
MessageBox(0,'You're not VIP','Error',0);
end;
Well, it works fine, but it is very easy to circumvent this system with sniffers, packet editor or proxy.
So, I want to get some information (in PHP) that changes every time, and that could be possible get the same information by my application.
What can I do?
I don't need codes. Just tips, suggestions, please...
Thanks...
Generally i suggest you not to try to outsmart everyone and invent brand new bicycle - you'd 99% fail with some stupid error making your approach completely insecure. There were a lot of precedences like DVD encryption or Win95 security. You'd better try some industry-approved mechanics, that for years been tested for security, that should have readymade implementations for both Delphi and PHP. Few are
TLS (https:// protocol) http://en.wikipedia.org/wiki/Transport_Layer_Security - that would give no protection from MITM attacks, but it sounds exactly what you asked and would require least possible change.
You may try implementing SSO via integrated windows authentication if you server would support that
You may try setting up OpenID or OAuth environments. Generally their v.1 would be simpler than v.2
You may try to bail out of HTTP and use XMPP/Jabber authentication - they take security seriously and libraries for PHP and Delphi exist. Though it should not be much more secure than just using TLS, you may hope that dumb attackers would not be prepared for non-HTTP protocols (there is not internet outside Facebook and such).
You may use Bluetooth-like approach to make special connection("handshake") once (when both client and servers are controlled) just to make special "tokens" interchanged and stored. That is a generic trait to use "controlled environment" to make 1st connection and use some tokens to prove "we had met before" on later connections using generic challenge/response trait. Those tokens should be unique for each client-user-server combinations! If you'd make one server-global clients-shared set of tokens - they would just be easily copied form one client to another and no more security remains.
Those may be coefficients for some not most trivial RNG. constructed be server and saved by both client and server. Then server "challenges" with RNG seed and client should response with proper random value, prooving he knows coefficients.
Those may be some asymmetric crypto, where token is some random "message", then server sends client encruyption keys and expects the correct message encrypted by them, or the token is the password and server generates random text and expects it's correct crypto digital signature to be passed back. You may find encyption libraries at Torry.net for examples. Lockbox3 and Spring4Delphi are among most tested and noted crypto libraries for Delphi implementing some encrypting standards.
Consider you priorities and make your choice.
Would you be able to switch all the authentication layer in one key turn later, having absolutely no care for backward compatibility with non-updated clients, then you might choose the most simple one and only enhance it later if needed. If your users are lazy at upgrades then you'd better choose most secure approach from starters, since you would have no practical way to disable insecure implementation later.
I'm not familiar with Delphi (looooooong time ago...), but as far as the php and security is concerned:
I would use post instead of get (and https if possible)
If you can read php sessions with Delphi, you could add a session variable with a random number and add that as a hidden form field, send it in and check it against the session variable.

Implementing (secure) Api Keys in an app

I wrote a Web Application and I would like to allow other developers to get the information from it.
The server Im working on is not that awsome and cant handle that many request, so the idea is to generate and assign api keys to everyone that wants to query our information. With Api keys I can limit the daily requests and perhaps collect some statistics to see what information is really useful for the other developers.
The thing is, Im concerned about the security aspect of it. Since the Api key is going to be sent to our server (via GET/POST etc), someone could sniff the request with wireshark and get the developers API key without much effort, right?
I thought about generating a secret key and an API key. I could then instruct the other developers to concatenate them and send a hash of it to our API. I would then validate that the hash is valid and allow the request... But then the same problem would persist. A hacker could still sniff that hash and make requests on behalf of the other developer's app.
So my questions are
How can I avoid this problem?
Or better yet, Is my concern even valid? Is that a real problem?
Is there a better and secure way to allow access to my information without making it too complicated for the other developers?
What do you guys think?
I think you're trying to solve a bunch of different questions here.
If your objective is to limit the number of requests to your server, you should create a throttling mechanism. This is non-trivial, but I'd base it on IP address rather than a license key - a single licensed user might swamp your system with lots of requests. You can throttle by IP address without implementing a license mechanism.
If you want to create a licensing scheme, you need to understand cryptography etc. - it's a non-trivial problem. For instance, how do you stop a legitimate user sharing their license key with all their friends? How do you stop a hacker from stealing your key and sharing it with all of his friends?
There are a number of solutions to this - they all impose some degree of pain on your users. For instance, you can run your service on HTTPS; this stops snooping, but reduces performance. You can issue "tokens" for your service which expire after a certain number of uses; getting new tokens requires a cryptographic exchange (which might check your IP address). You might require a "challenge/response" type of logic (including an IP address validation). All these steps make life harder for your users; they probably won't thank you much for the extra work they have to do.
With respect to sniff, your problem can be solved with HTTPS on your server.
it definitely makes sense to put some authentication on the API if you want to limit access + potential some usage rate limits. If you use an API key and want to avoid sniffing then HTTPS is definitely the way to go. If that's not an option then you can also use a hash-style auth like oAuth 1.0 (http://oauth.net/core/1.0/) or Amazon AWS authentication. These work by issuing your API users with an ID and a Secret. They use the secret on the client side by inserting it into the message body, computing a hash and including the hash (not the secret) in the request. On the incoming side you compare the hash with the same operation done on the message content with their specific secret included.
This means that you can verify the sender without having to send the secret over the wire (note that the content still isn't secure - but you avoid passing the key over the wire with every request). The downside is that it's complex for developers to implement. Even if you use the oAuth 1.0 pattern which there are libraries for it's a bit of an overhead.
I work at 3scale and some of our tools might be helpful also - our systems provide API Keys, oAuth Secret sharing and also API rate limits out of the box (http://www.3scale.net and the PHP libraries are here: https://github.com/3scale/3scale_ws_api_for_php).

Secure login: public key encryption in PHP and Javascript

I'm trying to make a "normal" username/password login form secure, without needing HTTPS. My idea is this:
Server generates a keypair for some kind of assymetric encryption algorithm. It stores this keypair in a temporary table of sorts (or perhaps the local session data).
Server sends the form to the client and includes the public key.
User fills in the form.
Before it's sent to the server, Javascript encrypts the password using the given public key.
Form is sent.
Server decrypts the password with it's private key (which it gets from the temporary table, using the public key to find it).
What I need to know for this is:
Which encryption method is the best to use? RSA?
How can I decrypt the password in PHP?
And probably the most difficult one, how can I make Javascript encrypt the password?
In advance: I'm sorry for being negative, however;
Implementing your own security protocol is never a good idea, unless you're a highly trained security expert, or you actually don't really care about the security and only want to create an impression of security (marketing) and stop the script kiddies.
SSL is definitely not a fingerprint lock, as so say in your comments, JCryption and your proposal are equal to having a door where you can enter a two-digit code to open the door and you have infinite many retries. It's hard to break if you're not really interested and just passing by, but if you want to get in that house (and you probably do, else security wouldn't be needed), you will get in.
Another point is that people often forget to mention what they want to achieve. Security has the famous three components called CIA, namely confidentiality, integrity and availability. Is it for you important that the data you transport is confidential, or is integrity important (i.e. you're sure that the sent data comes from the one you expect and not the man in the middle)?
To make it concrete in this case, the only thing that you achieve here is that a passive attacker cannot see whats passing by on the line. As soon as your attacker gets active and changes the messages on their route, your whole security falls apart. So my advice would be to just stick with the solution the experts have come up with (TLS in this case, not ssl since that is the old version of it) and just make sure your server supports it.
edit:
Btw, SSL/TLS cannot work without certificates. The whole point in public key crypto is that there should be at least somewhere some trusted party.
On the other hand, if you don't care that your users will get an "invalid certificate" message, you can just create your own certificate which is really easy. In that case your certificate isn't trusted by the browsers, however, you can be sure that at least your communication is safe (okay, there are exceptions in this case, but still ...)
The argument that certificates should be for free is really from a perspective point of view. I think people who claim it is bogus/idiotic don't know what it takes to be a certification authority. These companies invest millions in order to keep the communication secure, and sure they make nice money out of selling certificates, but hey its their job and they also deserve to make money, just like any others.
edit2: after comments
I indeed say that you have a secure communication. However, you miss the point that with self signed certificates you dont know to whom you talk securely. Imagine a dark room which is completely isolated from eavesdropping a conversation. Now imagine the difference between such a room with and without light. If the room has light, you can actually see to whom you're talking securely and only choose to talk to people you like to trust. Now imagine doing the same in a completely dark room. You can only hope that the guy you talk to inside this dark room is just an ally and not your adversary. However, you cannot know that, just hope that it's ok. And although your conversation itself is secure, nobody can listen in, you still dont have "full" security.
If I, being a crook, do a man-in-the-middle attack, I can create a self signed certificate without the user noticing. So the advantage of using TLS with self signed certificates is that you have at least the implementation of the protocol corrent (and even implementing this is far from easy). Moreover you can avoid the ugly warnings by advising your users to manually trust the certificate once. However, this is only possible if you have a relatively small group of returning visitors, for a public website this is not really a solution.
This doesn't seem that secure from the perspective of the client. Two (related) problems:
How does the client trust the server? How can it verify that the key the sever's presenting is the one that belongs to it?
It's possible to do man-in-the-middle attacks. A malicious proxy could strip out and store the public key before the client sees it, substituting its own, then decrypt the password when the client authenticates, store it, and re-encrypt and send the response on so the client doesn't realise something's up.
What's wrong with ordinary SSL? There has to be a consensus that it's secure, otherwise vendors and organisations would drop support for it overnight. By contrast, most attempts to invent a funky new way to do security "on the cheap" usually miss something fundamental.
It looks like a lot of what you want to do is supplied by the jquery plugin JCryption. It even assumes PHP as the backend, so a good fit for you.
Livejournal does something similar to what you want where:
Server generates a challenge string, inserts this into form. [1]
Client generates response by MD5 hashing the password, then MD5 hashing the previous hash with the challenge prepended [2].
Server gets response, checks challenge validity, then does same as step 2, comparing the result to the response.
This is a very good idea, and it's already been done. See jCryption.
jCryption looks interesting, I've not seen it before.
But I have to ask what is wrong with SSL?
Encryption code is notoriously hard to do right, and you can bet that the SSL implementations found in browsers and http servers are much more rigorously tested and reviewed than the jCryption stuff.
That said, jCryption looks neat if you absolutely need to avoid SSL, and you're not dealing with super-sensitive information.
By storing the passwords in encrypted method on the server the server can retrieve the passwords and verify checksum sent by client. Send a session password and ask client to make a hash of session password and the user inputted password, do the same on the server and compare the two hashes.
This will not secure users from MITM attacks - local admins, NSA, telecom, router hijacks, but it will keep the password safe in open wlan.

Categories