Struts2 S2-045 漏洞觸發流程不嚴謹推測
// 根據 已有的一些資訊和修復版本的程式碼,推測應該是如下的觸發流程
// 因為沒有測試環境,也只是不嚴謹的程式碼觸發流程推測,不保證正確性,歡迎大神交流分享。
//core\src\main\java\org\apache\struts2\dispatcher\multipart\JakartaMultiPartRequest.java
public void parse(HttpServletRequest request, String saveDir) throws IOException
{
try
{
setLocale(request);
processUpload(request, saveDir); // 呼叫 1
}
catch (FileUploadBase.SizeLimitExceededException e)
{
if (LOG.isWarnEnabled())
{
LOG.warn("Request exceeded size limit!", e);
}
String errorMessage = buildErrorMessage(e, new Object[] {e.getPermittedSize(), e.getActualSize()});
if (!errors.contains(errorMessage))
{
errors.add(errorMessage);
}
}
catch (Exception e) // 呼叫 7 捕獲異常
{
if (LOG.isWarnEnabled())
{
LOG.warn("Unable to parse request", e);
}
String errorMessage = buildErrorMessage(e, new Object[] {}); //呼叫 8
if (!errors.contains(errorMessage))
{
errors.add(errorMessage);
}
}
}
protected String buildErrorMessage(Throwable e, Object[] args)
{
String errorKey = "struts.messages.upload.error." + e.getClass().getSimpleName();
if (LOG.isDebugEnabled())
{
LOG.debug("Preparing error message for key: [#0]", errorKey);
}
return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, e.getMessage(), args);
// 呼叫9,觸發
// 因為 args 為空,使用預設的 e.getMessage() 為 "the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is" + content-type
// If a message is found, it will also be interpolated. Anything within ${...} will be treated as an OGNL expression and evaluated as such.
// 故執行了http 請求頭content-type 中的{}內部引入的指令
// reference:https://struts.apache.org/maven/struts2-core/apidocs/com/opensymphony/xwork2/util/LocalizedTextUtil.html#findText(java.lang.Class, java.lang.String, java.util.Locale, java.lang.String, java.lang.Object[])
}
protected void processUpload(HttpServletRequest request, String saveDir) throws FileUploadException, UnsupportedEncodingException
{
for (FileItem item : parseRequest(request, saveDir)) // 呼叫2,如下所示
{
if (LOG.isDebugEnabled())
{
LOG.debug("Found item " + item.getFieldName());
}
if (item.isFormField())
{
processNormalFormField(item, request.getCharacterEncoding());
}
else
{
processFileField(item);
}
}
}
protected List<FileItem> parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException
{
DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
ServletFileUpload upload = createServletFileUpload(fac);
return upload.parseRequest(createRequestContext(servletRequest)); // 呼叫 2.1
}
protected ServletFileUpload createServletFileUpload(DiskFileItemFactory fac)
{
ServletFileUpload upload = new ServletFileUpload(fac);
upload.setSizeMax(maxSize);
return upload;
}
// commons - fileupload - 1.2.1.jar org.apache.commons.fileupload.servlet ServletFileUpload.java
public class ServletFileUpload extends FileUpload
{
public static final boolean isMultipartContent(final HttpServletRequest request)
{
if (!"post".equals(request.getMethod().toLowerCase()))
{
return false;
}
final String contentType = request.getContentType();
return contentType != null && contentType.toLowerCase().startsWith("multipart/");
}
public ServletFileUpload()
{
}
public ServletFileUpload(final FileItemFactory fileItemFactory)
{
super(fileItemFactory);
}
public List parseRequest(final HttpServletRequest request) throws FileUploadException
{
return this.parseRequest(new ServletRequestContext(request)); // 呼叫 2.2
}
public FileItemIterator getItemIterator(final HttpServletRequest request) throws FileUploadException, IOException
{
return super.getItemIterator(new ServletRequestContext(request));
}
}
// commons - fileupload - 1.2.1.jar org.apache.commons.fileupload FileUploadBase.java
public List parseRequest(final RequestContext ctx) throws FileUploadException
{
try
{
final FileItemIterator iter = this.getItemIterator(ctx); // 呼叫 3
final List items = new ArrayList();
final FileItemFactory fac = this.getFileItemFactory();
if (fac == null)
{
throw new NullPointerException("No FileItemFactory has been set.");
}
while (iter.hasNext())
{
final FileItemStream item = iter.next();
final FileItem fileItem = fac.createItem(item.getFieldName(), item.getContentType(), item.isFormField(), item.getName());
try
{
Streams.copy(item.openStream(), fileItem.getOutputStream(), true);
}
catch (FileUploadIOException e)
{
throw (FileUploadException)e.getCause();
}
catch (IOException e2)
{
throw new IOFileUploadException("Processing of multipart/form-data request failed. " + e2.getMessage(), e2);
}
if (fileItem instanceof FileItemHeadersSupport)
{
final FileItemHeaders fih = item.getHeaders();
((FileItemHeadersSupport)fileItem).setHeaders(fih);
}
items.add(fileItem);
}
return items;
}
catch (FileUploadIOException e3)
{
throw (FileUploadException)e3.getCause();
}
catch (IOException e4)
{
throw new FileUploadException(e4.getMessage(), e4);
}
}
public FileItemIterator getItemIterator(final RequestContext ctx) throws FileUploadException, IOException
{
return new FileItemIteratorImpl(ctx); //呼叫 4
}
private class FileItemIteratorImpl implements FileItemIterator
{
private final MultipartStream multi;
private final MultipartStream.ProgressNotifier notifier;
private final byte[] boundary;
private FileItemStreamImpl currentItem;
private String currentFieldName;
private boolean skipPreamble;
private boolean itemValid;
private boolean eof;
private final /* synthetic */ FileUploadBase this$0;
// 建構函式呼叫 5
FileItemIteratorImpl(final RequestContext ctx) throws FileUploadException, IOException
{
if (ctx == null)
{
throw new NullPointerException("ctx parameter");
}
final String contentType = ctx.getContentType();
if (null == contentType || !contentType.toLowerCase().startsWith("multipart/"))
{
throw new InvalidContentTypeException("the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is " + contentType);
// 呼叫6,丟擲異常
}
InputStream input = ctx.getInputStream();
if (FileUploadBase.this.sizeMax >= 0L)
{
final int requestSize = ctx.getContentLength();
if (requestSize == -1)
{
input = new LimitedInputStream(input, FileUploadBase.this.sizeMax)
{
protected void raiseError(final long pSizeMax, final long pCount) throws IOException
{
final FileUploadException ex = new SizeLimitExceededException("the request was rejected because its size (" + pCount + ") exceeds the configured maximum" + " (" + pSizeMax + ")", pCount, pSizeMax);
throw new FileUploadIOException(ex);
}
};
}
else if (FileUploadBase.this.sizeMax >= 0L && requestSize > FileUploadBase.this.sizeMax)
{
throw new SizeLimitExceededException("the request was rejected because its size (" + requestSize + ") exceeds the configured maximum (" + FileUploadBase.this.sizeMax + ")", requestSize, FileUploadBase.this.sizeMax);
}
}
String charEncoding = FileUploadBase.this.headerEncoding;
if (charEncoding == null)
{
charEncoding = ctx.getCharacterEncoding();
}
this.boundary = FileUploadBase.this.getBoundary(contentType);
if (this.boundary == null)
{
throw new FileUploadException("the request was rejected because no multipart boundary was found");
}
this.notifier = new MultipartStream.ProgressNotifier(FileUploadBase.this.listener, ctx.getContentLength());
(this.multi = new MultipartStream(input, this.boundary, this.notifier)).setHeaderEncoding(charEncoding);
this.skipPreamble = true;
this.findNextItem();
}
//......
}
// commons - fileupload - 1.2.1.jar org.apache.commons.fileupload FileUploadException.java
public FileUploadException(final String msg, final Throwable cause)
{
super(msg);
this.cause = cause;
}
我的部落格即將同步至騰訊雲+社群,邀請大家一同入駐。
相關文章
- 「SAP技術」SAP不夠嚴謹?
- struts2 漏洞測試工具
- 書寫一個嚴謹的單例單例
- 理解力尚可,但嚴謹度欠缺……
- 測試流程必須嚴格執行嗎?
- Scala與Haskell的嚴謹優雅性比較Haskell
- struts2的工作流程
- Oracle vs PostgreSQL Develop(25) - plsql vs plpgsql(語法嚴謹性)OracleSQLdev
- 雙十一前不排隊!超值觸控AIO好推薦AI
- STRUTS2的getClassLoader漏洞利用
- 漏洞問題嚴重 谷歌、三星將每月為安卓手機推安全更新谷歌安卓
- 透過 Drone CLI 手動觸發 CI/CD 流程
- 從WS-AppServer中觸發BPM流程APPServer
- 深入分析Struts2工作流程
- 軟體測試需要嚴進嚴出
- 從5.56*45mm NATO彈看塔科夫的資料嚴謹性
- 思科IP電話存嚴重RCE漏洞!
- 谷歌稱macOS核心存在“嚴重”漏洞谷歌Mac
- Rails框架再爆嚴重安全漏洞AI框架
- “百度系”APP存嚴重漏洞?APP
- 計算機史上最嚴重漏洞被公開,風險等級嚴重計算機
- 不尋常的 1 月更新:NSA 首次向微軟報告 Windows 的嚴重安全漏洞微軟Windows
- 騰訊推無人機或觸發百億消費級市場無人機
- DNS漏洞不容小覷 謹防DDoS攻擊乘虛而入DNS
- PKAV 發現 Struts2 最新遠端命令執行漏洞(S2-037)
- Struts2遠端程式碼執行漏洞檢測的原理和程式碼級實現
- 網站查詢漏洞滲透測試大體流程介紹網站
- 雙擊事件(dblclick)時,不觸發單擊事件(click)事件
- 微信使用touchstart錄音,安卓觸發不靈敏安卓
- PLSQL方式更新LOB不會被觸發器捕獲SQL觸發器
- Struts2遠端程式碼執行漏洞預警
- 【3分鐘速覽】如何“嚴謹地”判斷兩個變數是否相同變數
- 【RAC】Oracle RAC12c+ srvctl操作命令變化(引數更嚴謹了)Oracle
- 嚴謹而浪漫!20個來自德國最優秀的網頁設計網頁
- 開發板觸控式螢幕測試
- struts2架構網站漏洞修復詳情與利用漏洞修復方案架構網站
- Oracle觸發器觸發級別Oracle觸發器
- $(document).click() 在iphone上不觸發事件解決辦法iPhone事件