I am developing a custom server application that will access a database. I need to decide where I will store the credentials (and to address) to that server.
A common solution is to put the credential in a config file. However, I do not want a compromised server to mean that the hacker has access to the DB (which is hosted on a separate server).
I could store the credentials in the environment, but that is just security through obscurity. Mr. Evil can just look in the environment to find it.
Someone suggested encryption. However, if I store the key in the executable, a quick de-compile (we are using Java) and I am still doomed.
I also want to avoid having to enter a paraphrase every time I start the server.
Any suggestions? I feel like I'm missing something simple.
Thanks
I don't think you're missing something simple. Either the server in question can connect to the database without your help, in which case it has to have the credentials; or it cannot connect without your supplying them. You can take various steps like the ones you've listed to make it harder for a compromised server to reveal the credentials to the database, but at the end of the day, if it has to have those credentials and supply them to the DB server to connect, they'll have to be stored on it somewhere — or at least, it will have to have some means of getting them, and so will be hackable in that sense.
Your best bet is to focus on finding out about intrusions (compromised servers) as quickly as possible, keeping good off-site, off-line backups for the worst case, putting up lots of barriers to intrusion in the first place, etc.
I am sharing, the way I had solved this.
Build API, to query the authentication details from a foreign domain.
Use public key, and private key to read through the details.
But, honestly the only thing this did was over complicate simple things. After that, I created several users to the database, with different privileges.
Like
guest can only to SELECT
mod can only CREATE, INSERT, UPDATE, DELETE
etc and switched the user, whenever authenticated users appeared.
With the combination of users and session, I have been able to escape the threats so far. But ofcourse the code vulnerability have to be tested thoroughly.
Lock it down. Prevent Mr. Evil from gaining root. I know, easy right?
Write a secure application and keep your application server locked down. Follow best practices there, and that's most of the work.
When I've setup databases in a secure environment, the only server that was on the same physical network with the database server was the application server. There were two ways to access the database server:
Application server
Console
Therefore, in order to compromise the database server, they'd have to compromise the application server.
So, lock down the application server. Of course the only thing worse than being compromised is being compromised and not knowing about it. If you do discover a compromise, you need to fix the vulnerability if there was one. Forensics are important here (enable logs and monitor them). You also need a recovery plan in place.
Prevention, detection, correction, and recovery are paramount.
Related
I have have a BIG problem in the past few days. I'm developing an application for a customer and I have an external database in the web. In the program there are a login and some modules. At the time I store the data for access to the DB hardcoded in the Java code. Of course this is not a way to store those data.
Then I was searching so much to find out a way to connect to the database.
Store the password in a properties (.xml) file on the PC
Encrypt the password
etc.
But all of this is not really secure. Then I found something good. "Three-Tier Application Server" sounds really good and a possible way that I don't have to save the data on the PC. But I read everytime how a Three-Tier server works, but nowhere how to develop something like this in java. And is there a possibility that a hacker write an application that connects to this server too and get all of the data, because he decompile the application and get the access data?
Thanks for help
There are indeed many ways you can go about this.
The best way is to have the authentication checks spread throughout your code to where it would be very hard to remove them.
Have the authentication with SHA256/512 and or MD5 and have the user send a login request to the server.
Only authenticate the user if the server responds that it is registered.
Do not store any information other than the users info on the client end.
All the checks should be made and validated on the server side.
You also most definitely want to obfuscate your client sided code as well.
Is it possible to hide database details in jnlp-file? My app use jws and MySQL-database. In jnlp-file i have defined db connection details (username, pw, hostname).
Like this:
property name="dbuser" value="username"
Is there any alternative ways to define database details? Details must be easy to change!
Look at the JnlpDownloadServlet Guide: Substitutions.
JnlpDownloadServlet makes convenient substitutions in your JNLP files. When the client requests a JNLP file, the servlet reads the original file, substitutes values, and returns the results.
Is it possible to hide database details in jnlp-file?
No. Not to a power user.
The app probably shouldn't be talking directly to the database unless you trust all your users. Instead, you should hide your database behind a service, for example a REST service.
Never trust the client. The user can modify your program to do what they want and they can read anything you store on their system or anything sent over the network. Even if you use encryption, if it is decrypted on their computer then they can read it.
It is not a good idea to hide a secret on someone's computer and hope they don't see it. Even less so when your program is frequently reading this secret, making its location obvious.
You should assume that somewhere you have a hostile user who has modified your program (that runs on their computer) to do their bidding, and they know all the information you send to their computer.
You could create a database user for each of your users and still let them connect directly to your database, where their database user has very limited access. I think this would also be a bad idea. Databases often don't have the best security.
Instead, firewall off your database and only let your internal systems access it directly. Your users (through your java app) can instead access a web service like Chris suggested. This gives you a much smaller attack surface, which is easier to secure.
I have an SQLite Database on a webserver. I would like to access the database from a typical Java Desktop Application. Presently, I'm doing this thing...
Download the Database file to a local directory, perform the queries as necessary.
But, I'm unable to perform any update queries on this. How can I do this. [ On the actual database]
Another question is, to directly access the database from web in java (is this possible), make direct queries, updates anything etc,.
How can I achieve this type?
I've written code for connection of Java to SQLite and is working pretty fine, if the db file is in local directory. What changes or anything I have to do to establish a link to the file on webserver without having to download the database file.?
Thanks in advance...
CL. is right saying that if you need to access from desktop applications to a web database, SQLite is not an appropriate choice.
Using SQLite is fine in small web sites, applications where your data have to be accessed from and only from the web site itself; but if you need to access your data from - say - your desktop, without downloading the data file, you can't achieve that with SQLite and HTTP.
An appropriate choice for your web application would be MySQL or other client/server database, so that you could be able to connect to the database service from any place other than your web application, provided server access rules set permit that (e.g. firewalls, granted authentication, etc.).
In your usage scenario, you would be facing several orders of problems.
1) Security
You would be forced to violate the safety principle saying that database files must be protected from direct web exposure; in fact, to access your web SQLite database file from your desktop you would be forced to expose it directly, and this is wrong, as anyone would be able to download it and access your data, which by definition must be accessible just by you.
2) Updatability without downloading
Using HTTP to gain access to the database file can only lead to the requested resource download, because HTTP is a stateless protocol, so when you request GET or even POST access to the database, the web server would provide it to you in one solution, full stop.
In extreme synthesis, no chance to directly write back changes to the database file.
3) Updatability with downloading
You could download your file with a HTTP GET request, read data, make changes and the rest, but what if your online database changes in the meanwhile? Data consistency would be easily compromised.
There could be a way
If you give up using HTTP for your desktop application access to the database, then you could pick FTP (provided you have access credentials to the resource).
FTP lets you read data from and write data to files, so - on Linux - you could use FUSE to mount a remote FTP sharing and access it just like if it was connected to your local file system (see this article, for example).
In synthesis, you:
Create a mount point (i.e. a local directory) for FTP sharing
Use curlftpfs to link the remote FTP resource to your mount point
Access to this directory from your application as if it was a conventional directory
This way you could preserve security, keeping the database file from being exposed on the web, and you would be able to access it from your desktop application.
That said, please consider that concurrent access by several processes (desktop app + webserver instance) to a single database file could lead to problems (see this SO post to have an idea). Keep that in mind before architecting your solution.
Finally, in your usage scenario my suggestion is to program some server-side web service or REST interface that, under authentication, let you interact with the database file performing the key operations you need.
It is safe, reliable and "plastic" enough to let you do whatever you want.
EDIT:
MySQL is widely used for web sites or web applications, as it is fast, quite scalable and reasonably reliable. Activating MySQL server is a little bit OT on StackOverflow and quite long-winded to report, but in that case you could google around to find plenty of articles discussing such topic for your operating system of choice.
Then use MySQL JDBC driver to access the database from your Java desktop application.
If your idea is to stick with SQLite, though, you could basically prepare four web endpoints:
http://yourwebsite.com/select
http://yourwebsite.com/insert
http://yourwebsite.com/update
http://yourwebsite.com/delete
(Notice I specified "http", but you could consider moving to SSL encrypted http connection, a.k.a. "https", find details here and here. I don't know which webserver are you running, but still googling a little bit should point you to a good resource to properly configure https.)
Obviously you could add any endpoint you like for any kind of operation, even a more generic execute, but play my game just for a while.
Requests towards those endpoints are POST, and every endpoint receives proper parameters such as:
table name
fields
where clause
... and the like, but most important is security, so you have to remember 2 things:
1. Sign every request. You could achieve this defining a secret operation key (a string which is known to your client and you server but never travels in clear text), and using it in a hashing function to produce a digest which is sent together with other parameters as an incontrovertible proof for the server that that request it's receiving comes from a genuine source. This avoids you to send username and password in every request, which would introduce the problem of password encryption if you don't use https, and involves that the server has to be able to reconstruct the same signature for the same request using the same algorithm. (I flew over this thing at 400Mph, but the topic is too large to be correctly treated here. Anyways I hope this could point you in the right direction.)
2. Properly escape request parameters. "Sanitize" parameters someone calls it, and I think the metaphor is correct. Generally speaking this process involves some filtering operations performed by the server's endpoint, but it basically could be written as "use prepared statements for your queries". If you don't it could be likely that some malicious attacker injects SQL code in requests to exploit your server in some manner.
SQLite is an embedded database and assumes that the database file is directly accessible.
Your application is not an appropriate use of SQLite.
You should use a client/server database.
In any case, you should never make a database directly accessible on the internet;
the data should go through a web service.
We currently have a centralised web app and database (running on glassfish and oracle) which is accessed from multiple stations distributed about the country.
At the stations there is data entered into and read from the system (through the browser).
When the (external) connection goes down between the station and the centralized web app we would like for the stations to continue to function - store and present data, then when the connection returns the data is pushed back into the central server maintaining database integrity.
Given that we would be willing to change our app server or database if it was worth it, how is this best handled, is there any out of the box solution for this?
Install the servers at the individual locations, replicate what you want to share across them "routinely", and leave all of the other centralized, but non-vital tasks (like, say, reporting) on the central system.
There is not "out of the box" solution. You system is centralized for whatever reason it's centralized. You're asking for it to be decentralized. By doing so you need to reconsider why it's centralized in the first place, and what dependencies there are because of that centralization (such as each site having instant access to data at all of the other sites).
Address those issues of what you can do without, for how long, and how to share it, and then you can set up autonomous sites. The magnitude and complexity of this process is dependent upon you application and the services it supplies to the remote users.
If you can tolerate losing the current sessions I would point you to look for a distributed database (replication). Oracle probably supports it. In each office you would have a glassfish server
But it is going to cost a lot:
Licences
Hardware (servers)
Properly securing the server
(Lots of) tuning/rewritting to avoid new bottlenecks
Maybe it would be easier / cheaper if you chose to just use redundant internet access for all of your offices.
If you are willing to go cutting edge, then look into HTML 5 with Local Storage. Note that the local storage specification in HTML 5 is still in transition. The second link I included has a good fallback option for when HTML 5 local storage is unavailable. With the fallback option of Store.js, you won't even need to require your clients to use a modern browser, though it definitely helps.
Another option, if you are open to moving in that direction, is to use Adobe Flex 3 for your UI, talking through LiveCycle to your application hosted on Glassfish. There will be more moving parts and a steeper learning curve though.
Architecture:
A bunch of clients send out messages to a server which is behind a VIP. Obviously this server poses an availability risk.
The client monitors a resource and the server is responsible to take action based on the what status the majority of the clients report to it and hence the need for only 1 server/leader.
I am thinking of adding another server as a backup on the VIP, which gets turned on only when the first server fails. However when the backup comes up it would have no information to process and would lose time waiting for clients to report and waiting for the required thresholds etc.
Problem:
What is the best and easiest way to have two servers share client state information with only one receiving client traffic?
Solution1:
I thought of have having the server forward client state information to backup server and in the event of a failure when the backup server comes up, it can take it from there.
Is there any other way to do this? I thought of having a common/shared place to store state information where both servers can read client state information from. But this doesn't work well as the shared space is a single point of failure too.
One option is to use a write-ahead log. Essentially, any modification you make to your state gets sent over to the backup server, which replays the change on its own copy of the state. As long as it can keep up with the streaming log, the backup is always up-to-date.
This is the approach generally used by most databases; if you use one as your backend, you may be able to get support for this with little work.
Be careful to have a plan to recover from communication failure - either save the log to disk and resend the missing portion, or send a snapshot of the state, plus all log entries since the snapshot on reconnect.
There are various distributed caching products which do the kind of thing you're talking about here. Some are supplied with App Servers, such as WebSphere's dynacache and Object Grid. In fact ObjectGrid can be used in JSE, no need for an App Server.
Those distributed cache products use various push and pull models with pub-sub messaging to achieve consistency across the instances. Working for IBM I'm a fan of ObjectGrid, but more impartant, I'm fan of not reinventing wheels. My take is that this stuff can get quite complex and hence finding something off-the shelf might save a load of work - there are links to various Open Source solutions here.
The is very much dependent on how available your solution needs to be (how many 9's). There is a spectrum of solution.
A lightweight one could be crafted around Memcache: extremely fast distributed state facility. As example, it is used extensively on Google AppEngine.