我有一个简单的脚本,可以读取用户的输入(密码)并将其保存到变量中
read -s -p "password: " PASSWD; printf "%b" "\n"
显然这并不安全,因为它以明文形式存储在内存中,并且可以通过核心转储访问它?我如何从内存中读取此变量。请注意,我不是在寻找更好的解决方案,我只是好奇我是否真的可以读取此密码/变量。
答案1
root 始终可以(对于几乎所有的始终值)读取进程内存,因此无论它如何存储,都可以提取它(即使密码被发送到安全存储设备(如智能卡、iButton 或 TPM 硬件))。
在您的示例中,PASSWD 将存储在本地变量中。进程的环境变量存储在其中/proc/PID/environ
,并可由该用户或 root 读取:
[choad ~]$ read -s -p "password: " PASSWD; echo
password:
[choad ~]$ echo $PASSWD
soopersekrit
[choad ~]$ ls -al /proc/self/environ
-r-------- 1 michael michael 0 May 6 14:46 /proc/self/environ
[choad ~]$ grep PASSWD /proc/self/environ
[choad ~]$ export PASSWD
[choad ~]$ tr '\000' '\n' < /proc/self/environ | grep PASSWD
PASSWD=soopersekrit
[choad ~]$ echo $$
19613
[choad ~]$ gdb -p 19613
(gdb) info proc mappings
0x91f2000 0x9540000 0x34e000 0 [heap]
(gdb) dump memory /tmp/bash.mem 0x91f2000 0x9540000
[choat ~]$ strings /tmp/bash.mem |grep ^PASSWD
PASSWD=soopersekrit
PASSWD=soopersekrit
注意:一些发行版启用了 Yama 的ptrace_scope
限制,以防止附加到同一用户拥有的任意进程。
注意:通过命令行传递密码时要格外小心。不要将任何内容作为参数传递,以免让所有人都知道。命令行不是受保护。
答案2
在实现以下操作系统的系统中,访问另一个进程的内存区域并不容易:内存保护。
如果您怀疑其他进程/用户会尝试此操作,则可以利用此变量,然后立即将其清空。如果这适用于您的情况,您还可以尝试存储密码的哈希副本。
答案3
不管怎样,密码都必须留在内存中以供您使用(您可以在 CPU 中存储一些 AES 密码,我忘了这种技术叫什么,但除此之外,它要么在内存中,要么您每次都提示用户重新输入然后擦除它)。
如果你想转储整个内存,你可以使用内存转储,但要小心,因为将其写入磁盘也会使用内存,所以您可能会在转储该部分之前覆盖它:)(当然,如果您的脚本/程序仍在运行,则该部分内存仍在“使用”,因此它不会被覆盖)
然后,您可以尝试在转储中查找您的密码,它会在那里(可能不止一次)。如果您不知道密码存储在哪里(以及它是什么),那么找出密码存储在哪里(以及它是什么)是一项困难得多的任务。
您还可以尝试阅读这- 该页面目前似乎已关闭,但谷歌仍缓存了它。