AICon 上海站|90%日程已就绪,解锁Al未来! 了解详情
写点什么

我用 GPT-3 在单个代码库中发现 213 个安全漏洞

  • 2023-03-30
    北京
  • 本文字数:4991 字

    阅读完需:约 16 分钟

我用GPT-3在单个代码库中发现 213个安全漏洞

本文最初发布于 Better Programming。


GPT-3 在这个Git代码库中发现了 213 个安全漏洞。相比之下,市场上一款比较好的商业工具(来自一家著名的网络安全公司)却只发现了 99 个问题,不过商业工具提供了更好的结构化上下文。我随机手动检查了 GPT-3 检测到的 213 个漏洞中的 50 个,只有一个是假阳性。这两种工具的假阴性都很多。


近年来,人工智能和机器学习领域取得了巨大的发展,并开辟了全新的可能性领域。其中一个备受关注的领域是基于人工智能的代码分析,特别是使用人工智能模型来检测代码中的安全漏洞。在这个实验中,我们使用 OpenAI 的 GPT-3 在代码库(包含 129 个有漏洞的文件)中查找安全漏洞。

工作原理


我使用的是 GPT-3 的一个变体(text-davinci-003),其上下文窗口有 4000 个词元,大约是 3000 个英语单词。这意味着每个请求最多只能处理几百行代码。很遗憾,GPT-3 的当前架构无法一次处理整个代码库。


为了解决这个问题,我必须用 GPT-3 单独扫描每个文件。也就是说,GPT-3 可能难以找到涉及多个代码文件交互的安全漏洞,除非 import/export 足够清楚,不需要具体查看代码就可以猜出那些函数的功能。


这种情况经常发生,特别是当源代码使用了常见的库时,如 express.js、Flask、Python 标准库、C 标准库等。GPT-3 很可能用到了许多最常见的库,有的是部分记忆的,有的是完全记忆的,有的是以其他方式编码的。在本文分析的代码中,GPT-3 对导入的库有足够的先验知识,因此能够准确检测安全漏洞,而不需要检查任何导入的库代码。


公平地讲,不只 GPT-3,我怀疑现在的许多商业漏洞扫描工具在进行静态分析时实际上并没有检查导入的库代码——所以与市场上已经存在的一些工具相比,它的工作方式并没有什么不同。

分析的代码


代码库中的每个文件夹都以一种类型的安全漏洞命名,其中的文件包含存在一个或多个漏洞的示例代码。这些文件中的代码有些没什么价值,但也有许多是你可能在生产代码库中遇到的很实际的代码片段(注意:它们不过是代码片段,并没有更大代码库的上下文信息)。代码库中每个文件夹下的 README.md 文件包含了 GPT-3 针对该文件夹中每个文件生成的安全漏洞分析。


接下来,让我们通过一些例子看看 GPT-3 是如何做到的!

示例 1


下面是一个容易受到格式字符串攻击的简单的C程序


#include <stdio.h> int main(int argc, char **argv) {    char *secret = "This is a secret!\n";     printf external link(argv[1]);     return 0;}
复制代码


下面是 GPT-3 的分析(它是对的):


检出的漏洞:

  1. 未验证用户输入:程序没有检查用户输入的长度,这可能导致缓冲区溢出攻击。

  2. 格式字符串漏洞:程序没有检查用户输入的格式,这可能导致格式字符串攻击。

示例 2


让我们看一个用高级语言编写的不那么简单的程序,比如下面这个包含 Log Forging 漏洞的C#程序。类似的代码,我在开源项目和生产代码库中都见过(不是那么没价值):


using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc;using Microsoft.Extensions.Logging;using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;
namespace WebFox.Controllers{ [Route("api/[controller]")] [ApiController] public class LogInjection : ControllerBase { private readonly ILogger<LogInjection> _logger;


public LogInjection(ILogger<LogInjection> logger) { _logger = logger; }
[HttpGet("{userInfo}")] public void injectLog(string userInfo) { _logger.LogError("error!! " + userInfo); } }}
复制代码


以下是 GPT-3 的输出:


检出的漏洞:

日志注入漏洞:代码容易受到日志注入攻击,因为用户输入直接被记录,没做任何消毒处理。


GPT-3 的评价是对的——这段代码中有一个日志注入漏洞。

示例 3


下面的C程序读取并操作一幅图像。它包含许多安全漏洞,包括越界(Out Of Bounds)读写:


#include<stdio.h>#include<stdlib.h>#include<string.h>
struct Image{ char header[4]; int width; int height; char data[10];};
int ProcessImage(char* filename){
FILE *fp; char ch; struct Image img;
fp = fopen(filename,"r");
if(fp == NULL) { printf("\nCan't open file or file doesn't exist."); exit(0); }
printf("\n\tHeader\twidth\theight\tdata\t\r\n");
while(fread(&img,sizeof(img),1,fp)>0){ printf("\n\t%s\t%d\t%d\t%s\r\n",img.header,img.width,img.height,img.data); int size1 = img.width + img.height; char* buff1=(char*)malloc(size1);
memcpy(buff1,img.data,sizeof(img.data)); free(buff1); if (size1/2==0){ free(buff1); } else{ if(size1 == 123456){ buff1[0]='a'; } }
int size2 = img.width - img.height+100; //printf("Size1:%d",size1); char* buff2=(char*)malloc(size2);
memcpy(buff2,img.data,sizeof(img.data));
int size3= img.width/img.height; //printf("Size2:%d",size3);
char buff3[10]; char* buff4 =(char*)malloc(size3); memcpy(buff4,img.data,sizeof(img.data));
char OOBR_stack = buff3[size3+100]; char OOBR_heap = buff4[100];
buff3[size3+100]='c'; buff4[100]='c';
if(size3>10){ buff4=0; } else{ free(buff4); }
free(buff2); } fclose(fp);}
int main(int argc,char **argv){ ProcessImage(argv[1]);}
复制代码


GPT-3 的输出:


检出的漏洞:

  1. 未检查返回值:未检查 fopen()函数的返回值,这可能导致空指针解引用。

  2. 越界读取:使用 memcpy()函数将数据从 img.data 复制到 buff1 和 buff2,而不检查目标缓冲区的大小,这可能导致越界读取。3.越界写入:在写入 buff3 和 buff4 数组时未检查源缓冲区大小,这可能导致越界写入。

  3. 未初始化内存访问:在未初始化的情况下访问 OOBR_stack 和 OOBR_heap 变量,这可能导致未定义的行为。

  4. 内存泄漏:如果 size3 变量大于 10,则 buff4 数组不会释放,这可能导致内存泄漏。


GPT-3 再次判断正确!

示例 4


最后一个Java示例是我最喜欢的,因为很遗憾,在第一次阅读这段代码时,我没有发现它有任何问题。对我来说,它看起来完全无害且很常见——我实际见过类似的代码,但从未有过任何其他的想法。


class Utils{    // 该函数序列化一个对象,并将其写入一个文件    public static void SerializeToFile(Object obj, String filename)    {        try        {            FileOutputStream file = new FileOutputStream(filename);            ObjectOutputStream out = new ObjectOutputStream(file);
// 将对象序列化到文件中 System.out.println("Serializing " + obj.toString() + " to " + filename); out.writeObject(obj);
out.close(); file.close(); } catch(Exception e) { System.out.println("Exception: " + e.toString()); } }
// 该函数从文件反序列化对象 public static Object DeserializeFromFile(String filename) { Object obj = new Object();
try { FileInputStream file = new FileInputStream(filename); ObjectInputStream in = new ObjectInputStream(file);
// 从文件反序列化对象 System.out.println("Deserializing from " + filename); obj = in.readObject();
in.close(); file.close(); } catch(Exception e) { System.out.println("Exception: " + e.toString()); }
return obj; }}
复制代码


GPT-3 的输出:


检出的漏洞:

  1. 不安全的反序列化:反序列化不受信任的数据可能导致远程代码执行。

  2. 不安全的文件权限:正在写入或读取的文件可能具有不安全的权限,从而导致未经授权的访问。


GPT-3 再次判断正确。

网络安全“终极”左移


左移是在开发过程早期应用安全实践的过程——比如在将代码部署到生产环境之前测试安全漏洞。


人工智能代码分析代表了网络安全领域的终极左移,它通过应用最佳安全实践,在开发人员编写和提交代码时为他们提供网络安全指导。这可以真正地在组织内部培养起强大的网络安全文化,甚至可以防止下一次大规模黑客攻击,但是……


不可否认,这项技术还不完美,它会遗漏一些事情,而一个有经验的网络安全专业人士在审计时就不会遗漏。尽管如此,作为一种通用的大型语言模型,它还是非常不错的,而且成本比其他替代方案低很多。


目前,GPT-4 的发布日期还不确定,但我相信,随着这些大型语言模型的功能越来越多,它们会继续向前发展。

假阳性


在手动检查 GPT-3 检出的 213 个漏洞中的约 50 个后,我唯一发现的假阳性是在这个JavaScript程序的第 13 行:


var express = require('express');var cookieParser = require('cookie-parser');var escape = require('escape-html');var serialize = require('node-serialize');var app = express();app.use(cookieParser()) app.get('/', function(req, res) { if (req.cookies.profile) {   var str = new Buffer(req.cookies.profile, 'base64').toString();   var obj = serialize.unserialize(str);   if (obj.username) {     res.send("Hello " + escape(obj.username)); // <--- GPT-3在这里犯了一个错误   } } else {     res.cookie('profile', "eyJ1c2VybmFtZSI6ImFqaW4iLCJjb3VudHJ5IjoiaW5kaWEiLCJjaXR5IjoiYmFuZ2Fsb3JlIn0=", {       maxAge: 900000,       httpOnly: true     }); } res.send("Hello World");});app.listen(3000);
复制代码


GPT-3 的输出:


检出的漏洞:

  • 不安全的 cookie 设置(未设置安全标志)

  • 未验证的用户输入(cookie)反序列化

  • 未对用户输入(用户名)进行转义,可能存在 XSS 漏洞 GPT-3 对于前 2 个漏洞的判断是正确的,但第 3 个漏洞是假阳性—— obj.username 已经进行了编码,但 GPT-3 说没有。

GPT-3 检测结果


实验结果表明,经过扫描,GPT-3 在 129 个文件的到 86 个中检出了安全漏洞。这真是令人印象深刻!


以下是脚本summarize_results.py生成的 GPT-3 检测结果的完整摘要:


在129个文件中,有86个检出了漏洞。总共检出了213个漏洞。
GPT-3回复中使用的介绍性句子的出现频率(每个扫描的文件一个回复):{'vulnerabilities detected': 73, 'no vulnerabilities detected.': 43, 'vulnerability detected': 6, 'answer': 2, 'potential vulnerabilities detected': 2, 'analysis': 1, 'security vulnerabilities detected': 1, 'no response given': 1}
扫描的文件类型的分布:总计129个代码文件(不包括markdown和平面文件){'.php': 50, '.js': 20, '.cs': 16, '.c': 14, '.java': 9, '.py': 8, '.rb': 5, '.asp': 3, '.ts': 2, '.go': 1, '.html': 1}
复制代码

与商业产品的对比


为了完善这个实验,我将 GPT-3 的结果与商用代码漏洞扫描工具Snyk Code(由 Snyk 公司开发)做了比较。我认为,Snyk 公司开发的安全产品非常出色。通过扫描,Snyk Code 从这个代码库中发现了 99 个安全漏洞,而 GPT-3 发现了 213 个安全漏洞。



其中一个原因是 Snyk Code 只支持其中部分编程语言,并且只能扫描大约 103 个文件,而 GPT-3 扫描了 129 个文件。


此代码库中存在漏洞的代码片段来自snoopysecurity/Vulnerable-Code-Snippets,这是一个很棒的资源。我试着删除了嵌入在代码段中的注释,从中可以看出这个代码段中包含哪些安全漏洞。这些需要删除的注释中包含指向这些示例片段出处的博文链接。要查看它们在原代码库中的位置,可以查看attributions.md文件。


原文链接:https://betterprogramming.pub/i-used-gpt-3-to-find-213-security-vulnerabilities-in-a-single-codebase-cc3870ba9411

2023-03-30 07:004052

评论 1 条评论

发布
用户头像
一些代码检查工具不行吗,sonarqube的插件,比如findbugs也是根据模式发现bug的
2023-03-31 09:29 · 辽宁
回复
没有更多了
发现更多内容

👊 【Spring技术原理】异步编程机制以及功能分析讲解

码界西柚

spring springboot 异步编程 8月日更

来!看排名一年上升16位的ClickHouse,如何在京东落地实践

京东科技开发者

数据库 Clickhouse

关于告警管理的软件,您还只知道Pagerduty吗?

睿象云

运维 告警 运维平台 智能告警 告警管理

使用mock模拟登录接口数据

与风逐梦

大前端 后端 Mock

Go- 切片的定义

HelloBug

slice Go 语言 切片

Go- 切片的使用

HelloBug

Go 语言 切片 追加 拷贝 扩缩容

如何用 Nacos 构建服务网格生态

阿里巴巴云原生

干货!4大实验项目,深度解析Tag在可观测性领域的最佳实践!

观测云

可观测性 dataflux tag ngix

高可用 | Xenon 实现 MySQL 高可用架构 部署篇

RadonDB

MySQL 数据库 Xenon RadonDB

关于飞书的告警通知,这里有个更好的办法

睿象云

运维 告警 运维平台 智能告警

关于C++中“不能返回对象引用”的思考

她的男人是程序员

计算机网络常用知识总结

Java 架构 后端 网络 计算机

TCP协议认知篇

邱学喆

TCP协议 拥塞避免算法 慢启动算法 坚持定时器 TCP状图切换

通过明道云实现培训机构客户管理

明道云

如何对接口参数的描述进行集中管理

CodeNongXiaoW

大前端 测试 后端 接口工具

华为18级工程师三年心血终成趣谈网络协议文档(附大牛讲解)

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

阿里资深架构师终于把微服务架构与实践第2版PDF分享出来了

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

【“互联网+”大赛华为云赛道】GaussDB命题攻略:支持三种开发语言,轻松完成数据库缓冲池

华为云开发者联盟

数据库 华为云 GaussDB 互联网+ 缓冲池

浅析智慧交通有哪些应用场景?

一只数据鲸鱼

数据可视化 智慧城市 智慧交通 城市交通

WebRTC中的RefCountedObject解析

她的男人是程序员

打开vscode好像打开了原神?vscode原神背景推荐,比博燃

CodeNongXiaoW

vscode vscode背景 原神

Spring 配置加载

樊江。

Spring Framework

如何从内部保障企业数据安全?用IT运维审计系统可以吗?

行云管家

网络安全 数据安全 堡垒机 IT运维 运维审计

模块一作业

当归

CERT和CWE之间有什么联系?

鉴释

安全编码规范 cwe cert

云原生多云容器编排平台karmada上手指南

谐云

云原生 开源技术

微信业务架构 | 架构实战营

樊江。

架构实战营

仿照Hystrix,手写一个限流组件

码农参上

限流 Hystrix 8月日更

Go- 数组

HelloBug

数组 Go 语言

cocoapods 的主模块如何判断子模块有没有被加载?

fuyoufang

ios swift 8月日更

阿里巴巴首发:Java核心框架指导手册1小时点击量破千万!

Java 编程 面试 程序人生 Alibaba

我用GPT-3在单个代码库中发现 213个安全漏洞_开源_Chris Koch_InfoQ精选文章