深入浅出Flask PIN( 二 )

def get_pin_and_cookie_name(app: "WSGIApplication",) -> t.Union[t.Tuple[str, str], t.Tuple[None, None]]:"""Given an application object this returns a semi-stable 9 digit pincode and a random key.The hope is that this is stable betweenrestarts to not make debugging particularly frustrating.If the pinwas forcefully disabled this returns `None`.Second item in the resulting tuple is the cookie name for remembering."""pin = os.environ.get("WERKZEUG_DEBUG_PIN")rv = Nonenum = None# Pin was explicitly disabledif pin == "off":return None, None# Pin was provided explicitlyif pin is not None and pin.replace("-", "").isdigit():# If there are separators in the pin, return it directlyif "-" in pin:rv = pinelse:num = pinmodname = getattr(app, "__module__", t.cast(object, app).__class__.__module__)username: t.Optional[str]try:# getuser imports the pwd module, which does not exist in google# App Engine. It may also raise a KeyError if the UID does not# have a username, such as in Docker.username = getpass.getuser()except (ImportError, KeyError):username = Nonemod = sys.modules.get(modname)# This information only exists to make the cookie unique on the# computer, not as a security feature.probably_public_bits = [username,modname,getattr(app, "__name__", type(app).__name__),getattr(mod, "__file__", None),]# This information is here to make it harder for an attacker to# guess the cookie name.They are unlikely to be contained anywhere# within the unauthenticated debug page.private_bits = [str(uuid.getnode()), get_machine_id()]h = hashlib.sha1()for bit in chain(probably_public_bits, private_bits):if not bit:continueif isinstance(bit, str):bit = bit.encode("utf-8")h.update(bit)h.update(b"cookiesalt")cookie_name = f"__wzd{h.hexdigest()[:20]}"# If we need to generate a pin we salt it a bit more so that we don't# end up with the same value and generate out 9 digitsif num is None:h.update(b"pinsalt")num = f"{int(h.hexdigest(), 16):09d}"[:9]# Format the pincode in groups of digits for easier remembering if# we don't have a result yet.if rv is None:for group_size in 5, 4, 3:if len(num) % group_size == 0:rv = "-".join(num[x : x + group_size].rjust(group_size, "0")for x in range(0, len(num), group_size))breakelse:rv = numreturn rv, cookie_name返回的rv就是PIN码,但这个函数核心是将列表里的值hash,我们不需要去读懂这段代码,只需要将列表里的值填上直接运行代码就行 。
生成要素:

username
通过getpass.getuser()读取,通过文件读取/etc/passwd
modname
通过getattr(mod,“file”,None)读取,默认值为flask.app
appname
通过getattr(app,“name”,type(app).name)读取,默认值为Flask
moddir
当前网络的mac地址的十进制数,通过getattr(mod,“file”,None)读取实际应用中通过报错读取
uuidnode
通过uuid.getnode()读取,通过文件
/sys/class.NET/eth0/address得到16进制结果,转化为10进制进行计算
machine_id
每一个机器都会有自已唯一的id,machine_id由三个合并(docker就后两个):1./etc/machine-id
2./proc/sys/kernel/random/boot_id 3./proc/self/cgroup
当这6个值我们可以获取到时,就可以推算出生成的PIN码
生成算法修改一下就是PIN生成算法
import hashlibfrom itertools import chainprobably_public_bits = ['root',# username'flask.app',# modname'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))'/usr/local/lib/python3.7/site-packages/flask/app.py'# getattr(mod, '__file__', None),]# This information is here to make it harder for an attacker to# guess the cookie name.They are unlikely to be contained anywhere# within the unauthenticated debug page.private_bits = ['2485377957890',# str(uuid.getnode()),/sys/class/net/ens33/address# Machine Id: /etc/machine-id + /proc/sys/kernel/random/boot_id + /proc/self/cgroup'861c92e8075982bcac4a021de9795f6e3291673c8c872ca3936bcaa8a071948b']h = hashlib.sha1()for bit in chain(probably_public_bits, private_bits):if not bit:continueif isinstance(bit, str):bit = bit.encode("utf-8")h.update(bit)h.update(b"cookiesalt")cookie_name = f"__wzd{h.hexdigest()[:20]}"# If we need to generate a pin we salt it a bit more so that we don't# end up with the same value and generate out 9 digitsnum = Noneif num is None:h.update(b"pinsalt")num = f"{int(h.hexdigest(), 16):09d}"[:9]# Format the pincode in groups of digits for easier remembering if# we don't have a result yet.rv = Noneif rv is None:for group_size in 5, 4, 3:if len(num) % group_size == 0:rv = "-".join(num[x: x + group_size].rjust(group_size, "0")for x in range(0, len(num), group_size))breakelse:rv = numprint(rv)


推荐阅读