我在Python中有一个服务器/客户端套接字对。服务器接收特定命令,然后准备响应并将其发送到客户端。
在这个问题中,我关注的是代码中的可能的注入:如果可以通过第二个参数请求服务器做一些奇怪的事情 - 如果控制命令内容不足以避免不良行为。
编辑:
shell=True
时添加了参数check_output
。不应该是危险的,因为命令是一个简单的'dir'。
self.client, address = self.sock.accept()
...
cmd = bytes.decode(self.client.recv(4096))
ls
:执行系统命令,但只读取目录的内容。
if cmd == 'ls':
if self.linux:
output = subprocess.check_output(['ls', '-l'])
else:
output = subprocess.check_output('dir', shell=True)
self.client.send(output)
cd
:只需致电os.chdir
。
elif cmd.startswith('cd '):
path = cmd.split(' ')[1].strip()
if not os.path.isdir(path):
self.client.send(b'is not path')
else:
os.chdir(path)
self.client.send( os.getcwd().encode() )
get
:将文件内容发送给客户端。
elif cmd.startswith('get '):
file = cmd.split(' ')[1].strip()
if not os.path.isfile(file):
self.client.send(b'ERR: is not a file')
else:
try:
with open(file) as f: contents = f.read()
except IOError as er:
res = "ERR: " + er.strerror
self.client.send(res.encode())
continue
... (send the file contents)
答案 0 :(得分:3)
除了实现细节之外,我看不到直接注入任意代码的任何可能性,因为您不使用您使用的唯一命令中的接收参数(ls -l
和{{1} })。
但是您可能仍然存在一些安全问题:
通过路径定位命令而不是使用绝对位置。如果有人可以改变路径环境变量会发生什么...... =>我建议你直接使用dir
,它是便携的,风险较小。
您似乎无法控制允许的文件。如果我正确地记得在较旧的Windows版本上阅读os.listdir('.')
或其他特殊文件会产生奇怪的结果。你应该从不提供任何合理的文件,配置,......
您可以控制所询问文件的长度,以避免用户尝试使用异常长的文件名打破服务器。
答案 1 :(得分:2)
客户端 - 服务器方案中的典型问题是:
shell=True
,也会发生这种情况。例如。将subprocess.check_output('dir %s' % dir, shell=True)
与客户端提供的dir
变量一起使用将是一个安全问题,dir
可能会有c:\ && deltree c:\windows
之类的值(由于其灵活性,已添加了第二个命令shell的命令行解释器)。这种攻击的一种相对罕见的变化是客户端能够影响像PATH
这样的环境变量,欺骗服务器运行与预期不同的命令。fopen()
不仅会打开文件,还会提取URL。这允许将URL传递给期望文件名的功能,并使用服务器软件播放各种技巧。幸运的是,Python是一种理智的语言 - open()
适用于文件而不是其他任何东西。但是,如果使用客户端提供的信息(SQL Injection)动态生成SQL查询,则数据库命令仍然存在问题。../../../etc/passwd
作为参数,您可以读取任何文件。另一种典型情况是服务器允许只读取具有特定文件扩展名的文件(例如.png
),但传递类似passwords.txt\0harmless.png
的内容仍允许读取其他类型的文件。在这些问题中,只有最后一个似乎存在于您的代码中。实际上,您的服务器根本不检查客户端应该允许读取的目录和文件 - 这是一个潜在的问题,客户端可能能够读取机密文件。