挑战
我需要一个密码管理工具,它将被其他进程(各种脚本:python、php、perl等)调用,它将能够识别和验证调用方脚本,以便执行访问控制:返回密码或退出-1
当前实现
在研究了各种框架之后,我决定使用python的keepassdb,它能够处理Keepass V1.X后端数据库文件并构建自己的访问控制覆盖层(因为这可以在以后被定制并集成到LDAP中以供用户/组访问)。访问控制是通过重载每个条目的notes字段来完成的,以包括允许访问密码的SHA-256哈希列表。(请注意,这也会验证脚本是否被任何人更改)
使用-p参数调用密码管理器,该参数是被调用方脚本/应用程序的PID,将执行以下步骤:从它自己的PID开始递归地“向上”查找并寻找父对象。在到达进程1之前,必须找到调用方PID,该进程是父进程0的init。这样我们就可以确定谁调用了这个密码管理器实例。在
获取该(父)进程的完整命令行并分析它,寻找脚本语言,包括python、perl、php、bash、bat、groovy等(为此使用shlex)
找出脚本的绝对路径并计算其SHA
将其与数据库值进行比较,看看是否存在,如果存在,则允许脚本具有以标准格式返回的stdout中的密码。否则,用-1退出。在
问题
上面的实现对于合法脚本很好地工作,但是很容易混淆它。让caller.py是一个允许访问特定项e的脚本。运行它的命令行看起来像python /path/to/caller.py arg1 arg2。解析命令行的代码是: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())
父进程的命令行通过以下方式获取:
^{pr2}$
现在,混淆上述函数的最简单方法是创建一个不带.sh扩展名的shell脚本,该扩展名将caller.py作为第一个参数。sh不使用其参数,而是调用密码管理器查询条目e。命令行看起来像fake_sh ./caller.py,因此上面的代码返回pass。。。这样做是错误的。在
问题
有人会认为这是很久以前解决的一个常见问题,没有程序员对脚本/应用程序进行硬编码,但我做了几天的研究,似乎没有找到任何类似的方法。我明白这个问题是开放式的,所以我接受以下问题的答案:我是在重新发明轮子吗?有没有一个框架/软件可以做类似的事情?在
依靠PIDs,这是正确的方法吗?还有别的办法吗?在
在实现方面,是否可以改进发布的代码,使其更健壮,而不是那么容易混淆?(shlex分析部分)