turbomail无任何限制getshell

2014-05-19T00:00:00
ID SSV:95635
Type seebug
Reporter Root
Modified 2014-05-19T00:00:00

Description

简要描述:

turbomail 官方windows版本存在多个漏洞,综合利用,没有任何限制getshell

详细说明:

今天看到 WooYun: TurboMail邮箱系统默认配置不当可进入任意邮箱及获取管理员密码(官网也中招及大量实例) 看到此系统影响如此深远,因此自己也下载一个学习分析一下。 找到官方地址 下载: http://www.turbomail.org/download.html 我下载的是windows版本,安装之后 开始学习使用。 由于是邮件系统,因此首先需要用户输入口令才能登录,当然正常邮件服务器都是这样的,因此首先看一下 对用户的验证过程。 没有登录系统时,能够请求的页面是有限的,目前只能看到maintlogin.jsp

<img src="https://images.seebug.org/upload/201405/19190534d7e68d89313987e7bb53a75a2084f77f.png" alt="1.PNG" width="600" onerror="javascript:errimg(this);">

因此看一下登录页面maintlogin.jsp代码

<img src="https://images.seebug.org/upload/201405/19190603c92621c411a1c485198d830d22c5f92d.png" alt="2.PNG" width="600" onerror="javascript:errimg(this);">

发现数据是post到了mailmain?type=login请求。根据WEB-INF/web.xml的配置

<img src="https://images.seebug.org/upload/201405/191906341b5cb8f15f02c25caf6e221360642e01.png" alt="3.PNG" width="600" onerror="javascript:errimg(this);">

该serverlet对应的类是turbomail.web.MailMain,使用jad反编译代码,可以看到该类的完整代码。从web.xml可以看出系统没有使用统一的拦截器进行处理所有请求,因此猜测系统本身一旦考虑不周就会导致权限问题 由代码可以看出,该MailMain是全局控制类,当type是不同值时,就会调用不同的类和对应方法,对请求数据进行处理。并且看一下访问控制,发现使用session获得一个get方式传入的sessionid进行身份确认,当用户登录后会创建一个表示用户身份的sessionid,每次请求时,都会携带该数据表示用户已经登录 比如这样一个保存节点功能

<img src="https://images.seebug.org/upload/201405/19190855a9d84c178475cb13a847e41fe3e97b3f.png" alt="4.PNG" width="600" onerror="javascript:errimg(this);">

可以通过客户端进行请求,在该函数中首先调用WebUtil.getms对用户的登录状态进行校验

<img src="https://images.seebug.org/upload/201405/191909293f3e8c50ad0fb244b3cd156c00cdf8bd.png" alt="5.PNG" width="600" onerror="javascript:errimg(this);">

获取sessionid,判断是否已经存在,如果不存在则验证失败 看到这里,大概明白系统对用户权限的验证,主要是调用WebUtil.getms对用户权限验证,并且在web.xml没有编写全局的过滤器对权限进行统一检查,因此 猜测系统不会每个重要接口都对用户身份进行检查,肯定存在某个重要接口存在未授权访问漏洞。 但由于系统代码比较多,接口比较多,因此逐一接口进行人工查看 可能不太现实。因此考虑怎样写个小程序对代码进行过滤? 程序主要考虑问题: 怎样判断客户端可以访问呢?jsp里面由客户端可以访问的函数都会传入两个参数 request和response。因此只要一个函数的参数包含 request和response即可90%确定是可以由客户端访问的。 如果在这样的函数中前5行未找到WebUtil.getms代码,即认为是存在未授权访问。 这个过程由人工来看自然很精确,但是系统有太多的文件,如果一个一个来看,真的挺苦逼的,如果有个功能可以自动判断真的就省事多了。想想是否可以找到这样的功能呢?还没有看到过。(因为这个需求可能仅适合本系统) 因此,首先使用jad,将所有class进行反编译。获得原java文件。然后使用c#实现上述功能,开始初略过滤。 由于篇幅有限,就不贴完整代码:

<img src="https://images.seebug.org/upload/201405/19191359612094c19af45fa20b2b1f70f8e52533.jpg" alt=".JPG" width="600" onerror="javascript:errimg(this);">

初步获得一个结果列表

<img src="https://images.seebug.org/upload/201405/191914504780867ba2cb2d7625a0cfd5e56ae7fb.jpg" alt="1.JPG" width="600" onerror="javascript:errimg(this);">

仅一部分结果 剩下来,就是体力活了,需要一个一个看。 首先看turbomail类下面的,比如: c:\temp\turbomail\ajax\action\GetResource.java--15 对应代码如下

<img src="https://images.seebug.org/upload/201405/19191544758d4057d98ec86717864d66b019769a.png" alt="6.PNG" width="600" onerror="javascript:errimg(this);">

该函数实现确实没有调用权限判断函数,但是怎样请求到该函数呢?对代码有个大概分析就可以知道,其实大部分请求都是由turbomail\ajax\AjaxMain.java(ajax) 和\turbomail\web\MailMain.java 这两个类进行调用的,这两个应该是请求的入口,由该类的文件可以确定这个应该是通过ajax调用进来的。因此在turbomail\ajax\AjaxMain.java中,查找GetResource.service(静态方法,通过类名和函数名进行调用)

<img src="https://images.seebug.org/upload/201405/19191613e552a13abac054dbd13fe999ca98dd4e.png" alt="7.PNG" width="600" onerror="javascript:errimg(this);">

是请求第一个功能,在进一步分析未授权功能,即可知道构造的请求是 http://myturbomail.com:8080/mailmain?intertype=ajax&type=getresource&resource=login.password&lang=ENGLISH

<img src="https://images.seebug.org/upload/201405/1919163921bafab8b5ded83f701819d5702a3f73.png" alt="8.PNG" width="600" onerror="javascript:errimg(this);">

通过该功能即可获得resource配置信息,这个文件没有重要信息。 大概的分析过程就是这样,因此这里省略需要查找的过程,直接看一些稍微有价值的未授权访问。

<img src="https://images.seebug.org/upload/201405/191917119b7c15d2b5ce0d2d1b69b273b02a44cd.png" alt="9.PNG" width="600" onerror="javascript:errimg(this);">

<img src="https://images.seebug.org/upload/201405/19191734e4c6d08121d7900108baf65f5979092d.png" alt="10.PNG" width="600" onerror="javascript:errimg(this);">

看到这个未授权访问,真的是兴奋,任意文件读取。

<img src="https://images.seebug.org/upload/201405/1919184252d123b728f471bf4f102a965282c76d.png" alt="10-1..PNG" width="600" onerror="javascript:errimg(this);">

想读什么就读什么,真是... 当然我们的目的是为了,读取系统配置信息,因此就不能指定绝对路径了。该函数作者已经想到了,给了一个读取相对路径文件的方法,因此即使你不是该系统安装的绝对路径,也可以。看下面的请求,直接获得postmaster系统管理员的密码,默认是base64加密的。 http://myturbomail.com:8080/outImg?domain=..&imgLocation=..&imgName=../accounts/root/postmaster/account.xml

<img src="https://images.seebug.org/upload/201405/191919313b89f38970be429aaafb8562e26a1a75.png" alt="11.PNG" width="600" onerror="javascript:errimg(this);">

这个功能真的是太管用了。 意味着可以读取任意用户的密码,当前首选需要知道用户名称,当然内置的管理员用户postmaster等就成为了攻击目标。 接着看一下,

<img src="https://images.seebug.org/upload/201405/19192017ba6151f9d6b78f302613763324df8085.png" alt="12.PNG" width="600" onerror="javascript:errimg(this);">

<img src="https://images.seebug.org/upload/201405/1919203737986cc88a118ef85f98b6d08bce2502.png" alt="13.PNG" width="600" onerror="javascript:errimg(this);">

可以遍历所有用户名和域名 http://myturbomail.com:8080/mailmain?intertype=ajax&type=getAllUserList_simple

<img src="https://images.seebug.org/upload/201405/19192115a3567a6755841cf7bc2e2c6a31150ba9.png" alt="14.png" width="600" onerror="javascript:errimg(this);">

这个漏洞配合上一个漏洞,就可以读取任意用户的任意密码。即使内置账号被删除,被改名等等都可以。 在接着测试时,我发现了另一个不知道是后门 还是什么的东西

<img src="https://images.seebug.org/upload/201405/19192147e129a474b812a77f48e36c207fec7bd5.png" alt="15.PNG" width="600" onerror="javascript:errimg(this);">

这个是主控制文件,功能比较多,这里主要关心一下这个请求

<img src="https://images.seebug.org/upload/201405/19192219547f3a2ad0de041478e91e7bf5851414.png" alt="16.PNG" width="600" onerror="javascript:errimg(this);">

看一下文件,发现这个功能威力也很大

<img src="https://images.seebug.org/upload/201405/19192249fa80dd47437d0cbadc0f942cab213b82.png" alt="17.PNG" width="600" onerror="javascript:errimg(this);">

将所有用户的密码都设置为initPassword(即默认的82807217~!@) http://myturbomail.com:8080/mailmain?type=db2txt

<img src="https://images.seebug.org/upload/201405/19192347e891ae4246792218ec44b7f4d85b69e9.png" alt="17-1.PNG" width="600" onerror="javascript:errimg(this);">

所有密码都被设置成这个。不信你看

<img src="https://images.seebug.org/upload/201405/191924103562b40859aac029da5191164a7afec2.png" alt="18.PNG" width="600" onerror="javascript:errimg(this);">

是base64编码形式。 634行可以查看版本信息

<img src="https://images.seebug.org/upload/201405/19192434fed7d8416901dfd56c47cbfedf07c6dd.png" alt="19.PNG" width="600" onerror="javascript:errimg(this);">

漏洞证明:

从上面的简单过滤,可以看出,如果当没有任何权限的情况下。可以通过两种方式获得权限。 1.首先调用接口,查看版本 http://myturbomail.com:8080/mailmain?type=ver 如果返回是5.2.0则继续(因为其他版本没有进行测试) 2.1读取所有用户名 http://myturbomail.com:8080/mailmain?intertype=ajax&type=getAllUserList_simple 根据这个信息可以知道所有用户和对应的域信息 2.1.1 读取对应用户的配置文件,即获得密码   http://myturbomail.com:8080/outImg?domain=..&imgLocation=..&imgName=../accounts/test.com/123/account.xml   如读取123@test.com文件密码    2.2批量修改用户名密码 http://myturbomail.com:8080/mailmain?type=db2txt 当然这里只是从筛选的程序中确定,一些比较关注的未授权访问,其实还有一些跟系统业务相关功能的未授权这里就不一一列举,因为有些功能也不是特别清楚,怎样去触发的 其实可以获得系统的后台权限,就已经危害比较巨大,因为对于系统来说最主要的就是数据了。获得服务器权限本身也不是那么重要。但是为了本文的完整性,还是给出后台获得webshell的方法。(可能很多,这里就举个例子吧) 经过分析知,该系统安装了一个mysql数据库,数据库连接配置在C:\turbomail\conf\dbconf.xml中

<img src="https://images.seebug.org/upload/201405/19192623ed235abe43c0f867b49f3154d1393fd2.png" alt="20.PNG" width="600" onerror="javascript:errimg(this);">

连接数据库,查看信息发现,

<img src="https://images.seebug.org/upload/201405/19192709be47ec41632e10242d3ea016b6991d78.png" alt="21.PNG" width="600" onerror="javascript:errimg(this);">

只用root一个账号,并且不允许远程连接,因此风险还小点,可能只能本地提权(安装该系统的服务器,又安全了其它程序如iis,利用iis可以搞到一个低权限webshell,然后利用该mysql就可以提权,也是常规思路,当然这个不是这里主要讨论的问题)。 继续查看,默认安装时,有如下几个表:

<img src="https://images.seebug.org/upload/201405/19192746e684e75b1ae8b55f08266cccafb148cc.png" alt="22.PNG" width="600" onerror="javascript:errimg(this);">

由前面分析已经知道,最关心的口令信息,系统使用LDAP方式保存到文件里面的,因此数据库中没有,这几个表都是基本信息,理论上来说,即使是有注入对于数据来说,感觉危害不大(也许更关心业务的客户,认为还是有危害的).但是系统使用的mysql 最高权限连接,这样如果存在注入,就可以直接利用注入点,创建文件,即将注入转换为文件操作,这样危害就大了些。 根据这几个表名,很容易在界面上找到对应的功能,即对应数据库操作类文件。经过查找,发现当请求intertype=ajax&type=getBulletin时,在AjaxMain.java

<img src="https://images.seebug.org/upload/201405/19192831faad1bd44f8f5a79391152e093ff61de.png" alt="23.PNG" width="600" onerror="javascript:errimg(this);">

中会调用BullentinAjax.list

<img src="https://images.seebug.org/upload/201405/1919292524369ec1884c2280c4ab5effa994cb58.png" alt="24.PNG" width="600" onerror="javascript:errimg(this);">

最终会调用BulletinUtil.getBulletinlistByCondi

<img src="https://images.seebug.org/upload/201405/19193002c9486f9be26f1af70f0da1701d94a9e4.png" alt="25.PNG" width="600" onerror="javascript:errimg(this);">

该函数的实现没有使用参数化查询,导致sql注入。因为此处是select注入,满足要求可以创建文件。 注:进入后台可以看到站点绝对路径:

<img src="https://images.seebug.org/upload/201405/1919310142d24fd5ce7ef899a71d634e2fd8dc84.png" alt="26.PNG" width="600" onerror="javascript:errimg(this);">

利用sql注入,创建文件

<img src="https://images.seebug.org/upload/201405/19193206277b7d48779db4d5c210798b213810f6.png" alt="27.PNG" width="600" onerror="javascript:errimg(this);">

直接在站点根目录下,创建2.jsp文件 jsp小马

<img src="https://images.seebug.org/upload/201405/191932576f0929aaf344d4fb72a3a0da73ee97ef.png" alt="28.PNG" width="600" onerror="javascript:errimg(this);">

就写到这里了,其实后台问题等多的,就不一一列举了。