| 1 | #!/usr/bin/python |
|---|
| 2 | # -*- coding: UTF-8 -*- |
|---|
| 3 | |
|---|
| 4 | """ |
|---|
| 5 | EvilEval - a PyLucid Plugin |
|---|
| 6 | |
|---|
| 7 | Created by Jens Diemer |
|---|
| 8 | license: GNU General Public License (GPL) |
|---|
| 9 | |
|---|
| 10 | - execute Python |
|---|
| 11 | - execute commands on the shell |
|---|
| 12 | |
|---|
| 13 | Inspired of code from the package: |
|---|
| 14 | colubrid.debug by Armin Ronacher, Benjamin Wiegand, Georg Brandl |
|---|
| 15 | """ |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | __version__ = "$Rev: 0 $" |
|---|
| 20 | |
|---|
| 21 | __ToDo__ = """ |
|---|
| 22 | """ |
|---|
| 23 | |
|---|
| 24 | |
|---|
| 25 | import os, sys, traceback, time |
|---|
| 26 | |
|---|
| 27 | select_function = """ |
|---|
| 28 | <ul> |
|---|
| 29 | <li> |
|---|
| 30 | <a href="%(python_url)s">execute Python code</a><br /> |
|---|
| 31 | with <em>Python v%(sysversion)s</em> |
|---|
| 32 | </li> |
|---|
| 33 | <li> |
|---|
| 34 | <a href="%(shell_url)s">execute shell commands</a><br /> |
|---|
| 35 | as <em title="Username">%(userinfo)s</em> on <em title="os uname">%(osuname)s</em> |
|---|
| 36 | </li> |
|---|
| 37 | </ul> |
|---|
| 38 | <h2>Note:</h2> |
|---|
| 39 | <ul> |
|---|
| 40 | <li>This is a potential safety hole!</li> |
|---|
| 41 | <li>For security reasons, you should deactivate that plugin, if you do not need it any longer!</li> |
|---|
| 42 | </ul> |
|---|
| 43 | """ |
|---|
| 44 | |
|---|
| 45 | python_input_form = """Execute code with Python v%(sysversion)s:<br /> |
|---|
| 46 | <form method="post" action="%(url)s"> |
|---|
| 47 | <textarea name="codeblock" rows="10" style="width: 95%%;">%(old_code)s</textarea> |
|---|
| 48 | <br /> |
|---|
| 49 | <label for="pylucid_access">access to pylucid objects:</label> |
|---|
| 50 | <input name="pylucid_access" value="1" type="checkbox" checked="checked"> |
|---|
| 51 | <br /> |
|---|
| 52 | <input value="execute" name="execute" type="submit"> |
|---|
| 53 | </form> |
|---|
| 54 | <p> |
|---|
| 55 | With access to pylucid objects you can use this objects:<br /> |
|---|
| 56 | <p>%(objectlist)s</p> |
|---|
| 57 | Use <em>help(object)</em> for more information ;) |
|---|
| 58 | </p> |
|---|
| 59 | """ |
|---|
| 60 | |
|---|
| 61 | shell_input_form = """Execute a command as <em title="Username">%(userinfo)s</em> on <em title="os uname">%(osuname)s</em><br /> |
|---|
| 62 | <form method="post" action="%(url)s"> |
|---|
| 63 | <label for="command">page name:</label> |
|---|
| 64 | <input name="command" value="" maxlength="255" type="text" style="width: 95%%;"> |
|---|
| 65 | <input value="execute" name="execute" type="submit"> |
|---|
| 66 | </form> |
|---|
| 67 | """ |
|---|
| 68 | |
|---|
| 69 | |
|---|
| 70 | from PyLucid.tools.out_buffer import Redirector |
|---|
| 71 | from PyLucid.system.BaseModule import PyLucidBaseModule |
|---|
| 72 | |
|---|
| 73 | |
|---|
| 74 | class EvilEval(PyLucidBaseModule): |
|---|
| 75 | |
|---|
| 76 | def lucidTag(self): |
|---|
| 77 | #~ self.response.debug() |
|---|
| 78 | try: |
|---|
| 79 | osuname = " ".join(os.uname()) |
|---|
| 80 | except AttributeError: |
|---|
| 81 | # Windows?!? |
|---|
| 82 | osuname = "" |
|---|
| 83 | context = { |
|---|
| 84 | "python_url": self.URLs.actionLink("python"), |
|---|
| 85 | "shell_url": self.URLs.actionLink("shell"), |
|---|
| 86 | "sysversion": sys.version, |
|---|
| 87 | "userinfo": self._userinfo(), |
|---|
| 88 | "osuname": osuname, |
|---|
| 89 | } |
|---|
| 90 | self.response.write(select_function % context) |
|---|
| 91 | |
|---|
| 92 | def _userinfo(self): |
|---|
| 93 | try: |
|---|
| 94 | return os.getlogin() |
|---|
| 95 | except Exception,e: |
|---|
| 96 | return "[os.getlogin error: %s]" % e |
|---|
| 97 | |
|---|
| 98 | #_________________________________________________________________________ |
|---|
| 99 | |
|---|
| 100 | def python(self): |
|---|
| 101 | """ Führt Python code aus """ |
|---|
| 102 | |
|---|
| 103 | if "codeblock" in self.request.form: |
|---|
| 104 | # abgeschickter code ausführen |
|---|
| 105 | old_code = self.exec_python() |
|---|
| 106 | else: |
|---|
| 107 | old_code = ( |
|---|
| 108 | "for i in xrange(5):\n" |
|---|
| 109 | " print 'This is cool', i" |
|---|
| 110 | ) |
|---|
| 111 | |
|---|
| 112 | objectlist = self._get_objectlist() |
|---|
| 113 | |
|---|
| 114 | context = { |
|---|
| 115 | "url": self.URLs.actionLink("python"), |
|---|
| 116 | "sysversion": sys.version, |
|---|
| 117 | "old_code": old_code, |
|---|
| 118 | "objectlist": ", ".join(objectlist), |
|---|
| 119 | } |
|---|
| 120 | self.response.write(python_input_form % context) |
|---|
| 121 | |
|---|
| 122 | def exec_python(self): |
|---|
| 123 | try: |
|---|
| 124 | codeblock = self.request.form["codeblock"] |
|---|
| 125 | except KeyError: |
|---|
| 126 | # Noch kein code abgeschickt |
|---|
| 127 | return "" |
|---|
| 128 | |
|---|
| 129 | codeblock = codeblock.replace("\r\n", "\n") # Windows |
|---|
| 130 | |
|---|
| 131 | self.exec_code(codeblock) |
|---|
| 132 | |
|---|
| 133 | #~ self.page_msg(codelines) |
|---|
| 134 | return codeblock |
|---|
| 135 | |
|---|
| 136 | def exec_code(self, sourcecode): |
|---|
| 137 | |
|---|
| 138 | start_time = time.time() |
|---|
| 139 | |
|---|
| 140 | stdout_redirector = Redirector(self.page_msg) |
|---|
| 141 | globals = {} |
|---|
| 142 | locals = {} |
|---|
| 143 | |
|---|
| 144 | try: |
|---|
| 145 | code = compile(sourcecode, "<stdin>", "exec", 0, 1) |
|---|
| 146 | if "pylucid_access" in self.request.form: |
|---|
| 147 | exec code |
|---|
| 148 | else: |
|---|
| 149 | exec code in globals, locals |
|---|
| 150 | except: |
|---|
| 151 | etype, value, tb = sys.exc_info() |
|---|
| 152 | tb = tb.tb_next |
|---|
| 153 | msg = ''.join(traceback.format_exception(etype, value, tb)) |
|---|
| 154 | sys.stdout.write(msg) |
|---|
| 155 | |
|---|
| 156 | output = stdout_redirector.get() |
|---|
| 157 | |
|---|
| 158 | duration = time.time() - start_time |
|---|
| 159 | |
|---|
| 160 | self.response.write( |
|---|
| 161 | "<fieldset><legend>executed in %.3fsec.:</legend>" % duration |
|---|
| 162 | ) |
|---|
| 163 | self.response.write("<pre>") |
|---|
| 164 | self.response.write(output) |
|---|
| 165 | self.response.write("</pre></fieldset>") |
|---|
| 166 | |
|---|
| 167 | def _get_objectlist(self): |
|---|
| 168 | objectlist = [] |
|---|
| 169 | for obj in dir(self): |
|---|
| 170 | if obj.startswith("_"): |
|---|
| 171 | continue |
|---|
| 172 | objectlist.append("self.%s" % obj) |
|---|
| 173 | return objectlist |
|---|
| 174 | |
|---|
| 175 | #_________________________________________________________________________ |
|---|
| 176 | |
|---|
| 177 | def shell(self): |
|---|
| 178 | """ Führt einen Befehl auf der shell aus """ |
|---|
| 179 | |
|---|
| 180 | if "command" in self.request.form: |
|---|
| 181 | # abgeschickter Befehl ausführen |
|---|
| 182 | self.run_command() |
|---|
| 183 | |
|---|
| 184 | try: |
|---|
| 185 | userinfo = os.getlogin() |
|---|
| 186 | osuname = " ".join(os.uname()) |
|---|
| 187 | except AttributeError: |
|---|
| 188 | # Windows?!?! |
|---|
| 189 | userinfo = "" |
|---|
| 190 | osuname = "[Windows ?]" |
|---|
| 191 | |
|---|
| 192 | context = { |
|---|
| 193 | "url": self.URLs.actionLink("shell"), |
|---|
| 194 | "userinfo": userinfo, |
|---|
| 195 | "osuname": osuname, |
|---|
| 196 | } |
|---|
| 197 | self.response.write(shell_input_form % context) |
|---|
| 198 | |
|---|
| 199 | def run_command(self): |
|---|
| 200 | |
|---|
| 201 | command = self.request.form["command"] |
|---|
| 202 | |
|---|
| 203 | start_time = time.time() |
|---|
| 204 | |
|---|
| 205 | timeout = 5 |
|---|
| 206 | process = self.tools.subprocess2(command, ".", timeout) |
|---|
| 207 | |
|---|
| 208 | output = process.out_data |
|---|
| 209 | |
|---|
| 210 | duration = time.time() - start_time |
|---|
| 211 | |
|---|
| 212 | self.response.write( |
|---|
| 213 | "<fieldset><legend>executed in %.3fsec.:</legend>" % duration |
|---|
| 214 | ) |
|---|
| 215 | self.response.write("<pre>") |
|---|
| 216 | self.response.write(output) |
|---|
| 217 | self.response.write("</pre></fieldset>") |
|---|
| 218 | |
|---|
| 219 | if process.killed == True: |
|---|
| 220 | self.page_msg( |
|---|
| 221 | result, process.returncode, |
|---|
| 222 | "Error: subprocess timeout (%.2fsec.>%ssec.)" % ( |
|---|
| 223 | time.time()-start_time, timeout |
|---|
| 224 | ) |
|---|
| 225 | ) |
|---|
| 226 | |
|---|
| 227 | if process.returncode != 0 and process.returncode != None: |
|---|
| 228 | self.page_msg(result, process.returncode, "subprocess Error!") |
|---|