Python Subprocess库在运用中或许存在的安全危险总结

访客5年前关于黑客接单1563

在各大抢手言语排行榜中,Python言语屡次独占鳌头,其高效的开发功率和高雅的编程风格招引不少开发人员的喜爱,不少公司将技能栈切换至Python。跟着Python 言语的愈来愈盛行,其安全问题也益发遭到安全人员的重视。作为新一代的言语,尽管其相较于PHP等传传统(资历老一些的言语)言语在安全性上有许多改善,但仍然面对不少安全问题,本文以最为盛行的Python 子进程库subprocess为例剖析其在运用中常见的安全圈套,详文如下。
0×01.  函数调用死锁危险
1)死锁 *** 1
subprocess.call
subprocess.check_call
subprocess.check_output
以上三个函数在运用stdout=PIPE or stderr=PIPE 存在死锁危险
处理计划:
若要运用stdout=PIPE or stderr=PIPE,主张运用popen.communicate()
subprocess 官方文档在上面几个函数中都标示了安全正告:

2) 死锁 *** 2
关于popen ,  popen.wait() 或许会导致死锁
处理计划:
那死锁问题怎么防止呢?官方文档里引荐运用 Popen.communicate()。这个 *** 会把输出放在内存,而不是管道里,所以这时分上限就和内存大小有关了,一般不会有问题。并且假如要取得程序返回值,能够在调用 Popen.communicate() 之后取 Popen.returncode 的值。
3)死锁 *** 3
call、check_call、popen、check_output 这四个函数,参数shell=True,指令参数不能为list,若为list则引发死锁
处理计划:
参数shell=True时,指令参数为字符串 ***
0×02. 封闭subprocess.Popen 子进程时存在子进程封闭失利而成为僵尸进程的危险
Python 规范库 subprocess.Popen 是 shellout 一个外部进程的首选,它在 Linux/Unix 平台下的完成 *** 是 fork 发生子进程然后 exec 载入外部可履行程序。
所以问题就来了,假如咱们需求一个相似“夹具”的子进程(比方运转 Web 集成测验的时分跑起来的那个被测验 Server), 那么就需求在退出上下文的时分整理现场,也便是完毕被跑起来的子进程。
最简略粗犷的做法能够是这样:
 @contextlib.contextmanager
def process_fixture(shell_args):
 proc = subprocess.Popen(shell_args)
 try:
    yield
 finally:
    # 不管是否发作反常,现场都是需求整理的
     proc.terminate()
     proc.wait()
    
if __name__ == '__main__':
    with process_fixture(['python', 'SimpleHTTPServer', '8080']) as proc:
    print('pid %d' % proc.pid)
    print(urllib.urlopen('http://localhost:8080').read())
那个 proc.wait() 是不能够偷闲省掉的,不然假如子进程被间断了而父进程持续运转, 子进程就会一向占用 pid 而成为僵尸,直到父进程也间断了才被托孤给 init 整理掉。
这个简略粗犷版对简略的状况或许有用,可是被运转的程序或许没那么听话。被运转程序或许会再fork 一些子进程来作业,自己则只当监工 —— 这是不少 Web Server 的做法。 对这种被运转程序假如简略地 terminate ,也即对其 pid 发 SIGTERM , 那就相当于谋杀了监工进程,真实的作业进程也就因而被托孤给 init ,变成变形的看护进程…… 嗯没错,这便是我一开始遇到的问题,CI Server上分明现已间断了 Web Server 进程了,下一轮测验跑起来的时分端口仍然是被占用的。
处理计划:
这个问题略微有点扎手,由于自从被运转程序 fork 今后,发生的子进程都享有独立的进程空间和pid ,也便是它超出了咱们触碰的规模。好在 subprocess.Popen 有个 preexec_fn 参数,它承受一个回调函数,并在 fork 之后 exec 之前的空隙中履行它。咱们能够运用这个特性对被运转的子进程做出一些修正,比方履行 setsid() 建立一个独立的进程组。Linux 的进程组是一个进程的调集,任何进程用体系调用 setsid 能够创立一个新的进程组,并让自己成为领袖进程。领袖进程的子子孙孙只需没有再调用 setsid 建立自己的独立进程组,那么它都将成为这个进程组的成员。 之后进程组内只需还有一个存活的进程,那么这个进程组就仍是存在的,即便领袖进程现已逝世也不破例。 而这个存在的含义在于,咱们只需知道了领袖进程的 pid(一起也是进程组的 pgid ), 那么能够给整个进程组发送 signal ,组内的一切进程都会收到。
因而运用这个特性,就能够通过 preexec_fn 参数让 Popen 建立自己的进程组, 然后再向进程组发送 SIGTERM 或 SIGKILL ,间断 subprocess.Popen 所发动进程的子子孙孙。当然,条件是这些子子孙孙中没有进程再调用 setsid 割裂自立门户。
前文的比如通过修正是这样的:
import signal
import os
import contextlib
import subprocess
import logging
import warnings
@contextlib.contextmanager
def process_fixture(shell_args):
 proc = subprocess.Popen(shell_args, preexec_fn=os.setsid)
 try:
    yield
 finally:
    proc.terminate()
    proc.wait()
 try:
    os.killpg(proc.pid, signal.SIGTERM)
 except OSError as e:
    warnings.warn(e)
Python 3.2 之后 subprocess.Popen 新增了一个选项 start_new_session ,Popen(args, start_new_session=True) 即等效于 preexec_fn=os.setsid 。这种运用进程组来整理子进程的子孙的 *** ,比简略地间断子进程自身愈加“洁净”。根据 Python 完成的 Procfile 进程管理东西 Honcho 也采用了这个 *** 。当然,由于不能确保被运转进程的子进程必定不会调用 setsid , 所以这个 *** 不能算“通用”,只能算“相对可用”。假如真的要百分之百通用,那么像 systemd 那样运用 cgroups 来追溯进程创立进程也许是仅有的 *** 。也难怪说 systemd是之一个能正确地封闭服务的 init 东西。

[1] [2]  黑客接单网

相关文章

深化了解Json Web Token之概念篇

以下,或许你能够在各大网站上搜到,可是关于JWE 的内容,却鲜有见识。下文是我读了json web token handle book后,用自己的了解写下的,如有疑问,欢迎谈论。首要参阅文本JWT H...

我的世界黑客寻找是什么歌

ubuntuRestart=on-abortServer built: 2018-03-02T02:19:31我的世界黑客寻找是什么歌, 漏洞分析该token字段包含不可见的某些位对齐子字段,最低的8...

Game-of-Thrones-CTF-1.0靶机实战演练

0×01 前语 这个靶机的主题是“权力的游戏”,难度在中高水平,方针是取得七国的flag和四个额定的flag,其间包含三个secret flag和一个final flag,需求一点《权力的游戏》的常识...

危机处理专家_黑客能找什么样的工作-去哪里找黑客呢

「危机处理专家_黑客能找什么样的工作-去哪里找黑客呢」图18 HackRF脚本遍历后得到完好的跳频序列MITM,全称为Man In The Middle,即中间人。 地址解析协议是建立在网络中各个主机...

全国最大诚信黑客接单_国外怎么找黑客合作

这种办法中,关于给定的种子文件 S1,随机选取 chunk C1,随机选取种子文件 S2,找到 S2 中与 C1 类型相同的 chunk C2,将 C2 替换到 C1 的方位上。 · 一群欺诈者建立...

木马制作_手机被黑客锁了找客服-黑客接单平台

region.save(pic_text_path)CLR 和 保管代码(Manage Code)这儿咱们能够运用一种更为高档的注入方法——cookie注入。 cookie注入其原理也和平常的注入相同...