
Tivoli FastBack Server (6.1.4) is vulnerable to a stack-based buffer overflow allowing threat-actors to gain Arbitrary Code Execution (ACE) via a remote TCP-connection. The PoC provided in this repository leverages this vulnerability to establish a reverse-shell.
The Tivoli FastBack Server (6.1.4) application is vulnerable to a stack-based buffer overflow allowing threat-actors to gain Arbitrary Code Execution (ACE) via a remote TCP-connection. The PoC provided in this repository leverages this vulnerability to both execute CMD.exe on the target and handle the incoming connection to establish a reverse-shell.

[!NOTE] This PoC is based on a previously published PoC, and has been expanded with an ASLR bypass in addition to an improved architecture following common software-engineering paradigms. Since the recommended multi-file structure may not be desirable for all cases, a single-file version of the exploit is provided in
assets/single.py.
The PoC communicates with the vulnerable application through TCP-port 11460. Data transmitted to this port must follow the structure defined below:
0x00000123 0x00000000 0x00000000 0x00000000
0x00000ABC 0x00000AAA 0x00000111 0x00000BBB
0x00000222 0x00000CCC 0x00000333 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000
<buffer 1> ...
<buffer 2> ...
<buffer 3> ...
Using the aforementioned packet-structure, the PoC invokes the _FXCLI_SetConfFileChunk function identified by opcode 0x534. From here, the execution leads to a call to sscanf whose arguments are read from buffer (1) without proper sanitisation. By providing a block of exactly 0x118 bytes, the eip pointer is overwritten with whatever value resides in the last 4 bytes.
In order to bypass ASLR, the PoC invokes the FXCLI_DebugDispatch function by sending the aforementioned network-packet with the opcode 0x2000. This function reads the first buffer for a specific functionality, some of which are listed below:
DumpMemoryPoolsReadRepositorySectorsSymbolOperationThe PoC uses the SymbolOperation functionality, which inputs an arbitrary symbol and returns its base address. With this, the address of N98E_CRYPTO_get_new_lockid is resolved from which its offset (0x14E0) is subtracted. This ultimately results in the base address of libeay32IBM019.dll, which will be used extensively in the next bypass stage.
Before the ROP is constructed, the base is checked on potential bad-characters. If these are present, the vulnerable application is restarted by overflowing the buffer and overwriting eip with the non-sensical value of 0x90909090. Afterwards, the application is probed until it's back online restarting the cycle.
A ROP-chain is built where the base acquired from the previous bypass-stage is used. This ROP-chain invokes the WriteProcessMemory, and copies the contents of the "invite" to the code-cave of the .text section in libeay32IBM019.dll.
When the ROP-chain is constructed, all of its (resolved) contents are yet again checked for potential bad-characters. If these are present, the application is restarted in the same way as is done in the previous bypass stage, and the cycle starts again.
[!NOTE] To prevent an infinite loop during the bypass phase, the PoC has been configured to reattempt bypassing for at most 10 minutes. After this, the exploit will terminate as the timeout has been reached.
After the exploit mitigations have been bypassed, generic ACE is already achieved. This ACE is leveraged to execute specific shellcode which creates a process of CMD.exe with CreateProcessA. The arguments of this call are set to redirect all pipes (STDIN, STDOUT, STDERR) to a socket connection that is connected with the localhost.
Simultaneously, the PoC starts a listener on the localhost that catches the inbound request from the remote host and starts a very basic CLI-interface to interact with the created CMD.exe process.
graph
a("Start")
b("Buffer overflow: crash")
c("Buffer overflow: hijack")
subgraph sa["ASLR Bypass"]
a1["Resolve API with 'SymbolOperation'"]
a2["Subtract offset (0x14E0)"]
a3{"Base contains bad-chars?"}
a1 -->| N98E_CRYPTO_get_new_lockid | a2
a2 -->| libeay32IBM019.dll | a3
end
subgraph sb["DEP Bypass"]
b1["Construct ROP"]
b2{"ROP contains bad-chars?"}
b3["Locate shellcode"]
b4["Locate code-cave"]
b5["Invoke WriteProcessMemory"]
b6["Return to shellcode"]
b1 --> b2
b2 -->| no | b3
b3 --> b4
b4 --> b5
b5 --> b6
end
subgraph sc["Reverse Shell"]
c1["(Remote) connect to localhost"]
c2["(Local) listen on available port"]
c3["(Local) accept connection"]
c4["(Local) loop over CMDs"]
c1 --> c2
c2 --> c3
c3 --> c4
end
a3 -->| no | sb
b2 -->| yes | b
a3 -->| yes | b
a --> sa
b --> a
b6 --> c --> sc
| field | description | target |
|---|
123 | size | packet |
ABC | opcode | function |
AAA, 111 | offset, size | buffer (1) |
BBB, 222 | offset, size | buffer (2) |
CCC, 333 | offset, size | buffer (3) |