pwncat
pwncat copied to clipboard
File read/write and prompt switch issues while using 'effective' user/group IDs
Bug Description
While trying to upload or download a file to which we have access through euid or egid, pwncat shows an access error.
pwncat version
$ pwncat --version
0.4.3
Target System (aka "victim")
Regular Kali Linux as a VM
Steps to Reproduce
Steps to reproduce the behavior:
- Prepare a SUID binary for
bashowned byroot - Get a session in
pwncatusing a normal user (non-root) - Use that SUID binary to elevate your privileges
- Upload a test file to
/root - See the error
Expected Behavior
pwncat should upload the test file without any access errors
Screenshots
Found during KoTH

Read issue

Write issue

NOTE: I had updated the
PROMPTSlist forzshanddefault, thus the prompt doesn't showrootas the user($(whoami))
Possible solution
Before performing upload or download, we need to refresh_uid()
In pwncat/platform/linux.py
491 class LinuxPath(pathlib.PurePosixPath):
...
494 def readable(self):
495 """Test if a file is readable"""
496
497 # refresh the uid, to pick up any changes
498 self._target.refresh_uid()
499
...
504 # get the stats for the current path
505 _stat = self.stat()
506
507 file_uid = _stat.st_uid
508 file_gid = _stat.st_gid
509 file_mode = _stat.st_mode
510
511 # check for uid, euid, gid, egid <<<<<
...
520 def writable(self):
521 """Test if the path is writable"""
522
523 # refresh the uid, to pick up any changes
524 self._target.refresh_uid()
...
530 # get the stats for the current path
531 _stat = self.stat()
...
Even if we use refresh_uid() under readable() and writable() methods, we have one issue.
The first Input is refresh_uid() call, and the second Input is the file write using gtfobins.json database and abilities.

We surely want to exploit stuff with pwncat - man sh

There is one minor issue with readlink and shell resolution
While I was testing my modifications with upload and download by checking euid and egid along with uid and gid,
SGID binary seems to be causing a permission error on the symlink when I use C-d to switch to pwncat local prompt
Using a SGID binary

Pressed C-d here, and received some errors

Cannot readlink current process when using SGID binary

Any suggestions, is there anything that I am doing or assuming incorrectly?
Again for shell resolution, there is another possible issue when the binary is removed

" (deleted)" is appended to exe's path
Here is Hack The Box - Knife machine
Invoking a reverse shell

pwncat listener

I am using
caleb/masterbranch
pwncat errors out, this is because of the unhandled OSError raised in readlink method
pwncat/platform/linux.py
1779 def readlink(self, path: str):
...
1788 except CalledProcessError as exc:
1789 raise OSError(f"Invalid argument: '{path}'") from exc <<< HERE
1597 def interactive(self, value: bool):
...
1613 try:
1614 # Get the PID of the running shell
1615 pid = self.getenv("$")
1616 # Grab the path to the executable representing the shell
1617 self.shell = self.Path("/proc", pid, "exe").readlink()
1618 except (FileNotFoundError, PermissionError):
1619 # Fall back to SHELL even though it's not really trustworthy
Caleb, I hope there are no issues if I am taking up space here, you can surely clear any redundant stuff :sweat_smile:
@calebstewart What do you think about this issue?
Using /bin/sh -c ... to run commands will drop privileges that were obtained by using a SUID / SGID binary
So if we had access (read / write) to something then that might be lost with /bin/sh -c ...
Given uid=1000 gid=1000 euid=0, the following would fail
/bin/sh -c "dd if=/root/.ssh/id_rsa"
Whereas this would work
dd if=/root/.ssh/id_rsa
In my PR #180, now closed, I replaced /bin/sh -c with /bin/sh -p -c and that caused issues elsewhere
For instance, it caused issues with /bin/sh -p -c "sudo ..." while using run enumerate
Should we add a check or extra commands to be tested while using enumerate and/or other modules?


I'm not sure what the best solution is here. There's fundamentally two problems detailed here:
euidpermissions are lost duringPopencalls due to/bin/sh -c- Processes with
euidset cannot read/proc/$$/exeregardless of using/bin/sh -c
Lost Permissions during Popen
I think this can be solved by simply not using /bin/sh -c. Looking at the code, I don't think this is strictly speaking needed. The shell argument to Popen is documented as using /bin/sh -c to execute the command, but that is already effectively how commands are executed by pwncat anyway. I think this is fine to remove and effectively ignore the shell argument to Popen. I tried this locally, and at the very least all tests pass. I'm going to do a little more testing and then push a branch.
Failure to read /proc/$$/exe
This is a trickier problem. I'm not sure why we are unable to read that file. Interestingly, my local machine (Arch Linux), this doesn't happen, but in a Ubuntu container it does.
In the short-term, I think that catching the OSError is the best course forward. If readlink() raises an exception, we can simply catch the OSError and fallback to the SHELL environment variable as was intended if that method fails. This doesn't fix the problem, but it at least ensures pwncat doesn't crash and lose your session. A sad side-effect of this is that in this situation, we lose the nice syntax highlighting as pwncat ends up falling back to assuming SHELL=/bin/sh in most cases. This isn't the end of the world, and is mostly cosmetic, though.
In the long term, I need to implement a module to correct euid != uid situations. Since this doesn't always work, the above needs to be implement to ensure pwncat functions in that situation, but the real fix is just replacing uid with euid so we have the full permissions of the target user.
Example of /proc/$$/exe fix:

Again, this is not ideal, but I think it's the best we can do until we fix the euid situation.
If you have some time to do some independent testing of the above pull request, I'd appreciate it. The tests pass, and some anecdotal testing seems positive, but I haven't thoroughly tested these changes yet.
Upload error in pwncat-cs what can i do anyone have solution?
