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

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

缺陷编号:wooyun-2014-048041

漏洞标题:Pconline某后台源码泄露之后续代码执行

相关厂商:太平洋电脑网

漏洞作者: Mr .LZH

提交时间:2014-01-06 16:32

修复时间:2014-02-20 16:33

公开时间:2014-02-20 16:33

漏洞类型:命令执行

危害等级:高

自评Rank:15

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-01-06: 细节已通知厂商并且等待厂商处理中
2014-01-06: 厂商已经确认,细节仅向厂商公开
2014-01-16: 细节向核心白帽子及相关领域专家公开
2014-01-26: 细节向普通白帽子公开
2014-02-05: 细节向实习白帽子公开
2014-02-20: 细节向公众公开

简要描述:

Pconline某后台环境配置问题导致部分源码及隐私信息泄露
通过上次的漏洞获得源码,一时没有时间继续挖掘就发布漏洞,昨晚无聊拿源码继续挖,发现了问题。

详细说明:

一 http://pdscore.pconline.com.cn/util/cvs.jsp页面
该页面没有任何权限检查,由command关键词传参,调用Runtime.getRuntime().exec()执行命令。源码如下:

<%@page contentType="text/html; charset=GBK" import="java.io.*" %><%
response.setHeader("Expires", "0");
String path = getServletContext().getRealPath("/");
String cmd = request.getParameter("command");
if(cmd == null) cmd = "up";
Process p = Runtime.getRuntime().exec("cvs -q "+cmd,null,new File(path));
BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stderr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
boolean err = false;
out.println("CVS updating at "+new java.sql.Timestamp(System.currentTimeMillis())+"<pre>");
while(true) {
if(!stdout.ready() && !stderr.ready()) {
try {
p.exitValue(); //test if Ant process terminated
break;
} catch(IllegalThreadStateException ex) { //not terminated
Thread.sleep(100);
continue;
}
}
if(stderr.ready()) err = true;
boolean fromOut = stdout.ready();
String s = fromOut ? stdout.readLine() : stderr.readLine();
if(s == null) break;
System.out.println(s);
out.println(s.replaceAll("<","&lt;"));
out.flush();
}
stdout.close();
stderr.close();
%>


附上之前获取到的cvs连接信息 :pserver:[email protected]:/usr/cvs/pconline
二 http://pdscore.pconline.com.cn/util/exception/javax.jdo.JDOException.jsp页面
该页面也没有任何权限检查,通过检查参数,最后调用Runtime.getRuntime().exec()执行命令。参数由用户传过去,只做简单判断,源码如下:

<%@page contentType="text/html; charset=GBK" %>
<%@page isErrorPage="true" import="java.io.*,java.util.*" %>
<% if(request.getAttribute("exception") != null) exception = (Throwable) request.getAttribute("exception"); %>
<%
String msg = exception == null ? "" : exception.getMessage();
boolean needEnhance = request.getParameter("enhance") != null
|| msg.startsWith("One or more classes in the JDO meta data have not been enhanced:");
boolean needMigrate = request.getParameter("migrate") != null
|| msg.startsWith("javax.jdo.JDOFatalDataStoreException: Mapping error ") //启动时数据库检查失败
|| msg.startsWith("java.sql.SQLException: ORA-00942: ") //表丢失
|| msg.startsWith("Query failed: java.sql.SQLException: ORA-00904: ") //表字段丢失
|| msg.startsWith("java.sql.SQLException: ORA-00904: "); //表字段丢失
if(!needEnhance && !needMigrate) if(exception == null) return; else throw exception;
if(needMigrate || needEnhance && exception == null)
try { //非异常调用时(直接访问本页),检查管理员权限
pageContext.include("/sys-adm.jsp");
if(request.getAttribute("needLogin") != null) return;
} catch(IOException ex) {} //无“/sys-adm.jsp”则不检查权限
if(exception != null && application.getAttribute("__UPDATING__") != null) {
out.println("服务器正在更新,请稍候,10秒钟本页面会自动刷新。<meta http-equiv='refresh' content='10'>");
return;
}
application.setAttribute("__UPDATING__","");
if(exception != null) out.println("<font color=red><pre>"+exception+"</pre></font><p>");
out.println("Sorry, the server was updated recently, please wait a while for re-enhancement...<pre>");
out.println(new char[255]); out.flush();
//执行Ant脚本完成增强或数据结构同步:
boolean isWindows = System.getProperty("os.name").startsWith("Windows");
String ant = isWindows ? "ant.bat" : "ant";
String quot = isWindows ? "\"" : "";
Process p = null;
try {
ant += " -f "+quot+getServletContext().getRealPath("/WEB-INF/build.xml")+quot;
if(needEnhance) ant += " enhance";
if(needMigrate) {
String db = request.getParameter("db");
ant += " migrate"
+" -Ddirect="+(request.getParameter("direct") != null)
+(db == null ? "" : " -Ddb="+db)
+" -DcheckExtraColumns="+(request.getParameter("allowdrop") != null);
}
p = Runtime.getRuntime().exec(ant);
} catch(Exception ex) {
application.removeAttribute("__UPDATING__");
ex.printStackTrace(new PrintWriter(out));
return;
}
BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stderr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
boolean err = false;
while(true) {
if(!stdout.ready() && !stderr.ready()) {
try {
p.exitValue(); //test if Ant process terminated
break;
} catch(IllegalThreadStateException ex) { //not terminated
Thread.sleep(100);
continue;
}
}
if(stderr.ready()) err = true;
boolean fromOut = stdout.ready();
String s = fromOut ? stdout.readLine() : stderr.readLine();
if(s == null) break;
System.out.println(s);
out.println(s.replaceAll("<(?!/?font)","&lt;"));
out.flush();
}
stdout.close();
stderr.close();
application.removeAttribute("__UPDATING__");
if(err) {
out.println("!!!!!! Ant build failed. Please contact webmaster...");
return;
}
if(exception == null) return;
if(needEnhance) {
out.println("</pre>Now restarting... <meta http-equiv='refresh' content='0'>");
} else if(needMigrate) {
out.println("</pre>After synchronizing the DB schema, you can reload the page then...");
}
%>


此页面虽然是山路十八弯,但只要构造好参数,最终还是可以到达Runtime.getRuntime().exec()执行命令的。

漏洞证明:

个人对代码执行不是很熟悉,证明的话麻烦主页君给贴上吧。

修复方案:

给页面加上权限验证。其他页面虽然有些没加上验证,但影响不大,这两个页面影响较大,故反馈上来。
代码审计到此,没找到其他bug,已将源码删除。
接下来要考试了,祝我不挂科吧。(*^__^*) 嘻嘻

版权声明:转载请注明来源 Mr .LZH@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2014-01-06 18:13

厂商回复:

非常感激“Mr .LZH”提供的漏洞信息,我们已经在安排修复该漏洞了。
对“Mr .LZH”大大专业的“挖洞”精神非常的敬佩,有大大们的支持我们相信会做的更好更完善,为用户提供更优质的服务~
帅气滴“Mr .LZH”,礼物已安排投递。
感谢你对 太平洋系列网站 信息安全作出的贡献。
预祝学业进步!(*^__^*)

最新状态:

暂无