Category: Cyber Security

Common Cryptographic vulnerabilities

Common cryptographic vulnerabilities

Cryptography is often used in the most sensitive places, such as authentication, protection of secrets and communication. Despite its importance, cryptography often goes wrong, and when it goes wrong the impact is severe. According to OWASP, it is currently on the second place of the most critical web security risks [1].

This blog post describes three of the most common cryptographic failures and what can be done to avoid them.

Hardcoded secrets

Secrets, such as database passwords and encryption keys, should never be stored in source code. Instead, they should be generated dynamically and provided to the application through other means, such as environment variables. Many cloud platforms also offer a specialized service to store secrets for applications that are deployed in the cloud.

When secrets are stored in source code, they are in a risky position, because:

  • They can be accidentally shipped as part of an application, or pushed to a public repository. It is important to remember that any application that is shipped to a client can be reverse engineered, no matter how well it is obfuscated.
  • It is hard to follow best practices when secrets are stored in source code, such as updating the secret periodically and using independent secrets for each environment.

Detailed information on secret management can be found in the OWASP cheatsheet series [2].

Incorrect usage of encryption algorithms

Cryptographic algorithms are only secure when they are used correctly. For example, many cryptographic algorithms require a key and nonce. For these algorithms, a pair of key and nonce should never be reused. An example of this are AES-CTR and AES-GCM. If an attacker is able to obtain different ciphertexts that were encrypted with the same key and nonce, the attacker may be able to decrypt them without knowing the key. For some algorithms, the requirements are even more strict. ECDSA requires that the nonce is a secret random value without bias. If it is not, an attacker may even be able to recover the key. Sometimes, the security of an algorithm is broken by an implementation flaw. For AES-CBC, it is important that an attacker cannot distinguish a ciphertext with valid padding from one with invalid padding. If the server tells the client whether a given ciphertext is decrypted successfully or not, through a direct or indirect way (such as timing), an attacker can use this to decrypt any ciphertext that was encrypted by the server. In short, before using an encryption algorithm, it is important to understand its pitfalls and how it must be used. Always consult an expert when in doubt.

Insecure random number generators

Random number generators (RNGs) are often used to generate secrets, such as session keys, MFA codes and password reset tokens. If an attacker can predict the next secret, they can often bypass authentication or decrypt sensitive data.

Unfortunately, many RNGs are not secure. If an attacker can recover the seed, or observe enough output of the RNG, they can predict all numbers that will be generated in the future and (usually) all numbers that were generated in the past. This is even possible when only parts of the RNG output are exposed to the attacker [3].

For secrets, it is important to use an RNG that is cryptographically secure, which means that its output cannot be predicted. Whether an RNG is secure is often explained in its documentation. So, before you use an RNG:

  1. Consider whether its output must be kept secret
  2. If it must be kept secret, check whether the RNG is cryptographically secure

Here are some examples of RNGs that are secure and RNGs that are not:

Language

Secure

Insecure

Python

  • The secrets module
  • os.urandom
  • The random module

PHP

  • random_int
  • random_bytes
  • rand
  • mt_rand
  • array_rand
  • shuffle

Java

  • java.security.SecureRandom
  • java.util.Random

C#

  • System.Security.Cryptography.RandomNumberGenerator
  • System.Random

Golang

  • crypto/rand
  • math/rand

Because it is so difficult to get everything right, Securance offers various security services, including code reviews and pentesting. If you would like us to assess the security of your application, feel free to reach out by contacting us below.

Sources:

[1]: https://owasp.org/www-project-top-ten/
[2]: https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html
[3]: https://github.com/fx5/not_random

Detecting and bypassing anti-Adversary-in-the-Middle (AitM) tokens

Detecting and bypassing anti-Adversary-in-the-Middle (AitM) tokens


Within the Advanced Red Teaming (ART) framework it is possible to skip the initial compromise phase of a red team engagement and start from a “Assumed Compromise” scenario. However phishing attacks are commonly used to breach the perimeter. In this blog, we will discuss a specific detection method for Adversary-in-the-Middle attacks (AitM) commonly used by adversaries such as ransomware groups to gain access to the organization’s data. Then we explore how this method can be bypassed. First, we must understand what AitM-attacks are and how they are commonly used to steal login credentials and (MFA) tokens.

AitM-attacks are highly effective as they allow an attacker to position themselves between the victim and the target, which can be a legitimate service such as the Microsoft login page. From this position the attackers are able to capture the network traffic, retrieving the e-mail, password, cookies and session tokens. By possessing the tokens, we can bypass Multi-Factor Authentication (MFA). This highlights the importance of detecting and mitigating such attacks.

Implementing Adversary-in-the-Middle detection with Canarytokens

Some research has already been done into how certain tokens can be implemented to detect Microsoft 365 AitM attacks, such as these from Zolder.io and Clarion. The detection method works by implementing a token in a hidden background image URL within the company branding CSS file for the Microsoft login page. This company branding is commonly used by organizations to implement their own company logo and background. Whenever a user enters their e-mail on the Microsoft login page at https://login.microsoftonline.com, the web browser loads the company branding files, if they have been configured. The example given in the research, lists the CSS code as shown below. To test this implementation, we used the CSS cloned website function from https://canarytokens.org to get a token. During the configuration set the protected site value to https://login.microsoftonline.com/. This blog is not about the implementation of these tokens. If you want to know the specific steps of how this can be implemented, check out the research in the previously linked blogs from Zolder or Clarion. An example configuration of such background-image in the company branding would be:

.ext-footer
{
background-image: url(‘<YOUR_CANARY_TOKEN>’);
background-size 0 0;
}

Figure 1 – Canarytoken in a hidden background image in the Custom CSS file.

Typically, when a user logs into Microsoft, the referer header contains the value https://login.microsoftonline.com/. However, when using a reverse proxy tool such as Evilginx the referer header will be set to the value of the phishing domain. In our example the phishing domain is https://login.fake.com, thus the referer header will be:

Referer: https://login.fake.com

When the Referer header differs from the one configured as the protected URL during CSS Canarytoken generation, Canarytokens will generate an alert. This occurs due to a mismatch between the Referer value (https://login.fake.com) and the protected domain (https://login.microsoftonline.com). Below is an example of such an alert:

Figure 4 – Detection token in the hidden background image.

Detecting anti – adversary-in-the-middle tokens

If we want to bypass these tokens, we should check how these tokens are loaded into the web browser. First, we need to identify a way to load the company brandings files for the target tenant. This can easily be done without having any valid email for the tenant by simply adding the whr parameter to the URL. In the case of NVIDIA, the complete URL would then be: https://login.microsoftonline.com/?whr=nvidia.onmicrosoft.com. When visiting the page, the company branding will load without triggering a sign-in event. However, if you log in using a valid e-mail, it would register an incomplete sign-in.

Figure 3 – Using the whr parameter to load in the company branding files. 

Now how do we find out where these detection tokens are stored? By opening the network tab in the developer tools, we can filter for the word customcss. In the example of NVIDIA, no custom CSS file is used for the company branding, as they only configured a custom logo and background. However, in our development tenant we have set up a custom CSS with a canary token in the hidden background image, as can be seen in the customcss response below.

Figure 4 – Detection token in the hidden background image.

We have developed a simple tool to make it easier to locate these tokens. This script parses the custom CSS file and identifies any URLs contained within them. If it finds a custom CSS file without any URLs, it will output the entire CSS for manual review, just to ensure nothing is missed. If you want to play around with it, you can clone it from here: https://github.com/HackDefenseNL/aitm-detect. Below is an example output from our developer tenant and the DHL tenant which has a custom CSS implemented but no background image URLs:

 

Figure 5 – Automated discovery of detection tokens in company branding CSS files.

Bypassing anti-Adversary-in-the-Middle tokens

The most interesting part of our research is figuring out how we can bypass these tokens. Because we are proxying all the content, we have multiple solutions available to us. One way is by changing the value of the referer header to the normal value: https://login.microsoftonline.com/. However, Evilginx does not seem to currently support this. Another solution is by inserting our own Content Security Policy (CSP), which blocks the token from being loaded into our proxied Microsoft 365 page. 

We can simply create a new sub_filter in our Microsoft 365 Evilginx phishlet. These sub_filters can be used to search for certain content in HTML, CSS and JS files and then replace it with a new value. This exactly what we need to add our custom CSP to the proxied page. There are likely several options to implement this, but in our approach, we search for the first <head> HTML tag and replace it with a new one. Following that we add a new meta tag, containing the CSP and set the MIME type to search for text/html content.

Figure 6  – Sub_filter with the CSP bypass in the Microsoft 365 phishlet for Evilginx.

If you remember from the first paragraph, the detection tokens are implemented through the background-image url(<TOKEN URL>), so the content that we should be blocking are images. In the CSP this can be accomplished with the content option img-src. Obviously, we do not want to block all the images because that would make the page look completely different. 

When using company branding files for the logo, background, etc., they are loaded from Microsoft’s own domain. However, there is not just a single domain, different domains are used to load different kind of company branding files and Microsoft’s own images. In the example below the NVIDIA image is loaded from aadcdn.msftauthimages.net:

Figure 7 – Example of a company branding file loaded from Microsoft’s domain.

From my testing with different company branding files, it seems to be the following domains that are used to load the images: 

⦁ aadcdn.msftauthimages.net 

⦁ aadcdn.msauthimages.net 

⦁ aadcdn.msftauth.net

⦁ aadcdn.msauth.net 

If you add these to your CSP you should end up with the following sub_filter:

sub_filters:
– {triggers_on: ‘login.microsoftonline.com’, orig_sub: ‘login’, domain: ‘microsoftonline.com’, search: ‘<head>’, replace: ‘<head><meta http-equiv=”Content-Security-Policy” content=”img-src aadcdn.msftauthimages.net aadcdn.msauthimages.net aadcdn.msauth.net aadcdn.msftauth.net”>’, mimes: [‘text/html’]}

Note that if you use something like frameless BiTB, you should also add your own phishing subdomains (e.g. login.fake.com) to the CSP, unless you’re not using any images on your domain.

We could also take a look at the Microsoft documentation to see which domains are used to load content during the portal authentication: https://learn.microsoft.com/en-us/azure/azure-portal/azure-portal-safelist-urls?tabs=public-cloud#azure-portal-authentication

Conclusion

Company branding files provide an easy way to implement tokens which can be used to detect AitM attacks. However, these company branding files are publicly accessible and can therefore easily be checked for the existence of these tokens.

By using the Evilginx phishlet filters we managed to implement a Content Security Policy, which blocks the tokens from being loaded into the proxied Microsoft 365 page, effectively bypassing this specific AitM detection method. 

This is just the first blog in our Red Team series. In the next one we will talk about Modern phishing techniques for Microsoft 365.

What is XXE (XML eXternal Entity) injection?

What is XXE (XML eXternal Entity) injection?

A lot of modern web applications still use XML for transportation and storage of data. In 1996 the World Wide Web Consortium (W3C) created this standard and to this day, it is used for a wide variety of implementations. XML has many features that developers are not always familiar with, offering hackers an opportunity for abuse.

Insecure implementations of some XML functionalities can introduce vulnerabilities, one of which is XML External Entity injection (XXE). XXE means that the XML functionality of the application can be used to fetch external sources through a reference in the XML. Vulnerable software that parses the XML interprets the reference, enabling XXE attacks. This vulnerability can sometimes be used to read files from the server, or even to execute commands on it.

The XXE vulnerability is one of the most critical security issues according to the OWASP Top 10. It is categorized under “A05:2021-Security Misconfiguration” and is the 5th most critical vulnerability in 2021.

XML-basics

XML is also known as Extensible Markup Language and is based on Standard Generalized Markup Language (SGML) just like HTML. So, the XML format has a lot in common with the HTML format. It also has declarations, elements and attributes, as shown in the image below

An XML file starts with an XML declaration. This declares which XML version is used. In most cases this is set to <?xml version=”1.0″?>. 

After that, the Document type declaration (DTD) tells the software how the file is structured. This is declared in the element <!DOCTYPE …>. The author can define a definition, or can reference a remote or local definition file. This definition can be stored in a .dtd file or can be defined in the Document type declaration using square brackets[ … ]. It’s also quite common to reference an external DTD on the internet. 

The DTD is followed by the data structured in elements and attributes, where (external) entities can be used. 

Entities in XML

Entities can be compared to a variable in a programming language. In the following example the entity msg contains the value “Hello World”. The value will be stored in the <message> element. A reference to this entity is written as &msg;.

<!DOCTYPE xml [ <!ENTITY msg “Hello World”>]>
<xml>
<message>&msg;</message>
</xml>

This is an example of an internal entity. There are also external entities and these are used in XXE attacks. An external entity can be used like in the example below. In this example the entity ext references an external source: https://example.com/. The software that parses the XML will fetch the external source when the XML file is interpreted. Also, notice the SYSTEM keyword which indicates that it is an external entity.
<!DOCTYPE xml [ <!ENTITY ext SYSTEM “http://example.com/” > ]>
<xml>
<site>&ext;</site>
</xml>

Besides requesting data form external sources, it is also possible to include local files (on the server) using an external entity.

XXE attack

An XXE attack is possible when XML functionalities are used that support dangerous features like external entities. To demonstrate this vulnerability, we’ve used the xxelab made by Joshua Barone. This lab environment is intentionally vulnerable to XXE attacks for testing purposes. It contains a vulnerable application with a registration form that uses XML. The following screenshot shows how the form data is structured and how the<email> element returns in the response.

To check if this form supports XML entities, use an internal entity, like this: <!DOCTYPE foo [ <!ENTITY xxe “This is an internal entity” >]> 

Because the value of <email> is reflected in the response, we can use this to exploit this vulnerability. In the following example the entity XXE is used to display the value “This is an internal entity” in the response.

To exploit this vulnerability to read local files, use an external entity, like in the following example: 

<!DOCTYPE foo [ <!ENTITY xxe SYSTEM “file:///etc/passwd” >]> 


This external entity references the local file /etc/passwd on the file system of the server hosting the application. Because the value of <email> is reflected in the response, we can use this to display the contents of the local file /etc/passwd. The screenshot below illustrates how the external entity xxe can be used to read the local file/etc/passwd:

What else can you do with XXE?

An XXE attack can be used for multiple exploitation vectors. An XXE attack can be used as a DoS attack (known as the Billion Laughs attack). This attack creates a lot of copies of an entity, so the application has to use large amounts of server memory to process the XML.

In some cases, an XXE vulnerability can be used for port scanning. This can be achieved by references to the internal network. In some situations, the response or response time can give an indication if the port (referenced by the URL in the external entity) is open or closed.

And, worst case scenario, an XXE vulnerabiltiy can also be used to execute commands directly on the local system

Fixing XXE vulnerabilities

Most XXE vulnerabilities arise when an application supports dangerous functionalities like external XML entities. So, the most effective way to mitigate these vulnerabilities is to disable these functionalities or to limit the application through filtering. There are a lot of platforms and libraries that support XML, but here are some fixes for some common ones:

⦁ Java – javax.xml.parsers.DocumentBuilderFactory
– factory.setFeature(“http://apache.org/xml/features/disallow-doctype-decl”, true);

⦁ PHP – libxml2
 – libxml_set_external_entity_loader(null);

⦁ .NET –XmlTextReader
–  reader.ProhibitDtd = true;

For mitigations for other platforms, please check the OWASP XXE Prevention cheatsheet. Nowadays most libraries are protected from XXE attacks because loading of external entities is not enabled by default.

The use of a local static DTD can enforce safe and correct XML input. A DTD file defines some rules that have to be satisfied before the XML input can be loaded. Also make sure that the application does not accept DTD’s from user input.

It also might be an option to look at other data storage formats like YAML and JSON. But be careful, these formats can be dangerous as well if not implemented incorrectly.

Is the local administrator’s password reused in your environment?

Is the local administrator’s password reused in your environment?

The Windows operating system by default includes an administrator account for management purposes whose password is the same in many environments on multiple systems.

Why password reuse is common

The password for the local administrator account is regularly reused and is therefore the same on multiple systems within the organization. This may be because, for example, one image is used for all servers and one image is used for all workstations. In this image the local administrator account is set and the password is then never changed. Or the organization uses a script to set a default password on each system.

If an attacker has administrator rights to one of these machines and manages to recover the password or encrypted version of it, he can reuse it to gain access to multiple or sometimes all systems within the domain

Test environment overview

In our test domain playground.local, the same local administrator password was used for all systems within the domain. The hashed version of the password (NTLM hash) can be retrieved by reading the local SAM database on one of these systems.
A hash is the output of a hash function that converts a string to a string of letters and numbers. By doing so, an application can verify that the user has entered the correct password without storing the plaintext password.

It is possible to use this hash for a pass the hash attack. With this attack the attacker authenticates using the NTLM hash instead of a plaintext password. To demonstrate this attack we set up a lab environment consisting of one Windows client and two Windows server including a webserver and a domain controller. The lab looks like the following:

Executing the attack

We demonstrate this attack within our lab by using an account that has local administrator privileges on a workstation. Using these privileges an attacker can dump the password of (local) users using Invoke-Mimikatz. To do so the following command can be used: Invoke-Mimikatz -Command ‘”privilege::debug” “token::elevate” “lsadump::sam”‘

The hash (48e723f6efb3eff9ae669e239c42fff3) of the local administrator account can be used by the attacker to perform a pass the hash attack attempting to authenticate as the local administrator on any machine within the domain. An attacker can do this, for example, using the NetExec tool.

The orange letters in the image above indicate that we have local administrator rights on two systems. This means that we have full control of all systems except the domain controllers. By default, it is not possible to authenticate as the local administrator on the domain controller, unless AD restore mode is enabled. 

Local Administrator Password Solution

Local Administrator Password Solution (LAPS) is a tool used to manage local administrator passwords. LAPS generates a unique password for each local administrator. This password is then by default rotated every thirty days. Next, the password is stored in the Ms-Mcs-AdmPwd attribute. 

Access to the password is granted through the Control access right on the attribute. Control access is an Extended Right in Active Directory, meaning that if a user has the All Extended rights authorization on that attribute or an object above it, he can see the password in. An example is shown below:

Saving the unencrypted password is not a problem because the field in which this occurs requires special permissions to be read. If an attacker has an account that has access to the domain controller to read it or a user account with permissions, he has much more rights than local administrator accounts.

Retrieving LAPS passwords.

The passwords, if requested over the network, are sent encrypted by the LAPS GUI and PowerShell. The LAPS GUI looks as follows if an authorized user requests the password:

It is also possible to retrieve the password using PowerShell with the following command:

Get-AdmPwdPassword -Computername ‘computernaam’