With Eir being unreachable via phone, I decided to poke the router they sent me, to see if I could tamper with the request that was causing issues. Basically, in the set of four requests that were XHR’d over to the router, I wanted to drop the first one.
First stop, a tick in Firefox’s debugger to say “break on any XHR request”, and this let me start crawling the stack trace from pressing the Apply button to the network request leaving the browser. It became evident that a regular list of key:value data was being fed to the JS , and it was turning it into the flattened list of XPath requests.
To make life easier, I told Firefox to prettify the JavaScript, and loaded it into Notepad++ to read. It turns out the settings.js file on this router is 500 kB of compacted, compressed code – it expands to about 3.5 MB on disk. That’s a lot of JS to trawl through to find where the conversion is happening. Thankfully, when you tell Firefox to prettify, the breakpoints and stack traces point to the pretty line numbers, not the compacted line numbers.
At around line 48,653, there’s an application factory class for “Dhcp”, with a class attribute of “save”, which points to an anonymous function (caveat: I am not a JS programmer, my terms may be a bit wrong). This anonymous function defines a list, populates it based on the key:value data passed in, validates it, converts it to the XPath requests, and kicks it out the door.
Inside that list population, there was a snippet that looked like
// test && test, foo && bar, ...
(
$.config.modules.myBox.dhcp.updateDNS === !0 &&
cache.dnsServer === cache.ipv4Address
||
$.config.modules.myBox.dhcp.updateDNS &&
$.config.showedpages.dtagGpon
)
&&
(
saveData[$.xpaths.mySagemcomBox.dhcp.dnsServer] = data.ipv4Address
)
//, ...
It’s in the middle of a 1200 character line, containing layers of nested tests and insertions into the saveData structure.
How do I know this is the line I care about? Well, there’s another snippet of code around line 41,500 that declares a big data structure, which includes:
$.xpaths = {
// ...
mySagemcomBox: {
dns: {
server: 'Device/DHCPv4/Server/Pools/Pool[Alias=\'DEFAULT_POOL\']/DNSServers',
}
}
}
I know this is the bit I’m looking for, because of my initial exploration over in this blog post.
So, now I know where the code is doing the translation of the inbound data from the form to the notation that’s sent over to the router API endpoint. What I now need is a way to tamper with the JS in the browser to remove that earlier snippet of code that sets the DNS server path for the DHCP service. Doing this in-browser is not easy, especially when trying to horizontal scroll 1200 characters in a single line.
A bit of ‘net searching, and up pops a tool called Fiddler. This tool can be inserted as a proxy for all requests from the browser, and it can do things like capture, replay, and with a bit of scripting, tampering. Some more research led me to FiddlerScript rules, and how to point to a file on disk when a particular request is seen.
static function OnBeforeResponse(oSession: Session) {
if (oSession.PathAndQuery.Contains("/2.0/gui/js/scripts.js")) {
oSession["x-replywithfile"] ="eir_scripts.js";
}
}
That’s it. That’s the entire tamper required. The eir_scripts.js file is in a location specified by Fiddler, and a forced refresh in the browser (to skip the cache) showed that I was now pulling a 3.5 MB file instead of a 500 kB one. Delete the snippet that tries to set the DNS server value, force reload again, change the IP of the device and the DHCP pool (have to change both when changing the subnet), and it all worked!
So, thank you Sagemcom for doing all of the heavy lifting in JavaScript, instead of in the code running on the router. It made it much easier to tamper with the request and bypass your broken UI. If this had been a case of the form submitting the raw key:value data, and the device doing server-side processing, I’d not have been able to fix this.

The firmware in question is SGDX10000033. Some forum posts in Australia indicate that there’s at least version 105 available, but I’m presuming I have to get that from the ISP that I can’t get hold of due to a broken phone tree.