I'm building an Android application that needs to communicate with a MySQL database. The application isn't meant to be published, and I want the application to be the only thing allowed to interface with the web service I'll create for DB access.
I've been thinking how I can secure the system, and this is the idea I've come up with. I'd appreciate any feedback or other ideas. Surely there is a method built into Android that I am unaware of.
My thought is to give the web service a GUID. Each time a call is made to one of it's public methods, the web service matches its GUID with the GUID given to it by the Android application. If the GUIDs do not match, the web service refuses access. In short, my system has a 128-bit password.
If you trust the individual to administrative your database then everything should be fine. The most important change is that all of this communication must be done over HTTPS. If a hacker sees this traffic your database will get hacked.
I would still use a username/password combo to access the system. I recommend using the existing mysql.users table with the MySQL password() function. This GUID sounds identical to a cookie, and I would seriously consider using an existing session handling system such as php's session_start() instead of rolling your own. Re-inventing the wheal is bad, especially when it comes to security.
Related
We are making android application, which needs to get data from mongodb database. There will be many entries in database and there will be requests quite frequently. Should we access it directly or make a PHP script, which would access it and return required results in JSON?
Should we access it directly
You definitely do not want to expose your MongoDB server(s) to the Android application directly, especially if the application will have a user role allowing write access to the database. Anyone with access to the Android app could potentially discover and extract those credentials, and if your Android app is designed to connect from a wider network this exposes your MongoDB server unnecessarily. You may also be opening your MongoDB server to possible denial-of-service attacks or rogue queries.
The MongoDB documentation has a detailed section on Security Concepts including network exposure and security. Best practice for any database deployment is to limit the range of network addresses that can connect directly. Generally direct connections should be limited to your application servers and monitoring apps, which are probably hosted within the same network infrastructure.
make a PHP script, which would access it and return required results in JSON?
Yes, a recommended approach would be to write your own interface which provides a suitable API and authentication controls. You should be able to find a PHP framework and/or libraries to minimise the amount of custom code you have to write (eg. REST, JSON, Oauth).
The interface you implement can:
put some constraints on the type of queries that end users can run (only what you provide, rather than the full MongoDB API)
allow the application to authenticate with appropriate user privileges without having the database credentials embedded in the Android app
add additional user security such as token-based OAuth or Twitter/Facebook authentication
abstract the endpoint that the Android app connects to (your web interface) from the infrastructure detail of your MongoDB deployment
potentially include caching for common queries or session data
I would pick the option of creating the PHP script that will handle all the logic and data filteration, send back as JSON response to be ready for the application.
as marked in bold, that will allow you not to worry about filter the data in your client "android application" side, and leave all the dirty work to be done on the server side.
There is a two options
Make an API service that will contains all CRUD operations so you
will be able to call from you application.
You are able to access directly via Java MongoDb Driver. Read
more here how to get start with java mongodb driver.
I see many people trying to connect an Android device directly in a database like SQL Server or MySql and the answers are always the same: Use a web service. Why not connect directly an Android device with a database? I'm using a local network with my Android application.
There are a number of reasons.
Security- If the user has direct access, they can get anything from your database. Plus they will have a password into your database. As a result, if the SQL server you are using has a flaw, then they can exploit it. Also, if your permissions are set up wrong, the could wipe your database.
Speed- If the users frequently use large queries, then it can bog down your system quickly and needlessly. If you go through a web interface, you can throttle it.
Accessibility- Web queries are supported by almost everything. It requires special clients to access SQL databases directly.
But if you trust your users completely, have the right libraries/drivers, then you could allow direct querying, and it might even be a bit quicker.
If your app connects directly to the database server you have to hardcode username / password which is very insecure. With some tools an attacker can decompile your apk and can access username / password in this way and can connect to your database with read (+write) access without using your app.
Another reason not to access database directly
Problem If you changed database architecture.
you have two solutions.
1- in direct access you will need to update every Client app
2- using service you only need to upgrading the service.
The reason is the connection
You're not sure how many time you'll have to maintain this connection, if it's stable and if you're not going to lost it
Secondly, web-service are optimized to retrieve an information and serve it beautifully with standarts. You can also cache the informations to spare your DB
I came across a few tutorials online explaining how to connect to MySQL from an Android app, but they are a bit surface.
If I just write SQL and send/receive it in a POST, it seems problematic for a few reasons:
1) Hardcoding SQL with obvious issues there
2) Security concerns about sending sql - is that safe to send that request? or should it only be done via SSL?
3) To connect to the db, in order to insert things, I need to have the db connection info inside the app - is that safe? Can the code be read by someone hacking the device and the apps?
What is the best way to go about connecting and using a remote db from an Android app?
Thanks!!
Wrap everything in an API and manage authentication either with encryption with public/private keys or with a token-based system. You should never, ever, ever accept raw SQL in any way, shape or form from any device or site. Most often if you need live, remote data to run you should reconsider your application workflow and work off slightly stale data or provide the information in the background due to the possible spotty connections. Hitting even an API can be a costly endeavor so it shouldn't be something that has to occur frequently.
To incorporate some of the ideas above you could a couple things. For the public/private key read up on http://en.wikipedia.org/wiki/Public-key_cryptography. The basic concept is you store the public key on the device then negotiate a private key after the installation of the application that is also stored on the device (although not coded into the application). This key is the one you have to protect so it should be negotiated on installation and stored with the lifecycle of the application. You could contact an API with a unique hash of the device (say the device ID) and a password that the user could set. In that way if the data is wiped, since the password is stored on the server you can validate that a request to generate a new key is valid for that device ID and also protect against attackers trying to disrupt everyone's keys.
Obviously this is still susceptible to someone intercepting the initial request but if you are using HTTPS (which you should) then it should mitigate most of these issues.
You have to make sure an attacker just cant send in random device ID requests to generate new keys as it would disrupt the actual user's device of that hash, which is why the password set is important. Of course they could also do this against device IDs not currently registered but you could easily implement throttling and blacklisting against the initial API.
There are many things you can do but depending on your sensitive data it may be overkill. You'll have to make that judgement call and figure out who you are trying to protect your data from.
Use a webservice through which to communicate with the database. End User clients generally do not communicate with the database over the internet. Multitier_architecture
I am in the process of developing an app with the help of someone else for a site I am developing. This app being developed will require access to the database on the web server. So my question here is typically I would want to keep my servers access limited to specific IP's however. Mobile devices all have there own ip's from what I hear. So if this is the case I essentially have to open up my database access to allow any inbound remote connection. Which is more than possible, but I forsee a potential security risk with that. namely in the notion of someone attempting to brute force the DB to gain root access or something to the effect there of. With that my question comes down to is there a more secure way of doing what I need in the overall? Is there any methods I can apply that would allow me a little more peace of mind. The DB I am currently using is mySQL, and will generally remain that type til later in the future.
Your concerns about security risks are valid. You should avoid a situation where countless mobile apps are making database connections to your MySQL database. A better solution would be to host a REST API layer in front of the database. This would allow you to control what portions of your database are accessed, but potentially include authentication routines as well. The REST web services you publish will give you the opportunity to produce permitted representations of your data rather than raw access to the data. That means in addition to producing web services, you'll need to develop the app to be a REST client that consumes these services or makes "requests" to them on an as needed basis. Obviously, this requires planning on both sides of development (back-end and front-end).
One possible solution to consider for producing REST web services is here:
http://phprestsql.sourceforge.net/
There are additional frameworks available for PHP, Java, ASP.NET and other platforms.
http://peej.github.com/tonic/
http://jersey.java.net/
Good luck!
Why not access the database via an API and then secure the API? So in essence, you should have a REST(or anything) API on your web server which your mobile application talks to which subsequently talks to the database. Accessing and securing your API will make a more cleaner and leaner design.
I need to make requests to a web service via android application.
The webservice can be designed as needed.
It seems to me that no matter which approach I will choose, someone who wants to hack it, will just need to reverse engineer My android appliaction code (which isn`t very hard) and
could see exactly what I do, wheather I encrypt the data, use hardcoded Password or any other solution for that matter.
Is there a solution which will be 100% secure?
There is no 100% secure, all you can do is make things harder for your attacker. Things you can consider:
Encryption - Passing your requests over encrypted channels will stop
basic sniffing (this can be countered with MITM)
Obfuscation - Make your intent harder to understand when they do decompile your app
The second part to this is mitigation - the ability to notice when your app has been compromised and deal with it. A typical way of handling this is to assign a unique token to each client on first run then pass this as an argument on each call to your service.
This way if somebody decompiles your app and figures out how to call your service you can at least start monitoring where the abusive requests are coming from and also monitor for suspicious behaviour (i.e. multiple requests from the same key in a short period across different IP addresses). From there you can start blocking keys.
You're worried about "hacking ", but the base of any security discussion is defining the risk.
What are you trying to protect against?
For example, are you trying to protect against an attacker to read someone else's connection to the server?
A simple and secure solution for this scenario would be to use an asymmetric key exchange for your symmetric encryption keys, or use an existing protocol that does this (e.g. HTTPS). embed the server's private key (or certificate if using HTTPS) to also defend against man-in-the-middle attacks. Reverse-engineering your app won't help an attacker here.