API安全(二)-SQL注入与防范

1、什么是注入攻击

  使用了用户输入的但是我们没有校验过的数据,来拼装一个可以行的指令,交给系统去执行,结果导致执行了我们不希望发生的命令。注入攻击用很多种,最常见的是SQL注入。

2、SQL注入攻击

  Java程序员知道,使用Statement进行查询时会造成SQL注入攻击,从而使用PreparedStatement来进行SQL预编译,从而有效的防止SQL注入攻击。但是日常开发中,我们一般多使用框架来进行数据库操作,如JdbcTemplate、Spring-Data-Jpa、Mybatis等,但是使用起来,我们也要注意,避免写出可注入程序。

3、JdbcTemplate注入代码示例

  3.1、UserDO实体类与UserDTO

/**
 * @author caofanqi
 * @date 2020/1/20 13:08
 */
@Data
@Entity
@Table(name = "user")
public class UserDO {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    public UserDTO buildUserDTO(){
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(this,userDTO);
        return userDTO;
    }

}

/**
 * @author caofanqi
 * @date 2020/1/20 13:08
 */
@Data
public class UserDTO {

    private Long id;

    private String name;

}

  3.2、UserController,提供一个根据用户名称进行查询用户的API接口

/**
 * 用户控制层
 *
 * @author caofanqi
 * @date 2020/1/20 13:05
 */
@RestController
@RequestMapping("/users")
public class UserController {

    @Resource
    private UserService userService;

    @GetMapping
    public List<UserDTO> query(String name) {
        return userService.query(name);
    }

}

  3.3、UserService实现类,使用JdbcTemplate进行条件拼接查询,会产生SQL注入问题

/**
 * 用户业务层实现类
 *
 * @author caofanqi
 * @date 2020/1/20 13:52
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Override
    public List<UserDTO> query(String name) {

        String sql = "SELECT * FROM user WHERE name = ‘" + name + "‘";
        log.info("执行的SQL为:{}",sql);
        List<UserDO> queryResult = jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(UserDO.class));

        List<UserDTO> result = queryResult.stream().map(UserDO::buildUserDTO).collect(Collectors.toList());

        return result;
    }

}

  3.4、启动项目,向数据库中插入3条数据,如下:

  

  3.5、访问http://127.0.0.1:9090/users?name=zhangsan 可以正常查询到结果

  

  3.6、但是执行http://127.0.0.1:9090/users?name=‘ or ‘1‘=‘1 时,就会把数据库中所有的用户都查询出来,这样就会导致信息泄漏。

  

  控制台打印日志如下

2020-01-20 21:48:07.263  INFO 18540 --- [nio-9090-exec-3] c.c.s.service.impl.UserServiceImpl       : 执行的SQL为:SELECT * FROM user WHERE name = ‘‘ or ‘1‘=‘1‘

  往下追溯源码可以发现,该query方法,底层使用的是Statement

  

  3.7、解决这个问题,我们修改query代码如下,使用了预编译SQL。

    @Override
    public List<UserDTO> query(String name) {

        String sql = "SELECT * FROM user WHERE name = ? ";
        List<UserDO> queryResult = jdbcTemplate.query(sql, new Object[]{name}, BeanPropertyRowMapper.newInstance(UserDO.class));
        List<UserDTO> result = queryResult.stream().map(UserDO::buildUserDTO).collect(Collectors.toList());

        return result;
    }

  3.8、http://127.0.0.1:9090/users?name=‘ or ‘1‘=‘1 时,查询不到结果,预防了SQL注入攻击

  

  往下追溯源码可以发现,该query方法,底层使用的是PreparedStatement

  

4、EntityManager注入代码示例

  在使用JPA的EntityManager执行拼接SQL时,将参数拼接到SQL中,一样会有SQL注入问题

@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public List<UserDTO> query(String name) {

        String sql = "SELECT * FROM user WHERE name = ‘" + name + "‘";

        Query nativeQuery = entityManager.createNativeQuery(sql, UserDO.class);
        List<UserDO> queryResult = nativeQuery.getResultList();

        List<UserDTO> result = queryResult.stream().map(UserDO::buildUserDTO).collect(Collectors.toList());

        return result;
    }

}

  需要修改成如下:

        String sql = "SELECT * FROM user WHERE name = ? ";
        Query nativeQuery = entityManager.createNativeQuery(sql, UserDO.class);
        nativeQuery.setParameter(1, name);
        List<UserDO> queryResult = nativeQuery.getResultList();

5、如何防止SQL注入

  上面的情况只是针对与查询,多查出来数据,更危险的攻击可能会修改或删除数据,甚至调用存储过程,删表等。我们如何防止SQL注入呢?

  5.1、控制数据库用户权限(对分配给应用程序的用户权限进行限定,一般只有对数据的CRUD权限)

  5.2、对传入的参数进行校验

  5.3、使用一些高级的框架进行数据库操作,对于一些复杂的情况,需要进行SQL拼接时,不要将参数拼接到SQL中,要使用预编译SQL。

项目源码:https://github.com/caofanqi/study-security/tree/dev-SQL-injection

原文地址:https://www.cnblogs.com/caofanqi/p/12219669.html

时间: 2024-08-29 11:50:56

API安全(二)-SQL注入与防范的相关文章

SQL注入与防范

SQL注入简介: 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句. SQL注入方法: 一.拼接字符串(通过输入框输入SQL语句使其改变原意) Select * from T_User where UserID

目前日向博客对xss跨站脚本注入和sql注入的防范

昨天本博客受到了xss跨站脚本注入攻击,3分钟攻陷--其实攻击者进攻的手法很简单,没啥技术含量.只能感叹自己之前竟然完全没防范. 这是数据库里留下的一些记录.最后那人弄了一个无线循环弹出框的脚本,估计这个脚本之后他再想输入也没法了. 类似这种: <html> <body onload='while(true){alert(1)}'> </body> </html> 我立刻认识到这事件严重性,它说明我的博客有严重安全问题.因为xss跨站脚本攻击可能导致用户Co

sql注入攻击与防御第二版读书笔记二——SQL注入测试

寻找SQL注入 该阶段的主要目标是识别服务器响应中的异常并确定是否由SQL注入漏洞产生,随后确定在服务器端运行的SQL查询的类型(select,update,insert或delete),以及将攻击代码注入查询中的位置(比如from,where或者order by等) 我们需要关注:get,post,cookie,host,referer,useragent. 理解并利用SQL注入漏洞所涉及的主要技术包括:在心里重建开发人员在Web应用中编写的代码以及设想远程SQL代码的内容.如果能想象出服务器

PHP 关于SQL注入的防范措施。

最近在使用框架的时候还是有点不安,不知道框架的设计者有没有考虑到SQL-Injection的问题,我在顶层需不需要做一些必要的过滤等等,由 此我特意的去StackOverflow看了下,真是获益良多,然后我去看了下框架的DB库的内部方法,然后就比较安心了.分享下国内外PHP程序员在处 理SQL-Injection的一些方案. 国外普遍都推荐,只要你是使用查询都应该做到两点:1.prepared statements(准备好的声明) 2.parameterized queries (参数化的查询请

DWVA手把手教程(二)——SQL注入

欢迎来到sql注入章节,此次我们使用的工具为sqlmap. 我们已经察觉到了经典参数id的存在,厚着脸皮的说一句:sql注入漏洞是存在的. 那么我们应该如何去证明呢? 好习惯,先抓包,get方法提交的,掏出万能的sqlmap.. 划重点,敲黑板,懵逼时刻:302? 在这里我们无视它(才不是没看懂的说)直接回车看会发生什么. "假的吧!!我的sqlmap从来没靠谱过!!"咳咳,这句话我已经喊了俩月了.. 原因其实很简单,sqlmap对该页面的访问被重置到了登陆界面. 所以在这里我们要赋予

sql注入以及防范

登陆验证注入: //万能用户名失效 //万能密码 xx' or 1='1 //万能用户名 xxx' union select * from users/* $sql="select * from users where username='$username' and password='$password'"; //万能密码 33 union select * from users //万能用户名 89 union select * from users;/* $sql="

java sql 注入 与防范

1.注入 2 .预防 package com.jdbc; import java.sql.*; import java.util.Scanner; public class loginDemo { public static void main(String[] args)throws ClassNotFoundException, SQLException { //1.注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2.连接 String

记录一下学习PDO技术防范SQL注入的方法

最近学习了使用PDO技术防范SQL注入的方法,在博客里当做一次笔记.若果有新的感悟在来添上一笔,毕竟也是刚开始学习.一. 什么是PDO PDO全名PHP Data Object PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口. PDO 提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据. 二.如何去使用PDO防范SQL注入?/防范sql注入这里使用quate()方法过滤特殊字符和通过预处理的一些方式以及bindPar

Sql 注入详解:宽字节注入+二次注入

sql注入漏洞 原理:由于开发者在编写操作数据库代码时,直接将外部可控参数拼接到sql 语句中,没有经过任何过滤就直接放入到数据库引擎中执行了. 攻击方式: (1) 权限较大时,直接写入webshell 或者直接执行系统命令 (2) 权限较小时,通过注入获得管理员密码信息,或者修改数据库内容进行钓鱼等 常出现的地方: 登录页面.获取HTTP头(user-agent.client-ip等).订单处理等,HTTP头里面client-ip 和 x-forward-for 常出现漏洞,在涉及购物车的地方