From a394a3fe49d4f8d67931e11bb7a8cc793047d62b Mon Sep 17 00:00:00 2001 From: oe73773 Date: Sun, 13 Jun 2021 22:30:21 +0200 Subject: [PATCH] FB 7.24 Login --- fritzbox__connection_uptime.py | 2 +- fritzbox__cpu_temperature.py | 2 +- fritzbox__cpu_usage.py | 2 +- fritzbox__memory_usage.py | 2 +- fritzbox__power_consumption.py | 2 +- fritzbox__traffic.py | 2 +- fritzbox__traffic_down.py | 2 +- fritzbox__traffic_up.py | 2 +- fritzbox__uptime.py | 2 +- fritzbox__wifi_devices.py | 2 +- fritzbox_helper.py | 66 +++++++++++++++++++++++++++++----- 11 files changed, 67 insertions(+), 19 deletions(-) mode change 100644 => 100755 fritzbox__connection_uptime.py mode change 100644 => 100755 fritzbox__cpu_temperature.py mode change 100644 => 100755 fritzbox__cpu_usage.py mode change 100644 => 100755 fritzbox__memory_usage.py mode change 100644 => 100755 fritzbox__power_consumption.py mode change 100644 => 100755 fritzbox__traffic.py mode change 100644 => 100755 fritzbox__traffic_down.py mode change 100644 => 100755 fritzbox__traffic_up.py mode change 100644 => 100755 fritzbox__uptime.py mode change 100644 => 100755 fritzbox__wifi_devices.py mode change 100644 => 100755 fritzbox_helper.py diff --git a/fritzbox__connection_uptime.py b/fritzbox__connection_uptime.py old mode 100644 new mode 100755 index b36d76f..728c1ab --- a/fritzbox__connection_uptime.py +++ b/fritzbox__connection_uptime.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ fritzbox_connection_uptime - A munin plugin for Linux to monitor AVM Fritzbox connection uptime Copyright (C) 2015 Christian Stade-Schuldt diff --git a/fritzbox__cpu_temperature.py b/fritzbox__cpu_temperature.py old mode 100644 new mode 100755 index e608c72..7f5d2f5 --- a/fritzbox__cpu_temperature.py +++ b/fritzbox__cpu_temperature.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ fritzbox_cpu_temperature - A munin plugin for Linux to monitor AVM Fritzbox Copyright (C) 2015 Christian Stade-Schuldt diff --git a/fritzbox__cpu_usage.py b/fritzbox__cpu_usage.py old mode 100644 new mode 100755 index 9109844..c46c3cf --- a/fritzbox__cpu_usage.py +++ b/fritzbox__cpu_usage.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ fritzbox_cpu_usage - A munin plugin for Linux to monitor AVM Fritzbox Copyright (C) 2015 Christian Stade-Schuldt diff --git a/fritzbox__memory_usage.py b/fritzbox__memory_usage.py old mode 100644 new mode 100755 index 868ce43..9a24ee1 --- a/fritzbox__memory_usage.py +++ b/fritzbox__memory_usage.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ fritzbox_memory_usage - A munin plugin for Linux to monitor AVM Fritzbox Copyright (C) 2015 Christian Stade-Schuldt diff --git a/fritzbox__power_consumption.py b/fritzbox__power_consumption.py old mode 100644 new mode 100755 index 8f1a143..07a2154 --- a/fritzbox__power_consumption.py +++ b/fritzbox__power_consumption.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # coding=utf-8 """ fritzbox_power_consumption - A munin plugin for Linux to monitor AVM Fritzbox diff --git a/fritzbox__traffic.py b/fritzbox__traffic.py old mode 100644 new mode 100755 index 73fe90a..a6bc96f --- a/fritzbox__traffic.py +++ b/fritzbox__traffic.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ fritzbox_traffic - A munin plugin for Linux to monitor AVM Fritzbox WAN traffic Copyright (C) 2015 Christian Stade-Schuldt diff --git a/fritzbox__traffic_down.py b/fritzbox__traffic_down.py old mode 100644 new mode 100755 index 9f9b13d..d2fd544 --- a/fritzbox__traffic_down.py +++ b/fritzbox__traffic_down.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ fritzbox_traffic - A munin plugin for Linux to monitor AVM Fritzbox WAN traffic Copyright (C) 2015 Christian Stade-Schuldt diff --git a/fritzbox__traffic_up.py b/fritzbox__traffic_up.py old mode 100644 new mode 100755 index 8c1a8eb..70e1e1d --- a/fritzbox__traffic_up.py +++ b/fritzbox__traffic_up.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ fritzbox_traffic - A munin plugin for Linux to monitor AVM Fritzbox WAN traffic Copyright (C) 2015 Christian Stade-Schuldt diff --git a/fritzbox__uptime.py b/fritzbox__uptime.py old mode 100644 new mode 100755 index 6463626..d00a0e4 --- a/fritzbox__uptime.py +++ b/fritzbox__uptime.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ fritzbox_uptime - A munin plugin for Linux to monitor AVM Fritzbox Copyright (C) 2015 Christian Stade-Schuldt diff --git a/fritzbox__wifi_devices.py b/fritzbox__wifi_devices.py old mode 100644 new mode 100755 index f9efb9a..ecefd33 --- a/fritzbox__wifi_devices.py +++ b/fritzbox__wifi_devices.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ fritzbox_wifi_devices - A munin plugin for Linux to monitor AVM Fritzbox Copyright (C) 2015 Christian Stade-Schuldt diff --git a/fritzbox_helper.py b/fritzbox_helper.py old mode 100644 new mode 100755 index 7c9fcd3..074b01e --- a/fritzbox_helper.py +++ b/fritzbox_helper.py @@ -1,12 +1,17 @@ -#!/usr/bin/env python """ fritzbox_helper - A munin plugin for Linux to monitor AVM Fritzbox Copyright (C) 2015 Christian Stade-Schuldt Author: Christian Stade-Schuldt Like Munin, this plugin is licensed under the GNU GPL v2 license http://www.opensource.org/licenses/GPL-2.0 - Add the following section to your munin-node's plugin configuration: + Copyright (c) 2021 Oliver Edelmann + Author: Oliver Edelmann + Like Munin, this plugin is licensed under the GNU GPL v2 license + http://www.opensource.org/licenses/GPL-2.0 + + + Add the following section to your munin-node's plugin configuration: [fritzbox_*] env.fritzbox_ip [ip address of the fritzbox] env.fritzbox_password [fritzbox password] @@ -24,10 +29,49 @@ import hashlib import sys import requests +import urllib.parse from lxml import etree USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:10.0) Gecko/20100101 Firefox/10.0" +""" + Code from https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AVM_Technical_Note_-_Session_ID_deutsch_2021-05-03.pdf + start +""" +class LoginState: + def __init__(self, challenge: str, blocktime: int): + self.challenge = challenge + self.blocktime = blocktime + self.is_pbkdf2 = challenge.startswith("2$") + +def calculate_pbkdf2_response(challenge: str, password: str) -> str: + """ Calculate the response for a given challenge via PBKDF2 """ + challenge_parts = challenge.split("$") + # Extract all necessary values encoded into the challenge + iter1 = int(challenge_parts[1]) + salt1 = bytes.fromhex(challenge_parts[2]) + iter2 = int(challenge_parts[3]) + salt2 = bytes.fromhex(challenge_parts[4]) + # Hash twice, once with static salt... + hash1 = hashlib.pbkdf2_hmac("sha256", password.encode(), salt1, iter1) + # Once with dynamic salt. + hash2 = hashlib.pbkdf2_hmac("sha256", hash1, salt2, iter2) + return f"{challenge_parts[4]}${hash2.hex()}" + + +def calculate_md5_response(challenge: str, password: str) -> str: + """ Calculate the response for a challenge using legacy MD5 """ + response = challenge + "-" + password + # the legacy response needs utf_16_le encoding + response = response.encode("utf_16_le") + md5_sum = hashlib.md5() + md5_sum.update(response) + response = challenge + "-" + md5_sum.hexdigest() + return response +""" + Code from https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AVM_Technical_Note_-_Session_ID_deutsch_2021-05-03.pdf + start +""" def get_session_id(server, password, port=80): """Obtains the session id after login into the Fritzbox. @@ -52,14 +96,17 @@ def get_session_id(server, password, port=80): print(err) sys.exit(1) + root = etree.fromstring(r.content) session_id = root.xpath('//SessionInfo/SID/text()')[0] + user_id = root.xpath('//SessionInfo/Users/User/text()')[0] + challenge = root.xpath('//SessionInfo/Challenge/text()')[0] + if session_id == "0000000000000000": - challenge = root.xpath('//SessionInfo/Challenge/text()')[0] - challenge_bf = ('{}-{}'.format(challenge, password)).encode('utf-16le') - m = hashlib.md5() - m.update(challenge_bf) - response_bf = '{}-{}'.format(challenge, m.hexdigest().lower()) + if challenge.startswith("2$"): + response_bf = calculate_pbkdf2_response(challenge, password) + else: + response_bf = calculate_md5_response(challenge, password) else: return session_id @@ -67,9 +114,10 @@ def get_session_id(server, password, port=80): "Content-Type": "application/x-www-form-urlencoded", "User-Agent": USER_AGENT} - url = 'http://{}:{}/login_sid.lua?&response={}'.format(server, port, response_bf) + url = 'http://{}:{}/login_sid.lua?version=2'.format(server, port) try: - r = requests.get(url, headers=headers) + data = {"username": "fritz8535", "response": response_bf} + r = requests.post(url, urllib.parse.urlencode(data).encode(), headers=headers) r.raise_for_status() except requests.exceptions.HTTPError as err: print(err)