首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >非交互过程的密码管理

非交互过程的密码管理
EN

Stack Overflow用户
提问于 2015-12-20 11:40:43
回答 1查看 277关注 0票数 1

挑战

我需要一个密码管理工具,它将被其他进程(所有类型的脚本: python、php、perl等)调用,并且它将能够识别和验证调用者脚本以执行访问控制:要么返回密码,要么退出-1。

目前的执行情况

在研究了各种框架之后,我决定使用pythonkeepassdb,它能够处理Keepass V1.X后端数据库文件并构建我自己的访问控制覆盖层(因为以后可以为用户/组访问定制并集成到LDAP中)。访问控制是通过重载每个条目的notes字段来完成的,其中包括允许访问密码的SHA-256散列。(请注意,这也验证了脚本没有被任何人更改)

使用-p参数调用密码管理器,该参数是被调用脚本/应用程序的PID,将执行以下步骤:

  1. 从它自己的PID开始,递归地“向上”查找父母。在到达进程1之前,必须找到调用方PID,该进程是具有父级0的init。这样,我们就知道是谁调用了这个密码管理器实例。
  2. 获取该进程的完整命令行,并对其进行分析,寻找脚本语言,包括python、perl、php、bash、bat、groovy等(为此使用shlex)。
  3. 计算脚本的绝对路径并计算其SHA。
  4. 将其与数据库值进行比较,看看是否存在,是否允许脚本具有以标准格式以stdout格式返回的密码。如果没有,用-1退出。

问题所在

上面的实现对于合法的脚本很有效,但是很容易混淆它。让caller.py是允许访问特定条目e的脚本。运行它时,命令行看起来像python /path/to/caller.py arg1 arg2。分析命令行的代码是:

代码语言:javascript
运行
复制
cmd = walk_ppids(pid)
lg.debug(cmd)
if cmd is False:
    lg.error("PID %s is not my parent process or not a process at all!" % pid)
    sys.exit(-1)

cmd_parts = shlex.split(cmd)
running_script = ""
for p in cmd_parts:
    if re.search("\.(php|py|pl|sh|groovy|bat)$", p, re.I):
        running_script = p
        break

if not running_script:
    lg.error("Cannot identify this script's name/path!")
    sys.exit(-1)

running_script = os.path.abspath(running_script)
lg.debug("Found "+running_script)

phash = hash_file(open(running_script, 'rb'), hashlib.sha256())

父进程的命令行是使用以下方法获得的:

代码语言:javascript
运行
复制
os.popen("ps -p %s -o args=" % ppid).read().strip()

现在,混淆上述函数的最简单方法是创建一个没有.sh扩展的shell脚本,该扩展以caller.py作为第一个参数。sh不使用其参数,而是调用查询条目e的密码管理器。命令行看起来像fake_sh ./caller.py,因此上面的代码返回.这是不该做的事。

问题

人们可能会认为,这是很久以前解决的一个常见问题,没有程序员硬编码就会进入脚本/应用程序,但我做了几天的研究,似乎找不到任何类似的方法。我明白这个问题是比较开放的,所以我会接受以下的答案:

  • 我在重新发明方向盘吗?是否有类似的框架/软件?
  • 这是依赖PID的正确方法吗?还有别的办法吗?
  • 就实现而言,所发布的代码是否能够得到改进,使其更健壮,也不那么容易混淆?(shlex分析部分)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-20 13:43:24

改进:使规则更加严格

第一步是确认正确的扩展在正确的解释器上运行,这意味着caller.py不能在/bin/bash上运行。

类似的漏洞可以通过python利用,例如命令python -W ./caller.py ./myUberHack.py。命令行分析器查找解释器的第一个.py参数时会认为caller.py正在运行.但事实并非如此。

为所有解释器构建所有调用规则太费时了,所以我对假设进行了硬编码。这些存储在tuple中,每一行都是:

代码语言:javascript
运行
复制
(file extension, positional argument, interpreter first letters)
代码语言:javascript
运行
复制
exts = (
    (".py", 1, "python"), 
    (".php", 2, "php"),
    (".pl", 1, "perl"),
    (".sh", 1, "/bin/bash"), # Assumption, we accept only bash 
    (".groovy", 1, "groovy"),
    (".rb", 1, "ruby"),
)
"""Matching extensions to positional arguments and interpreters"""

现在的验证代码是:

代码语言:javascript
运行
复制
for i in exts:
    # Check the specified cmdline position and extension
    if cmd_parts[i[1]].strip().endswith(i[0]):
        lg.debug("Checking "+cmd_parts[i[1]])
        running_script = cmd_parts[i[1]]

        # Make sure that the interpretter matches the extension
        if running_script.endswith(i[0]) and not cmd_parts[0].startswith(i[2]):
            lg.error("Wrong interpretter... go away...")
            sys.exit(-1)

        break

现在没有比这更好的了..。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34380618

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档