MySQL5.7-pymysql模块和SQL注入

Posted 花_城

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL5.7-pymysql模块和SQL注入相关的知识,希望对你有一定的参考价值。

系列文章目录

一、pymysql模块

  • 作用:

    该模块可以帮助我们使用python代码,操作数据库。

  • 安装:

    该模块是第三方模块,需要手动安装:

    python3 -m pip install PyMySQL
    
  • 语法:

    # 导入模块
    import pymysql
    
    # 建立与MySQL服务器的连接
    conn = pymysql.connect(host='localhost',   # MySQL服务器的主机地址
                           port=3306,          # 端口号
                           user='root',        # 用户名
                           password='123456',  # 密码
                           database='task',    # 目标数据库
                           charset='utf8mb4'   # 编码,不要加“-”,否则报错
                           )
    
    
    # 创建游标
    # 游标是专门用于执行sql语句的
    cursor = conn.cursor()
    
    # sql语句,不要忘记分号
    sql = 'INSERT INTO user(name,age) values(%s,%s);'
    
    try:
        # 执行sql语句
        cursor.execute(sql,('hugh',17))
        
        # 提交对数据库的修改
        conn.commit()
    
    except:
        # 执行回滚
        conn.rollback()
    
    • 第24行,execute()方法,第一个参数是要执行的SQL语句;第二个参数是SQL语句需要的值(在sql语句中用%s占位),采用元组形式传入。
      其实,这里的SQL语句是字符串,我们完全可以采用格式化输出的方式直接修改,之所以这样大费周章的采用传参数的形式,是为了防止SQL注入。这个SQL注入会在下一节讲。
      execute()方法的返回值是SQL语句影响的记录行数。比如,插入了4行记录,就返回4。一般用不到这个返回值。
    • 如果要一次插入多个值,就改用executemany()方法,传入的参数采用列表包含元组的形式:
       sql = 'INSERT INTO user(name,age) values(%s,%s)'
       cursor.executemany(sql,[('张三',11),('李四',21),('王五',31)])
      
    • 第26行,在提交修改前,所有的修改操作都只是作用于内存当中临时的数据库,不是真正的数据库。一旦提交修改,才会应用到硬盘中保存的真正的数据库。
    • 第30行,回滚用于SQL语句执行失败的时候,它会将撤销所有的修改操作,让数据库(不是真正的数据库,是内存当中临时的数据库)恢复到执行SQL语句之前的模样。
  • 获取SQL的执行结果:
    这些方法通常只在查询操作中使用:

    # 获取sql的查询结果,返回值为元组类型
     cursor.fetchone()  # 获取一行记录
     cursor.fetchmany(数量)  # 获取指定数量的记录
     cursor.fetchall()  # 获取所有记录
    
    • 返回值默认为元组类型,比如:((1, 'hugh', 'male', 18), (2, 'tom', 'male', 33))

    • 在创建游标时,向cursor()方法传入参数cursor=DictCursor,可以使查询结果以字典形式返回,其中,键就是字段名:
      [{'id': 1, 'name': 'hugh', 'gender': 'male', 'age': 18}, {'id': 2, 'name': 'tom', 'gender': 'male', 'age': 33},

    • 游标取完第n条记录后,会向后移动到第n+1条记录的位置,下次再获取时,会从n+1条开始继续获取。

    • 移动游标:

      游标.scroll(偏移量, 模式)
      

      偏移量代表移动的步数,正数代表向后移,负数代表向前移;

      模式有两种:

      相对位移——relative:从当前位置开始移动;

      绝对位移——absolute:从第一条记录的位置开始移动。

  • 调用存储过程:

    游标.callproc(存储过程名称, (存储过程的实参列表))
    

二、SQL注入及解决方法

永远不要信任用户的任何输入!

  • SQL注入的概念:

    SQL注入是一种常见的网络攻击手法,它利用sql的语法特性和程序员编写程序时产生的漏洞,完成一些如跳过密码验证等的非法操作。

  • 举例:

    比如,在编写登录模块时,我们使用了如下查询语句来查询用户信息:

    SELECT * FROM usrs WHERE username=用户输入的用户名 AND password=用户输入的密码;
    

    并且,我们没有对用户的输入做任何处理,直接放到了SQL语句中。那么,当黑客输入了xxx' OR 1=1 -- haacyugjavh作为用户名时,原来的SQL语句就会变成下面的样子:

    SELECT * FROM usrs WHERE username='xxx' OR 1=1 -- haacyugjavh' AND password=;
    

    username='xxx' OR 1=1是一个恒成立的条件,所以无论输入什么用户名都会返回True;而--后面的语句被当作注释忽略掉了,密码验证也被跳过。最终,黑客成功登录。

  • 解决方法:

    不要手动拼接sql语句,而是交给pymysql去处理。

    先用%s占位:

    sql = 'SELECT * FROM usrs WHERE username=%s AND password=%s;'
    

    再在执行sql语句时,以元组形式传入用户输入:

    cursor.execute(sql,(username,password))
    

    pymysql会自动处理用户输入,防止SQL注入。

下一篇

以上是关于MySQL5.7-pymysql模块和SQL注入的主要内容,如果未能解决你的问题,请参考以下文章

node.js 的繁琐模块是不是有任何防止 sql 注入的功能?

Thinkphp 5.1.7 SQL注入漏洞

CTFHUB-SQL注入

Navicat工具pymysql模块 sql注入

OpenEMR登录模块SQL注入分析

Pikahu-SQL注入模块(Sql inject)(实验实战篇)