4

I am developing a server which serves two purposes: it is a CMS for people to use and maintain some data, and a Web Service for a mobile app to get this data. It runs on a Debian server running Tomcat 6 (using Java/JSP) on AWS cloud.

Now, the server uses logins/passwords to identify users in both cases — in case of the mobile app, the login/password is in the app and shared across all instances of the app. If anyone starts looking at the network traffic of the client, he will see URL, login and password, will go to the URL and will be able to log into the CMS (or at least launch a brute-force attack against the login service).

What is the best way to secure the CMS? My ideas are roughly:

  1. Move the CMS to a different server instance and a different domain. It will still share the underlying DB with the Web Service.
  2. Obscure the login point of the server. Instead of basically redirecting all invalid URLs to the login page, send them strictly to 404 and rename login to something random.
  3. Make sure the mobile app uses logins/passwords that don't work in CMS (by implementing different roles for CMS editor / app user) and harden the login against (brute force etc) attacks.
Gilles 'SO- stop being evil'
  • 50,912
  • 13
  • 120
  • 179
vektor
  • 202
  • 2
  • 8
  • 1
    Serve ALL of your login forms and login actions over `https`. This at least prevents anyone from seeing passwords transmitted over the network. –  Aug 12 '12 at 19:20
  • I am not afraid of people stealing the password from unsecured network - the password is in the app anyway. You can just get the app and take the password from there, or run it on your Android and look at what gets encrypted into the HTTPS stream. –  Aug 12 '12 at 19:23
  • What OS/version, Cloud/location, Language/runtime are you using? It really matters on how you make it. It's impossible to answer this question in an abstract way, because it would take 1000 pages. – Andrew Smith Aug 13 '12 at 12:12
  • @AndrewSmith my question is environment-agnostic, but I added the information to the question. – vektor Aug 13 '12 at 12:15
  • @vektor, I'm finding it hard to work out precisely what you are asking. I suggest you step back for a moment and spend some time thinking through the requirements, the security goals, and the threat model. Then, take some time to articulate this clearly. Ask a new question. Right now I think you might be too caught up in the details of your current mechanism. We've had to do several rounds of back-and-forth to dig out details of what you're asking, and that's a sign you need to spend more time thinking through the problem statement. – D.W. Aug 13 '12 at 20:01
  • (cont.) This site relies upon carefully thought-out questions. If the question isn't carefully laid out, you probably won't get good answers. And, a piece of advice: try to describe the problem statement, without assuming any particular technical solution or mechanism. You should not assume that the solution to your problem will necessarily take any particular form, or that it will necessarily look anything like what you are currently doing. – D.W. Aug 13 '12 at 20:02
  • @D.W. Of course the question is not well thought-out. However, phrasing it and having a back-and-forth in this discussion helped me figure it out and get to the answer already. Did I intentionally misuse the site? Yes. Should I get minus points? Definitely:) Do I now have the answer? Yes... I will share it here, just in case. – vektor Aug 13 '12 at 20:20

5 Answers5

2

If I understand correctly, your CMS serves two types of users, which supposedly have different privileges:

  1. Non-app users (e.g users that access the CMS directly from their browser). Read and write access.
  2. Mobile app users. Only read access.

According to your system's design, it is possible for an app user to find out the user/password combination that his/her app uses (because it's hardcoded in the app) to login to the CMS. So, the only thing that keeps the app user from manipulating the CMS's data is the fact that he/she is using the app.

Your immediate concern should be the role separation in your CMS. If you are using sessions in JSP, this should be easy (perhaps add another column in your users table that will represent the user's role and have a role check in every .jsp).

Regarding to your CMS's login point, obscuring it might fool some bots but this is not enough. You could use iptables to stop bruteforce attacks or you could implement a daemon of some sort that monitors Tomcat's logs and bans suspicious behavior (an example of mine used to ban SSH bruteforcers: https://github.com/epadillas/ssh_banhammer.py).

Also, always use HTTPS when dealing with sensitive information such as authentication credentials.

epadillas
  • 46
  • 3
  • Yes, exactly, this is what I am going to do (see my answer). In case nothing miraculously better appears, this will be accepted:) – vektor Aug 13 '12 at 20:44
1

First, use SSL (https). This will prevent an eavesdropper from learning users' credentials.

See What are the pros and cons of site wide SSL (https)?, HSTS extra security over HTTPS, Guidance for implementors of HTTPS-only sites (Server side).

If you are embedding a password in the code of the mobile app that the user downloads, that's a bit weird and does not sound like good practice. That's effectively equivalent to putting that password on your web site for everyone to see: anyone can download the app and look at the bytes to find the password. Nothing stored in a program binary should be treated as secret.

If the user types in his/her password into the app, it is fine to store it in app-private storage and reuse it on every connection. Or, it is fine to generate a private key on first launch of the app, securely send the corresponding client cert up to the server (over an SSL connection authenticated by the user's password), and then use SSL with client certs to authenticate the mobile client to the server on all subsequent connections (so the user does not need to type in his/her password again).

If the content on the CMS is intended for the public to see, then you should remove the password for viewing content, as it is a bit pointless. If the mobile app is available to the public, and anyone with the mobile app can read the content on the CMS, you've effectively decided that the content on the CMS is intended for the public to see.

D.W.
  • 98,420
  • 30
  • 267
  • 572
  • 1
    In this case it does not help. Any user of the app can just look at it and find the password there. Or use a tool to see what goes into the HTTPS stream before it is encrypted. So I have to assume that the user has the apps credentials. – vektor Aug 13 '12 at 06:59
  • @vektor, I don't understand what the problem is. Why do you want to prevent the user from seeing his/her own password? Perhaps I have not understood what you are trying to do. I'm assuming the password you are storing in the mobile app is the password for the user's own account. If not, please explain in more detail what's going on. You should not send passwords to the user that they're not authorized to see; so, you should not send an app to the user with a password embedded in it that the user isn't authorized to see. – D.W. Aug 13 '12 at 18:10
  • The password is per-app, for a certain version of the app it is hardwired in it. It can be easily extracted, and therefore is considered not too secure - just for a read-only access. But, as the password represents a valid user of the system, it can (at the present time) be used to access the CMS - which I don't want. First of all, I need to split users into those who can and cannot access the CMS - via roles. But I would still like to somehow "hide" the CMS. My question: what is the best practice here? Have one server but "hidden" login URL, or have a secondary server accessing the same DB? – vektor Aug 13 '12 at 18:25
  • It's like the old joke. Patient: Doctor, Doctor, it hurts when I grant user X more access than I really want user X to have! Doctor: Well, don't do that, then. – D.W. Aug 13 '12 at 19:27
0

You can generate an "API key" for each user that they will use to retrieve data, so that if it's stolen/compromised, it cannot be used to access the CMS, and it could also be reset from there.

Also, you should respond with an error (e.g. 401 Unauthorized or 403 Forbidden) to invalid logins instead of redirecting them to the login endpoint.

If you want to add an optional layer of security to the CMS, I suggest you to add some multifactor authentication (for example Google Authenticator).

Apart from these, you should secure your server(s) against brute force attacks (block an address after repeated failed request, or maybe add a CAPTCHA to the login form), various injections (check the code carefully, especially SQL queries) and sniffing (encrypt the traffic between the mobile app and the web service, and using SSL on the CMS server). And obviously, keep any third-party software and libraries up to date.

  • Sorry, I don't get the point with the API keys. Could you please elaborate? Also the redirection to 401/403 does not make much sense in the context of how a login on a web page usually works... – vektor Aug 13 '12 at 07:00
  • In any case, multifactor authentication is definitely a good idea, as well as using CAPTCHA. – vektor Aug 13 '12 at 07:01
0

The environment always matters, because the security layers go up from physical to application one.

Java has it's own security, hence it's different then e.g. PHP, Python or Ruby. Java is compiling the source code and it's static language. OO access modifiers make sense in separating the rights of parts of the code, and it's considered safe as you cant do code injection in Java like you do with PHP, most of the time.

Basically what you need to do for such an app:

  • First, you need to split your applications in different isolated context using Tomcat. With PHP or IIS you do this with different system user. In Tomcat, you just setup separate application. You can also isolate them via virtualization, e.g. two tomcats and two ips.
  • Each application must use different login for Database, and have only required permissions, for example, frontend and backend can have different levels, so SQL Injection on frontend wont break the complete system. If they all use the same DB. You can use Views to do it.
  • You make sure that you use HTTPS for every login as well for backend user session
  • You can install Apache with ModSecurity in front of it with mod_proxy
  • Make sure that your session is secureid, e.g. it's cryptographically secure token

And above all:

  • Frontend and backend users should be kept in separate tables and its access should be limited to frontend or backend. So when the frotend is breached, no modification to database is possible except just few innocent columns.
  • Passwords needs to be hashed with salt at minimum.
  • Reasonable password recovery.

Also:

  • Try securing the machine with SELinux
  • Make a good resilient IPTABLES firewall - this and above prevents rooting the machine

Also, if you have lot's of audience:

  • Isolate login, registration and password recovery (and reporting) to yet another tomcat with exclusive write access to users tables, but it could be separate Tomcat application no problem. Just make sure that each execution context in Tomcat cannot read the config files / db passwords from each other.
Andrew Smith
  • 1
  • 1
  • 6
  • 19
  • Hi @Andrew, I will ignore the general advice, which is already implemented (or most of it, anyway), and focus on clarification of the points relevant to my question. I really like the idea of separating the app into 2 Tomcats, and probably will implement it that way. I am not sure about the different tables for frontend and backend users - what advantage is compared to when you just create different roles for CMS and WS? Another Tomcat just for keeping track of users is a good idea again. – vektor Aug 13 '12 at 15:29
0

This is what I have decided upon as a result of this discussion.

  1. Everything is over HTTPS, of course.
  2. I will separate roles for CMS and mobile app users, so that the login/password from the app is useless in the CMS.
  3. I will harden the login service by implementing measures against brute force/dictionary attacks.
  4. There seems to be no "best practice" as to how to prevent too many attackers come knocking on the login door of the CMS - either split the CMS and WS to different servers/domains/..., or just "hide" the login URL, or both, or whatever - it does not really matter that much.
vektor
  • 202
  • 2
  • 8