调用这个,能复现tomcat的报错
http://localhost:8182/defaultroot/DownloadServlet?modeType=2&path=html&FileName=…\login.jsp&name=123&fiewviewdownload=2&cd=inline&downloadAll=2
springboot项目如何隐藏?
springboot内嵌了tomat,比如这个版本:tomcat-embed-core-8.5.96
找到这个tomcat-embed-core的源码,
将showReport=true,修改为showReport=false
将showServerInfo=true ,修改为showServerInfo=false
方法一:
在项目中增加ErrorReportValve.java ,实现覆盖内嵌中的类。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.apache.catalina.valves;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.ServletException;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.util.ErrorPageSupport;
import org.apache.catalina.util.IOTools;
import org.apache.catalina.util.ServerInfo;
import org.apache.coyote.ActionCode;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.descriptor.web.ErrorPage;
import org.apache.tomcat.util.res.StringManager;
import org.apache.tomcat.util.security.Escape;
/**
* 解决调试信息泄露漏洞,修改showReport=false,showServerInfo=false
*/
public class ErrorReportValve extends ValveBase {
private boolean showReport = false;
private boolean showServerInfo = false;
private final ErrorPageSupport errorPageSupport = new ErrorPageSupport();
public ErrorReportValve() {
super(true);
}
public void invoke(Request request, Response response) throws IOException, ServletException {
this.getNext().invoke(request, response);
if (response.isCommitted()) {
if (response.setErrorReported()) {
AtomicBoolean ioAllowed = new AtomicBoolean(true);
response.getCoyoteResponse().action(ActionCode.IS_IO_ALLOWED, ioAllowed);
if (ioAllowed.get()) {
try {
response.flushBuffer();
} catch (Throwable var5) {
ExceptionUtils.handleThrowable(var5);
}
response.getCoyoteResponse().action(ActionCode.CLOSE_NOW, request.getAttribute("javax.servlet.error.exception"));
}
}
} else {
Throwable throwable = (Throwable)request.getAttribute("javax.servlet.error.exception");
if (!request.isAsync() || request.isAsyncCompleting()) {
if (throwable != null && !response.isError()) {
response.reset();
response.sendError(500);
}
response.setSuspended(false);
try {
this.report(request, response, throwable);
} catch (Throwable var6) {
ExceptionUtils.handleThrowable(var6);
}
}
}
}
protected ErrorPage findErrorPage(int statusCode, Throwable throwable) {
ErrorPage errorPage = null;
if (throwable != null) {
errorPage = this.errorPageSupport.find(throwable);
}
if (errorPage == null) {
errorPage = this.errorPageSupport.find(statusCode);
}
if (errorPage == null) {
errorPage = this.errorPageSupport.find(0);
}
return errorPage;
}
protected void report(Request request, Response response, Throwable throwable) {
int statusCode = response.getStatus();
if (statusCode >= 400 && response.getContentWritten() <= 0L && response.setErrorReported()) {
AtomicBoolean result = new AtomicBoolean(false);
response.getCoyoteResponse().action(ActionCode.IS_IO_ALLOWED, result);
if (result.get()) {
ErrorPage errorPage = this.findErrorPage(statusCode, throwable);
if (errorPage == null || !this.sendErrorPage(errorPage.getLocation(), response)) {
String message = Escape.htmlElementContent(response.getMessage());
String reason;
if (message == null) {
if (throwable != null) {
reason = throwable.getMessage();
if (reason != null && reason.length() > 0) {
Scanner scanner = new Scanner(reason);
try {
message = Escape.htmlElementContent(scanner.nextLine());
} catch (Throwable var17) {
try {
scanner.close();
} catch (Throwable var15) {
var17.addSuppressed(var15);
}
throw var17;
}
scanner.close();
}
}
if (message == null) {
message = "";
}
}
reason = null;
String description = null;
StringManager smClient = StringManager.getManager("org.apache.catalina.valves", request.getLocales());
response.setLocale(smClient.getLocale());
try {
reason = smClient.getString("http." + statusCode + ".reason");
description = smClient.getString("http." + statusCode + ".desc");
} catch (Throwable var16) {
ExceptionUtils.handleThrowable(var16);
}
if (reason == null || description == null) {
if (message.isEmpty()) {
return;
}
reason = smClient.getString("errorReportValve.unknownReason");
description = smClient.getString("errorReportValve.noDescription");
}
StringBuilder sb = new StringBuilder();
sb.append("<!doctype html><html lang=\"");
sb.append(smClient.getLocale().getLanguage()).append("\">");
sb.append("<head>");
sb.append("<title>");
sb.append(smClient.getString("errorReportValve.statusHeader", new Object[]{String.valueOf(statusCode), reason}));
sb.append("</title>");
sb.append("<style type=\"text/css\">");
sb.append("body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}");
sb.append("</style>");
sb.append("</head><body>");
sb.append("<h1>");
sb.append(smClient.getString("errorReportValve.statusHeader", new Object[]{String.valueOf(statusCode), reason})).append("</h1>");
if (this.isShowReport()) {
sb.append("<hr class=\"line\" />");
sb.append("<p><b>");
sb.append(smClient.getString("errorReportValve.type"));
sb.append("</b> ");
if (throwable != null) {
sb.append(smClient.getString("errorReportValve.exceptionReport"));
} else {
sb.append(smClient.getString("errorReportValve.statusReport"));
}
sb.append("</p>");
if (!message.isEmpty()) {
sb.append("<p><b>");
sb.append(smClient.getString("errorReportValve.message"));
sb.append("</b> ");
sb.append(message).append("</p>");
}
sb.append("<p><b>");
sb.append(smClient.getString("errorReportValve.description"));
sb.append("</b> ");
sb.append(description);
sb.append("</p>");
if (throwable != null) {
String stackTrace = this.getPartialServletStackTrace(throwable);
sb.append("<p><b>");
sb.append(smClient.getString("errorReportValve.exception"));
sb.append("</b></p><pre>");
sb.append(Escape.htmlElementContent(stackTrace));
sb.append("</pre>");
int loops = 0;
for(Throwable rootCause = throwable.getCause(); rootCause != null && loops < 10; ++loops) {
stackTrace = this.getPartialServletStackTrace(rootCause);
sb.append("<p><b>");
sb.append(smClient.getString("errorReportValve.rootCause"));
sb.append("</b></p><pre>");
sb.append(Escape.htmlElementContent(stackTrace));
sb.append("</pre>");
rootCause = rootCause.getCause();
}
sb.append("<p><b>");
sb.append(smClient.getString("errorReportValve.note"));
sb.append("</b> ");
sb.append(smClient.getString("errorReportValve.rootCauseInLogs"));
sb.append("</p>");
}
sb.append("<hr class=\"line\" />");
}
if (this.isShowServerInfo()) {
sb.append("<h3>").append(ServerInfo.getServerInfo()).append("</h3>");
}
sb.append("</body></html>");
try {
try {
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
} catch (Throwable var18) {
ExceptionUtils.handleThrowable(var18);
if (this.container.getLogger().isDebugEnabled()) {
this.container.getLogger().debug("Failure to set the content-type of response", var18);
}
}
Writer writer = response.getReporter();
if (writer != null) {
writer.write(sb.toString());
response.finishResponse();
}
} catch (IllegalStateException | IOException var19) {
}
}
}
}
}
protected String getPartialServletStackTrace(Throwable t) {
StringBuilder trace = new StringBuilder();
trace.append(t.toString()).append(System.lineSeparator());
StackTraceElement[] elements = t.getStackTrace();
int pos = elements.length;
int i;
for(i = elements.length - 1; i >= 0; --i) {
if (elements[i].getClassName().startsWith("org.apache.catalina.core.ApplicationFilterChain") && elements[i].getMethodName().equals("internalDoFilter")) {
pos = i;
break;
}
}
for(i = 0; i < pos; ++i) {
if (!elements[i].getClassName().startsWith("org.apache.catalina.core.")) {
trace.append('\t').append(elements[i].toString()).append(System.lineSeparator());
}
}
return trace.toString();
}
private boolean sendErrorPage(String location, Response response) {
File file = new File(location);
if (!file.isAbsolute()) {
file = new File(this.getContainer().getCatalinaBase(), location);
}
if (file.isFile() && file.canRead()) {
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
try {
OutputStream os = response.getOutputStream();
InputStream is = new FileInputStream(file);
IOTools.flow(is, os);
return true;
} catch (IOException var6) {
this.getContainer().getLogger().warn(sm.getString("errorReportValve.errorPageIOException", new Object[]{location}), var6);
return false;
}
} else {
this.getContainer().getLogger().warn(sm.getString("errorReportValve.errorPageNotFound", new Object[]{location}));
return false;
}
}
public void setShowReport(boolean showReport) {
this.showReport = showReport;
}
public boolean isShowReport() {
return this.showReport;
}
public void setShowServerInfo(boolean showServerInfo) {
this.showServerInfo = showServerInfo;
}
public boolean isShowServerInfo() {
return this.showServerInfo;
}
public boolean setProperty(String name, String value) {
ErrorPage ep;
if (name.startsWith("errorCode.")) {
int code = Integer.parseInt(name.substring(10));
ep = new ErrorPage();
ep.setErrorCode(code);
ep.setLocation(value);
this.errorPageSupport.add(ep);
return true;
} else if (name.startsWith("exceptionType.")) {
String className = name.substring(14);
ep = new ErrorPage();
ep.setExceptionType(className);
ep.setLocation(value);
this.errorPageSupport.add(ep);
return true;
} else {
return false;
}
}
public String getProperty(String name) {
String result;
ErrorPage ep;
if (name.startsWith("errorCode.")) {
int code = Integer.parseInt(name.substring(10));
ep = this.errorPageSupport.find(code);
if (ep == null) {
result = null;
} else {
result = ep.getLocation();
}
} else if (name.startsWith("exceptionType.")) {
String className = name.substring(14);
ep = this.errorPageSupport.find(className);
if (ep == null) {
result = null;
} else {
result = ep.getLocation();
}
} else {
result = null;
}
return result;
}
}
方法二:
将修改好的.class文件替换tomcat-embed-core.jar的源码
重新编译,将生成的ErrorReportValve.class替换掉原始的tomcat-embed-core的jar包。
解决!
修复完成