GPT-4,有人说「好用」,当把一段杂乱的文本内容分享给它时,它会自动调优,输出一段合理、逻辑通顺的语句;有人说「没什么帮助」,它生成的代码片段经常引入了不存在的库,无法快速地投入到生产环境中;也有人说「不好」,怎么都绕不开它一本正经胡说八道的圈。
在不同场景下,GPT-4 的优劣有所差异,但究竟如何,还得切身体验了才知道。近日,美国调查新闻网站 The Intercept 信息安全部总监、DDoSecrets 顾问 Micah Lee 心血来潮,拿着 GPT-4 去 CTF(Capture The Flag,中文一般译作“夺旗赛”,在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式)上“炸了一把场”。
庆幸的是,CTF 中(几乎)没有作弊这一说。在 GPT-4 的帮助下,他不仅获得了更多的“旗帜”,也有一些不同的 GPT-4 的使用经验想要分享。接下来,我们不妨一起来看一下。
解决问题与出错并存的 GPT-4
Micah Lee 表示,“如果没有 GPT-4 的帮助,我肯定只能得到有限的几个旗帜。对于 GPT-4 不能独立解决的问题,它提供了非常有用的提示,或者快速编写了一些脚本,而这些脚本对于我自己来说,是非常乏味或耗时的。
我还发现有几种情况,ChatGPT 可能会直接报错并拒绝给我答案。我想这是当我明显地想在黑客方面得到帮助时,才会发生的情况。例如,当我问它如何编写一些可以绕过特定的 XSS 过滤器的 JavaScript 代码,并且使用明确表示我正在尝试绕过 XSS 过滤器的语言时,它就输出失败并且报错。似乎 ChatGPT 有一些名义上的保护措施来防止人们将其用于恶意黑客攻击,但如果你只是询问详细的技术问题(可用于进攻或防御),它往往会回答这些问题。”
综上,Micah Lee 基于以下三个技术挑战进行了经验分享:
Shamir 秘密共享
perckel
Shell 障碍
之所以选择这个三个挑战,Micah Lee 解释道,部分原因是给 GPT-4 提供回答问题所需的背景并不容易描述。例如,你不能向 GPT-4 发送一个 30MB 的 APK 文件,然后要求它帮助你进行逆向工程,或者把一个网络应用的所有源代码复制到 GPT-4 中,然后要求它找到漏洞。不过,你可以把所有问题划分成小模块,然后逐个向 GPT-4 提问。
Shamir 秘密共享
Shamir 秘密共享(Shamir Secret Sharing,SSS)是一种加密算法,它允许不同的各方通过持有*shares* 来共同共享单个秘密的所有权。
在这个挑战中,Micah Lee 在大赛会场上四处寻找可以扫描的 QR 码。在 Shamir 秘密共享方案中,一个秘密被分成一定数量,如果一个人拥有这些部分的答案,他们就可以解密。
在这个背景下,秘密被分成了 7 个部分,阈值为 5。最终,Micah Lee 转了一圈之后,找到了其中 6 个部分。然后他简单地要求 GPT-4 来解决问题:
以下是 Shamir 秘密共享的部分内容:
Share 1 of 7 (min 5): (x1, y1) = (1, 12214173319090360239218007) Field prime = 2^89 - 1 Flag = CTF{secretasletters} Secret -> base 27 a = 1, b = 2, ... z = 26 (base 27)
Share 3 of 7 (min 5): (x3, y3) = (3, 272214528378786743506941922) Field prime = 2^89 - 1 Flag = CTF{secretasletters} Secret -> base 27 a = 1, b = 2, ... z = 26 (base 27)
Share 4 of 7 (min 5): (x4, y4) = (4, 404905998942651879217397287) Field prime = 2^89 - 1 Flag = CTF{secretasletters} Secret -> base 27 a = 1, b = 2, ... z = 26 (base 27)
Share 5 of 7 (min 5): (x5, y5) = (5, 589183787842889173793388269) Field prime = 2^89 - 1 Flag = CTF{secretasletters} Secret -> base 27 a = 1, b = 2, ... z = 26 (base 27)
Share 6 of 7 (min 5): (x6, y6) = (6, 338337360147368973687481536) Field prime = 2^89 - 1 Flag = CTF{secretasletters} Secret -> base 27 a = 1, b = 2, ... z = 26 (base 27)
Share 7 of 7 (min 5): (x7, y7) = (7, 479528534189573769684386994) Field prime = 2^89 - 1 Flag = CTF{secretasletters} Secret -> base 27 a = 1, b = 2, ... z = 26 (base 27)
我如何解密?
在提出这一问题之后,GPT-4 给出了它的回答:
这个答案有用吗?
为了验证,Micah Lee 把 GPT-4 给出的 Python 脚本复制到了 Decrypt.py 里面,并运行了一下:
$ python3 decrypt.pyCTF{perasperaadastra}震惊了。特别是因为这个挑战实际上包括一个与 base-27 有关的非常棘手的部分,但 GPT-4 在第一次尝试时就解决了所有问题,没有额外提示。
最终,Micah Lee 用 GPT-4 生成的答案,提交了旗帜并得到了分数。
perckel
在 CTF 大赛上,当系统给出这个界面时,Micah Lee 下载了这个名为 flag.bin 的文件,然后试图运行它来弄清楚这个文件是什么。
$ file flag.binflag.bin: perl Storable (v0.7) data (network-ordered) (major 2) (minor 11)不过,Micah Lee 表示,“我不知道这是什么,而且我已经有十多年没有用 Perl 写过任何代码了,所以我问 GPT-4。”
这个文件是什么?
flag.bin: perl Storable (v0.7) data (network-ordered) (main 2) (minor 11)
GPT-4 给出了详细的解释,「这个名为 "flag.bin "的文件是一个二进制文件,其中包含使用 Perl Storable 模块序列化的数据」。
还不错。也许 GPT-4 还能直接编写一个 Perl 脚本,这样我们也就可以看到那个文件里有什么。
所以,Micah Lee 进一步要求 GPT-4:
写一个 Perl 脚本,用于显示该文件中的内容。
成功了!在不懂 Perl 语言的情况下,GPT-4 生成脚本,Micah Lee 把脚本另存为 script.pl 并尝试运行它:
$ perl script.plCan't eval, please set $Storable::Eval to a true value at /System/Library/Perl/5.30/darwin-thread-multi-2level/Storable.pm line 421, at script.pl line 9它希望能够执行任意代码。
当 Micah Lee 在电脑上运行这个时,他想着一直要谨慎操作,但同时让我们看看 GPT-4 是否能帮助解决这个问题:
无法评估,请在 /System/Library/Perl/5.30/darwin-thread-multi-2level/Storable.pm 第 421 行,在 script.pl 第 9 行,将 $Storable::Eval 设为 True 值。
很好, GPT-4 修复了这个脚本。
Micah Lee 成功更新了 script.pl,但他不想直接在电脑上运行它。(GPT-4 很好,分别三次警告有安全风险)。所以,Micah Lee 决定在 Docker 容器中运行这个脚本。
于是,Micah Lee 创建了一个新的 Ubuntu 容器,安装了正确的 Perl 依赖项,然后运行它:
root@22b72f43fc3d:/src# perl ./script.pl Name "Storable::Eval" used only once: possible typo at ./script.pl line 9.$VAR1 = { 'shqa' => 'iryaeuxfc', 'jwjepylpxecq' => 'yfebe',--snip-- 'iruvqhgdnfstz' => 'smkohnqw', 'qcotpliscszql' => 'efzhu', 'decode_flag' => sub { "DUMMY" }, 'htxj' => 'pmifolpyh', 'lftq' => 'pxqqgeqy', 'adbsjrhouqhgg' => 'srndfdboqqmfc', 'avarqfgzrufc' => 'thgzdhdstum', 'pdeqoerfqxbro' => 'grugrmrocnekt', 'ujlw' => 'ooxnyiyu', 'flag' => '��;���@��(�P��@HTX�Т�@��ڂ���@(!k�8�@��Q���@�,��}F�@0Z��W�@��R�J�@���JM��@�#*,�@��E~���@�A����@���Y]��@�v���@@�Nb�@���co6�@������@�� �9�D�|� �@�'Mi�e�@i��^9�@', 'lquykkphh' => 'bjyrsce', 'ruybrycyo' => 'othebxvqngu',--snip-- 'zxyybaaawc' => 'kbzr', 'pojhbzugch' => 'dqxiybapwepfh' };root@22b72f43fc3d:/src#这个脚本输出了 1000 多行代码,显示了这个 Perl 对象的值。大多数键值对似乎都是垃圾,但有两个键很有意思:flag 是一个二进制数据块,另一个 decode_flag 显然是一个 Perl 函数。听起来,也许 flag 是被编码的,Micah Lee 认为可以调用 decode_flag 解码它。
$data 对象有两个有趣的键,flag 是二进制数据,另一个 decode_flag 是一个函数。更新脚本调用该函数 decode_flag 并传入flag 值。
Micah Lee 更新了脚本并再次运行它:
root@22b72f43fc3d:/src# perl script.plName "Storable::Eval" used only once: possible typo at script.pl line 9.Decoded flag: CTF{ooohhh_purrrrl_<3}Shell 障碍
这个挑战提供了一个 Web Terminal 的链接。Micah Lee 可以通过 netcat 进入该主机,并获得一个 shell。下面是 Web Terminal 的样子:
以下是一些命令的输出(为清楚起见,对主机名进行了编辑):
ctf@shurdles:~$ ls -ltotal 2220-r-x--x--x 1 root ctf 2270141 Apr 16 2020 shurdlesMicah Lee 的主文件夹shurdles 有一个调用的可执行文件。他尝试运行它:
ctf@shurdles:~$ ./shurdles shurdle 0 failed: expected at least 1 argument没想到,程序运行失败,并显示一条错误消息,指出它至少需要 1 个参数。这是第一个障碍(shell 障碍),但它很容易解决——Micah Lee 只是通过一个论点:
ctf@shurdles:~$ ./shurdles ASDFshurdle 2 failed: I expected to be called /shurdles, not ./shurdles这奏效了。于是,Micah Lee 便进入了下一个障碍。
没想到的是,下一个障碍很难。这个程序希望 Micah Lee 运行 /shurdles,而不是 ./shurdles。那么该怎么做,再次问问 GPT-4:
我有一个 bash shell。有一个名为 /home/ctf/shurdles 的可执行文件。我可以通过以下命令来运行它:
/home/ctf/shurdles
或者通过更改为文件夹 /home/ctf,然后运行:
./shurdles
我可以使用此命令运行它,而无需创建符号链接吗?
/shurdles
GPT-4 没过多久迅速给出了回应:添加 /home/ctf 到我的 PATH 中,这样我就可以运行 shurdles 了,尽管它并不完美。
不过,Micah Lee 还是试过了,但没有用:
ctf@shurdles:~$ export PATH=$PATH:/home/ctfctf@shurdles:~$ shurdles ASDFshurdle 2 failed: I expected to be called /shurdles, not shurdles所以,Micah Lee 回到 GPT-4 并恳求额外的帮助。
可以运行:
shurdles
但是我该如何运行:
/shurdles
在这种情况下,GPT-4 告诉 Micah Lee 要创建一个 symlink ,尽管这需要root。
然而,Micah Lee 没有 root 权限,所以他要求 GPT-4 想想其他办法。
有没有办法在不使用 symlink 链接和不使用 root 权限的情况下做到这一点?
然后 GPT-4 想出了一个 Micah Lee 自己可能没有想到的好主意:使用 shell 函数。
不幸的是,这仍然不起任何作用:
ctf@shurdles:~$ function /shurdles() { /home/ctf/shurdles "$@"; }ctf@shurdles:~$ /shurdles ASDFshurdle 2 failed: I expected to be called /shurdles, not /home/ctf/shurdles程序的表面看起来好像是在运行打开 /shurdles,但实际这个 shell 函数正在打开的是 /home/ctf/shurdles,所以这是进程看到的第一个参数。为此,Micah Lee 要求更多帮助:
这是一个好主意,但我实际上需要 argv 的第一个值是 /shurdles。
紧接着,GPT-4 回应了一个出乎意料的答案,用 Micah Lee 自己的话来讲,就是“我甚至从来没听过 exec -a 这个命令”。
Micah Lee 还是决定用这个答案来试一试,不过,因为他的电脑上并没有 vim 或 nano。因此,出于懒惰,Micah Lee 只是要求使用 echo 保存 shurdles_wrapper.sh 的命令。
如何使用 echo 而不是文本编辑器来创建 shurdles_wrapper.sh 脚本?
GPT-4 给了确切的代码:
Micah Lee 对这段代码稍微修改了一下,他将脚本存储在 /tmp/wrapper.sh 而不是 /home/ctf/shurdles_wrapper.sh 中,因为他没有 /home/ctf 的写入访问权限,但这段代码仍然起作用了:
ctf@shurdles:~$ echo -e '#!/bin/bash exec -a /shurdles /home/ctf/shurdles "$@"' > /tmp/wrapper.shctf@shurdles:~$ chmod +x /tmp/wrapper.shctf@shurdles:~$ /tmp/wrapper.sh ASDF shurdle 3 failed: I expected the environment variable "HACKERS" to look like hack the planet on separate lines过了这道坎之后,下一个挑战随之而来。熬过了那个嘈杂!为了节省时间,Micah Lee 再次划分问题,交给了 GPT-4 给答案:
如何将环境变量“HACKERS”设置为“hack the planet”,并让每句都在单独的一行上?
GPT-4 回答道,「你可以通过使用换行符 " "将环境变量 "HACKERS "设置为 "hack the planet "的值,这让每行都在单独的一行里。下面是具体的操作方法.....」
不出意外,GPT-4 再次有效提供了可用的代码:
ctf@shurdles:~$ export HACKERS=$'hack the planet'ctf@shurdles:~$ /tmp/wrapper.sh ASDF shurdle 5 failed: expected workdir "/run/. -- !!"来到下一个障碍。当 Micah Lee 问 GPT-4 如何让他当前的工作目录看起来像:/run/. -- !!,而不需要实际创建该文件夹并对其进行修改。
GPT-4 有一些好主意,包括运行 export PWD='/run/. -- !!' ,不过这段代码没有起作用。
当 Micah Lee 进一步询问 GPT-4,一个命令如何学习其工作目录的不同方式。GPT-4 的建议是,它可以使用 PWD 环境变量,也可以用 getcwd 函数。当 Micah Lee 问 getcwd 如何在没有 PWD 环境变量的情况下学习工作目录时,它给出了一个详细的答案:
Micah Lee 表示,这些 Linux 实现细节涉及了他的知识盲区。要知道,对于开发者而言,他所需要做的事情就是对 GPT-4 提问,并能看懂这款模型输出的代码内容,也不一定完全要掌握相关语言的每个技术点。不过,GPT-4 有时候会自信地说胡话。
在这里,由于 Micah Lee 最初找错了 tree,当他意识到这一问题时,他也发现所有 CTF 大赛的用户都有 /run 的写入权限,所以可以直接创建文件夹并对它进行更改。
在这里,Micah Lee 自己解决了这个障碍问题。
ctf@shurdles:~$ mkdir '/run/. -- !!'ctf@shurdles:~$ cd /run/. -- !!/ctf@shurdles:/run/. -- !!$ /tmp/wrapper.sh ASDFshurdle 6 failed: fd 3 isn't open不过,紧接着,系统便报错了——“fd 3 isn't open”。
对于这个错误,Micah Lee 并不能理解,究竟是必须打开文件或是其他东西。于是,他再次求助 GPT-4:
根据 GPT-4 的解答,Micah Lee 知晓他正在运行的程序需要打开一个文件,所谓 fd 3 是指 file descriptor 3。那解决方案是什么,当以下面疑问向 GPT-4 提问时:
有什么办法可以让我在运行产生这个错误的程序时,让它打开一个额外的资源,这样 file descriptor 3 就会被打开?
GPT-4 建议可以使用 exec 3 命令:
在对这个命令一无所知的情况下,Micah Lee 还是尝试着运行了:
ctf@shurdles:/run/. -- !!$ exec 3>/tmp/fd3_output.txtctf@shurdles:/run/. -- !!$ /tmp/wrapper.sh ASDFshurdle 6 failed: expected fd 3 to be a file of 1337 bytes in length运行结果让跨越这个障碍的进度条再次多了一些。根据提示,接下来 Micah Lee 要做的便是需要在 /tmp/fd3_output.txt 输入 1337 字节的内容。
Micah Lee 表示虽然他自己知道该怎么做,但是想试试 GPT-4 是否会速度更快一些。于是,他提问:
如何使 /tmp/fd3_output.txt 长度为 1337 字节?
GPT-4 如预期中那样,推荐使用 dd 命令:
当 Micah Lee 运行 dd 命令时,/tmp/fd3_output.txt 中内容的确实现了 1337 字节。但是当他运行 exec 3>/tmp/fd3_output.txt 时,意外出现了,系统截断了文件,显示零字节。那该如何解决这个问题呢?
如何修改命令:
exec 3>/tmp/fd3_output.txt
所以当它创建文件 /tmp/fd3_output.txt 时,如何有 1337 字节长?
Micah Lee 用了 GPT-4 输出的代码试过了...但没有用。
ctf@shurdles:/run/. -- !!$ dd if=/dev/zero of=/tmp/fd3_output.txt bs=1 count=1337 && exec 3>/tmp/fd3_output.txt1337+0 records in1337+0 records out1337 bytes (1.3 kB, 1.3 KiB) copied, 0.00219604 s, 609 kB/sctf@shurdles:/run/. -- !!$ /tmp/wrapper.sh ASDFshurdle 6 failed: expected fd 3 to be a file of 1337 bytes in length这其中哪块出现了偏差?把下面这个问题抛给 GPT-4:
当我运行下面代码时:
dd if=/dev/zero of=/tmp/fd3_output.txt bs=1 count=1337 && exec 3>/tmp/fd3_output.txt
似乎 /tmp/fd3_output.txt 仍然是 0 字节。
$ ls -l /tmp/fd3_output.txt -rw-r--r-- 1 CTF CTF 0 23 月 06 日 17:3 /tmp/fd<>_output.txt
GPT-4 对于自己输出错误的内容立刻进行了道歉,并给了另一个解决方案:
运行试试:
ctf@shurdles:/run/. -- !!$ dd if=/dev/zero of=/tmp/fd3_output.txt bs=1 count=1337 && exec 3<>/tmp/fd3_output.txt1337+0 records in1337+0 records out1337 bytes (1.3 kB, 1.3 KiB) copied, 0.0021625 s, 618 kB/sctf@shurdles:/run/. -- !!$ /tmp/wrapper.sh ASDFshurdle 7 failed: tz Local != America/Los_Angeles又一个障碍被跨过去了!接下来,按照运行的结果,就是更新一下时区:
如何将时区设置为 "America/Los_Angeles",以便我运行的下一个命令将其识别为时区?
GPT-4 的答案:
复制代码,运行一下:
ctf@shurdles:/run/. -- !!$ exec 3<>/tmp/fd3_output.txt && TZ="America/Los_Angeles" /tmp/wrapper.sh ASDFshurdle 8 failed: could not find shurdles-helper很轻松地成功了。现在,系统又提示让找到 shurdles-helper。对于这个问题。Micah Lee 自己动手解决了,他创建一个新文件夹,将一个调用的可执行文件放入 shurdles-helper 其中,然后将其添加到 PATH 中。
ctf@shurdles:/run/. -- !!$ mkdir /tmp/binctf@shurdles:/run/. -- !!$ echo -e '#!/bin/bash echo helper' > /tmp/bin/shurdles-helperctf@shurdles:/run/. -- !!$ chmod +x /tmp/bin/shurdles-helperctf@shurdles:/run/. -- !!$ export PATH=/tmp/bin:$PATHctf@shurdles:/run/. -- !!$ exec 3<>/tmp/fd3_output.txt && TZ="America/Los_Angeles" /tmp/wrapper.sh ASDFshurdle 9 failed: expected /home/ctf/.cache/shurdles, does it exist?成功!进入下一个障碍。根据提示,系统希望有 /home/ctf/.cache/shurdles 路径的存在。Micah Lee 再次自己直接创建了一个文件解决了这个问题。
ctf@shurdles:/run/. -- !!$ mkdir -p /home/ctf/.cachectf@shurdles:/run/. -- !!$ touch /home/ctf/.cache/shurdlesctf@shurdles:/run/. -- !!$ exec 3<>/tmp/fd3_output.txt && TZ="America/Los_Angeles" /tmp/wrapper.sh ASDFshurdle 9 failed: /home/ctf/.cache/shurdles was modified in the last day, sorry它也成功了。现在,它需要将时区设置为 America/Los_Angeles。
提问:
你是如何更新文件的修改时间戳的?
GPT-4 回答:
好吧,很简单。Micah Lee 把它设置为一个月前:
ctf@shurdles:/run/. -- !!$ touch -t 202303231430 /home/ctf/.cache/shurdlesctf@shurdles:/run/. -- !!$ exec 3<>/tmp/fd3_output.txt && TZ="America/Los_Angeles" /tmp/wrapper.sh ASDFCongratulations!!!CTF{you_made_it_past_the_hurdles}最后,Congratulations!
写在最后
至此,借助 GPT-4,Micah Lee 在全球最高技术水平和影响力的 CTF 竞赛中取得不错的成绩。而 GPT-4 在不断地提示词之下,虽然其中有些小差错,但也输出了不少非常实用的代码,能为开发者的知识盲区提供一些技术意见。可以说,稍加利用,GPT-4 在辅助编码上将是一股不容忽视的力量。
不过,对此也有网友表示,“这就像在数学考试中使用计算器一样。在某些测试中虽然这项工具是被允许的,但是有些赛事中确实是明令禁止的。这也会让大赛失去一些竞技和趣味”。为此,你怎么看?
参考:
https://news.ycombinator.com/item?id=35683265
https://micahflee.com/2023/04/capturing-the-flag-with-gpt-4/