目录
存在sql注入条件
判断数据库类型
注入mysql思路
判断网站是否存在注入点
判断列名数量(字段数)
文件读写操作
网站路径获取方法
注入类型
按注入点数据类型来分类
根据提交方式分类
猜测查询方式
sql盲注
注入拓展
加解密注入
json注入
Ladp注入
DNSlog注入
二次注入
堆叠注入
中转注入
WAF绕过
绕过waf的必要条件
绕过方法
WAF举例
安全狗
SQLMap
SQLMAP参数
思维导图(mysql为例):
了解数据库
详细数据库类型的文章
数据库类型
不同数据库注入语句不同,方法也不同,最高权限用户也不同,以mysql为例 一般的网站下一般存放了很多数据库。
比如网站A -数据库A -数据库用户A 网站B-数据库B-数据库用户B
每一个网站给定用户一定的执行权限,权利过大可能导致黑客跨站操作等都有可能
网站之间的数据库可能相互影响,要利用数据库探测内部信息可就需要一步一步往下爆
数据库名——>表名——>列名(字段名)——>拿到我们想要的数据
access数据库比较特别
直接存放表名
列名
数据
此数据库一般会存放在网站源码下面,不同网站之间数据库不会互相影响
access数据库没有文件读写,也不需要爆破数据库名,但是access存在偏移注入
access偏移注入原理 - 浅易深 - 博客园
就是判断sql语句能进行拼接
老方法:
运用逻辑运算符
新方法:
例如 :Select * from usrs where id=1dadadada 其实就是判断字符被带入数据库参与查询即可
在正常语句后加上 order by x x为正常与错误的临界的那个值(例如 Select * from users where id=1 order by 3 正常 order by 4 显示错误 我们就可以判断存在四个字段)
不是所有的字段都会回显,可以通过union select 字段数 来判断存在的回显点 为之后的数据库信息获取做准备
知识点:
在mysql5.0 版本以上中自带一个数据库名为information_schema,他是一个存储记录所有数据库名,表名,列名的数据库,相当于可以通过他来查询指定数据库下面的表名或列名信息。
数据库符号"."代表下一级的意思 例如: admin.user 查询的就是admin数据库下的user表
有点绕但是要理解
猜解多个数据可以用 limit x,1 意思就是从x行加载一条数据
x变动从而显示不同的值
也可以使用group_concat()连接显示所有要查询的信息
这个操作需要一定权限,权限一定要给到要不然实现不了
Load_file() : 读取函数
例如 注:‘\\’是防止浏览器编码'\'而失效
读取配置文件
Into outfile或者 into dumpfile:导出函数
补充知识:
在mysql中 my.ini 中
secure_file_priv 这个变量被用于限制导入和导出的数据目录,比如 LOAD DATA 和 SELECT ... INTO OUTFILE 语句,以及 LOAD_FILE() 函数。这些操作限制了哪些用户拥有文件操作权限。
secure_file_priv 有些设置选项:
magic_quotes_gpc函数
在php配置文件php.ini 设置是否开启
magic_quotes_gpc函数在php中的作用是判断解析用户提示的数据,如包括有:post、get、cookie过来的数据增加转义字符“\”,以确保这些数据不会引起程序,特别是数据库语句因为特殊字符引起的污染而出现致命的错误。
在magic_quotes_gpc = On的情况下,如果输入的数据有
单引号(’)、双引号(”)、反斜线(\)与 NULL(NULL 字符)等字符都会被加上反斜线。
addslashes()函数与其类似
未开启前的查询语句
开启函数后
绕过方法:
十六进制编码
127.0.0.1/sql/Less-1/?id=-1'union select 1,load_file("c://2.txt"),3--+ 为转码会被转义
此时我们使用hex编码 127.0.0.1/sql/Less-1/?id=-1'union select 1,load_file(0x433A5C5C322E747874),3--+
使用编码后查询就不再需要双引号了,只需要去掉双引号对c://2.txt编码即可
报错显示:部分网站在显示错误时会显示路径
遗留文件:比如phpinfo.php php搭建的网站会比较多
漏洞报错:利用一些漏洞爆出路径
平台配置文件:可以利用文件读取函数,获得文件路径,但是配置文件的路径不固定
相关防注入:
自带防御:魔术引导 比如说magic_quotes_gpc函数 这个方法的绕过方式很简单
内置函数:int 等 通过判断用户输入的数据类型防止用户的恶意注入
例如:
自定义关键字:select ,union等等 比如通过str_replace()函数将恶意注入语句中的关键字替换 或者直接丢弃该条语句
例如:
WAF防护软件:安全狗,宝塔,阿里云盾等
(1)数字型注入点
许多网页链接有类似的结构 http://xxx.com/users.php?id=1 基于此种形式的注入,一般被叫做数字型注入点,缘由是其注入点 id 类型为数字,在大多数的网页中,诸如 查看用户个人信息,查看文章等,大都会使用这种形式的结构传递id等信息,交给后端,查询出数据库中对应的信息,返回给前台。这一类的 SQL 语句原型大概为 select * from 表名 where id=1 若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:select * from 表名 where id=1 and 1=1
(2)字符型注入点
网页链接有类似的结构 http://xxx.com/users.php?name=admin 这种形式,其注入点 name 类型为字符类型,所以叫字符型注入点。这一类的 SQL 语句原型大概为 select * from 表名 where name='admin' 值得注意的是这里相比于数字型注入类型的sql语句原型多了引号,可以是单引号或者是双引号。若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:select * from 表名 where name='admin' and 1=1 ' 我们需要将这些烦人的引号给处理掉。
(3)搜索型注入点
这是一类特殊的注入类型。这类注入主要是指在进行数据搜索时没过滤搜索参数,一般在链接地址中有 "keyword=关键字" 有的不显示在的链接地址里面,而是直接通过搜索框表单提交。此类注入点提交的 SQL 语句,其原形大致为:select * from 表名 where 字段 like '%关键字%' 若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:select * from 表名 where 字段 like '%测试%' and '%1%'='%1%'
(4)Json
JSON注入是指应用程序所解析的JSON数据来源于不可信赖的数据源,程序没有对这些不可信赖的数据进行验证、过滤,如果应用程序使用未经验证的输入构造 JSON,则可以更改 JSON 数据的语义。在相对理想的情况下,攻击者可能会插入无关的元素,导致应用程序在解析 JSON数据时抛出异常。
在JSON中是根据引号(“)、冒号(:)、逗号(,)、花括号({})来区分各字符的意义的。如果向JSON中注入恶意字符,那么JSON将解析失败。
JSON注入和XML注入、SQL注入一样,都需要对影响语句的内容进行转义,如双引号、花括号等。
例如注入语句:
当后台实现注入语句
我们的注入语句可以这样写
dumb后面的单引号将’闭合
+
在注入时不同数据类型要注意',",),%,}等字符的干扰 选择不同的符号去闭合 ,同时不同的数据类型语句也会不同
例如利用网站源码中可能使用$_SERVER['']获取用户信息,如果与数据库有交互,在此添加参数实现注入 例如sqllabs第十八关
$_SERVER详解
$_SERVER[‘HTTP_ACCEPT_LANGUAGE’]//浏览器语言
$_SERVER[‘REMOTE_ADDR’] //当前用户 IP 。
$_SERVER[‘REMOTE_HOST’] //当前用户主机名
$_SERVER[‘REQUEST_URI’] //URL
$_SERVER[‘REMOTE_PORT’] //端口。
$_SERVER[‘SERVER_NAME’] //服务器主机的名称。
$_SERVER[‘PHP_SELF’]//正在执行脚本的文件名
$_SERVER[‘argv’] //传递给该脚本的参数。
$_SERVER[‘argc’] //传递给程序的命令行参数的个数。
$_SERVER[‘GATEWAY_INTERFACE’]//CGI 规范的版本。
$_SERVER[‘SERVER_SOFTWARE’] //服务器标识的字串
$_SERVER[‘SERVER_PROTOCOL’] //请求页面时通信协议的名称和版本
$_SERVER[‘REQUEST_METHOD’]//访问页面时的请求方法
$_SERVER[‘QUERY_STRING’] //查询(query)的字符串。
$_SERVER[‘DOCUMENT_ROOT’] //当前运行脚本所在的文档根目录
$_SERVER[‘HTTP_ACCEPT’] //当前请求的 Accept: 头部的内容。
$_SERVER[‘HTTP_ACCEPT_CHARSET’] //当前请求的 Accept-Charset: 头部的内容。
$_SERVER[‘HTTP_ACCEPT_ENCODING’] //当前请求的 Accept-Encoding: 头部的内容
$_SERVER[‘HTTP_CONNECTION’] //当前请求的 Connection: 头部的内容。例如:“Keep-Alive”。
$_SERVER[‘HTTP_HOST’] //当前请求的 Host: 头部的内容。
$_SERVER[‘HTTP_REFERER’] //链接到当前页面的前一页面的 URL 地址。
$_SERVER[‘HTTP_USER_AGENT’] //当前请求的 User_Agent: 头部的内容。
$_SERVER[‘HTTPS’]//如果通过https访问,则被设为一个非空的值(on),否则返回off
$_SERVER[‘SCRIPT_FILENAME’] #当前执行脚本的绝对路径名。
$_SERVER[‘SERVER_ADMIN’] #管理员信息
$_SERVER[‘SERVER_PORT’] #服务器所使用的端口
$_SERVER[‘SERVER_SIGNATURE’] #包含服务器版本和虚拟主机名的字符串。
$_SERVER[‘PATH_TRANSLATED’] #当前脚本所在文件系统(不是文档根目录)的基本路径。
$_SERVER[‘SCRIPT_NAME’] #包含当前脚本的路径。这在页面需要指向自己时非常有用。
$_SERVER[‘PHP_AUTH_USER’] #当 PHP 运行在 Apache 模块方式下,并且正在使用 HTTP 认证功能,这个变量便是用户输入的用户名。
$_SERVER[‘PHP_AUTH_PW’] #当 PHP 运行在 Apache 模块方式下,并且正在使用 HTTP 认证功能,这个变量便是用户输入的密码。
$_SERVER[‘AUTH_TYPE’] #当 PHP 运行在 Apache 模块方式下,并且正在使用 HTTP 认证功能,这个变量便是认证的类型
在实际环境中,可能网站对不同提交方式的过滤措施不同可以,尝试多换几种注入方式 例如 sqllabs 20关 对post 进行过滤 也许进行cookie注入就可以轻松绕过可以用迪总这个php代码自己搭建去试一试理解一下提交方式
根据网站功能我们可以对执行的数据库语句进行猜想,从而进行注入
Select 查询数据
在网站中进行数据显示查询操作
例如: select * from news where id=1
Insert 插入数据
在网站中进行用户数据注册添加等操作
例如: insert into new(id,url,text) values (2,'x','$t')
Delete 删除数据
后台管理里面删除用户信息等操作
例如:delete from news where id =$id
Update 更新数据
后台同步数据或缓存等操作
例如:update user set pwd='$p' where id=2 and username='admin'
Order by 排序数据
一般结合表名或者列名进行数据排序操作
例如:select * from news order by $id
盲注就是在注入过程中,获取的数据不能回显至前段页面。我们需要利用一些方法进行判断或尝试,这个过程称之为盲注。
盲注的三种分类:
搭配函数:
Like ‘ro%' #判断ro或者ro…… 是否成立
Regexp '^xiaodi[a-z]' #匹配xaiodi及xiaodi…等
If(条件,5,0) #若条件成立则返回5,反之返回0
Sleep(5) #sql语句延时执行五秒
Mid(a,b,c) #从位置b开始,截取a字符串里面的c位
Substr(a,b,c) #从b位置开始,截取字符串a的c长度
Left(a,b) #从左侧截取a的前b位
Length(a)=8 #判断字符串长度
Ord=ascii ascii(a)=97 #判断a的ascii值是否等于97
实战中需要我们灵活应用
源码端执行数据库语句时对接收的数据进行了解密,例如 sqllabs 21关
前提条件:
目的(优点):解决盲注不能回显,效率低的问题
Dns在域名解析时会留下域名和解析ip的记录,利用这点我们可以使用Dnslog(日志)记录显示我们的注入结果。通过load_file()不仅可以查看本地文件,也可以访问远程共享文件。
前提:涉及到文件读取等操作,所以要求用户拥有高权限 例如:mysql中的root用户
需要用到dns的一个平台
CEYE - Monitor service for security testing (需要使用)
和一个常用工具DnslogSqlinj GitHub - ADOOO/DnslogSqlinj
工具的配置:
这个工具需要python2.7去运行(这个如果之前安装不是这个版本的python,涉及多个版本python使用问题,可能会出现报错,我自己也弄了好久,不会解决的可以评论区问问)
一般在白盒测试下才会使用
例如 sqllabs 24关
在修改密码处有以下一段代码
注册时注册已有的用户名+‘闭合update语句+想要执行的sql语句 例如dhakkan'#
即可实现注入
在修改dhakkan'#用户密码时数据库会执行语句
UPDATE users SET PASSWORD =‘$pass' where username='dhakkan'#'and password='$curr_pass'
成功修改了dhakkan用户的密码
这个注入要考虑是否限制了提交参数的长度,前端检测可以轻松绕过,后端就没有办法了
多条sql语句同时执行,在数据库语句中通常使用“;”将语句分隔开来,我们使用“;”就可以一次性执行多条sql语句。与union联合注入不同,这里可以执行任意注入语句,而联合注入却是有限的。
局限性:
堆叠注入并不是在每一个环境下都可以执行,可能受到API或者数据库引擎不支持的限制
例如sqlmabs第38关 使用insert语句向表中添加用户
网站URL注入点是经过编码的,不能直接结合sqlmap进行漏洞利用,所以本地搭建一个网站,写一个php脚本编码文件,就可以结合sqlmap工具进行测试。因为,注入点经过复杂编码之后,就不能直接结合sqlmap进行漏洞攻击。或者sqlmap自己编写tamper脚本进行攻击
Web应用防护系统(也称为:网站应用级入侵防御系统。英文:Web Application Firewall,简称: WAF)。利用国际上公认的一种说法:Web应用防火墙是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品
waf拦截其实也是通过匹配关键字实现拦截,阻止恶意用户的非法操作
干货 | 常见WAF拦截页面总结
MySQL数据库特性绕过
借助mysql特性来实现绕过
语句: /*!五位版本号+关键字*/
例如: /*!50001 select*/
需要注意的是这不仅仅是简单的SQL内联注释绕过,而是在MySQL中有其特定含义。对于MySQL数据库而言,对于上述payload,如果开头是5个数字的话,其含义为当数据库版本大于5.00.01,就把之后的内容当作正常语句来执行,而如果数据库版本如果小于5.00.01,就把后面的内容当作注释的内容来执行。而对于一般waf而言,则只会把该语句当作普通的payload来处理。
http参数污染
如果出现多个相同参数,不同的服务器搭建网站会出现参数接受的差别,从而令原有的参数失效。
HPP发生在查询参数中,查询参数通常是指URI中“?”和URI结尾之间的部分,是一系列的域值对,可以参考RFC 3986查看其具体定义,这些域值对是通过“&”分开的,例如:name=admin&password=Test@123。如果用户输入的name的值为:admin&password=123,数据没有经过任何处理用于提交请求,那么这个URL就会被篡改为:name=admin&password=123&password=Test@123。
Web环境
|
参数获取函数 |
获取到的参数 |
PHP/Apache |
$_GET("par") |
last |
JSP/Tomcat |
Request.getParameter("par") |
first |
Perl(CGI)/Apache |
Param("par") |
first |
Python/Apache |
getvalue("par") |
["first","last"] |
ASP.NET/IIS |
Request.QueryString("par") |
first,last |
完整表格:
ip白名单
方式一:IP白奖单
从网络层获取的ip,这种一般伪造不来,
前提对方是利用脚本去接收ip地址 而不是通过网络层的协议,
这时如果是网站自己的IP,这样就可能存在伪造IP绕过的情况。
测试方法:修改http的header来bypass waf
考虑对方ip地址的接收方式来伪造ip
x-forwarded-for
x-remote-IP
x-originating-IP
x-remote-addr
x-Real-ip
方式二:静态资源
特定的静态资源后缀请求,常见的静态文件(.js .jpg .swf .css等等),类似白名单机制,waf为了检测效率,不去检测这样一些静态文件名后缀的请求。
让waf认为参数是上传到静态资源文件上的,但实际上是传递给数据库的,从而绕过检测(部分老的waf可以直接绕过)
http://10.9.9.201/ sql.php?id=1
http://10.9.9.201/sql.php/1.js?id=1
备注: Aspx/php只识别到前面的.aspx/.php后面基本不识别
方式三:url白名单
为了防止误拦,部分waf内置默认的白名单列表,如admin/manager/system等管理后台。只要url中存在白名单的字符串,就作为白名单不进行检测。常见的url构造姿势:
http://10.9.9.201/sql.php/admin.php?id=1
http://10.9.9.201/sql.php?a=/manage/&b=../etc/passwd
http://10.9.9.201/../../../ manage/../sql.asp?id=2
waf通过/manage/"进行比较,只要uri中存在/manage/就作为白名单不进行检测,这样我们可以通过/sql.php?a=/manage/&b=../etc/passwd 绕过防御规则。
有时注入语句没有问题,但是就是注入进不去,可能WAF检测了注入工具
方式四:爬虫白名单
部分waf有提供爬虫白名单(各大浏览器的爬虫,例如百度,谷歌)的功能
可以通过伪造官方的搜索引擎爬虫进行扫描
识别爬虫的技术一般有两种:
1、根据user-agent
2、通过行为来判断
UserAgent可以很容易欺骗,我们可以伪装成爬虫尝试绕过。User Agent switcher (Firefox附加组件),下载地址:
https : //addons.mozilla.org/en-us/firefox/addon/user-agent-switcher/
扩展一:有的WAF检测的是其他字段,可以使用burp抓包进行替换这个字段,来进行绕过。(只是修改一个)
扩展二:将注入语句生成txt文件,放在sqlmap目录下跑。(可以支持跑多个)
采用工具注入会被拉黑
下载网址:http://free.safedog.cn/website_safedog.html
安装成功之后,开启拦截,之前的注入会被拦截
开启的拦截匹配规则越多,拦截的语句就越多,但有时候会干扰到正常用户的操作
用来绕过安全狗waf
url编码:
使用注释语句的符号:
/**/
通常为了躲避检测我们经常重复套用并且加入其他字符进行干扰 例如/*/b*/
原理
安全狗检测渗透脚本是采用整体验证
简单举例:unint select 这个整体,可以使用以上方法,使用unint/*!*/select可不触发waf
一部份可用的payload
id=-1' union/*/a*/%23%0aselect 1,/*!22222database%23%0a*//*/s*/(),3--+ mysql特性+字符混用绕过
?id=-1 union /*///--/*/ select 1,2,3--+ 注释符混用
?id=1 /*&id=-1 union select 1,database(),3%23*/ http参数污染
SQLMAP是一个开源的自动化SQL注入工具,其主要功能是扫描、发现并利用给定的URL的SQL注入漏洞。目前支持的数据库有:MySql、Oracle、Access、PostageSQL、SQLServer、IBMDB2、SQLite、Firebird、Sybase和SAP MaxDB等
官网地址:https://sqlmap.org/(安装之前需要安装好python环境)
sqlmap执行过后会有本地缓存文件,影响接下来使用的结果
Sqlmap全面支持六种SQL注入技术:
使用示例(无waf)
常见参数:
参数:-u 直接输入目标URL
参数:-m 从文件中取出保存的url进行检测
参数:-r 从文本文件中获取http请求,一般在存在cookie注入时使用。
参数:-g 测试注入Google的搜索结果的GET参数
参数:-l 从Burp或者WebScarab代理中获取日志
–current-user #获取当前用户名称
–current-db #获取当前数据库名称
枚举参数
参数:-b,--banner 列出版本号
参数:--dbs 列出所有数据库的库名
参数:--current-db 列出当前使用的数据库库名
参数:--tables 列出数据库中的表
参数:--columns 列出数据表中的字段
参数:--dump 转储数据库表项,查询字段值
参数:--users 列出所有管理用户
参数:--passwords 列出并破解数据库用户的hash
参数:--privileges 列出数据库管理员权限
请求参数
参数:--method 指定使用的http方法
参数:--data 把数据以POST方式提交
参数:--param-del GET或POST的数据用&以外的其他字符分割
参数:--cookie,--load-cookies,--drop-setcookie 设置cookie
参数:--referer 伪造HTTP中的Referer头
参数:--user-agent 自定义HTTP中的User-Agent头
参数:--headers 增加额外的http头,不同的头使用“\n”分隔
参数:--timeout 设置超时时间
参数:--retries 设置重试次数
检测参数
参数:-V显示等级,共有7个等级,为0时只显示python错误以及严重的信息,为1时(默认)同时显示基本信息和警告信息,为2时同时显示debug信息,为3时同时显示注入的payload,为4时同时显示HTTP请求,为5时同时显示HTTP响应头,为6时同时显示HTTP响应页面。
参数:--risk 风险等级,共有4个等级
参数:-p,--skip 手动用-p参数设置想要测试的参数,-skip设置跳过的参数
参数:--flush-session 清空SQLMAP缓存的会话信息
注入技术参数
参数:--technique 指定sqlmap使用的探测技术,B表示布尔盲注,T表示时间盲注(延退注入),E表示报错注入,U表示联合查询注入,S表示堆查询注入
参数:--time-sec 设定延退注入的时间(默认为5秒)
参数:--union-cols 设定UNION查询字段数
参数:--union-char 设定UNION查询时使用的字符
参数:--second-order 设置二次注入的URL
参数:--tamper 使用sqlmap自带的tamper或者自己写的tamper来混滑payload,通常用来绕过WAF和IPS。自带的一般用来做ctf,实际环境中需要自己动手写(比如绕waf等等)。
当调用多个脚本的时候,脚本之间用逗号隔开,调用的脚本在 sqlmap文件夹下的 tamper 文件夹中,自己写的脚本也可以放入其中,因支持自定义而变得强大
操作系统权限参数
参数:--os-cmd执行操作系统命令
参数:--os-shell交互式的操作系统的shell
文件读写参数
参数:--file-read
读取文件
参数:--file-write
写入文件
参数:--file-dest指明写入文件的绝对路径
例如:
python sqlmap.py -u“ http://10.1.1.1/sql-labs1/?id=1 ”-D数据库名 -T表名 -C字段名1,字段名2,字段名3..(互相用逗号隔开开)-dump//显示数据
Python sqimap.py -r a.txt(a.txt存放好所要用到的http请求)