日本語

Server Security

Defense against external attacks

The public awareness of system security is increasing and it is becoming common sense, but we describe it for confirmation.
The infrastructure used in this project consists of GCP (Compute Engine) + WEB server (nginx) + Firebase. Therefore, consider these three places to protect.
The key to protecting the Compute Engine is firewall and SSH protection. As for the WEB server, the application team has a lot to do. Firebase uses Firestore, Authentication, and Analytics.
Protecting your Google account is paramount as a common point of defense.

Compute Engine


Firewall settings:
With Compute Engine, the firewall is set by default, and the default state is that only SSH / RDP / ICMP / HTTP / HTTPS is allowed.
My server is Linux and doesn't require a GUI so I immediately disabled RDP. ICMP is also disabled because it has no use so far.
Steady action is the first step in system security. If you still have unnecessary ports open, be sure to block them.
Of course, if you open additional ports, you should minimize the ports and use filters as much as possible to limit the IP.

Protect SSH:
By default, the Compute engine is set up to allow SSH from anywhere.
If anyone is using it in this state, check the security log once - /var/log/secure.log, for CentOS - . There should be plenty of evidence of malicious login attempts - invalid user -. In the default state, many password-based brute force attacks occur.
By the way, we are using the "OS login" method to log in to the server [Official document: Setting up OS Login ] . Since there is no password setting, there is no need to worry about the damage caused by password brute force attacks. There is no doubt that you are still under attack, so you need to set your firewall to prevent it from being attacked.
If you access only from the corporate LAN, it is easy because you can limit the IP with a firewall filter.
For specific reason, some PCs used to log in to the server are prohibited from being installed something locally. Therefore, instead of connecting directly from the terminal via SSH, we have to log in from the browser. Since the original IP when accessing from a browser is not fixed - that is IP from web servers of google -, the method of restricting the IP with a firewall filter cannot be used.
Security in such cases can be achieved using Google's Identity-Aware Proxy (IAP) [Official documentation: Using IAP with TCP forwarding] . With this setting, only Google accounts allowed by our IAM on GCP will be accessible via the browser. Now the security log no longer shows an invalid user error.

Protect WEB server


WEB server for Development:
There are production and development web servers running on the Compute engine. The development WEB server limits the IPs that can be accessed by setting nginx. The home IP of the member who is working remotely is also added to the settings.
The reason why the development WEB server raises the level of security is... Production WEB server:
Since there are no IP restrictions on the home WEB server, it can be accessed from anywhere. Again, check the error log (/var/log/nginx/error.log for nginx). You should find that various URLs are being tried. I also have various things like /db/dbadmin/index.php and /admin/sqladmin/index.php. As you can guess from the URL, it seems that the intruder are aiming for a maintenance page. If you're using this kind of maintenance feature on your publicly available web server, you should turn it off immediately.
The production WEB server that is open to the public cannot be blocked on the infrastructure side to make it inaccessible. The only thing infrastructure personnel can do is not release features that they don't want intruders to touch, such as maintenance functions. The rest is the work of the applicant.
In this project, the maintenance function is often created with bash on the server. However, there is also a maintenance function that makes us want a WEB screen, so in that case it is running on the development WEB server.

index.htm:
By default, nginx does not automatically display the list of files in that directory when the index.html file does not exist. If it does, it will give the intruder extra information and should be stopped.

About "robots.txt"

If there is robots.txt in the error log of the WEB server, please handle it.
This is not a hacker-like access, but an access that people should definitely read.
robots.txt provides information to search engine crawlers. Read [Official documents:Introduction to robots.txt] and register.

Another search engine related topic

There are many cases that "localhost" is running on WEB server to check the operation. In such case, you need to be careful about the content of the page displayed there. I had a problem because I was displaying the same content as the production server. Now I've changed it to show a customized 404 error screen.
For more informatiion, visit I recommend you to check “localhost” in nginx right now.

Firebase

Firestore:
As I wrote in my last blog, the Firestore rule is set to [Lock Mode] and direct access from the browser - Javascript - is prohibited.
For more information, visit Use multiple Firebase projects properly in WEB application development

Authentication:
It has all the necessary functions for user account management. I definitely recommend it.
Our application authenticates users according to the following flow.
  1. Create new account
  2. Our app is a business application, and the scheme is to charge each company according to the number of accounts it has. Since it is necessary for the company to control the number of accounts, the system administrator of each company registers the account creation instead of the user himself / herself. Use user's email address for their account.
  3. Initial password
  4. When you create a new account, the system assigns a random alphanumeric character to the initial password. Since it is not the user who registers the account, the initial password must be hidden from anyone.
  5. Confirmation email
  6. If the account is created successfully, a confirmation email will be sent to his / hers email address. Attach the link URL (*) to the password change screen - the screen created by our team - in the email . A seemingly random character string that can be converted to an ID and initial password by a certain logic is added to the URL as a parameter. On the password change screen, this is decrypted and used for password change processing.
  7. Forgot password?
  8. When you apply for a password change, you will receive a link to your password change screen - the default screen provided by Google - at your email address.
  9. First login
  10. Since no one knows the initial password, you cannot log in unless you receive a confirmation email or receive an email from a password change request and change your password by yourself. Either way, only accounts that have been confirmed to be legitimate owner of that email address will be available.
Since the account management related logic is provided as a common program, the same mechanism can be used in multiple projects.

* A problem occurred here.
To attach a password change screen link to the confirmation email, do the following. Official documents : Passing state/continue URL in email actions


 const firebase = require('firebase');
 ........
 let actionCodeSettings = {
  "url": "https://exsample.com/change_password.html" + "#" + [Encrypted ID and initial password],
  "handleCodeInApp": false,
 };
 firebase.auth().currentUser.sendEmailVerification(actionCodeSettings)


The Firebase Authentication used here is a library for the front end, and only the Admin SDK is available for the back end. And the Admin SDK doesn't have the ability to send confirmation emails with links.
In other words, you can send emails with links in JavaScript, but not in python.
There was a need to execute JavaScript on the back end, so we decided to run nodeserver.

Analytics:
Since it is for acquiring statistical information and has nothing to do with the requirements of the application, apiKey is managed separately.
The Firebase project has an application registered exclusively for Analytics. - Firebase => project overview => project settings => general => add apps -
The apiKey created here has an HTTP referrer and is set only the minimum required permissions for Analytics. We set only two permissions, the Firebase Installations API and the Firebase Management API.
Since the content of the authority is minimal, there is no problem if this apiKey is published, but since it needs to be used properly in multiple Firebase projects, it is managed in the same way as the key file of the service account.

Protect Google Account:

The most important protection to protect your Google cloud environment is your Google account. If an intruder breaks through here, everything will collapse. Of course, your Google account requires two-step verification.
Google Accounts are managed by IAM, but only infrastructure personnel are registered. The person in charge of the application does not need to log in to the server, so we does not register him / her.
The Google Account used by infrastructure personnel is created exclusively for infrastructure management operations, and it is prohibited to use this account for any other purpose. All the phone numbers for 2-step verification of the account distributed to the person in charge of infrastructure should be the system administrator's number. When using a different PC than usual, the permission of the administrator is always required.
The administrator must not allow the application for use of the smartphone or tablet from the person in charge of infrastructure. Once they are registered as trusted devices, they will be able to log in to another device from there.