前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >代码审计-Java项目&JDBC&Mybatis&Hibernate&注入&预编译&写法

代码审计-Java项目&JDBC&Mybatis&Hibernate&注入&预编译&写法

作者头像
没事就要多学习
发布2024-07-18 15:39:58
690
发布2024-07-18 15:39:58
举报
文章被收录于专栏:Cyber Security

Javaweb-数据库操作-模式&写法&预编译等

环境搭建

VulDemo审计源码百度云 在Java中执行SQL语句一般有以下几种方式:

JDBC 注入分析

代码语言:javascript
复制
        String sql = "select * from user where id ="+req.getParameter("id");
        PrintWriter out = resp.getWriter();
        out.println("Statement Demo");
        out.println("SQL: "+sql);
        try {
            Statement st = conn.createStatement();
            ResultSet rs = st.executeQuery(sql);
            while (rs.next()){
                out.println("<br>Result: "+ rs.getObject("name"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

这里sql语句与请求参数进行了拼接(使用了JDBC API Statement执行sql语句的方法)

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
        PrintWriter out = resp.getWriter();
        out.println("prepareStatement Demo3");
        String sql = "select * from user where id = ?";
        out.println(sql);
        try {
            PreparedStatement pstt = conn.prepareStatement(sql);
            // 参数已经强制要求是整型
            pstt.setInt(1, Integer.parseInt(req.getParameter("id")));
            ResultSet rs = pstt.executeQuery();
            while (rs.next()){
                out.println("<br> id: "+rs.getObject("id"));
                out.println("<br> name: "+rs.getObject("name"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

PreparedStatement(也是JDBC API执行sql语句的方法)

在这里插入图片描述
在这里插入图片描述

Statement和PreparedStatement是Java JDBC API中两种常用的执行SQL语句的方式 Statement: Statement对象用于执行静态SQL语句,即在编译时已经确定了SQL语句的结构。 Statement执行SQL语句时,直接将完整的SQL语句发送给数据库执行。 Statement对象适用于执行不带参数的简单SQL查询或更新操作。 由于Statement对象没有预编译阶段,每次执行SQL语句时都需要将SQL语句编译一次,这可能导致一定的性能开销。 由于没有参数化输入的机制,使用Statement对象时需要谨慎处理输入数据,以防止SQL注入攻击。 PreparedStatement: PreparedStatement对象用于执行动态SQL语句,即在执行时才确定SQL语句的具体参数值。 PreparedStatement对象在创建时需要提供一个SQL模板,其中的参数使用占位符(例如,“?”)表示。 在执行PreparedStatement时,首先会对SQL语句进行编译和优化,然后只需提供参数值,而不需要重新编译SQL语句。 PreparedStatement适用于频繁执行带有参数的SQL语句,如参数化查询。 由于PreparedStatement具有预编译和参数化输入的特性,可以提高性能和安全性,并且能够防止SQL注入攻击。

安全写法(SQLDemo3): “select * from user where id = ?”; //参数化执行sql语句 不安全写法(SQLDemo): “select * from user where id =”+req.getParameter(“id”);

关于预编译

编译器在编译sql语句时,会依次进行词法分析、语法分析、语义分析等操作, 预编译技术会让数据库跳过编译阶段(sql语句已经编译好了),也就无法就进行词法分析,关键字不会被拆开,所有参数 直接 变成字符串 进入 数据库执行器执行。 参考:https://blog.csdn.net/qq_42521154/article/details/110785392

Mybatis 注入分析

代码语言:javascript
复制
<?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.demo.dao.UserDao">
    <select id="QueryByName" parameterType="String" resultType="com.demo.bean.User">

        select *  from user where name = ${name}
    </select>
    以下方式可以防御SQL注入
    <select id="QueryByName" parameterType="String" resultType="com.demo.bean.User">

        select *  from user where name = #{name}
    </select>
</mapper>

#号会点语句进行预编译 ${ } 只是进行string 替换,动态解析SQL的时候会进行变量替换

安全写法(): select * from user where name = #{name} 不安全写法(UserDao.xml):select * from user where name = ${name}

代码语言:javascript
复制
#{name}和${name}是MyBatis中两种常用的参数传递方式,具有不同的行为和特点
#{name}(参数占位符):
是一种安全的参数传递方式,会自动进行参数值的转义和处理,防止SQL注入攻击
使用#{name}时,MyBatis会将参数值作为预编译的参数,将其安全地插入到SQL语句中。
-----------------------------------------------------------------------------
${name}(文本替换):
${name} 是一种简单的文本替换方式,它会将 ${name} 直接替换为参数值,不进行参数值的转义或处理。
使用${name}时,参数值会被直接拼接到SQL语句中,存在SQL注入的风险。

Hibernate 注入分析

代码语言:javascript
复制
        PrintWriter out = resp.getWriter();
        out.println("Hibernate Demo");
        try {
            tx = session.beginTransaction();
            String parameter = req.getParameter("name");
//            List user = session.createQuery("FROM User where name='" + parameter + "'").getResultList();
            // from user where name = 'Yu or 1=1'
            Query query = session.createQuery("from com.demo.bean.User where name = ?1", User.class);

            query.setParameter(1, parameter);
            List user = query.getResultList();
            for (Iterator iterator =
                 user.iterator(); iterator.hasNext(); ) {
                User user1 = (User) iterator.next();
                out.println(user1.toString());
            }
            tx.commit();
        }catch (HibernateException e) {
            if (tx!=null) tx.rollback();
            e.printStackTrace();
        }finally {
            //session.close();
        }

安全写法():参数绑定预编译 Query.query=session.createNativeQuery(“select * from user where name=:name”); query.setParameter(“name”,parameter) ;

在这里插入图片描述
在这里插入图片描述

这里对’进行了转义;通过query.setParameter()方法将参数值设置到查询语句中,避免了直接拼接参数值到查询语句中的安全风险 不安全写法(User.java): Query.query=session.createNativeQuery(“select * from user where name=”+req.getParameter(“id”)); 这里同样也是拼接

总结:

1、预编译使用不当: sql=“select * from user where id = ?”; sql+=“and username =”+req.getParameter(“username”); 2、直接动态拼接: “select * from user where id =”+req.getParameter(“id”); 3、order by& like & in查询:(由于这两种不能预编译,所以需要过滤器或自定义过滤) 防御: 能预编译的情况都做预编译,一些特殊无法做预编译的,则过滤用户可控的参数。

Javaweb-代码审计SQL注入-INXEDU在线网校

思路:明确SQL三种模式->引用Mybatis->$()写法及XML文件->deleteArticleByIds->ArticleService.java->调用层次结构->deleteArticle->this.deleteArticle(aridArr) 路由:/admin/article/delete 参数:articelId

python sqlmap.py -r inxedu.txt

代码语言:javascript
复制
POST /admin/article/delete HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Cookie: BEEFHOOK=AOWdyRnbQnsrIpDhPuZf0a8oGzFzUKJrfRgGVHbRCB8cvznVuMjwWpmCPpPZuQyYjmiKPdtWLQJWbF80; _c_id=ascxsky7fw6uja985fn1635787683950vota; 3AB9D23F7A4B3C9B=YRQ5UHLXN2L3Z6RWJYHZNC3APNTMAJZNYXER2ILC6Z6TLFUDUAWZ4TLJA54Q37AMAKWGGT4LWNSNWYAUH6UJWZU74E; jSkQ_2132_ulastactivity=dcc8oerh%2F%2BcUSRVNiDd1%2B3wanKhoUM6O1jjHGfOa8wi1oDWf7zW5; jSkQ_2132_lastcheckfeed=1%7C1638707571; jSkQ_2132_nofavfid=1; JSESSIONID=12705DA8E13D05312443DE7F337F512F; inxedulogin_sys_user_=inxedulogin_sys_user_1
Host: 127.0.0.1:8080
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"

articelId=1*
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 环境搭建
  • JDBC 注入分析
    • 关于预编译
    • Mybatis 注入分析
    • Hibernate 注入分析
    • 总结:
    • Javaweb-代码审计SQL注入-INXEDU在线网校
    相关产品与服务
    代码审计
    代码审计(Code Audit,CA)提供通过自动化分析工具和人工审查的组合审计方式,对程序源代码逐条进行检查、分析,发现其中的错误信息、安全隐患和规范性缺陷问题,以及由这些问题引发的安全漏洞,提供代码修订措施和建议。支持脚本类语言源码以及有内存控制类源码。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档