Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 10725|回复: 0

pymysql 解决 sql 注入问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-4-14 09:49:44 | 显示全部楼层 |阅读模式

    1. SQL 注入

    SQL 注入是非常常见的一种网络攻击方式,主要是通过参数来让 mysql 执行 sql 语句时进行预期之外的操作。

    即:因为传入的参数改变SQL的语义,变成了其他命令,从而操作了数据库。

    产生原因:SQL语句使用了动态拼接的方式。

    例如,下面这段代码通过获取用户信息来校验用户权限:

    import pymysql sql = 'SELECT count(*) as count FROM user WHERE id = ' + str(input['id']) + ' AND password = "' + input['password'] + '"' cursor = dbclient.cursor(pymysql.cursors.DictCursor) cursor.execute(sql) count = cursor.fetchone() if count is not None and count['count'] > 0: print('登陆成功')

     

    但是,如果传入参数是:

    input['id'] = '2 or 1=1'
    

      

    你会发现,用户能够直接登录到系统中,因为原本 sql 语句的判断条件被 or 短路成为了永远正确的语句
    这里仅仅是举一个例子,事实上,sql 注入的方式还有很多种,这里不深入介绍了。
    总之,只要是通过用户输入数据来拼接 sql 语句,就必须在第一时间考虑如何避免 SQL 注入问题。
    那么,如何防止 SQL 注入呢?

     

    2. 预防 SQL 注入 – pymysql 参数化语句

    pymysql 的 execute 支持参数化 sql通过占位符 %s 配合参数就可以实现 sql 注入问题的避免。

    import pymysql sql = 'SELECT count(*) as count FROM user WHERE id = %s AND password = %s' valus = [input['id'], input['password']] cursor = dbclient.cursor(pymysql.cursors.DictCursor) cursor.execute(sql, values) count = cursor.fetchone() if count is not None and count['count'] > 0: print('登陆成功')

     

    这样参数化的方式,让 mysql 通过预处理的方式避免了 sql 注入的存在。
    需要注意的是,不要因为参数是其他类型而换掉 %s,pymysql 的占位符并不是 python 的通用占位符。
    同时,也不要因为参数是 string 就在 %s 两边加引号,mysql 会自动去处理。

     

    3. 预防 SQL 注入 – mysql 存储过程

    数据库存储过程是 mysql 的一种高级用法,但是一般来说,并不建议使用数据库的存储过程。


    主要原因是:

    •  存储过程的语法与普通 SQL 语句语法相差太大,增加维护成本
    •  存储过程在各数据库间不通用且差别较大,给数据库的移植和扩展带来困难
    •  编写困难,数据库脚本语言使用起来还是很不方便的,包括很多数据结构的缺失,让很多事情做起来很困难
    •  调试困难,虽然有一些功能强大的 IDE 提供了数据库存储过程的调试功能,但是通常你需要同时在数据库层面上和业务中同时进行调试,两处调试极为不便
    •  业务耦合,编写存储过程通常是需要在其中放入部分业务逻辑,这使得业务分散在数据层,业务层与数据层的耦合对于项目维护和扩展都会带来极大地不便。

    但是,虽然不建议使用存储过程,但是毕竟可以依赖他实现各种跨语言的 sql 注入预防,在复杂的场景下还是有其使用价值的。(以后需要用再去详细学,这里只作简单介绍

    3.1. 存储过程编写

    delimiter \DROP PROCEDURE IF EXISTS proc_sql \CREATE PROCEDURE proc_sql ( in nid1 INT, in nid2 INT, in callsql VARCHAR(255) ) BEGIN set @nid1 = nid1; set @nid2 = nid2; set @callsql = callsql; PREPARE myprod FROM @callsql; --   PREPARE prod FROM 'select * from tb2 where nid>? and nid<?'; 传入的值为字符串,?为占位符 -- 用@p1,和@p2填充占位符 EXECUTE myprod USING @nid1,@nid2; DEALLOCATE prepare myprod; END\delimiter ;

     

    3.2. pymsql 中调用

    import pymysql cursor = conn.cursor() mysql="SELECT * FROM user where nid > ? and nid < ?" cursor.callproc('proc_sql', args=(11, 15, mysql)) rows = cursor.fetchall() conn.commit()

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-20 02:05 , Processed in 0.061315 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表