漏洞挖掘365天挑战——Day052:blackhat议题之AIModel-Mutator: Finding Vulnerabilities in TensorFlow

链接:https://www.blackhat.com/eu-21/briefings/schedule/#aimodel-mutator-finding-vulnerabilities-in-tensorflow-24620

API fuzzing 不能发现隐藏在复杂代码逻辑中的深层漏洞,是因为这些漏洞必须在特定的上下文下才能够触发,而API fuzzing很难构建这种特定的上下文,

作者发明了一种新的机器学习框架的fuzzing方法,用来帮忙寻找这样的深层漏洞。

他们编写了一个叫 AIModel-mutator的fuzzing工具并在TensorFlow上进行了测试,发现了6个漏洞。

其实有输入就可能有漏洞,机器学习模型也是一样的

随机突变是不能解决的,提出了一个叫结构感知模型突变

先把模型文件加载,在模型的graph上进行突变

然后在输入的tensor上做一些随机行的fuzzing

输入的时候,怎么来选值是个问题。 随机选择不是一个好的选择,要根据上下文来确定边界。

然后是多个tensor的组合

组合Ops的时候,tensor的维度是一样的,输入的值必须等于原来的长度

既然[1,3]报错。那么[None,None]呢

然后是Op的突变

然后是AIModel-mutator的流程

fuzzing tf的结果如上

Slides:

官方的介绍: https://anquan.baidu.com/article/1519

TensorFlow saved_model_cli 代码注入漏洞分析

今天来分析一下还热乎的,TF的代码注入漏洞。出问题的是TF的saved_model_cli程序。

saved_model_cli 主要功能是用来保存模型,这个程序在安装TF的时候就默认自带了,不知道有多少人用过它。

下面是它run的用法:


(base) [~] saved_model_cli run -h                                     21:24:46
usage: saved_model_cli run [-h] --dir DIR --tag_set TAG_SET --signature_def
                           SIGNATURE_DEF_KEY [--inputs INPUTS]
                           [--input_exprs INPUT_EXPRS]
                           [--input_examples INPUT_EXAMPLES] [--outdir OUTDIR]
                           [--overwrite] [--tf_debug] [--worker WORKER]
                           [--init_tpu]

Usage example:
To run input tensors from files through a MetaGraphDef and save the output tensors to files:
$saved_model_cli show --dir /tmp/saved_model --tag_set serve \
--signature_def serving_default \
--inputs input1_key=/tmp/124.npz[x],input2_key=/tmp/123.npy \
--input_exprs 'input3_key=np.ones(2)' \
--input_examples 'input4_key=[{"id":[26],"weights":[0.5, 0.5]}]' \
--outdir=/out

可以看到,里面有一个--input_examples的参数,它接受一个字典作为值。



从源码中,我们去看下是怎么处理这个输入参数值的。

def preprocess_input_examples_arg_string(input_examples_str):
    input_dict = preprocess_input_exprs_arg_string(input_examples_str)
        ...

在preprocess_input_exprs_arg_string这个函数中,我们发现了一个很敏感的函数eval。


def preprocess_input_exprs_arg_string(input_exprs_str):
    input_dict = {}

for input_raw in filter(bool, input_exprs_str.split(';')):
      ...
        input_key, expr = input_raw.split('=', 1)
       # ast.literal_eval does not work with numpy expressions
      input_dict[input_key] = eval(expr)  # pylint: disable=eval-used
return input_dict

eval的存在,直接让恶意用户通过控制输入来让eval执行任意字符串,导致了代码注入。

这个漏洞在TensorFlow 2.7.0版本被修复,CVE号为CVE-2021-41228。

下图为修复的方法,现在使用了literal_eval来判断是否为合法的类型。


以前写过Python语言安全问题,这篇文章里面介绍的第一个敏感函数就是eval。


那为什么这么牛逼的Google项目还会犯这么低级错误呢?你注意到eval函数上面的注释了吗?如果你要挖这种漏洞,会用什么样的思路,欢迎留言讨论。



参考链接:
1.https://jfrog.com/blog/tensorflow-python-code-injection-more-eval-woes/
2.https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-41228
3.https://github.com/tensorflow/tensorflow/security/advisories/GHSA-3rcw-9p9x-582v
4.https://github.com/tensorflow/tensorflow/commit/8b202f08d52e8206af2bdb2112a62fafbc546ec7

Hacking with GPT-3

自从GPT-3开放API之后,出现了各种脑洞demo,开始挑战认知极限。

英语 到 LaTeX 翻译机

十秒生成一个Google首页

快速设计原型

自然语言到Shell命令互译

还可以帮忙写代码

最近,国外白帽子Ron和Filedescriptor,获得了GPT-3 API的内测资格,先恭喜他们。

他们使用GPT-3 API 对一些漏洞挖掘的场景进行了测试,来看看GPT-3能够给漏洞挖掘带来什么样的能力。

你还能想到网络安全中的哪些场景可以用GPT-3尝试解决呢?欢迎留言和分享。你也可以点击最后的阅读原文关注他们。

GPT-3 API出来之后,我就去申请了试用,目前为止没有通过。国外的开发者拿到试用资格的也比较少。GPT-3除了翻译之外并不支持中文处理,还得再等等。我以前也写过关于GPT-3的文章,可供参考。

如果你认为GPT-3使程序员淘汰,那你大概率不写代码

我也用GPT-2中文版生成过零分作文,可以看看生成的质量如何,也提供了GPT-2的使用教程。

零分作文《生活在树上》

最新Bin2Code框架CodeCMR解读

去年看过一篇用图神经网络进行二进制代码相似性分析的论文,主要的目标是把同一份源代码通过不同的编译器,不同的平台,不同的优化选项得到的不同的二进制代码找出来,有兴趣的同学可以看下论文和官方介绍。

论文链接: https://keenlab.tencent.com/en/whitepapers/Ordermatters.pdf

官方介绍:https://keenlab.tencent.com/zh/2019/12/10/Tencent-Keen-Security-Lab-Order-Matters/

最近他们又发了一篇论文,这次在上面任务的基础上升级了,主要是解决给出二进制代码,得到源代码的问题,这给了我这个逆向分析菜鸟一些希望。

论文提出了一个Bin2Code的端到端匹配框架CodeCMR,我们先来看看数据集。

训练的数据集主要由gcc-x64-O0和clang-arm-O3作为两种组合方式,生成了两个30000/10000/10000的训练/验证/测试集。

数据集下载:

https://github.com/binaryai/CodeCMR

我随便取了一个数据:

一个数据集有33列,包括了不同编译器(gcc,clang),不同平台(x86 / x64 / arm / arm64)和不同编译选项的(O1 / O2 / O3)的32种组合。

Index([‘c_label’, ‘gcc-x86-O0’, ‘gcc-x86-O1’, ‘gcc-x86-O2’, ‘gcc-x86-O3’,
‘gcc-x64-O0’, ‘gcc-x64-O1’, ‘gcc-x64-O2’, ‘gcc-x64-O3’, ‘gcc-arm-O0’,
‘gcc-arm-O1’, ‘gcc-arm-O2’, ‘gcc-arm-O3’, ‘gcc-arm64-O0’,
‘gcc-arm64-O1’, ‘gcc-arm64-O2’, ‘gcc-arm64-O3’, ‘clang-x86-O0’,
‘clang-x86-O1’, ‘clang-x86-O2’, ‘clang-x86-O3’, ‘clang-x64-O0’,
‘clang-x64-O1’, ‘clang-x64-O2’, ‘clang-x64-O3’, ‘clang-arm-O0’,
‘clang-arm-O1’, ‘clang-arm-O2’, ‘clang-arm-O3’, ‘clang-arm64-O0’,
‘clang-arm64-O1’, ‘clang-arm64-O2’, ‘clang-arm64-O3’],
dtype=’object’)

我取的源代码是:

static int dump_headers(FILE *inp)
 {
         struct bsid sid;
  while(!ensure_read(&sid, inp))
         {
   size_t s=0;
   dump_sid(&sid);
 s=(sid.Size)+(sid.dwStreamNameSize);
   if(skip_data(inp, s)) return -1;
  }
  return 0;
 }
对于的gcc-x64-O0.nx

seg000:0000000000000000 ; File Name   : \wsl\kali-linux\home\aipwn\Desktop\CodeCMR\CodeCMR\all-arch-nx\81313_1\gcc-x64-O0.nx
 seg000:0000000000000000 ; Format      : Binary file
 seg000:0000000000000000 ; Base Address: 0000h Range: 0000h - 0ADAh Loaded length: 00000ADAh
 seg000:0000000000000000
 seg000:0000000000000000                 .686p
 seg000:0000000000000000                 .mmx
 seg000:0000000000000000                 .model flat
 seg000:0000000000000000
 seg000:0000000000000000 ; ===========================================================================
 seg000:0000000000000000
 seg000:0000000000000000 ; Segment type: Pure code
 seg000:0000000000000000 seg000          segment byte public 'CODE' use64
 seg000:0000000000000000                 assume cs:seg000
 seg000:0000000000000000                 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
 seg000:0000000000000000                 db  80h ; €
 seg000:0000000000000001 ; ---------------------------------------------------------------------------
 seg000:0000000000000001                 add     al, 95h ; '
 seg000:0000000000000003                 iret
 seg000:0000000000000003 ; ---------------------------------------------------------------------------
 seg000:0000000000000004                 db  0Ah
 seg000:0000000000000005                 align 8
 seg000:0000000000000008                 dq 74656E188C000000h, 6C632E786B726F77h, 69642E7365737361h
 seg000:0000000000000008                 dq 78C946870617267h, 9468706172476944h, 28947D9481299493h
 seg000:0000000000000008                 dq 73696C6A64611A8Ch, 5F72656E6E695F74h, 6361665F74636964h
 seg000:0000000000000008                 dq 62088C9479726F74h, 94736E69746C6975h, 939474636964048Ch
 seg000:0000000000000008                 dq 5F65646F6E118C94h, 6361665F74636964h, 8C08689479726F74h
 seg000:0000000000000008                 dq 74615F6567646516h, 5F746369645F7274h, 9479726F74636166h
 seg000:0000000000000008                 dq 646F6E5F058C0868h, 7D014B28947D9465h, 5F776172088C2894h
 seg000:0000000000000008                 dq 17C589461746164h, 12030202E310000h, 20202002776F6C20h
 seg000:0000000000000008                 dq 6C6C616320012020h, 75736E6524070120h, 2646165725F6572h
 seg000:0000000000000008                 dq 747361663C090107h, 36746E695F5F223Ah, 2826202231612034h
 seg000:0000000000000008                 dq 325F726176250C01h, 222C382E290C0230h, 32612A20454C4946h
 seg000:0000000000000008                 dq 2E69647205012022h, 7D317B0401050238h, 20902382E3E0402h
 seg000:0000000000000008                 dq 12009022C090120h, 502342E78616505h, 104027D367B0401h
 seg000:0000000000000008                 dq 20393433203B2004h, 2C382E6964723D75h, 2C574F4C424C4728h
clang-arm-O3.nx
seg000:0000000000000000 ; File Name   : \wsl\kali-linux\home\aipwn\Desktop\CodeCMR\CodeCMR\all-arch-nx\81313_1\clang-arm-O3.nx
 seg000:0000000000000000 ; Format      : Binary file
 seg000:0000000000000000 ; Base Address: 0000h Range: 0000h - 0809h Loaded length: 00000809h
 seg000:0000000000000000
 seg000:0000000000000000                 .686p
 seg000:0000000000000000                 .mmx
 seg000:0000000000000000                 .model flat
 seg000:0000000000000000
 seg000:0000000000000000 ; ===========================================================================
 seg000:0000000000000000
 seg000:0000000000000000 ; Segment type: Pure code
 seg000:0000000000000000 seg000          segment byte public 'CODE' use64
 seg000:0000000000000000                 assume cs:seg000
 seg000:0000000000000000                 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
 seg000:0000000000000000                 db  80h ; €
 seg000:0000000000000001                 db    4
 seg000:0000000000000002                 db  95h ; 
 seg000:0000000000000003                 dd offset byte_7FE
 seg000:0000000000000007                 align 8
 seg000:0000000000000008                 dq 74656E188C000000h, 6C632E786B726F77h, 69642E7365737361h
 seg000:0000000000000008                 dq 78C946870617267h, 9468706172476944h, 28947D9481299493h
 seg000:0000000000000008                 dq 73696C6A64611A8Ch, 5F72656E6E695F74h, 6361665F74636964h
 seg000:0000000000000008                 dq 62088C9479726F74h, 94736E69746C6975h, 939474636964048Ch
 seg000:0000000000000008                 dq 5F65646F6E118C94h, 6361665F74636964h, 8C08689479726F74h
 seg000:0000000000000008                 dq 74615F6567646516h, 5F746369645F7274h, 9479726F74636166h
 seg000:0000000000000008                 dq 646F6E5F058C0868h, 7D014B28947D9465h, 5F776172088C2894h
 seg000:0000000000000008                 dq 14C589461746164h, 12030202E310000h, 20202002766F6D20h
 seg000:0000000000000008                 dq 342E307205012020h, 27D317B04010502h, 12009022C090104h
 seg000:0000000000000008                 dq 10502342E357205h, 202004027D317B04h, 2004012020202020h
 seg000:0000000000000008                 dq 3D7520433433203Bh, 20202020342E3072h, 2E35723D64202020h
 seg000:0000000000000008                 dq 31202E310A040234h, 20027A6E6A200120h, 6163200120202020h
 seg000:0000000000000008                 dq 6E65240701206C6Ch, 6165725F65727573h, 61663C0901070264h
 seg000:0000000000000008                 dq 524F57445F3A7473h, 30250C0128262044h, 2C342E290C023078h
 seg000:0000000000000008                 dq 12044524F57445Fh, 10502342E307205h, 2E3E04027D317B04h

literal features

{‘c_str’: [], ‘c_expr’: [2, 65, 61, 57, 64, 52, 65, 2, 65, 35, 65, 65, 61, 48, 57, 64, 65, 35, 65, 65, 49, 48, 57, 64, 48, 52, 65, 65, 61], ‘m_int’: [0, 0, 4294967295, 0, 0], ‘c_state’: [71, 75, 71, 72, 72, 72, 73, 71, 80, 80], ‘c_int’: [0, 4294967295, 0]}


CFG features

[(1, [[10, 56, 79, 73, 83, 74, 73, 74], [55, 80, 73, 73]]), (2, [[4, 75, 73, 78], [56, 79, 73, 83], [12, 78, 8, 78, 73, 73, 78], [44, 10, 56, 79, 73, 74, 12, 78, 8, 78, 73, 73, 73, 73, 73, 75, 80]]), (3, [[4, 75, 73, 74], [55, 80, 73, 73]]), (4, [[10, 56, 79, 73, 83, 74, 73, 74]]), (5, [[44, 74, 75, 80]]), (6, [[4, 75, 73, 74]])]

literal features
{‘c_str’: [], ‘c_expr’: [2, 65, 65, 61, 57, 64, 52, 65, 65, 57, 64, 52, 65, 57, 64, 65, 35, 65, 65, 61, 57, 64, 52, 65, 65, 61, 61], ‘m_int’: [0, 0, 0, 0, 4294967295], ‘c_state’: [71, 72, 73, 71, 80, 75, 71, 72, 73, 71, 78, 73, 71, 80, 80], ‘c_int’: [0, 0, 1, -1]}

CFG features

[(1, [[4, 74, 73, 74], [43, 56, 79, 73, 83, 74, 75, 80]]), (2, [[56, 79, 73, 83], [43, 56, 79, 73, 74, 12, 78, 78, 73, 75, 80]]), (3, [[44, 56, 79, 73, 83, 74, 75, 80]]), (4, [[4, 75, 73, 74], [55, 80, 73, 73]]), (5, [[4, 75, 73, 74]])]

下面我们来看论文的内容

二进制代码和对于的源代码

首先要面对的问题是自动提取特征。除了字符串,立即数,代码里面的隐藏的语义特征很关键。

从模型上看,是把字符级别的源代码,字符串和立即数,二进制代码提取的控制流图,字符串和立即数,这三个不同的输入(语义特征、字符串特征、立即数特征)分别用模型计算得到向量,再用拼接得到代码向量。

再来看看分别处理输入的语义模型

处理源代码的模型是DPCNN,处理二进制代码的是GNN。

实验效果

论文链接:https://keenlab.tencent.com/zh/whitepapers/neurips-2020-cameraready.pdf

官方介绍:https://keenlab.tencent.com/zh/2020/11/03/neurips-2020-cameraready/

官方还出了一个IDA的插件,可以在逆向时使用,相信不久这篇论文的成果也会集成在这个工具里面,可以试用一下。

工具文档:https://binaryai.readthedocs.io/en/stable/