1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Development Command-line router webpage access

Discussion in 'Software' started by badders, 16 Jan 2017.

  1. badders

    badders Neuken in de Keuken

    Joined:
    4 Dec 2007
    Posts:
    2,642
    Likes Received:
    74
    Hi All,

    I currently run a bash script twice an hour to check if my external IP (from an external source -http://icanhazip.com/ ) is different from the IP of my domain, and if it is, push my external IP address to my Domain registrar, in a dynamic-DNS setup, but with a regular Domain name.

    However, this relies on the external host being up and responding with the IP.

    My router, a plusnet Hub one, does display the external IP address, but only after you log in and go to the correct page.

    Hitting the correct page is not an issue, but the login page gives you a session cvookie, takes the password you type and adds it to an auth_key variable (supplied as a hidden field on the form), md5 hashes it in JS, and then passes that to index.cgi to verify the login.

    Once the session cookie is verified, I can use cURL to pick up the shown External IP address, but I can't seem to get it to login via the login page.

    This would all be much simpler if I could get telnet or SSH access to the router, but it's locked down.

    Does anyone have any ideas?

    Edit: I should say that the endgame is to get the external IP without contacting an external service, in case I wasn't clear!
     
  2. Krazeh

    Krazeh Minimodder

    Joined:
    12 Aug 2003
    Posts:
    2,124
    Likes Received:
    56
    You could flash it with OpenWRT/LEDE. However, that does require some soldering skills and a USB to serial cable. You do get a much more useful firmware at the end of it tho.
     
  3. badders

    badders Neuken in de Keuken

    Joined:
    4 Dec 2007
    Posts:
    2,642
    Likes Received:
    74
    I could, but I'm disinclined to do so just for this "nice-to-have" - it operates fine for everything else, I'd just like to reduce my reliance on an external service when the information is technically available from within my network!
     
  4. law99

    law99 Custom User Title

    Joined:
    24 Sep 2009
    Posts:
    2,390
    Likes Received:
    63
    Are you just after the external IP after a new session is established when connecting to your ISP? You don't need your router to do that.

    http://ipecho.net/plain
     
  5. Gareth Halfacree

    Gareth Halfacree WIIGII! Lover of bit-tech Administrator Super Moderator Moderator

    Joined:
    4 Dec 2007
    Posts:
    17,084
    Likes Received:
    6,635
    Ahem:
    The correct answer is to stop trying to parse webpages and just enable SNMP on the router. Then it's just a case of:

    snmpwalk -v2c -c public your_router_here ip | grep ipAdEntAddr

    (You may need to change what you're searching for depending on how your router responds - try it without the grep first.)

    EDIT: If your router doesn't support SNMP(!), then try logging in prior to snagging the you-must-be-logged-in-page:

    curl -s --data "loginuser=admin&loginpasswd=adminpassword" --cookie-jar cookies.txt http://[i]your_router_here[/i]/plusnetlogin.cgi > /dev/null
     
    Last edited: 17 Jan 2017
  6. deathtaker27

    deathtaker27 Modder

    Joined:
    17 Apr 2010
    Posts:
    2,238
    Likes Received:
    186
  7. badders

    badders Neuken in de Keuken

    Joined:
    4 Dec 2007
    Posts:
    2,642
    Likes Received:
    74
    Solved it, in a very hacky bash script!
    Code:
    #!/bin/bash
    routerip='192.168.1.254'
    pass='<PASSWORD>'
    page=`curl -Ls 'http://$routerip/index.cgi?active_page=9148' -H 'Cookie: rg_cookie_session_id=' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Cache-Control: max-age=0' -H 'DNT: 1' --data 'active_page=9121' --cookie-jar cookies.txt`
    posttoken=`echo $page |grep post_token |awk 'BEGIN { FS = "\"post_token\" value=\"" } ; {print $2}'|awk 'BEGIN { FS = "\"" } ; {print $1}'|xargs`
    requestid=`echo $page |grep request_id |awk 'BEGIN { FS = "\"request_id\" value=\"" } ; {print $2}'|awk 'BEGIN { FS = "\"" } ; {print $1}'|xargs`
    authkey=`echo $page |grep auth_key |awk 'BEGIN { FS = "\"auth_key\" value=\"" } ; {print $2}'|awk 'BEGIN { FS = "\"" } ; {print $1}'|xargs`
    passwordid=`echo $page |grep password_ |awk 'BEGIN { FS = "\"password_" } ; {print $2}'| awk 'BEGIN { FS = "\"" } ; {print $1}'|xargs`
    pass+=$authkey
    passhash=`echo -n $pass |openssl dgst -md5|awk '{print $2}'`
    postvars="request_id=$requestid&active_page=9148&active_page_str=bt_login&mimic_button_field=submit_button_login_submit%3A+..&button_value=&post_token=$posttoken&password_$passwordid=&md5_pass=$passhash&auth_key=$authkey"
    
    curl -Ls 'http://$routerip/index.cgi'  -H 'Content-Type: application/x-www-form-urlencoded' -H 'Cache-Control: max-age=0' -H 'Referer: http://192.168.1.254/index.cgi?active_page=9121' -H 'Connection: keep-alive' -H 'DNT: 1' --data "$postvars" --cookie cookies.txt >/dev/null
    
    IP=`curl -s  'http://$routerip/index.cgi?active_page=9121&nav_clear=1' -H 'DNT: 1' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: en-GB,en-US;q=0.8,en;q=0.6' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0' --cookie cookies.txt --compressed | grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" |head -n 1`
    
    echo $IP
    
    Edit: OK, so some clarification:
    The password is never sent in a POST variable, in the original page it is salted with the value of a Hidden field called "auth_key", supplied by the page, and then hashed usng a JS function called "hex_md5". I was able to emulate this in bash with echo -n $pass |openssl dgst -md5|awk '{print $2}'.
    This needs to be passed as POST data along with some other hidden fields from the page (used for verification server-side) - "post_token", "auth_key" and "request_id", as well as the unique name of the password field "password_xxxxxxxxxx", all of which change each session.
    The cookie supplied by the page is captured as cookies.txt by the first cURL call ( --cookie-jar cookies.txt), and then subsequently used by the other 2 cURL requests(--cookie cookies.txt) to ensure the session is the same.

    SNMP is unfortunately not enabled, and as the cgi is one application - e.g. there is no "plusnetlogin.cgi" page, I've had to do it this way.

    I'll continue to verify this over the next couple of router reboots, and if it keeps matching the IP I get from the external source, I'll switch over to using this and put some error-checking in place to ensure the IP is captured and not the software version number, which is what happens if the login fails.
     
    Last edited: 18 Jan 2017
  8. Gareth Halfacree

    Gareth Halfacree WIIGII! Lover of bit-tech Administrator Super Moderator Moderator

    Joined:
    4 Dec 2007
    Posts:
    17,084
    Likes Received:
    6,635
    Skills! Remember: if it's stupid and it works, it ain't stupid! (But seriously, Plusnet, get with the programme and enable SNMP, would you? This is *literally* what it's designed for.)
     
  9. law99

    law99 Custom User Title

    Joined:
    24 Sep 2009
    Posts:
    2,390
    Likes Received:
    63
    I can't see ISPs racing to make sure their "do WiFi, do obvious reset button" routers support SNMP.
     

Share This Page