File: su.py

package info (click to toggle)
weevely 4.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,336 kB
  • sloc: python: 7,732; php: 1,035; sh: 53; makefile: 2
file content (118 lines) | stat: -rw-r--r-- 4,013 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import re

from core import messages
from core.loggers import log
from core.module import Module, Status
from core.vectors import ShellCmd, PythonCode


class Su(Module):
    """Execute commands with su."""

    aliases = ['ifconfig']

    def init(self):

        self.register_info(
            {
                'author': [
                    'Emilio Pinna'
                ],
                'license': 'GPLv3'
            }
        )

        self.register_vectors(
            [
                ShellCmd(
                    """expect -c 'spawn su -c "${command}" "${user}"; expect -re "assword"; send "${ passwd }\r\n"; expect eof;'""",
                    name="sh_expect",
                    postprocess=lambda x: re.findall('Password: (?:\r\n)?([\s\S]+)', x)[0] if 'Password: ' in x else ''
                ),
                PythonCode(
                    """
                    import pexpect as p,sys
                    c = p.spawn("su ${user} -c ${command}")
                    c.expect(".*assword:");c.sendline("${ passwd }")
                    i = c.expect([p.EOF,p.TIMEOUT])
                    if i!=p.TIMEOUT:
                        sys.stdout.write(c.before[3:].decode("utf-8","replace"))
                    """,
                    name="pyexpect")
            ]
        )

        self.register_arguments([
            {'name': 'passwd', 'help': 'User\'s password'},
            {'name': 'command', 'help': 'Shell command', 'nargs': '+'},
            {'name': '-user', 'help': 'User to run the command with', 'default': 'root'},
            {'name': '-stderr_redirection', 'default': ' 2>&1'},
            {'name': '-vector-sh',
             'choices': ('system', 'passthru', 'shell_exec', 'exec', 'popen', 'proc_open', 'perl_system', 'pcntl')},
            {'name': '-vector', 'choices': self.vectors.get_names()}
        ])

    def setup(self):
        """Probe all vectors to find a working su command.

        The method run_until is not used due to the check of shell_sh
        enabling for every tested vector.

        Args:
            self.args: The dictionary of arguments

        Returns:
            Status value, must be Status.RUN, Status.FAIL, or Status.IDLE.

        """

        args_check = {
            'user': self.args['user'],
            'passwd': self.args['passwd'],
            'command': 'whoami'
        }

        (vector_name,
         result) = self.vectors.find_first_result(
            names=[self.args.get('vector', '')],
            format_args=args_check,
            condition=lambda result: (
                # Stop if shell_sh is in FAIL state
                    self.session['shell_sh']['status'] == Status.FAIL or
                    # Or if the result is correct
                    self.session['shell_sh']['status'] == Status.RUN and result and result.rstrip() == self.args['user']
            )
        )

        if self.session['shell_sh']['status'] == Status.RUN and result and result.rstrip() == self.args['user']:
            self.session['shell_su']['stored_args']['vector'] = vector_name
            return Status.RUN
        else:
            log.warn(messages.module_shell_su.error_su_executing)
            return Status.IDLE

    def run(self, **kwargs):

        # Join the command list and

        # Escape the single quotes. This does not protect from \' but
        # avoid to break the query for an unscaped quote.

        self.args['command'] = ' '.join(self.args['command']).replace("'", "\\'")

        format_args = {
            'user': self.args['user'],
            'passwd': self.args['passwd'],
            'command': self.args['command']
        }

        if self.args.get('vector_sh'):
            format_args['vector'] = self.args['vector_sh']

        if self.args.get('stderr_redirection'):
            format_args['stderr_redirection'] = self.args['stderr_redirection']

        return self.vectors.get_result(
            name=self.args['vector'],
            format_args=format_args
        )