Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Building Secure Systems Checklist, Part 2

DZone's Guide to

Building Secure Systems Checklist, Part 2

Securing your systems from the bad guys is a never ending battle. Read one for some tips on how to secure your Linux based system.

· Security Zone
Free Resource

Discover how to provide active runtime protection for your web applications from known and unknown vulnerabilities including Remote Code Execution Attacks.

This is part 2 of 'Building Secure Systems Checklist.' For part 1 click here.

You have secured a client-server communication with SSL. Well in today's world that is just not enough.

You should enable two-factor authentication. By using two-factor authentication you guarantee that even if the PC of the user is compromised, his data won't be.You can use a two-factor service like Google, or implement it yourself. It is easier than it looks.

  1. First, you generate a secret code according to TOTP. Store it next to the user account.
  2. Generate a QR code based on the TOTP.
  3. Scan the QR code.
  4. Use a free app to seed the OTP generator.
  5. Provide a 30 second OTP from the authenticator to the login screen.
  6. For the mobile part, you can use Google Authenticator or FreeOTP (my favorite).
  7. For the server-side, if you use java I can recommend this library.

Also, enable mutual TLS authentication. If you build an internal app, the best way to verify users is by using mutual TLS. The whole idea is to have the server, request the user certificate (which is stored in a Smart Card or a security device) during the SSL handshake. During user registration, you have to associate the certificate with the user account. After that, you have to check the certificate with a CA, a CRL list, and for expiration. Here is some sample code, using Bouncy Castle.

 private boolean checkIfCertificateIsValid(HttpServletRequest request,X509Certificate certificate) {
 try {
   certificate.checkValidity();
// Get CA certificate
   certificate.verify(secureKeystoreSystemService.getCaCertificate().getPublicKey());
   X500Name x500name = new JcaX509CertificateHolder(certificate).getSubject();
   RDN cn = x500name.getRDNs(BCStyle.CN)[0];
// Get CN in this example we use the email of the user   
String certificateEmail = IETFUtils.valueToString(cn.getFirst().getValue());

   // Get user and validate it with the certificate
   UserRedisDTO dto = authority.getUser(request.getHeader(Constants.AUTHORIZATION_HEADER));
   if (!dto.getEmail().equalsIgnoreCase(certificateEmail)) {
     return false;
   }
   User user = userDao.findUserByEmailWithNull(dto.getEmail());
   X509Certificate trustStoreCertificate = trustStoreDao.getCertificateByAlias(certificate.getSerialNumber().toString());
   trustStoreCertificate.checkValidity();
   if (!trustStoreCertificate.getSerialNumber().equals(certificate.getSerialNumber())) {
     return false;
   } else {
   return true;
}
   if (user!=null && StringUtils.isNotEmpty(user.getMutualSslOTPKey())){

   } else {
     return null;
   }
 } catch (Exception e) {
   log.error("ERROR VALIDATING CERT:",e);
   return null;
  }
  return false;
}
}

To force the browser to send the user certificate, you should configure your HTTP server to request it. The configuration defers from server to server, but the idea is to set verify required on the SSL connection. For Apache check here.

    • How to send critical data to the user's devices. Today users use a variety of devices to connect to the systems we build. Using PKI is a recommended practice, but how do you share the keys? Easy, use P2P. The trick is to use a P2P client on both user systems and send the sensitive keys, directly, without using an intermediate server that can be compromised. Have a look of WebRTC, as it guarantees end-to-end security and it is easy to implement in a Web/Mobile/Desktop application. You can check our P2P library for starters on how to use WebRTC.
    • Secure your final build. You deploy your code to a server, but what happens if someone changes your code? You have to sign your artifacts for every platform.
      • Most platforms like Android and iOS already require this, but that is not the case with server-side software. If you are using Java for your servers, use the jarsigner tool to sign your deployment.
    • Secure your code. Securing your code is a never ending battle with bugs. Some good practices you have to follow are:
      • Follow the OWASP Top Ten List.
      • Do static code analysis.
      • Create unit tests for critical components.
      • Always escape user input.
      • Do both client-side and server-side verification.
      • Check for buffer overflows.
      • Use prepared statements when communicating with a database.
      • Hold sensitive strings in a char array.
      • Peer-review your code.
      • And last, but not least, if possible open-source your code: Given enough eyeballs, all bugs are shallow.

Secure Your OS

Securing the OS is a critical task for every software system. If possible use OpenBSD/FreeBSD, where the default configuration prevents memory buffer overflows, randomizes mmap, and some other cool stuff. This looses compatibility with some Linux software, but if your app is not using some specific OS services, this should not matter. Anyway, most server applications run on Linux, so here are some steps to secure your Linux (CentOS) boxes:

  • Use LXC containers. By using LXC you separate the app from the other user processes. Forget SE Linux or AppArmour. With LXC you share the kernel but nothing else, so a rogue process, unless it crashes or exploits the kernel, will stay safe. Use Docker, Rocket, or pure LXC. It's up to you.
  • When using containers base them on minimal roots like Alpine. Thus you will minimize the installed base and get PaX and grsec enabled for free
  • Disable root login from SSH -  /etc/ssh/sshd_config 
    PermitRootLogin no
  • Edit your password policy -  /etc/security/pwquality.conf Example password policy:
minlen = 8
minclass = 4
maxsequence = 3
maxrepeat = 3
  • It's best to use random passwords for each server, and use a Password Manager like Keepassa to store them. You can use pwmake to generate random passwords. Here is an example for 128bit random pass):
    pwmake 128
    QABNEdabEpSoR!ESvoJzucTIkQ
  • Allow remote ssh only by using authentication keys. This way you can always remove a key when someone leaves your organization, and can a keep count of who has access to the servers.
  • Use a generic DENY ALL firewall policy and open ports only on a need to use, basis.
  • Disable physical login from TTY:
  • # cat /dev/null > /etc/securetty
  • Secure your BIOS/EFI with a password.
  • Secure your menu.

P.S. The above methods for physical security are not ideal, and given enough time anyone with physical access to the computer can beat them. The only things that help if you have to secure a physical machine are:

      1. Full disk encryption.
      2. Armed guards.
      3. A Faraday cage around the server to prevent electronic signals eavesdropping.

Conclusion

Security is a never-ending battle. It involves various tools and you are never 100% secure. The thing you can do is mitigate most attack vectors and harden your systems to the point that they are not worth the effort to hack.

Find out how Waratek’s award-winning application security platform can improve the security of your new and legacy applications and platforms with no false positives, code changes or slowing your application.

Topics:
security ,linux ,authentication ,tls ,two-factor authentication

Published at DZone with permission of Deyan Atanasov. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}