macOS_模糊测试_Safari解析PDF

575 阅读3分钟

1、模糊测试的原理


模糊测试,也称动态分析,是一种构造非法输入并将其提供给应用,以期让应用暴露出某些安全问题的艺术和科学。

模糊测试的基本理念就是重复向系统发送轻度畸形的输入。设计和实现得很好的应用应该能处理提供给它的任何输入,并应该拒绝无效的输入,继续等待后续数据。


模糊测试及时通过向程序发送数以百万计的输入,查看程序是否会崩溃(或执行某些其他未经许可的行为),以此来测试程序是否满足这一要求。测试人员在模糊测试期间会对应用进行监控,确定哪些输入会导致应用出错。


2、模糊测试举例


本文要对MacOS上的Safari应用做模糊测试,让Safari加载被处理过的PDF文件,以期找出Safari的bug。


(1)生成测试用例

根据一个PDF文件,重复生成随机变化后的pdf文件,python代码如下:

def fuzz_buffer(buffer, FuzzFactor): 
  buf = list(buffer)
  numwrites=random.randrange(math.ceil((float(len(buf))/FuzzFactor)))+1
  for j in range(numwrites):
    rbyte = random.randrange(256) 
    rn = random.randrange(len(buf)) 
    buf[rn] = "%c"%(rbyte);
    return "".join(buf)

虽然这段代码极为简单,但人们已经用它在MacOSX和iOS中找到过大量漏洞了。

(2)测试和监测应用

使用一个shell脚本,调用目标程序,并给它特定的参数,当目标程序崩溃时将崩溃日志写入 logdir文件夹内,以便分析崩溃原因。

crash.sh脚本内容如下:

# ! /bin/bash

mkdir logdir 2>/dev/null
app=$1
url=$2
sleeptime=$3
filename=~/Library/Logs/CrashReporter/$app*
mv $filename logdir/ 2> /dev/null
open -a "$app" "$url"
sleep $sleeptime
cat $filename 2>/dev/null

该脚本会接受待启动程序的名称、要传送给该程序的命令行参数和返回前要睡眠的时间作为命令行参数。

记得为这个shell脚本添加执行权限,例如:

chmod +x crash.sh

简单测试下这个脚本,启动Safari并访问一个网址,终端输入命令:

./crash.sh Safari http://www.360.cn 10


成功调用了Safari并请求到360主页。

(3)将上面(1)和(2)中提交的代码结合在一起

创建一个TestMain.py文件,代码如下:

#encoding=utf-8

import random
import math
import subprocess
import os
import sys

mid_str = '2'

def fuzz_buffer(buffer, FuzzFactor): 
  buf = list(buffer)
  numwrites=random.randrange(math.ceil((float(len(buf))/FuzzFactor)))+1
  for j in range(numwrites):
    rbyte = random.randrange(256) 
    rn = random.randrange(len(buf)) 
    buf[rn] = "%c"%(rbyte);
    return "".join(buf)

def fuzz(buf, test_case_number, extension, timeout, app_name): 
  fuzzed = fuzz_buffer(buf, 10)
  fname = str(test_case_number)+"-test-"+mid_str+extension
  out = open(fname, "wb")
  out.write(fuzzed)
  out.close()

  command_str = "./crash.sh " + app_name + ' ' + fname + ' ' + str(timeout)

  try:
    output = subprocess.check_output(command_str, shell=True)
  except:
    pass

  if len(output) > 0:
    print "Crash in "+fname
    print output
  else:
    os.unlink(fname)


if(len(sys.argv)<5):
  print "fuzz <app_name> <time-seconds> <exemplar> <num_iterations>"
  sys.exit(0)
else:
  print "test-----1"
  f = open(sys.argv[3], "r")
  inbuf = f.read()
  f.close()
  ext = sys.argv[3][sys.argv[3].rfind('.'):] 
  for j in range(int(sys.argv[4])):
    # 处理异常
    try:
      fuzz(inbuf, j, ext, sys.argv[2], sys.argv[1])
    except:
      pass
    continue # 出现异常,继续执行

找一个较为复杂的PDF文件作为测试的数据源,我们目前已经有三个文件,目录结构如下:


(4)执行模糊测试

终端进入当前目录,并执行如下命令:

python TestMain.py Safari 5 test2020.pdf 20

运行TestMain.py,参数1是app的名称,参数2是测试间隔秒数,参数3是pdf文件名,参数4是重复测试的次数。

可以看到Safari浏览器循环加载了多个被处理过的pdf文件,效果如下图:


本文只是举了个例子,告诉你如何做模糊测试。至于能不能挖到漏洞,就看各位大佬的发挥了。

(本文参考自《黑客攻防技术宝典:iOS实战篇》)

欢迎关注公众号:逆向APP