Skip to main content

Insecure authentication method - NTLM

Need

Secure authentication method implementation

Context

  • Usage of Ruby for building dynamic and object-oriented applications
  • Usage of net-ntlm for NTLM authentication in network communication
  • Usage of net-http for handling HTTP requests and responses in a Node.js application

Description

Non compliant code

require 'net/ntlm'
http = Net::HTTP.new('www.example.com', 80)
request = Net::HTTP::Get.new('/index.html')
request.ntlm_auth('username', 'domain', 'password')
response = http.request(request)

The above code demonstrates the use of the NTLM (NT LAN Manager) authentication protocol in a Ruby on Rails application. It uses the 'net/ntlm' library to send a GET request to 'www.example.com'.

Here is a breakdown of what the code does:

  1. It first requires the 'net/ntlm' library which provides NTLM authentication functionality.
  2. It then creates a new instance of the Net::HTTP class for 'www.example.com' on port 80.
  3. A GET request to '/index.html' is created.
  4. The NTLM authentication method is used to authenticate the request with a username, domain, and password.
  5. The request is sent and the response is stored.

This code is vulnerable because it uses the NTLM authentication protocol, which is known to have several security flaws. These include:

  • Relay attacks: An attacker can intercept the NTLM messages during the authentication process and use them to impersonate the client on another server.
  • Man in the Middle (MitM) attacks: An attacker can intercept and possibly alter the communication between two parties without their knowledge.
  • Brute force attacks: An attacker can repeatedly attempt to authenticate using different passwords until the correct one is found.

In addition to these, NTLM does not support modern security features such as salted hashes or server authentication, making it an insecure choice for authentication.

Steps

  • Replace the usage of the Legacy NTLM authentication protocol with a more secure authentication method.
  • Consider using modern authentication protocols such as OAuth or JWT.
  • Implement strong password policies and enforce password complexity requirements.
  • Implement multi-factor authentication to add an extra layer of security.
  • Regularly update and patch the application and its dependencies to ensure the latest security fixes are applied.
  • Perform regular security assessments and penetration testing to identify and address any vulnerabilities.
  • Educate developers and users about secure authentication practices and the risks associated with insecure authentication methods.

Compliant code

require 'jwt'
require 'net/http'
require 'uri'

http = Net::HTTP.new('www.example.com', 80)
request = Net::HTTP::Get.new('/index.html')

payload = { data: 'test' }
rsa_private = OpenSSL::PKey::RSA.generate 2048
rsa_public = rsa_private.public_key

token = JWT.encode payload, rsa_private, 'RS256'

request["Authorization"] = "Bearer #{token}"

response = http.request(request)

The above code replaces the insecure NTLM authentication with JWT (JSON Web Tokens). JWT is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

In the code, we first require the necessary libraries. We then create a new HTTP request to 'www.example.com'. Instead of using NTLM authentication, we create a JWT token. The payload of the token is a simple data object, but in a real-world scenario, this would contain the necessary authentication data.

We then use OpenSSL to generate a new RSA private key, and get the corresponding public key. The token is then encoded using the private key and the RS256 algorithm. This token is then added to the Authorization header of the HTTP request in the format "Bearer #{token}".

The request is then sent, and the response is stored in the 'response' variable. This method of authentication is much more secure than NTLM and is not vulnerable to the same types of attacks.

Remember to store your private key securely and never expose it in your code or version control system. In a production environment, you would likely use environment variables or a secure key management system to handle your keys.

Also, it's important to note that this is a basic example. In a real-world application, you would need to handle token expiration and renewal, error handling, and other edge cases.

References