How secure are Amazon AWS Access keys? - amazon-s3

I want to offer presigned urls to my s3 buckets with an expiry date.
The .net sdk nicely generates these urls, but looking at them makes me worry a little:
https://s3.amazonaws.com/upload_youtipit/myfile?AWSAccessKeyId=**MYACCESSKEY**&Expires=1317924047&response-content-disposition=attachment;filename=feedback.jpg&response-content-type=image/jpeg&Signature=podKJSrNeFel6%2B0aOneb342H5GA%3D
Why does it need to put my (public) AWSAccessKey in the Url? Shouldn't this be kept a bit more confidential? I know its not the secret, but I still don't feel comfortable exposing it in public..
How likely is it that, somebody who has my public key, can guess/bruteforce my private key?

The Access Key ID is not a secret and does not need protecting.
In fact, you can give expiring URLs to random strangers if you want them to access an S3 object. They can see the access key in that URL, but can't do anything with it that you have not authorized.
reference: http://docs.amazonwebservices.com/AWSSecurityCredentials/1.0/AboutAWSCredentials.html#AccessKeys

I kind of agree with the accepted answer, but there is an easy way to do what you want.
You need to use Amazon IAM to create a user that can only read files (it does not really matter, but they at least need read only to the bucket that you are dealing with). Then use THAT users AWS ID and secret to generate a download link.
This does not open up your whole bucket, as to see the whole bucket the person needs the AWSID of this IAM 'reader' user, plus their secret key. You still need to construct time limited URLs.
You can use the IAM console to create a user like that in a few mins. You only get one chance to get the secret key - at the time you make the user (or if you rotate his keys).
That should do it. This AWSID has no access to anything, and is not linked to you.
In general Amazon now recommends that your primary AWSID is not used 'for anything'. You create users with permissions in IAM, then use those codes. This allows for a lot of security flexibility. You can turn off your read only user with a simple action in the IAM console.

your private key is a one-way computation of some unknown parameters, it may not even use the public key itself as part of the algorithm. knowing your AWSAccessKeyId should have no effect on the complexity of brute-forcing your private key whatsoever.
https ensures the only thing someone can tell about your connection (if they are sniffing network traffic) is that it's between your IP and the IP of s3.amazonaws.com on port 443. even the fact that you're connecting to amazon would have to be deduced from known ip-address ranges assigned to them (which is probably well-known anyhow)
the only way to get at your AWSAccessKeyId in the address bar is to physically see it on your screen, installing some key-logger or trojan on your computer or MIM (man in the middle-ing) amazon's SSL certificate, which is extremely hard even if someone has access to the needed upstream network nodes.
leon

You can use AWS Security Token Service (AWS STS) if you concern of more security.
Temporary security credentials work almost identically to the long-term access key credentials that your IAM users can use, with the following differences:
Temporary security credentials are short-term, as the name implies. They can be configured to last for anywhere from a few minutes to several hours. After the credentials expire, AWS no longer recognizes them or allows any kind of access from API requests made with them.
Temporary security credentials are not stored with the user but are generated dynamically and provided to the user when requested. When (or even before) the temporary security credentials expire, the user can request new credentials, as long as the user requesting them still has permissions to do so.
Ref: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html

Related

MQTT Broker with TLS and JWT

We are currently working on a data-backup kinda project. We ship our own hardware to industrial customers. This hardware will then read out all related data the customer wants to backup and sends them to a cloud server using MQTT (Node.js Client and Mosca MQTT Broker).
Now my questions are:
Is there a free TLS certificate that i can use for my MQTT connection? The only ones that i found require a domain name.
To incease security, we are using JWT. We don't have any database though. The Token will be passed as an MQTT-Password argument. Is there a better alternative?
Is a self-signed TLS certificate bad practice even if the private cert
is not publicly available? It will only be shipped embedded into our
hardware and to our verified customers.
Of course it is bad practice (very bad practice). Get a certificate from a proper CA authority. Unless you want your company to be sued into the stone-age for a security breach.
Is there a free TLS certificate that i can use for my MQTT connection? The only ones that i found require a domain name.
The certificate "certifies" that the information is provided by a specific entity, where the entity is defined as "a domain name".
Asking for a TLS certificate which doesn't back to a domain name is like asking for a certified check drawn on a company that doesn't have a name.
To incease security, we are using JWT. We don't have any database though. The Token will be passed as an MQTT-Password argument. Is there a better alternative?
Yes, there is a better alternative. Have some sort of database (it can be a file system, it doesn't need to be a full-fledged SQL database) hold and manage the created tokens. Without a database to validate the tokens against the current expected values, any kind of token based security (JWT or otherwise) will be useless, as you can't determine if the token is currently valid.
Credential reuse (the replay of should-be-expired credentials) is a major security hole. All one needs to do is obtain the token, and then all future communications are accepted with the same credentials. This is closed by holding the tokens in a database, and expiring the tokens after some time by removing the tokens from the database. This means that any possible breach is limited to a shorter time span.
Without any kind of database, I can only guess that you might be permitting any access with an existing token, meaning that all your tokens are effectively valid forever, as they will be accepted if they exist. You need to possibly modify, and certainly validate, that expired tokens don't grant access to the controlled operations.
Your clients will connect to your MQTT broker, for this to be secure you will need a certificate which is tied to the address (domain name) the broker is running on. Clients need to know that the server they are talking to is authentic, the information needed for this is inside the certificate. If you're looking for a free certificate you could look at Let's encrypt
As for the JWT token, why are you looking for a better alternative? What issues doe you see?

secure api communication between two backend servers

I need to secure the communication between two backend servers. A simple api key was rejected by our security policy since attackers would be able to intercept it.
IP restriction also, because it could be spoofed.
I was suggested to use a nonce, but wouldn't this mean that a request requires two roundtrips? I don't really like the idea of having twice the latency.
without your description it's hard to be able to suggest the best way to do it.
If both servers are inside the same Datacenter, you can have some solution to have a private network.
If that's not the case, you can have and authentication system (oauth?) with a token which will be create and validated.
You can use some other techno to sign your data with private and public keys.
The nonce could be good too.
But if your servers are in a DC, they should have the same IP and not move. So why not have a whitelist (IP based) and something else like a nonce or a token

How can I secure internal roles in azure (SSL at minimum)

I am working on a HIPAA cloud project and am implementing a Key Store as a central repository for all of the key pairs for PHI(Private Health Information) encryption... I am not worried about the actual data because it will be encrypted at rest and in transit.
However when a worker or webrole needs to work with the data they need to decrypt and reencrypt it (if they do updates). That's where the key Store comes into play. However, I don't want this internal service exposed and I also need it to be SSLed, because sending keys in the clear, even inside a virtual network of roles wouldn't pass a security audit.
So any suggestions on how I can get a web or worker role to use SSL with an internal endpoint?
Thanks
I don't think you can. Internal endpoints are on a closed network branch, so https would normally be redundant (although I understand your compliance issues). I found this answer (to my question) very useful in figuring out the security of internal endpoints: How secure are Windows Azure internal endpoints? - see the more detailed post that Brent links to.

How secure this signature based authentication for mobile devices is

I am implementing an app where I don't have a system requiring username and password. What I do require is a name and a phone number.
The scenario is like this:
1) user opens the app for the first time
2)app makes a request to my server and gets a unique UserKey
3)from now one any request the app makes to my REST service also has a signature. The signature is actually a SHA(UserKey:the data provided in the request Base64Encoded)
4)The server also performs the same hash to check the signature
Why I don't use SSH:
not willing to pay for the certificate
I don't need to send sensitive data like passwords, so I don't see the benefit of using it
I just need a simple way to call my own WCF REST services from own app
I understand that there is a flow of security at step2 when the UserKey comes in cleartext, but this happens only once when the app is first opened. How dangerous do you think this is?
What would you recommend? Is there any .NET library that could help me?
Actually, there are several problems with that approach. Suppose there's man-in-the-middle whenever you make a request to the server. By analyzing, for example, 100 sent packets he would recognize similar pattern with signature in your requests. Then he would forge his own request and add your signature. The server checks the hash - everything's alright, it's you and your unique user key. But it's not.
There's a notion of asymmetric keys in cryptography which currently is really popular and provides tough security service. Main concept is the following: server generates two keys - public and private; public key is used to encode texts; they can be decoded only with the use of private key, which is kept by the server in secure location. So server gives client the public key to encode his messages. It may be made double: client generates public key and gives it to the server. Then server generates keys and gives encoded with client's public key his own public key. This way it's almost impossible for man-in-the-middle to make an attack.
Better yet, since the problem is really common, you could use OAuth to authorize users on your website. It is secure, widely used (facebook, g+, twitter, you name them) and has implementations already in variety of languages.
Since you control both the application itself and the webservices, you can do this with SSL (which gets rid of the problems with your current approach) without paying for anything. You can create a self-signed certificate and install that on your webserver; configure the SSL context of your client application to only trust that one certificate. Then, create a client-side self-signed certificate and install that within your application. Set the server up to require mutually-authenticated SSL and only allow your self-signed certificate for access.
Done. You client will only talk to your legitimate server (so no one can spoof your server and trick the client in to talking to it) and your server will only talk to your legitimate clients (so no one can steal information, ID, etc). And it's all protected with the strong cryptography used within SSL.

Setting up a web application to automatically run authenticated calls over HTTP to a remote website without repeated human authentication

I want to be able to set up a web application to automatically (i.e. on a cron run) send a POST request to a remote website. The remote website requires a username/password combination to be sent as part of the POST data. I want the web application to be able to make the POST requests of the remote website without requiring the user to provide the password to be sent with the POST data, each time the request is made.
It seems to me that the only way to do this is to store passwords directly in the database, so that the cron run can execute a POST request that includes the password as part of its POST data. Without storing the password in some form in the database, it seems it would be impossible to provide it in the POST data, unless the user provides it each time the request is made.
Question 1: Am I mistaken and somehow overlooking something logical?
Question 2: Assuming I have to store the passwords in the database, what is the safest procedure for doing so? (MD5 and similar one-way encryption clearly will not work because I have to send an unencrypted password in the POST request.)
Thank you for your help!
a. if you don't know the password... you can't authenticate, that's the idea of a password !
b. if you need to know the password - you need to save it in a decryptable way - hence - less secured.
c. if you own the site, you can use a cookie with a very long timeout value, but - you still need to authenticate at least once.
d. unless you're guarding money / rocket science, you need to encrypt the password and store it in the DB and decrypt it every time before use, at least you are guarded from DB theft.
e. make sure you're authenticating over secure channel (as https) so the password will no be sent as clear text.
One good solution is probably to use SSL (i.e. HTTPS). You can create a certificate authority on the server side, then have this certificate authority sign a client certificate that you generate. Make sure the HTTP server is configured to trust the newly created certificate authority.
Once this is done, you should install the certificate on the client side. The client must present the certificate when talking to the HTTP server. You have to configure the HTTP server to require a trusted certificate when POSTing to your secure URLs.
Awesome example of how to do this with Apache HTTPD is posted right here!
The document I linked doesn't describe how to set up the certificate authority and create self-signed certificates, but there are tons of examples out there, for example here.
This is a good solution because:
no passwords are stored in the clear
if the private key of the client's certificate is stolen or compromised, you can revoke it on the server side
The key here is that the client is providing its credentials to the server, which is the opposite of what is usually done in a browser context. You can also have the client trust your newly created certificate authority so that it knows it's talking to the right server and not a man in the middle.
Given that you have to send the password in clear-text and do it repeatedly without user-interaction you'll need to store and retrieve the same from a data-store (file/database/memory).
What you really need to consider is the last-line-of-security of the password store.
Whether you encrypt it or not doesn't matter. The person/program with access to the data or the cipher key will be able to read that password.
Sort this issue out, document it - (this becomes your security policy for the app) and then implement it.
Security is only a level of difficulty you implement to lessen a risk.
Fortunately, Tumblr now implements OAuth, which solves this problem.