FRITZ!Box Session-ID/Login mit Bash

lano

Aktives Mitglied
Manchmal möchte man Daten seiner FRITZ!Box abrufen um sie mittels Script weiter zu verarbeiten, anzuzeigen oder sonstigen Schabernack damit zu treiben. Dazu benötigt man eine Session-ID siehe https://avm.de/fileadmin/user_uploa...ttstellen/AVM_Technical_Note_-_Session_ID.pdf

Ein kleines Script hilf dabei

Bash:
#!/bin/bash

IP="fritz.box"
FBUID="user"
SECRET="passwd"

Als erstes brauchen wir die IP der FRITZ!Box, alternativ reicht uns auch der Domain Name, Standard mäßig fritz.box.
Dann muss natürlich ein User auf der FRITZ!Box existieren und wir brauchen das dazugehörige Password.

Als nächstes brauchen wir eine Challenge. Die bekommen wir von der FRITZ!Box mittels wget.
Bash:
CHALLENGE=`wget --no-check-certificate -O - "http://$IP/login_sid.lua" 2>/dev/null | sed 's/.*<Challenge>\(.*\)<\/Challenge>.*/\1/'`

Dann fügen wir Challenge und Password zu einem String zusammen.
Bash:
CPSTR="$CHALLENGE-$SECRET"
Von diesem String benötigen wir den MD5 Hash.

Bevor wir mit md5sum und awk den MD5 Hash erstellen müssen wir iconv bemühen um den String ind das passende Format zu bekommen.
Bash:
MD5=`echo -n $CPSTR | iconv -f ISO8859-1 -t UTF-16LE | md5sum -b | awk '{print substr($0,1,32)}'`
RESPONSE="$CHALLENGE-$MD5"
Nachdem die Challenge wieder vor unseren MD5 Hash gehängt wurde haben wir jetzt unseren Response.

Damit können wir jetzt die URL Parameter zusammen bauen die wir im nächsten Schrit dann wget mitgeben.
Bash:
URL_PARAMS="username=$FBUID&response=$RESPONSE"

Nun können wir die URL zusammen bauen und uns mit wget eine Session-ID holen.
Bash:
SID=`wget --no-check-certificate -O - "https://$IP/login_sid.lua?$URL_PARAMS" 2>/dev/null | sed 's/.*<SID>\(.*\)<\/SID>.*/\1/'`

Nun haben wir eine gültige Session-ID mit der wir nun reichlich viel Blödsinn anstellen können.

Als Beispiel können wir uns die Daten der Übersichtsseite der FRITZ!Box anzeigen lassen.
Bash:
JSON=`wget --no-check-certificate -O - --post-data "xhr=1&sid=$SID&lang=de&page=overview&xhrId=all&useajax=1&no_sidrenew="  "https://$IP/data.lua" 2>/dev/null`
echo $JSON

Als Ausgabe erhalten wir ein unschön formatiertes json.
 
Zuletzt bearbeitet:
Hallo lano,
hallo dev-community,

dieser Beitrag ist super. Gibt es eventuell eine Möglichkeit hier bestimmte Einstellungen anzupassen?

Es geht genau darum per BASH-Script schnell und einfach die VPN-Freigabe zu aktivieren/deaktivieren.

Die URL zu den Freigaben lautet:
Code:
http://fritz.box/?sid=[sid]&lp=shareVpn

Die Checkboxen haben die ids:
Code:
uiConnection2
uiConnection1

Im Grunde müsste hier ein POST-Request ausgeführt werden, welches bewirkt, dass die Checkbox uiConnection2 den Wert 1 (checked) erhält und ein Submit wird ausgelöst. Beim Deaktivieren entsprechend uiConnection2 = 0.

Per SOAP gab es hier kein Befehl, aber dein BASH-Script scheint hier vielversprechend. Ich versuche bereits seit mehreren Tagen erfolglos diese Funktion zu bewerkstelligen und möchte ungern auf ressourcenfressende Tools zurückgreifen.

Auf diese Weise könnte unter Linux per cronjob automatisch die VPN-Verbindung aktiviert und wieder deaktiviert werden.

Hast du hier einen Lösungsansatz? Dein Skript postet bereits Daten über die data.lua, jedoch will meine Herangehensweise nicht funktionieren. Auf mächtige Tools wie selenium würde ich hier gerne verzichten.

Vielen Dank,

Rivertoy
 
Im Grunde müsste hier ein POST-Request ausgeführt werden, welches bewirkt, dass die Checkbox uiConnection2 den Wert 1 (checked) erhält und ein Submit wird ausgelöst. Beim Deaktivieren entsprechend uiConnection2 = 0.
Das sollte funktionieren wenn man die Json daten ans Post mit dran hängt.
Per SOAP gab es hier kein Befehl, aber dein BASH-Script scheint hier vielversprechend.
Ich kann ja bei gelegenheit mal gucken.
 
fb_setJson.sh:
#!/bin/bash

IP="192.168.1.1"
FBUID=$1
SECRET=$2
PAGE=$3
CMD=$4

if [ "$#" -ne 2 ]; then
    echo "usage: $0 <username> <passwd>"
    echo "eg. $0 hans wurst"
    exit
fi


#if ! command -v iconv &> /dev/null
#then
#    echo "iconv could not be found."
#    exit
#fi

if ! command -v md5sum &> /dev/null
then
    echo "md5sum could not be found."
    exit
fi

if ! command -v awk &> /dev/null
then
    echo "awk could not be found."
    exit
fi

CHALLENGE=`wget --no-check-certificate -O - "https://$IP/login_sid.lua" 2>/dev/null | sed 's/.*<Challenge>\(.*\)<\/Challenge>.*/\1/'`

CPSTR="$CHALLENGE-$SECRET"

MD5=`echo -n $CPSTR | iconv -f ISO8859-1 -t UTF-16LE | md5sum -b | awk '{print substr($0,1,32)}'`
RESPONSE="$CHALLENGE-$MD5"
URL_PARAMS="username=$FBUID&response=$RESPONSE"
SID=`wget --no-check-certificate -O - "https://$IP/login_sid.lua?$URL_PARAMS" 2>/dev/null | sed 's/.*<SID>\(.*\)<\/SID>.*/\1/'`
echo `wget --no-check-certificate -O - --post-data "sid=$SID&$(cat post.data)"  "https://$IP/data.lua" 2>/dev/null`

Das Script. Wie man sieht werden die anderen Post Daten aus der post.data Datei genommen.
Die sieht dann so aus.

post.data:
xhr=1&connection1=on&active_connection1=1&apply=&lang=de&page=shareVpn
Das würde die erste VPN Verbindung aktivieren.

post.data:
xhr=1&connection1=off&active_connection1=0&apply=&lang=de&page=shareVpn
Das würde die erste Verbindung deaktivieren.
 
Hi,

vielleicht kannst Du kurz erklären, wie Du auf diese Post.data Daten kommst?

Ich versuche gerade ebenfalls etwas abzufragen und zwar möchte ich gern automatisiert von der "lp=kidPro" Seite die aktuell gültigen, nächsten 10 Ticket Nummern erhalten und ich vermute, dass auch das wieder anders funktioniert, als einfach die URL zu übergeben.

Vielen Dank im Voraus
Ramon
 
Ich habe die lua gefunden (internet/kids_profilelist.lua). darin werde ich einfach die Tabelle für die Tickets auslesen...

LG
 
darin werde ich einfach die Tabelle für die Tickets auslesen...
Dafür ist die TR064 Schnitstelle besser geeignet.
Ich versuche gerade ebenfalls etwas abzufragen und zwar möchte ich gern automatisiert von der "lp=kidPro" Seite die aktuell gültigen, nächsten 10 Ticket Nummern erhalten und ich vermute, dass auch das wieder anders funktioniert, als einfach die URL zu übergeben.
Bei der Seite liefert data.lua eine html seite zurück in der Die Daten in einer Tabelle stehen.
Das sollte nicht allzu großer Aufwand sein. Allerdings ist es mit der TR064 API einfach schöner.
 
Hallo zusammen,

ich habe mir das Scrip zusammengebaut und es scheint zu funktionieren. Zumindest bekomme ich keine Fehlermeldung und auf der FritzBox kann ich sehen, das sich der entsprechende Benutzer angemeldet hat.

Ich würde mir gern über das Script die Aufnahmen von meinem AB runterladen und gleich in eine wav konvertieren lassen.
Wenn ich folgenden Link aufrufe, kann ich mir die Aufnahme runterladen.


ich würde mir aber gerne die Datei in irgendein Verzeichnis auf meinem Pi über das script runterladen und direkt speichern.

Da ich leider keinerlei Erfahrungen mit Programieren habe, wäre es schön, wenn mir hier jemdand helfen könnte.

Danke!
 
Zuletzt bearbeitet von einem Moderator:
Hallo,

ich konnte es gerade selbst lösen:

Code:
JSON=`wget --no-check-certificate -O - --post-data "xhr=1&sid=$SID&lang=de&page=overview&xhrId=all&useajax=1&no_sidrenew=" --output-document /home/pi/AB/ansage.wav "https://$IP/cgi-bin/luacgi_notimeout?<SID>&script=/lua/photo.lua&myabfile=/data/tam/rec/rec.0.000" 2>/dev/null`
 
Zuletzt bearbeitet von einem Moderator:
Hallo,
kann mir jemand die Befehlszeile für einen Reboot der Box mitteilen?
7590 FW 7.51 BETA
Grüße und Danke
 
#Fritz.box rebooten

Code:
JSON=`wget --no-check-certificate -O - --post-data "xhr=1&sid=$SID&reboot=1&lang=de&page=reboot" "https://$IP/data.lua" 2>/dev/null`
 
Zuletzt bearbeitet von einem Moderator:
#Fritz.box rebooten

Code:
JSON=`wget --no-check-certificate -O - --post-data "xhr=1&sid=$SID&reboot=1&lang=de&page=reboot" "https://$IP/data.lua" 2>/dev/null`
Leider funktioniert es so noch nicht :-(
Nach langer Suche im Netz, bin ich doch noch auf eine funktionierende Lösung gestoßen...
FritzBox 7590 FW 7.56

Reboot.sh:
#!/bin/sh

IP="123.456.789.01"
FBUID="User"
SECRET="Passwort"

CHALLENGE=`wget --no-check-certificate -O - "http://$IP/login_sid.lua" 2>/dev/null | sed 's/.*<Challenge>.∗.∗<\/Challenge>.*/\1/'`
CPSTR="$CHALLENGE-$SECRET"
MD5=`echo -n $CPSTR | iconv -f ISO8859-1 -t UTF-16LE | md5sum -b | awk '{print substr($0,1,32)}'`
RESPONSE="$CHALLENGE-$MD5"
URL_PARAMS="username=$FBUID&response=$RESPONSE"

SID=`wget --no-check-certificate -O - "https://$IP/login_sid.lua?$URL_PARAMS" 2>/dev/null | sed 's/.*<SID>.∗.∗<\/SID>.*/\1/'`

#FritzBox rebooten
curl --insecure -s -X POST -d "xhr=1&sid=$SID&reboot=1&lang=de&page=reboot" "$IP/data.lua"
curl --insecure -s -X POST -d "xhr=1&sid=$SID&page=rootReboot" "$IP/data.lua"
curl --insecure -s -X POST -d "ajax=1&sid=$SID&no_sidrenew=1&xhr=1&useajax=1" "$IP/reboot.lua"

Lediglich bei IP, FBUID und SECRET eure eigenen Daten einsetzen.
 
Moin, ich versuche via Javascript (als Chrome-Extension) von meiner Fritzbox im lokalen Netzwerk eine Session-ID zu bekommen, schlägt allerdings fehl. Es gibt Antworten von der Box, Challenge und so weiter ... der zurückgesendete Hash wird aber offenbar (?) nicht erkannt, jedenfalls wird es mit einer neuen Challenge beantwortet und SessionID 000000000 zurückgeliefert (natürlich mit nerviger BlockTime).
Habe nun schon 3 verschiedene MD5-Funktionen probiert und bin sicher, dass es daran nicht liegt. Auch nicht an Username/Passwort: das habe ich nun 20x überprüft und komme mit den verwendeten Daten auch direkt im Browser auf die Fritzbox. Hat jemand noch eine Idee?
Der Code:

Javascript:
function getSessionID() {
    console.log('Fetching session ID...');
    return fetch('http://fritz.box/login_sid.lua')
        .then(response => response.text())
        .then(data => {
            console.log(data);
            const challengeMatch = data.match(/<Challenge>(.*?)<\/Challenge>/);
            if (!challengeMatch) {
                throw new Error('Challenge not found in response');
            }
            const challenge = challengeMatch[1];
            const responseHash = challenge + '-' + md5(challenge + '-pimpine77a');
            console.log('Challenge received:', challenge);
            console.log('Response hash:', responseHash);
            console.log(`http://fritz.box/login_sid.lua?username=fritz3978&response=${responseHash}`);
            return fetch(`http://fritz.box/login_sid.lua?username=fritz3978&response=${responseHash}`);
        })
        .then(response => response.text())
        .then(data => {
            console.log(data);
            const sessionIDMatch = data.match(/<SID>(.*?)<\/SID>/);
            if (!sessionIDMatch) {
                throw new Error('Session ID not found in response');
            }
            const sessionID = sessionIDMatch[1];
            if (sessionID === '0000000000000000') {
                throw new Error('Login failed');
            }
            console.log('Session ID received:', sessionID);
            return sessionID;
        });
}
 
Danke, daran lag es tatsächlich, hatte das dann auch gemerkt.

Ich bin dann aber am nächsten Schritt gescheitert ... die Liste der Anrufer ließ sich nicht abfragen ... es kam immer "unauthorized" zurück, obwohl mit gültiger SessionID. Die Dokumentation ist leider auch so konfus und unzureichend, habe es dann aufgegeben.

Das ganze TR-64-Theater ist Murks, kompliziert macht es nicht sicherer, schade!
 
Es könnte sein, dass die SessionID Null-Bytes enthält. Ich glaube, UTF16LE darf das. Wenn der String wie bei C verarbeitet wird, dann hält die Übertragung beim ersten Null-Byte an, da Null-Bytes das String-Ende anzeigen. Stichwort "Encoding".
 
Zurück
Oben Unten