博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jenkins任意文件读取漏洞复现与分析 -CVE-2018-1999002
阅读量:6456 次
发布时间:2019-06-23

本文共 5995 字,大约阅读时间需要 19 分钟。

jenkins任意文件读取漏洞复现与分析 -CVE-2018-1999002

0x00 漏洞影响版本

Jenkins weekly up to and including 2.132

Jenkins LTS up to and including 2.121.1

0x01 漏洞原理分析

在没有登陆(未授权,cookie清空)的情况下,只有当管理员开启了allow anonymous read access的时候,才能实现任意文件读取,否则仍需登陆。

jenkins任意文件读取漏洞复现与分析 -CVE-2018-1999002
以payload为例,请求的url为/plugin/credentials/.ini。而在hudson/Plugin.java:227

/**    * This method serves static resources in the plugin under hudson/plugin/SHORTNAME.**/public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {    String path = req.getRestOfPath();    String pathUC = path.toUpperCase(Locale.ENGLISH);    if (path.isEmpty() || path.contains("..") || path.startsWith(".") || path.contains("%") || pathUC.contains("META-INF") || pathUC.contains("WEB-INF")) {        LOGGER.warning("rejecting possibly malicious " + req.getRequestURIWithQueryString());        rsp.sendError(HttpServletResponse.SC_BAD_REQUEST);        return;    }    // Stapler routes requests like the "/static/.../foo/bar/zot" to be treated like "/foo/bar/zot"    // and this is used to serve long expiration header, by using Jenkins.VERSION_HASH as "..."    // to create unique URLs. Recognize that and set a long expiration header.    String requestPath = req.getRequestURI().substring(req.getContextPath().length());    boolean staticLink = requestPath.startsWith("/static/");    long expires = staticLink ? TimeUnit2.DAYS.toMillis(365) : -1;    // use serveLocalizedFile to support automatic locale selection    rsp.serveLocalizedFile(req, new URL(wrapper.baseResourceURL, '.' + path), expires);}

doDynamic函数用于处理类似/plugin/xx的请求,serveLocalizedFile在stapler-1.250-sources.jar!/org/kohsuke/stapler/ResponseImpl.java第209行左右:

public void serveLocalizedFile(StaplerRequest request, URL res, long expiration) throws ServletException, IOException {    if(!stapler.serveStaticResource(request, this, stapler.selectResourceByLocale(res,request.getLocale()), expiration))        sendError(SC_NOT_FOUND);}

先看最里面的request.getLocale(),然后再来分析stapler.selectResourceByLocale()。

跟入request.getLocale(),至jetty-server-9.2.15.v20160210-sources.jar!/org/eclipse/jetty/server/Request.java:692:

@Overridepublic Locale getLocale(){    ...    if (size > 0)    {        String language = (String)acceptLanguage.get(0);        language = HttpFields.valueParameters(language,null);        String country = "";        int dash = language.indexOf('-');        if (dash > -1)        {            country = language.substring(dash + 1).trim();            language = language.substring(0,dash).trim();        }        return new Locale(language,country);    }    return Locale.getDefault();}

这里用于处理HTTP请求中的Accept-Language头部。比如zh-cn,则会根据-的位置被分为两部分,language为zh,country为cn,然后返回Locale(language,country)对象。倘若不存在-,则country为空,language即对应我们的payload:../../../../../../../../../../../../windows/win,则此时返回一个Locale(language,"")

返回后即进入selectResourceByLocale(URL url, Locale locale),这里的locale参数即上一步返回的locale对象。

OpenConnection selectResourceByLocale(URL url, Locale locale) throws IOException {    // hopefully HotSpot would be able to inline all the virtual calls in here    return urlLocaleSelector.open(url.toString(),locale,url);}

urlLocaleSelector对象的声明见stapler-1.250-sources.jar!/org/kohsuke/stapler/Stapler.java:390:

private final LocaleDrivenResourceSelector urlLocaleSelector = new LocaleDrivenResourceSelector() {    @Override    URL map(String url) throws IOException {        return new URL(url);    }};

在stapler-1.250-sources.jar!/org/kohsuke/stapler/Stapler.java:324实现了LocaleDrivenResourceSelector类的open方法:

private abstract class LocaleDrivenResourceSelector {    /**        * The 'path' is divided into the base part and the extension, and the locale-specific        * suffix is inserted to the base portion. {@link #map(String)} is used to convert        * the combined path into {@link URL}, until we find one that works.        *        * 

* The syntax of the locale specific resource is the same as property file localization. * So Japanese resource for foo.html would be named foo_ja.html. * * @param path * path/URL-like string that represents the path of the base resource, * say "foo/bar/index.html" or "file:///a/b/c/d/efg.png" * @param locale * The preferred locale * @param fallback * The {@link URL} representation of the {@code path} parameter * Used as a fallback. */ OpenConnection open(String path, Locale locale, URL fallback) throws IOException { String s = path; int idx = s.lastIndexOf('.'); if(idx<0) // no file extension, so no locale switch available return openURL(fallback); String base = s.substring(0,idx); String ext = s.substring(idx); if(ext.indexOf('/')>=0) // the '.' we found was not an extension separator return openURL(fallback); OpenConnection con; // try locale specific resources first. con = openURL(map(base + '_' + locale.getLanguage() + '_' + locale.getCountry() + '_' + locale.getVariant() + ext)); if(con!=null) return con; con = openURL(map(base+'_'+ locale.getLanguage()+'_'+ locale.getCountry()+ext)); if(con!=null) return con; con = openURL(map(base+'_'+ locale.getLanguage()+ext)); if(con!=null) return con; // default return openURL(fallback); } /** * Maps the 'path' into {@link URL}. */ abstract URL map(String path) throws IOException;}

先看看开头的注释,这段代码本意是想根据对应的语言(Accept-Language)来返回不同的文件,比如在ja的条件下请求foo.html,则相当于去请求foo_ja.html,这个过程会先把foo.html分成两部分:文件名foo和扩展名.html,然后根据具体的语言/国家来组合成最终的文件名。

结合payload来看,我们请求的url为/plugin/credentials/.ini,则base为空,扩展名(ext变量)即为.ini,然后通过一系列的尝试openURL,在此例中即最后一个情形con = openURL(map(base+''+ locale.getLanguage()+ext));,会去请求../../../../../../../../../../../../windows/win.ini ,尽管目录_..并不存在,但在win下可以直接通过路径穿越来绕过。但在linux,则需要一个带有_的目录来想办法绕过。

0x02 限制

对windows系统: 没有限制

对linux系统: 目录中需要存在 '_'

参考链接:

转载于:https://blog.51cto.com/13770310/2156685

你可能感兴趣的文章
Mysql中文字符串提取datetime
查看>>
CentOS访问Windows共享文件夹的方法
查看>>
IOS 与ANDROID框架及应用开发模式对比一
查看>>
由中序遍历和后序遍历求前序遍历
查看>>
JQUERY Uploadify 3.1 C#使用案例
查看>>
coursera 北京大学 程序设计与算法 专项课程 完美覆盖
查看>>
firewall 端口转发
查看>>
wndows make images
查看>>
FS系统开发设计(思维导图)
查看>>
我学习参考的网址
查看>>
easyui的combotree以及tree,c#后台异步加载的详细介绍
查看>>
1、串(字符串)以及串的模式匹配算法
查看>>
[Processing]点到线段的最小距离
查看>>
考研随笔2
查看>>
ubuntu Linux 操作系统安装与配置
查看>>
操作系统os常识
查看>>
乱码的情况
查看>>
虚拟机centos 同一个tomcat、不同端口访问不同的项目
查看>>
在不花一分钱的情况下,如何验证你的创业想法是否可行?《转》
查看>>
Linux/Android 性能优化工具 perf
查看>>