Mitigating Android RAT Threats: A Practical Guide for Mobile Developers

Mitigating Android RAT Threats: A Practical Guide for Mobile Developers

In the past, we discussed one specific RAT (Remote Access Trojan), EagleSpy v3.

Now, we will further continue with guides for the mobile ecosystem. While threat actors attack every possible medium, the mobile environment is also at high risk. This is due to the large-scale usage, the opportunity to conduct corporate espionage, and because smartphones are usually at the end of multi-factor systems, essentially serving as a gateway to endless possibilities for stealing information.

Rise in threat actors and vulnerable code

Mobile developers can and should help mitigate as many vulnerable gates as possible, especially nowadays. What I mean by “nowadays” is the fact that we are entering a new era post-COVID, where the barrier of entry into software development and tech overall was just “a React course”, or “todo app.”.

Now, of course, I exaggerate a bit, senior positions and, in general, more experienced ones still had a high barrier of entry, with various algorithms and live coding based on the position. But entry-level roles became easier to obtain. And this is not a bad remark on my part, I was honestly impressed to see how, in a few years, we went from training 6-10 interns to 30 interns. Overall, the feedback was very good, and many actually thrived and continued evolving over time.

But with such a huge boom in the market and so many niche projects and requirements, people often move into senior jobs in specific areas of development without having a base in computer science, a base in networking, a bit of hardware knowledge, security, and so forth. Again, this is not a complaint but a reflection on the state of the industry.

On top of that, we now have LLMs, which are used virtually everywhere. This is a different topic altogether, but it’s worth mentioning that the code LLMs were trained on (for example, GitHub, Stack Overflow, and so on) turned out, in many cases, to be full of vulnerabilities and security flaws.

It’s like training an LLM with data from a history book versus training it with gibberish text or honeypots.

Basic secure coding practices

So, going forward, we have no choice but to recommend some practices that every developer can incorporate into their work, providing value for themselves and the product they work on, at least in theory.

Practice writing safer code

I advocate for safe code. Clean code is truly debatable, everyone has a different perception of clean. But safe is universal. This sometimes contradicts my own principle of writing as few lines of code as possible.

Overall, each line of code is a maintenance headache in the future, so it makes sense to think more than write, and write less and less.

However, writing safer sometimes contradicts many principles, such as DRY.

Input validation and sanitization

Input validation should be done regardless of business requirements. Setting a limit on various input data forms is highly encouraged. Threat actors make use of existing inputs, at least for conversation overflow, in which they take advantage of ‘unlimited’ character space to inject malware in various hidden ways.

Also, ensure that all inputs, especially those coming from external sources, are sanitized. This is one of the easiest ways to improve security in any web application, and a lot of the time it is ignored. There are now countless libraries that do this, and the process is as straightforward as adding a new attribute to that input. Sanitization helps prevent common exploits such as SQL injection and buffer overflow attacks, which can be used to introduce RATs into your application, along with many other malware types.

An unsafe Kotlin code example: we will now check if the provided password matches a stored password.

There are some flaws, that we will present and fix in the safer example:

The improvements:

Constant-Time comparison

The ‘MessageDigest.isEqual‘ method ensures that the comparison is done in constant time, making it resistant to timing attacks.

Timing attacks are a type of side-channel attack where the attacker exploits the time it takes to perform certain operations, in order to gain information about the system. For example, if the first character is wrong, the comparison will terminate very quickly. But if the first few characters are correct, and the fifth character is wrong, it will take slightly longer.

Hashing passwords

Always hash passwords before storing them in the database. As an extra step, a salt can be added, which is a random string combined with the password before hashing to ensure that even if two users have the same password, their hashed passwords will differ.

Use secure, adaptive hashing algorithms like bcrypt, Argon2, or PBKDF2. These algorithms are specifically designed for password hashing and can be configured to increase the computational cost, making them resistant to brute-force attacks.

Use of Secure APIs

While certain tasks and features can be done really easily, adding a security layer can sometimes be frustrating. It can be frustrating to estimate, track blockers during implementation, and deliver on time. But this is what makes or breaks an application.

There are many other security layers that can be easier to implement, but they should not be overlooked.

For instance, when dealing with cryptographic operations, use Android’s ‘javax.crypto‘ package, which offers secure implementations of encryption algorithms. Further read about quantum encryption.

Specifically in the database, when storing various sensitive credentials (not just passwords), hashing needs to be ensured. When sending those credentials to the client or other parties, encryption needs to be considered. More on that below.

Advanced secure coding practices

There is a fine line between beginner coding practices and advanced, so to clarify a bit, I will refer to the more development costly and more complex features. Even if it may not be entirely accurate.

App permissions

Limit the permissions your app requests. Excessive permissions can and will be exploited by RATs. Ensure that your app only requests the permissions that are absolutely necessary for its functionality. For admin functionality, where you can download or remove bulk data, a second factor is a great idea, a confirmation via email or SMS when attempting to take that kind of action.

Ensuring the principle of least privilege and monitoring when bulk operations are performed are key to maintaining good security practices. This will help in the worst-case scenario of a data breach.

Encryption

Encrypt sensitive data both at rest and in transit.

At Rest. Use Android’s Keystore to encrypt data before storing it, ensuring that even if a breach occurs, the data remains unusable without the encryption key.

In Transit. Use TLS (HTTPS) to encrypt data sent between the app and the server, preventing interception by attackers.

Here is a pseudocode example to aid understanding, as actual encryption code is more complex and depends on various implementation possibilities.

Content security policy (CSP) is not just for Web

The lines are starting to get blurry between mobile and web, and while this isn’t specifically about the native environment, there are use cases where CSP matters there as well. In short, CSP is a security layer for the web that ensures basic protection against Cross-Site Scripting (XSS) and data injection attacks. There are many other security risks on the web, but not all of them can be mitigated from the code base.

In the native world, if Web Views or browser environments are not used, CSP does not apply. However, similar concepts can still be applied.

Such concepts are:
Controlling and restricting network requests to trusted sources. This is similar to CSP’s role in controlling content sources, allowing only specific sources to connect and send/receive data.
Content integrity checks. Ensuring that the content is unaltered.
Certificate pinning. Ensuring proper certifications are in place and your app communicates with a trusted server.

Closing words

I understand it’s a lot to do, but good security hygiene isn’t achieved in a day, it’s something that can be built one step at a time.

Certain measures, once implemented, are particularly powerful and provide ongoing value, such as sanitizing inputs or establishing a proper content security policy. Some aspects, like defining app permissions, need to be addressed during the architecture blueprint phase of the project. However, writing safer code is a practice that should always be with us, no matter the stage of development.

I’ve worked as a web developer for more than 10 years, so this perspective doesn’t come from a pure cybersecurity expert but from a professional who has stepped into the realm of cybersecurity. Security has been a significant part of my coding practices, especially in the last 6 or 7 years. This is something every programmer will eventually embrace.

As programmers, we must commit to protecting our work as much as possible against threat actors.