News, news analysis, and commentary on the latest trends in cybersecurity technology.

How Development Teams Should Respond to Text4Shell

Yet another *4Shell exploit highlights the horror of strange visitors into enterprise environments. This Tech Tip focuses on what to do next.

Gabriel Manor - Liechtman, Technical Leader, Jit

November 23, 2022

9 Min Read
A shadowy figure stands outside a cozy home's window
Source: 16th via Adobe Stock

A family moves into their dream home, only to be plagued by ominous letters, a strange tenant, and sinister threats. Sound familiar?

It should. This is the story behind The Watcher, a true crime series that premiered on Netflix on October 13, 2022. It's also the story of the Text4Shell vulnerability, which was announced that same day, causing many people worldwide the horror of unknown attackers getting access to their private environments and threatening their applications.

Text4Shell is a remote code execution (RCE) vulnerability that allows attackers to remotely access a server and run malicious code on it. RCE attacks have become very popular lately, with vulnerabilities like Log4Shell and WannaCry, due to the growth of cloud applications that expose APIs (REST, GraphQL, LDAP, etc.) in public environments.

These attacks are straightforward for hackers to attempt. All they have to do is scan the Internet for applications running a known vulnerable tech stack, and search for the right external endpoint that will allow them to inject their malicious code.

How Does Text4Shell Work?

The Apache Common Text library is a widely used Java library for text manipulation and other string algorithms. It is a common dependency in the supply chain for many OSS libraries, and is used directly by many Java applications too.

One of the library functions, to create interpolators to substitute variables from a string, has flawed logic as it executes part of a given string without using isolation. This oversight makes the string accessible to the whole environment. In practical words, if you have a REST API with a request parameter such as 'https://your.app/user/{userID}', you would manipulate this 'userID' variable, with the 'createInterpolation(userID)' function.

In the case of a public API, any attacker can replace the 'userID' parameter with malicious code and have it execute it in your environment. The worst case scenario of such an attack is taking remote shell control of your environment (this is why this class of vulnerabilities are called *4Shell).

For future reading, this Palo Alto Networks post has a practical code example that you can run locally and see this flaw in action.

Can We Proactively Prevent RCEs?

While there is no way for enterprises to promise they will never be hacked, applying proactive DevSecOps methodology in progressive development organizations can save you a lot of pain in future RCEs and *4Shell attacks.

Progressive DevSecOps approaches make a concerted effort to assess all of the potential risks in the entire software development lifecycle, from the supply chain of your application to the runtime in production. It doesn't stop there, though. The more critical part is then making it possible to easily create continuous automated pipelines to detect, estimate, and remediate such security vulnerabilities.

The following best practices list will guide you step by step in creating self-defending engineering organizations, that autonomously maintain security based on security domain expertise available to defend against known hacking vectors.

1. Continuously Run SCA Tools on Your Code Base

Software Composition Analysis tools have been available for many years, with countless free and commercial tools that leverage online sources to detect vulnerable versions of libraries and tools used in software. Multiple tools out there differ in their level of inspection, and the quality and coverage of their vulnerability database. For Java, you can use open source tools such as OWASP dependency check (or commercial tools such as Snyk and Mend). Regardless of which you choose, you should find the SCA tool available for your tech stack and run it regularly. Some defense is better than no defense.

By running those tools periodically on the code base, you can detect any vulnerable versions of tools and libraries you are using in your supply chain, just in time. We recommend running it at least daily, while also continuously monitoring new code being pushed for any updates that may include vulnerable versions.

Another point is ensuring a well-defined strategy for updating versions of vulnerable third-party libraries and tools. You can get help through APIs like https://osv.dev, which collects data on vulnerabilities and the versions where they are resolved, and also create automated processes that commit the fixed version like the Dependabot or jit.io auto-remediation feature.

2. Use SAST Tools

Vulnerabilities found in third-party libraries should not always receive the highest priority for remediation. In the Text4Shell example, if you do not use the 'createInterpolator()' function in the code, there really is no reason to prioritize the upgrade, as it isn't possible to practically exploit the vulnerability. (This Twitter thread by Simon Bennetts, creator of OWASP ZAP, can teach a lot about prioritizing real risk based on the Log4Shell example that still has many in a frenzy).

So — how can you know if this is being used anywhere in your code? By running SAST tools.Static analysis security test (SAST) tools, as their name suggests, statically scan your code with tools like Abstract Source Tree (AST) or other string scanning methods to find if there are any places in the code that are vulnerable to known issues. Updated versions of such tools will detect the vulnerable code and will alert you. Some of the tools will even offer a practical fix for the vulnerabilities, so you'll only need to replace the code with the patch they suggest.

You can find SAST tools that are specific to languages such as Bandit for Python and GoSec for Golang, but there are also cross-language tools such as SonarQube and SemGrep.

You can also define those tools to run as part of the automated CI/CD pipelines so that any relevant new issues will be caught in time to avoid their propagation to production.

3. Avoid Default Errors

The explosion in the number of RCE attacks previously mentioned is the byproduct of the existence of public-facing APIs that provide attackers an easy way to explore the public Internet for vulnerable servers. The typical method is to create automated scripts that scan for error responses that use default error messages and pages – making it easy to identify the underlying technology. (For example, the Apache Java 404 default page, the most commonly used Web server, even today remains a gold mine for would-be attackers.) By wrapping any of the errors returned to users with a custom error, you make it hard for attackers to identify what server technology you used, for example.

Besides serving as a best practice for code reviews and code styling, many of the SAST and lint tools also provide the added benefit of monitoring every HTTP request static tree and alert about any raw error that is returned to the end user.

4. Configure Everything as Code

By configuring everything as code, all configuration is protocoled, monitored, and managed in a reliable and searchable way that makes changes and rollbacks fast and quiet. Not only that, you can use automated tools such as KICS and Checkov to scan the configuration files for any vulnerable configurations before you even deploy it to a real environment. By running these tools you can verify critical configuration issues such as:

  • Overly privileged containers, to ensure the container can only run only the particular code it should and also verify the narrowest set of permissions (also called least privilege).

  • API configurations and access to endpoints, to ensure all requests are validated for any potential code injections.

  • Scanning code runners to ensure containers don't have egress call access to a white list of addresses.

Like other static analysis tools, those tools make it very easy to create automated CI/CD pipelines that ensure every configuration deployed is the safest one, that changes are monitored, and that the human error factor is minimized to as close to zero as possible.

5. Do Not Run Code on Native Machines and Use Least Privilege

The biggest damage *4Shell vulnerabilities can cause is when you run these processes as standard processes in a (virtual) machine. Running code in containers minimizes the damage to the current running environment and enables you to maintain a very narrow set of permissions and privileges for the container.

By monitoring containers to run only in needed processes, alongside limiting the users that run the applications to only the required permissions, you can ensure there will not be any impact on the sensitive areas attackers will want to infiltrate.

Running all your applications in containers and other standard cloud-native methods also helps define a centralized network and privilege configuration that wraps up all the running applications, avoiding any manual configurations that can easily go bad.

When your architecture scales, you can use tools such as Wiz, Orca, and other cloud-native security observability tools to ensure everything is properly defined in real time.

6. Employ Dynamic API Scanning

Using DAST tools like ZAP, you can find out which of your applications are really vulnerable to Text4Shell. This can be useful if you have a large number of applications that are vulnerable, making it possible to prioritize fixing them, or if you need access to the source code. The ZAP Text4Shell Scan Rule is currently in the optional Alpha Active Scan Rules add-on and requires an OAST service in order to work.

Faster Security == Dev Velocity

We can't expect exploits to disappear, and it shouldn't surprise us when new *4Shell or any other zero days appear. What we can do is have the right guardrails and controls in place, so that we can quickly discover and remediate these without wreaking too much havoc on our already bogged-down dev processes.

By taking action today, you essentially avoid being caught off guard tomorrow and disrupting engineering delivery. We're privileged to be in an age with excellent open source security tooling that integrates well with our CI/CD and stacks, and we should make an effort to employ them as often as possible. What's more, this doesn't even require domain expertise any longer; there are plenty of DevSecOps tools (and, as noted above, open source tools) that will do this for you, and even SaaS-based offerings for those who are willing to pay for it that will orchestrate this end to end. Don't leave your house open to strangers. Start with the easy stuff — lock the front door.

About the Author

Gabriel Manor - Liechtman

Technical Leader, Jit

Gabriel Manor - Liechtman is a full-stack software technical leader with a favorite kid named Security. For over 10 years, he has enjoyed writing clean code, simplifying complex problems, leading feature development, and influencing innovation daily.

When he's not busy with code, you'll find him talking about application performance, building confidence in code bases, product architecture, developing organizational culture, and other nerdy dev stuff.

Besides all that, he's a father of two, a hobbyist photographer, a Lego builder, and a food creator.

Keep up with the latest cybersecurity threats, newly discovered vulnerabilities, data breach information, and emerging trends. Delivered daily or weekly right to your email inbox.

You May Also Like


More Insights