安全矩阵

 找回密码
 立即注册
搜索
查看: 2222|回复: 0

挖掘0day的一些思路技巧

[复制链接]

260

主题

275

帖子

1065

积分

金牌会员

Rank: 6Rank: 6

积分
1065
发表于 2022-4-14 22:02:16 | 显示全部楼层 |阅读模式
本帖最后由 luozhenni 于 2022-4-14 22:02 编辑

挖掘0day的一些思路技巧

原创 yhy0 谁不想当剑仙 2022-04-14 21:07
原文链接:挖掘0day的一些思路技巧
好久不见!

1.前言

待审计应用根据访问权限划分一般有以下几种情况:
  • 仅源码: 我们仅拥有目标的源代码,通常不包含完整的编译和测试环境,而且由于缺乏必须的关键依赖组件,往往无法构建出可运行的程序。这种情况一般只能使用静态分析的方式去进行审计;
  • 仅二进制程序: 我们仅拥有目标应用的二进制文件,比如 APK、EXE、jar 包或者 IoT 的系统固件等。这种情况下通常通过动态分析以及逆向工程的方式进行审计;
  • 有源码及二进制程序: 我们既能够访问目标应用的源代码,也拥有一个可运行的二进制程序,这给安全审计提供了最为有利的访问权限,通常目标是开源软件,包含了完整的构建环境和依赖。
  •   完全黑盒: 我们既没有目标的源代码,也没有可运行的二进制程序,因此只能通过外部接口去进行盲测。这在 Web 应用中较为常见。
    本文主要针对的是有源码情况下的代码安全审计, 这种的代码审计的一般思路是:
  • 通读全文代码,每个功能函数都跟踪一遍,查找漏洞
  • 使用工具进行静态代码扫描,然后分析扫描结果
  • 使用 IAST 加桩辅助挖洞
  • 最新很火的 CodeQL 挖洞
  •   ...
    代码审计是每个安全研究员都应该掌握的技能,但是网上对于代码审计的介绍文章却比较匮乏,比较多的都是漏洞利用,漏洞分析的文章。因此此次分享算是对于我这半年代码审计工作的的一个小总结,希望有兴趣的小伙伴可以常常交流。

2. 0day

    孙子兵法有云: 谋定而后动。凡事在开始之前,都需要确定好自己的目标和计划,这样才能保证不会偏离方向,对于代码审计来说亦是如此。我在代码审计的过程中,不喜欢通读全文代码,跟踪每个功能函数,这样可能很长时间都没有任何收获,既浪费时间,又打击信心。
    为了避免这种情况,在开始之前不妨先问下自己的目标是什么。这乍看起来是个很简单的问题,但对于不同的场景可能有不同的回答。通常安全研究人员的目标是在最短的时间内找到最有价值的漏洞;对于商业安全顾问而言,其目标是在项目预算允许的范围内尽可能达到更高的审计覆盖率;另外对于开发者或者安全架构师而言,则会花费更长的时间周期进行内部安全评审。
    对于我来说,审计的目的就是为了在打项目或者 hw 中起到一锤定音的效果,最好用的 0day 莫过于无条件 getshell 的漏洞,其他诸如xss、csrf这类不能快速拿 shell 的洞我认为是不值得花费时间测试的。
所以我的目的就是找到可以无条件 getshell 的漏洞,这里有两个关键字:
无条件: 不需要登录等手段就可以访问,即未授权访问
Getshell: 手段包括但不限于文件上传、命令执行、代码执行、sql 注入拿 shell。

3. 挖0day

根据以上目的我挖洞的重点就在于无条件,即可以未授权访问的文件或接口。
从国内各类 OA、CMS 曝出的 0day 可以看出,很大一部分产品的开发都不那么规范,没有按照标准流程来。很多漏洞被曝出详情后,对于安全人员来说,只要有源码去审计,大部分漏洞都是非常容易发现的。
我下文说到的小技巧就是建立在这种基础上的,个人感觉非常适合挖国内或者开发不规范类的产品,

3.1 未授权
3.1.1 未授权文件

    我拿到源码之后第一件事就是通过脚本筛选出可以被未授权访问的文件,这种手法不关心你是否能搭建起项目,毕竟国内产品大部分都是不开源的,仅仅拿到源码,对于大部分不是很懂开发的安全人员来说是不一定能搭建起来的。
  1. #!/usr/bin/python3
  2. # -*- coding:utf-8 -*-
  3. # @Author : yhy
  4. # 未授权文件获取脚本
  5. import os

  6. home_directory = "/Users/yhy/work/ROOT"     # 填入项目主目录,该目录名在拼接 uri 中会去除,要给全路径,不然有可能替换出错    # 本地或者公网的靶场地址
  7. suffix = ".jsp"             # 要找的后缀
  8. uris = []                   # 拼接的 uri 列表
  9. f = open('output.txt', 'w')

  10. def splicing(root, files):
  11.     for file in files:
  12.         if file.endswith(suffix):
  13.             uri = root + "/" + file + "\n"
  14.             # 去除获取的根目录名
  15.             uris.append(uri.replace(home_directory, ""))

  16. # 获取项目中所有的文件拼接而成的 uri
  17. def get_URI():
  18.     for root, dirs, files in os.walk(home_directory):
  19.         splicing(root, files)
  20.         # print("root", root)  # 当前目录路径
  21.         # print("dirs", dirs)  # 当前路径下所有子目录
  22.         # print("files", files)  # 当前路径下所有非目录子文件

  23. # 结果保存
  24. def output():
  25.     # 打开一个文件
  26.     fo = open("work.txt", "w")
  27.     fo.writelines(uris)
  28.     # 关闭打开的文件
  29.     fo.close()

  30. if __name__ == "__main__":
  31.     get_URI()
  32.     output()
复制代码



通过脚本遍历拼接所有文件路径后,我喜欢使用 httpx 筛选未授权文件。基本流程:
  1. 1. 执行`echo url | httpx -path work.txt -sc -cl -nc -o workHttpx.txt -fc 302,500,501,404`
  2. 2. 上一步执行可能还会存在一些提示需要登录的文件路径,记录下长度,再次执行`echo  url | httpx -path work.txt -sc -cl -nc -o orkHttpx.txt -fc 302,500,501,404 -fl 长度`
  3. 3. 之后重点查看筛选出的结果,如果审计过程中还存在一些干扰选项,可以不断的执行第二步来排除。
复制代码

    这种方法还可以用来筛选可以未授权访问的配置文件、xml文件等。
    而且根据这步结果,可以将利用脚本将未授权文件复制到另一个目录中,方便使用工具扫描。

3.1.2 未授权接口   


上一种方法只能对于一些未授权文件起作用,一个完整的 web 项目,肯定还有 api。这种的话就要求有对应的环境(自己搭建/公网授权访问), 或者分析项目代码架构从源码中提取 api。
    我后期审计是计划使用Burp来收集 api 接口: 通过收集所有经过 burp 的流量,然后再去除 cookie 访问,提取状态码为200的接口。Burp 中有一款插件AutoRepeater可以做到这个事情, 使用不是很顺手,后期打算二开魔改。
    还有就是最近在学习的 CodeQL,利用 CodeQL 去寻找所有的 API。

3.2 工具扫描   

只是人工的话,会受限于个人水平导致遗漏一些漏洞,所以还需要一些工具进行辅助, 我审计大概会用到以下几个工具:
  • BurpSuite    抓包、改包、收集流量使用
  • Seay源代码审计系统   快速找出可疑危险函数(PHP)
  • KunLun-M          同上(PHP)
  • fortify           同上(java)
  • Xray              被动扫描,辅助挖洞
  • MySQLMonitor      sql 语句执行监控
    当筛选出可以未授权访问的文件后,就可以使用静态扫描工具对这些文件进行扫描,寻找一些危险函数,能极大提高效率。

3.3 文件上传   


对于 getshell 的最有效方法之一就是文件上传,所以当我们筛选出未授权文件后,比如 php 项目就可以拿Seay工具扫描,这样就可以快速定位一些可能存在漏洞的文件,然后对这些文件进行详细的审计;如果对 php 很熟悉的话也可以不用工具扫描,比如: php 中上传文件就离不开move_uploaded_file函数,直接对未授权文件全局搜索该函数,然后重点分析文件。
    比如之前 E-office9 的某个版本就存在文件上传漏洞,编号为 CNVD-2021-49104

image-20220317112314751
这是打了补丁后的文件,未打补丁前,logo 上传没有进行后缀判断。
    利用我所说的这种方法,如果曝出漏洞前就有 e-office9 源码,不出 5 分钟就能挖到这个洞。

3.4 SQL 注入   


SQL 注入就是看项目本身有没有一些过滤函数,过滤的完不完整,还有就是配置文件有没有相应的防御措施。
在 E-office 9 最新版中就存在一个看着存在 SQL 注入,但是无法注入的情况

image-20220317114320473
后边的 '$userId' 参数,虽然没有使用过滤函数,但是该项目的 php 默认开启了魔术引号,这样就不存在字符型SQL注入,痛失一枚 0 day,O(∩_∩)O哈哈~。

image-20220317114526006
魔术引号是程序自动将进入PHP脚本的数据进行转义的过程。当打开后,所有的 '(单引号),"(双引号),\(反斜线)和 NULL 字符都会被自动加上一个反斜线进行转义。和 addslashes() 函数的作用完全相同。
关于 sql 注入挖掘,除了看代码外,下面说下我的一个想法来辅助挖 sql 注入。
    现有工具 MySQLMonitor 是通过监听Mysql 的general_log_file 日志文件,实时获取执行的 sql 语句的一个工具

image-20220316174135527
    但该工具的缺点也非常明显,对于大的项目来说,执行的语句非常多,对于发现哪里可以导致 sql 注入,该工具并没有很好的帮助效果,还是需要大量人力。
    我的一个想法是,在通过 burp 浏览访问时,获取访问日志,然后对于存在参数或者可能存在注入点的地方重新发包,字段中带上一些自定义标识 + sql 注入的一些简单 payload,然后魔改MySQLMonitor 工具,只输出存在自定义标识+payload 的语句。然后重点看这些输出的语句,都是大概率会存在 sql 注入的。
    这种方式就类似于 IAST 污点跟踪,都是跟踪 payload,然后查看 payload 是否被执行。

4. 总结

    我所说的这几个小技巧有的是可以半自动化实现,比如未授权文件筛选还可以通过分析项目的逻辑来实现,比如 E-offcie9 中访问控制是通过include_once("inc/auth.php");来实现的,所以只需要遍历全部文件,去除文件中存在include_once("inc/auth.php");然后在对文件上传函数 move_uploaded_file、SQL 语句执行的关键函数、命令执行的关键函数等一些高危函数进行匹配,最后辅助一点人工就可以做到半自动化捡洞了。
    本次分享只是一家之言,而且技巧比较片面,对于使用框架、标准流程开发的产品,可能就不是很好用了,成功的代码审计过程一定是务实、灵活且面向结果的。虽然讲究方法,但并不意味着根据别人的方法就能成功。代码审计是需要通过学习和练习去掌握的,推荐一个方法:
  • 找到公开的漏洞通告,根据标题的内容自己去相关模块中审计看是否能发现该漏洞
  • 如果发现不了,就回头接着看漏洞通告的细节,反思自己的审计方法
  • 不断重复,直到让自己可以认为找漏洞只是时间问题而不是能力问题
    任何行业都没有捷径,你看到的所谓魔法,很可能只是某人在某些事情上付出了你意想不到的时间。
5. 参考

代码安全审计之道 https://evilpan.com/2022/01/22/code-audit/
6. 题外话   

我司默安大量招人,安全研究/研发/业务支撑/产品/营销,周末真双休,上下班不打卡,工作氛围极好,研究院每周都会有人分享,此篇文章上月刚分享,今天又听了机器学习组大佬讲机器是如何认识文本信息-AI在安全中的落地,虽然听不懂,但大受震撼,灵魂接受了洗礼。
    有意向的欢迎滴滴我,安排内推。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-4-17 01:54 , Processed in 0.018669 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表