JMX是Java Management Extensions,它是一个Java平台的管理和监控接口。
为什么要搞JMX呢?因为在所有的应用程序中,对运行中的程序进行监控都是非常重要的,Java应用程序也不例外。我们肯定希望知道Java应用程序当前的状态,例如,占用了多少内存,分配了多少内存,当前有多少活动线程,有多少休眠线程等等。如何获取这些信息呢?
为了标准化管理和监控,Java平台使用JMX作为管理和监控的标准接口,任何程序,只要按JMX规范访问这个接口,就可以获取所有管理与监控信息。
JMX把所有被管理的资源都称为MBean(Managed Bean),这些MBean全部由MBeanServer管理,如果要访问MBean,可以通过MBeanServer对外提供的访问接口,例如通过RMI或HTTP访问。
在生产环境中,需要对应用程序的状态进行监控。前面我们已经介绍了使用JMX对Java应用程序包括JVM进行监控,使用JMX需要把一些监控信息以MBean的形式暴露给JMX Server,而Spring Boot已经内置了一个监控功能,它叫Actuator。
非常简单,只需要在一个正常的Springboot项目的pom.xml里面添加如下依赖:
org.springframework.boot
spring-boot-starter-actuator
对于 Gradle,请使用以下声明:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
}
然后正常启动应用程序,Actuator会把它能收集到的所有信息都暴露给JMX。
此外,Actuator还可以通过URL/actuator/
挂载一些监控点,例如,输入http://localhost:8080/actuator/health
,我们可以查看应用程序当前状态
{
"status": "UP"
}
许多网关作为反向代理需要一个URL来探测后端集群应用是否存活,这个URL就可以提供给网关使用。
Actuator默认把所有访问点暴露给JMX,但处于安全原因,只有health
和info
会暴露给Web。
Actuator提供的所有访问点均在官方文档列出,要暴露更多的访问点给Web,需要在Springboot里面的application.yml中加上配置:
management:
endpoints:
jmx:
exposure:
# exclude: '*'
include: "*"
web:
exposure:
include: ["health","info","beans","mappings","logfile","metrics","shutdown","env"]
# include: "*"
gitee有个demo
Actuator各个端点介绍都在:
Actuator 接口文档:
Gateway配置:
https://blog.csdn.net/nlcexiyue/article/details/112345499
https://www.jb51.net/article/217600.htm
可以说两者几乎水火不容,如果从starter-web排除tomcat会导致项目跑不起来,如果从gateway里面排除starter-web会直接导致gateway功能不可用
直接mvn命令打包
org.springframework.boot:name=SpringApplication,type=Admin
原因:spring.application.admin.enabled=true是IDEA启动自己加上去的,java -jar运行的时候没有
在application.yml里面加上spring.application.admin.enabled=true
检查配置(用户密码之类的)是否正确,有种情况需要jar报错退出再跑一次jar(相当于连两次数据库)
利用场景和exp:https://github.com/LandGrey/SpringBootVulExploit
讲的十分详细了
其中MySQL JDBC deserialization的poc有点问题,解决方案如下:
https://github.com/0xJDow/rogue-mysql-server
Due to this error:
Traceback (most recent call last):
File "rogue-mysql-server.py", line 102, in
run_mysql_server()
File "rogue-mysql-server.py", line 63, in run_mysql_server
_payload_hex = str(hex(len(deserialization_payload)/2)).replace('0x', '').zfill(4)
TypeError: 'float' object cannot be interpreted as an integer
Updated these lines to use //
to do float division
_payload_hex = str(hex(len(deserialization_payload)//2)).replace('0x', '').zfill(4)
_data_hex = str(hex(len(deserialization_payload)//2 + 5)).
deserialization_payload
is raw bytes and needs to be decoded into a str
before we can concatenate. This is to fix this traceback.
Traceback (most recent call last):
File "rogue-mysql-server.py", line 102, in
run_mysql_server()
File "rogue-mysql-server.py", line 67, in run_mysql_server
_data += _data_length + '04' + '0131fc' + _payload_length + deserialization_payload
TypeError: can only concatenate str (not "bytes") to str
We change
_data += _data_length + '04' + '0131fc' + _payload_length + deserialization_payload
to
_data += _data_length + '04' + '0131fc' + _payload_length + deserialization_payload.decode()