I am working through some security concepts right now and I was curious if this method has been tried and/or if it is safe taking into consideration "Brute Forcing" is still possible.
Take for example a Microsoft WebAPI Template in Visual Studio where you access a endpoint using a "GET".
The Endpoint would be accessible by any user/application
The String value that a user/application would get from this endpoint would be the password they need, but encrypted using a "KeyValue"
After a TLS Transmission of this Encrypted Value, the user/application would decrypt the String using their "KeyValue"
Is this a secure practice?
Thanks for indulging me and look forward to your responses.
EDIT: Added Further Clarification with Image to Help Illustrate
Suppose the following 2 Scenarios:
Communication between Server and Client
a. Your Server serves the Client application with an encrypted password.
b. The Client can request any password.
c. The passwords are encrypted with a shared Key that is known by both server and client application
As James K Polk already pointed out:
A knowledgable Attacker can and will analyse your deployed application and at some point will find your hardcoded decryption key ("KeyValue"). What prevents him from requesting every password that is stored on the Server?
Rule of thumb here would be: "Do not trust the client side."
Communication between Server and Server
a. You have 2 server applications. Application A is acting as some kind of database server. Application B is your Back-End for a user application of some kind.
b. Application A serves paswords to any requester, not only Server B. With no type of authentication whatsoever.
c. Confidentiality is guaranteed through a shared and hard-coded Key.
I think you are trying to overcomplicate things hoping that no one is able to piece together the puzzle.
Someone with enough time and effort might be able to get information about your server compilation and/or be able to get the Code of Application B. Which again defaults in the scenario of 1. Another point is that there are enough bots out there randomly scanning ips to check responses. Application A might be found and even-though they do not have the shared key might be able to piece together the purpose of Application A and make this server a priority target.
Is this a safe practice?
No. It is never a good idea to give away possibly confidential information for free. Encrypted or not. You wouldn't let people freely download your database would you?
What you should do
All Authentication/Authorization (for example a user login, that's what I expect is your reason to exchange the passwords) should be done on the server side since you're in control of this environment.
Since you didn't tell us what you're actually trying to accomplish I'd recommend you read up on common attack vectors and find out about common ways to mitigate these.
A few suggestions from me:
Communication between 2 End-points -> SSL/TLS
Authorization / Authentication
Open Web Application Security Project and their Top 10 (2017)
Related
I read a lot that you can't restrict your Public REST API to only your mobile application, but I have an idea and I want opinions on it:
Variable App Key Method
Mobile App
Get IP address of current connection
Use a secret algorithm to generate a hashed AppKey from IP address.
Send the AppKey with each API request
Server Side
Check the IP address of incoming request
Generate AuthKey from that IP address using same secret algorithm.
Compare AuthKey with AppKey, if they match then you know that your
Application is talking to you, because only the application knows
the secret algorithm.
When IP address changes:
On mobile App regenerate the AppKey using the new IP address
Server side will always generate same key because it depends
on IP address of the request
The main advantage of this is that the AppKey will always change, which is better than hardcoding 1 application key inside the code, which can be easily stolen by reading request headers. And even if you stole the AppKey from a user you must be using the same IP address where that key was generated.
Any thoughts?
The "secret" algorithm would have to be in the app... given to everybody. It is not secret at all. Security by obscurity is bad anyway, you should not have supposedly secret algorithms, because it's hopeless to keep them confidential. In this case the algorithm is trivially revealed.
Also refer to Schneier's law. :)
Edit:
So theoretically, this can never be secure, because any algorithm you put into the app needs to run on the client, and hence can be analysed and decompiled. But one can argue that it doesn't need to be theoretically secure, it is ok if it's "secure enough", ie. the risk is low enough, because for example the effort needed to get to the algorithm is too much.
But then consider the two possible options:
This is a really cool API that everybody totally wants to build a client for, or there is at least one such party. In this case, no effort is too much, and the algorithm will be "broken", that is, it will be decompiled and implemented in a different client.
People don't care all that much about this API, it is not very important for anybody else to build a client. In this case they probably won't build a client anyway, and much simpler methods can be used to prevent other clients from popping up with a reasonable success.
But obviously, it's your choice, an approach similar to what you describied does raise the bar somewhat - just don't expect it to be actually secure, because it will not be.
I have microservice on a new server/vps that will only ever be called via REST by monolith app to perform some heavy lifting and then post the operation results back to the monolith in few minutes.
How should I protect these two endpoints? I think my main goal, for now, is just preventing someone that found servers address to be able to do anything.
Almost every solution I google seems like overkill/premature optimization.
Is it sufficient that I generate random long token once on each machine and then just pass it to headers and check it's presence on the other end?
Do I even need to SSL this? As far as I understand we need SSL encryption for clients that are trying to send sensitive data via wireless or unsafe shared networks.
What are the chances(is it even possible?) that somebody is gonna eavesdrop between two digitalocean vps's sending data via http? Did it ever happen before ?
Q: Is it sufficient that I generate random long token once on each machine and then just pass it to headers and check it's presence on the other end?
A: Generally microservices are behind a GateKeeper/Gateway(nginx,haproxy) so you can expose the endpoints you want. In your case I would recommend to create a private network between the two vps's and expose your microservice on that internal IP.
Q: Do I even need to SSL this? As far as I understand we need SSL encryption for clients that are trying to send sensitive data via wireless or unsafe shared networks.
A: No. If you use internal networks and don't expose to the public then there is no need for SSL/TLS. If you would do something with Tier 3/4 then you would need encryption for cross datacenter communication.
Q: What are the chances(is it even possible?) that somebody is gonna eavesdrop between two digitalocean vps's sending data via http? Did it ever happen before ?
A: There are bots that scan for open ports on servers/computers and try to penetrate them with exploits. In all cases always use a firewall like UFW/firewalld.
So let's say you have two servers with these microservices using the internal private network from your favorite provider:
VPS1 (ip = 10.0.1.50)
FooBarService:1337
BarFooService:7331
VPS2 (ip = 10.0.1.51)
AnotherMicroService:9999
Now both VPS's can access each other's services by simply calling the ip + port.
Good luck.
There's a few simple solutions you could use to authenticate both servers back and forth. The one I would recommend if you want to keep it simple, as you say, is Basic Auth. As long as you're utilizing that over an SSL/HTTPS connection, it suffices as a super simple way to authenticate each end.
You state it is your main goal to protect these endpoints, but then ask if SSL/HTTP is even needed. If these servers are vulnerable to the web in any way, then I would say yes, your endpoints need to be protected, and if you're transmitting sensitive data, then you need to be sending it through a secure stream.
If you believe the data you're sending is not very sensitive, and is likely that no one that knows these two endpoints will even know how to properly manipulate your data by sending fake requests, then sure, you don't need any of this, but then you assume the risk and responsibility for if and when it ever is exposed. Basic Auth is super easy, and with LetsEncrypt it's incredibly easy to obtain an SSL certificate for free. It's good experience, so may as well try it out and protect these endpoints and ensure that they're safe.
A client asked me to do a back-end server for its iPhone application and want only users who bought the application to be able to call the server.
The problem is that he doesn't want to add a login system to the application, so that it seems to me there is no completely safe way to prevent someone without his application calls the server.
In any case, even if it can not be completely prevented, it would be sufficient to make it difficult to access servers without the application.
What is the best way to achieve this? Again, I do not need to fully protect the connection, there is no transit of sensitive information, I just want to make things a little more complicated for people who want to take advantage of server without paying the application.
The idea that seems most simple is to encrypt the data with a key stored within the client and known to the server, so that the message can be decrypted only decompiling the code and finding the key (of course instead of a key you could put a list of keys, which change every 6/12/24 hours).
Could this be a reasonable solution?
This will never be possible. Welcome to the nature of the client-server architecture. You can never trust the client. Just make sure the functionality you are exposing is safe.
well if its a paid app you could release the app for free with all the functionally locked down until a user does a in app purchase and then you could verify the receipt on your server therefore proving that the device is a iOS Device?
sharing a key between the client and the server seems to be a good way to go. But instead of depending on the stored keys only, try combining them with a Unique identifier, such as UUID and send it to server both with the combined key, and the UUID itself.
At that point users UUID will be his identifier (username) and the combined key will be his token (password). And this will be a login-like mechanism.
An SSL connection is not enought to prevent other people from getting the URL for the requests? Or even better using an SSL connection with a basic auth?
I'm building a client/server iPhone game, where I would like to keep third-party clients from accessing the server. This is for two reasons: first, my revenue model is to sell the client and give away the service, and second I want to avoid the proliferation of clients that facilitate cheating.
I'm writing the first version of the server in rails, but I'm considering moving to erlang at some point.
I'm considering two approaches:
Generate a "username" (say, a GUID) and hash it (SHA256 or MD5) with a secret shipped with the app, and use the result as the "password". When the client connects with the server, both are sent via HTTP Basic Auth over https. The server hashes the username with the same secret and makes sure that they match.
Ship a client certificate with the iPhone app. The server is configured to require the client certificate to be present.
The first approach has the advantage of being simple, low overhead, and it may be easier to obfuscate the secret in the app.
The second approach is well tested and proven, but might be higher overhead. However, my knowledge of client certificates is at the "read about it in the Delta Airlines in-flight magazine" level. How much bandwidth and processing overhead would this incur? The actual data transferred per request is on the order of a kilobyte.
No way is perfect--but a challenge/response is better than a key.
A certificate SHOULD use challenge/response. You send a random string, it encrypts it using the certificate's private key, then you get it back and decrypt it with the public key.
Depending on how well supported the stuff is on the iPhone, implementing the thing will be between trivial and challenging.
A nice middle-road I use is xor. It's slightly more secure than a password, trivial to implement and takes at least an hour or two of dedication to hack.
Your app ships with a number built in (key).
When an app connects to you, you generate a random number (with the same number of bits as the key) and send it to the phone
The app gets the number, xor's it with the key and sends the result back.
On the server you xor the returned result with the key which should result in your original random number.
This is only slightly hacker resistant, but you can employ other techniques to make it better like changing the key each time you update your software, hiding the random number with some other random number, etc. There are a lot of tricks to hiding this, but eventually hackers will find it. Changing the methodology with each update might help.
Anyway, xor is a hack but it works for cases where sending a password is just a little to hackable.
The difference between xor and public key is that xor is EASILY reversible by just monitoring a successful conversation, public key is (theoretically) not reversible without significant resources and time.
Who is your adversary here? Both methods fail to prevent cracked copies of the application from connecting to the server. I think that's the most common problem with iPhone game (or general) development for paid apps.
However, this may protect the server from other non-iPhone clients, as it deters programmers from reverse engineering the network packet interfaces between the iPhone and the server.
Have your game users authenticate with their account through OAuth, to authorize them to make game state changes on your server.
If you can't manage to authenticate users, you'd need to authenticate your game application instance somehow. Having authentication credentials embedded in the binary would be a bad idea as application piracy is prevalent and would render your method highly insecure. My SO question on how to limit Apple iPhone application piracy might be of use to you in other ways.
I want "A" computer to responsible for execute the command, and "B" computer will send the command to "A" computer. I have some ideas on the implementation.
Way1:
The "A" computer have a while true loop to listen for "B" computer's command, when it is received, it execute.
Way2:
Using a FTP Server, that store information that about the command.
The "A" computer have a while true loop to check whether the "B" computer uploaded any new information about the command. if yes, reconstruct the command and execute. After executed, the file on FTP Server will be deleted. And store a copy the "A" computer.
Way3:
this is similar to way2, but using database to store. After the command is executed, it will made as executed.
What is your suggestion about these 3 ways? Is that secure enough?
A generic way: ssh and scp.
Reliable secure database specific: depends on the platform: Service Broker, Oracle AQ, MQSeries.
Not so good idea: write a socket program w/o knowing anything about security.
You're assuming a trust relationship without giving any clues as to how you know that the payload from computer A is benign. How do you plan to prevent computer A from sending a task that says "reformat your hard drive after plundering it for all bank accounts and passwords?
AKA write a socket listener on computer B and let computer A connect to it. No security here.
FTP just saves you from having to write the transport protocol.
Database for persistence instead of file store - nothing new here.
None of your options have any security, so it's hard to say which one is more secure. FTP requires that the user know the URL of your FTP server and, if you aren't allowing anonymous access, a username and password. That makes 2 more secure than 1. 2 and 3 are equally (in)secure.
All can work, but all are risky. I see little or no security here.
Without more details, all I can suggest for security is to use SSL.
Using FTP or a database server will just add needless complexity, potentially without gaining any real value.
If you want a secure solution, you will need to carefully describe your environment, risks, and attackers.
Are you afraid of spoofing? Denial of service? Information disclosure? Interception?
1 has nothing to do with security.
2 uses FTP and not FTPS? Anyone and their grandparents can sniff the username/password. Do not use.
3 depends on how securely you connect to the database --- on both ends. Also, how can you be sure what's inserted into the database if from your trustee?
What are you really implementing here? With all due respect, it sounds like you should pick up at least an introductory book on information security.
From your examples it seems that you aren't so much interested in securing against malicious attacks and bit manipulation but what you want is reliable delivery.
Have a look at a message queue solution, for example MSMQ.
It depends what kind of security you need.
if it is guaranteed delivery - anything way that makes the message stored and approve the storing before deletion will do.
if it's about the sender and the receiver id you should use certificates.
if it's about the line security - you should encrypt the message.
All things can be achieve using WCF if you're on the Microsoft world.
and there are other libraries if you're on the Linux world.
(you can use https post for example).