• Web攻防--Java_SQL注入--XXE注入-- SSTI模板注入--SPEL表达式注入


    预编译

    编译器在编译sql语句时,会依次进行词法分析、语法分析、语义分析等操作,
    预编译技术会让数据库跳过编译阶段,也就无法就进行词法分析,关键字不会被拆开,注入语句也就不会被识别为SQL的关键字,从而防止恶意注入语句改变原有SQL语句本身逻辑。

    Java_JDBC注入

    在使用JDBC进行数据库操作时,有以下几种情况会产生SQL注入问题

    • 使用Statement方法单纯拼接SQL语句
      演示代码
    // 采用Statement方法拼接SQL语句,导致注入产生
    
    public String vul1(String id) {
    	
        Class.forName("com.mysql.cj.jdbc.Driver");//加载数据库驱动程序
        Connection conn = DriverManager.getConnection(db_url, db_user, db_pass);//建立数据库连接
    
        Statement stmt = conn.createStatement();//创建Statement对象用来执行sql语句
       
        String sql = "select * from users where id = '" + id + "'"; // 拼接语句产生SQL注入
        ResultSet rs = stmt.executeQuery(sql);//返回SQL语句执行结果
        ...
    }

    使用拼接方法进行SQL语句查询,预防SQL代码的方式可以采用黑名单过滤等方法

    • PrepareStatement错误使用预编译
      演示代码
    // PrepareStatement会对SQL语句进行预编译,但如果直接采取拼接的方式构造SQL,此时进行预编译也无用。
    
    public String vul2(String id) {
        Class.forName("com.mysql.cj.jdbc.Driver");//加载数据库驱动程序
        Connection conn = DriverManager.getConnection(db_url, db_user, db_pass);//建立数据库连接
        String sql = "select * from users where id = " + id;// 拼接语句产生SQL注入
        PreparedStatement st = conn.prepareStatement(sql);//创建预编译对象接受SQL语句
        ResultSet rs = st.executeQuery();//返回SQL语句执行结果
    }

    代码中虽然采用了预编译的方式进行SQL执行,但是依然在构造SQL语句时进行了拼接参数,这样无任何意义,依然可以进行拼接SQL注入
    正确使用预编译即可防止SQL注入

    // 正确的使用PrepareStatement可以有效避免SQL注入,使用?作为占位符,进行参数化查询
    
    public String safe1(String id) {
        String sql = "select * from users where id = ?";
        PreparedStatement st = conn.prepareStatement(sql);
        st.setString(1, id);
        ResultSet rs = st.executeQuery();
    }
    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注入攻击。

    Java_MyBatis注入

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

    在使用MyBatis进行SQL操作时,并不是所有SQL语句都可以进行预编译

    • order by注入
      错误代码
    // 由于使用#{}会将对象转成字符串,形成order by "user" desc造成错误,因此很多研发会采用${}来解决,从而造成SQL注入
    
    @GetMapping("/vul/order")
    public List orderBy(String field, String sort) {
        return userMapper.orderBy(field, sort);
    }
    
    // xml方式
    
    
    // 注解方式
    @Select("select * from users order by ${field} desc")
    List orderBy2(@Param("field") String field);
    • like模糊查询注入
      错误代码
    // 模糊搜索时,直接使用'%#{q}%' 会报错,部分研发图方便直接改成'%${q}%'从而造成注入
    
    @Select("select * from users where user like '%${q}%'")
    List search(String q);

    安全代码

    // 安全代码,采用concat
    @Select("select * from users where user like concat('%',#{q},'%')")
    List search(String q);
    

    关于MyBatis并不是所有语句都可以采用#{name}的方式,其实就是如果需要用数据库表的字段来替换的话就不能用参数绑定
    更多MyBatis防止SQL注入参考

    在进行代码审计时,由于MyBatisSQL错误语法的明显特征,可使用全局搜索特征关键字%${、${来查看是否存在注入,从而进一步分析。

    XXE注入

    在Java中的XXE注入与PHP中的XXE注入原理没有任何区别,只是在Java中所实现XML数据解析所用的方法不同,以下是在Java中常用于处理XML数据的相关接口、类、工具等
    XMLReader
    SAXReader
    DocumentBuilder
    XMLStreamReader
    SAXBuilder
    SAXParser
    SAXSource
    TransformerFactory
    SAXTransformerFactory
    SchemaFactory
    Unmarshaller
    XPathExpression
    相应的防护措施为禁用外部实体或者使用黑名单过滤,所使用处理XML数据的相关接口等不同,禁用外部实体的语句也不同。

    SSTI模板注入

    模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,利用模板引擎来生成前端的html代码,模板引擎会提供一套生成html代码的程序,然后只需要获取用户的数据,然后放到渲染函数里,然后生成模板+用户数据的前端html页面,然后反馈给浏览器,呈现在用户面前。

    当前使用的一些框架,比如python的flask,php的tp,java的spring等一般都采用成熟的的MVC的模式,用户的输入先进入Controller控制器,然后根据请求类型和请求的指令发送给对应Model业务模型进行业务逻辑判断,数据库存取,最后把结果返回给View视图层,经过模板渲染展示给用户。

    漏洞成因就是服务端接收了用户的恶意输入以后,未经任何处理就将其作为 Web 应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。其影响范围主要取决于模版引擎的复杂性。
    php常见的模板:twig,smarty,blade
    python常见的模板有:Jinja2,tornado
    java常见的引擎:FreeMarker, velocity
    具体参考SSTI(模板注入)漏洞(入门篇)

    SPEL表达式注入

    说白了就是RCE命令执行
    详情参考JAVA表达式注入漏洞

    以上内容仅作学习记录,如有错误或瑕疵,欢迎批评指正,感谢阅读。


    __EOF__

  • 本文作者: 了了青山见
  • 本文链接: https://www.cnblogs.com/Pengj/p/17692149.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    OpenCV图像处理学习十七,Canny边缘检测算法实现
    机器学习One-Hot编码
    【MySQL知识点】自动增长
    【C语言】入门——结构体
    测试工具链
    以太坊 CALL 数据解析【ETH】
    k8s学习-CKA真题-集群故障排查kubelet
    ASML大举向中国出口光刻机,或在于忧虑中国光刻机技术取得突破
    python系列笔记——可变数据类型和不可变数据类型常考知识点
    特性--反射
  • 原文地址:https://www.cnblogs.com/Pengj/p/17692149.html