设为首页 收藏本站
查看: 1308|回复: 0

[经验分享] jenkins任意文件读取漏洞复现与分析 -CVE-2018-1999002

[复制链接]

尚未签到

发表于 2018-9-16 08:35:09 | 显示全部楼层 |阅读模式
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的时候,才能实现任意文件读取,否则仍需登陆。
DSC0000.jpg

  以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:
  

@Override  
public 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>/**  * 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>  if(idx=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://xz.aliyun.com/t/2486



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-584353-1-1.html 上篇帖子: jenkins 未授权访问-任意命令执行 下篇帖子: 跟我一起学docker(十)--jenkins的使用
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表