1 (edytowany przez frutis 2024-01-01 13:18:36)

Temat: Atak MITM zastosowanie praktyczne - ZTE MF286D

Od jakiegoś czasu ZTE nie daje możliwośći aktualizacji oprogramowania dla MF286D Telia B02 oraz B06. Kolejne aktualizacje od wersji B07 do B12 działają prawidłowo.
Jako, że oprogramowanie routera nie weryfikuje certyfikatów można łatwo oszukać mechanizm aktualizacji. Przygotowałem skrypt w postaci dodatku do mitmproxy który pozwala wykonać aktualizację z wersji B02 oraz B06.

Do przeprowadzenia ataku użyłem routera oraz komputera z mitmproxy na którym był uruchomiony mitmproxy.

1. Na routerze ustawiamy adres ip komputera z mitmproxy dla hosta dmeu.ztems.com (np. w /etc/hosts dla dnsmasq)
2. Na komputerze z mitmproxy ustawiamy rzeczywisty adres dla dmeu.ztems.com (może to być również w /etc/hosts) jeśli korzystamy z serwera dns na routerze
3. Uruchamiamy mitmproxy udając serwer ZTE:

mitmproxy --mode reverse:https://dmeu.ztems.com@443 -s ztedm.py

4. Ustawiamy tryb "Ethernet" na MF286D
5. Podłączamy port WAN MF286D do routera i wyszukujemy aktualizację

A to skrypt ztedm.py

from base64 import b64decode, b64encode
from hashlib import md5
from xml.dom.minidom import parseString


class ZteDm:
    def __init__(self):
        self.nonce = None
        self.version = None
        self.fake_version = 'TELIA_MF286DV1.0.0B07'
        self.firmware = {
            'TELIA_MF286DV1.0.0B02': '/firmwarepackages/DE/ZTE/MF286D/214204/TELIA_MF286DV1.0.0B02-TELIA_MF286DV1.0.0B06-normal_CDN.dd',
            'TELIA_MF286DV1.0.0B06': '/firmwarepackages/DE/ZTE/MF286D/224366/TELIA_MF286DV1.0.0B06-TELIA_MF286DV1.0.0B07_CDN.dd'
            }

    def hmac_get(self, nonce, body, username, password, mark=':'):
        auth = username + mark + password
        mark_enc = mark.encode('utf-8')
        auth_b64 = b64encode(md5(auth.encode('utf-8')).digest())
        nonce_md5 = b64decode(nonce)
        body_b64 = b64encode(md5(body.encode('utf-8')).digest())
        hmac = auth_b64 + mark_enc + nonce_md5 + mark_enc + body_b64
        return b64encode(md5(hmac).digest()).decode('utf-8')

    def request(self, flow):
        username = 'ZTEDM'
        password = 'ZTEDM'
        if 'Content-Type' in flow.request.headers and flow.request.headers['Content-Type'] == 'application/vnd.syncml.dm+xml':
            xml_request = parseString(flow.request.text.strip())
            results = xml_request.getElementsByTagName('Results')
            if results:
                data = results[0].getElementsByTagName('Data')[0].firstChild.nodeValue
                for key in self.firmware:
                    if data == key:
                        self.version = data
                        results[0].getElementsByTagName('Data')[0].firstChild.nodeValue = self.fake_version
                        body = xml_request.toxml()
                        hmac = self.hmac_get(self.nonce, body, username, password)
                        flow.request.headers['x-syncml-hmac'] = f'algorithm=MD5, username="{username}", mac={hmac}'
                        flow.request.text = body
            next_nonce = xml_request.getElementsByTagName('NextNonce')
            if next_nonce:
                self.nonce = next_nonce[0].firstChild.nodeValue

    def response(self, flow):
        username = 'zxmdmp'
        password = 'ZTEPWD'
        if 'Content-Type' in flow.response.headers and flow.response.headers['Content-Type'] == 'application/vnd.syncml.dm+xml':
            xml_response = parseString(flow.response.text.strip())
            if self.version:
                targetref = xml_response.getElementsByTagName('TargetRef')[0].firstChild.nodeValue
                sid = targetref.split('keyid=')[1]
                replace_data = f'https://dleu.ztems.com:443/zxmdmp/download.do?doWhat=getDD&filename={self.firmware[self.version]}&sid={sid}'
                replace = xml_response.getElementsByTagName('Replace')
                if replace:
                    item = replace[0].getElementsByTagName('Item')
                    item[1].getElementsByTagName('Data')[0].firstChild.nodeValue = replace_data
                    body = xml_response.toxml()
                    hmac = self.hmac_get(self.nonce, body, username, password)
                    flow.response.headers['x-syncml-hmac'] = f'algorithm=MD5, username="{username}", mac={hmac}'
                    flow.response.text = body
                self.version = None
            next_nonce = xml_response.getElementsByTagName('NextNonce')
            if next_nonce:
                self.nonce = next_nonce[0].firstChild.nodeValue


addons = [ZteDm()]

@Cezary jeśli uważasz, że to powinno się znaleźć w wątku o MF286D to przenieś proszę.

2

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

Myślę że to powinno żyć własnym wątkiem, ale możesz w tamtym wątku podlinkować żeby było wiadomo gdzie szukać.

Masz niepotrzebny router, uszkodzony czy nie - chętnie przygarnę go.

3

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

Możnaby też rozszerzyć funkcjonalność... Przykładowo o MC801A , tam też jak wgra się oprogramowanie TMO do routera z Plusa , to się nie zaktualizuje do nowszego przez OTA.
Niestety nie mm aktualnie żadnego MC801A...

4

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

So, i've tried to put on mitmproxy to see the request, obviusly this unit cannot update because there is no new fw, but response is strange, that 401 seems to say "i'm not able to update". And where are current firmware? Is passed on another post?

here the request, and relative response:

<?xml version="1.0" encoding="UTF-8"?>
<SyncML
    xmlns='SYNCML:SYNCML1.2'>
    <SyncHdr>
        <VerDTD>1.2</VerDTD>
        <VerProto>DM/1.2</VerProto>
        <SessionID>3E8</SessionID>
        <MsgID>1</MsgID>
        <Target>
            <LocURI>https://dmeu.ztems.com:443/zxmdmp/dm</LocURI>
        </Target>
        <Source>
            <LocURI>IMEI:imei</LocURI>
        </Source>
        <Meta>
            <MaxMsgSize
                xmlns='syncml:metinf'>5000
            </MaxMsgSize>
        </Meta>
    </SyncHdr>
    <SyncBody>
        <Alert>
            <CmdID>1</CmdID>
            <Data>1226</Data>
            <Item>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>int
                    </Format>
                    <Type
                        xmlns='syncml:metinf'>org.openmobilealliance.dm.firmwareupdate.userrequest
                    </Type>
                    <Mark
                        xmlns='syncml:metinf'>indeterminate
                    </Mark>
                </Meta>
                <Data>0</Data>
            </Item>
        </Alert>
        <Alert>
            <CmdID>2</CmdID>
            <Data>1201</Data>
        </Alert>
        <Replace>
            <CmdID>3</CmdID>
            <Item>
                <Source>
                    <LocURI>./DevInfo/Ext/Correlator</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>chr
                    </Format>
                </Meta>
                <Data>0</Data>
            </Item>
            <Item>
                <Source>
                    <LocURI>./DevInfo/Ext/ErrCode</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>int
                    </Format>
                </Meta>
                <Data>0</Data>
            </Item>
            <Item>
                <Source>
                    <LocURI>./DevInfo/Ext/InnerV</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>chr
                    </Format>
                </Meta>
                <Data></Data>
            </Item>
            <Item>
                <Source>
                    <LocURI>./DevInfo/Ext/CompileT</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>chr
                    </Format>
                </Meta>
                <Data></Data>
            </Item>
            <Item>
                <Source>
                    <LocURI>./DevInfo/Ext</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>node
                    </Format>
                </Meta>
                <Data>CompileT/InnerV/ErrCode/Correlator</Data>
            </Item>
            <Item>
                <Source>
                    <LocURI>./DevInfo/DmV</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>chr
                    </Format>
                </Meta>
                <Data>1.2</Data>
            </Item>
            <Item>
                <Source>
                    <LocURI>./DevInfo/Lang</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>chr
                    </Format>
                </Meta>
                <Data>en</Data>
            </Item>
            <Item>
                <Source>
                    <LocURI>./DevInfo/DevId</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>chr
                    </Format>
                </Meta>
                <Data>IMEI:imei</Data>
            </Item>
            <Item>
                <Source>
                    <LocURI>./DevInfo/Man</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>chr
                    </Format>
                </Meta>
                <Data>ZTE</Data>
            </Item>
            <Item>
                <Source>
                    <LocURI>./DevInfo/Mod</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>chr
                    </Format>
                </Meta>
                <Data>MC7010</Data>
            </Item>
        </Replace>
        <Final/>
    </SyncBody>
</SyncML>

response:

<?xml version="1.0" encoding="UTF-8"?>
<SyncML>
    <SyncHdr>
        <VerDTD>1.2</VerDTD>
        <VerProto>DM/1.2</VerProto>
        <SessionID>3E8</SessionID>
        <MsgID>1</MsgID>
        <Target>
            <LocURI>IMEI:imei</LocURI>
        </Target>
        <Source>
            <LocURI>https://dmeu.ztems.com:443/zxmdmp/dm</LocURI>
        </Source>
        <RespURI>https://dmeu.ztems.com/zxmdmp/dm?sid=XXXXX.deudmweb2&amp;keyid=XXXXXX</RespURI>
        <Cred>
            <Meta>
                <Format
                    xmlns='syncml:metinf'>b64
                </Format>
                <Type
                    xmlns='syncml:metinf'>syncml:auth-md5
                </Type>
            </Meta>
            <Data>HgtIbE+zeYPHpfuWIbu64g==</Data>
        </Cred>
        <Meta>
            <MaxMsgSize
                xmlns='syncml:metinf'>5000
            </MaxMsgSize>
        </Meta>
    </SyncHdr>
    <SyncBody>
        <Status>
            <CmdID>1</CmdID>
            <MsgRef>1</MsgRef>
            <CmdRef>0</CmdRef>
            <Cmd>SyncHdr</Cmd>
            <TargetRef>https://dmeu.ztems.com:443/zxmdmp/dm</TargetRef>
            <SourceRef>IMEI:imei</SourceRef>
            <Chal>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>b64
                    </Format>
                    <Type
                        xmlns='syncml:metinf'>syncml:auth-MAC
                    </Type>
                    <NextNonce
                        xmlns='syncml:metinf'>XXXXX==
                    </NextNonce>
                </Meta>
            </Chal>
            <Data>401</Data>
        </Status>
        <Status>
            <CmdID>2</CmdID>
            <MsgRef>1</MsgRef>
            <CmdRef>1</CmdRef>
            <Cmd>Alert</Cmd>
            <Data>401</Data>
        </Status>
        <Status>
            <CmdID>3</CmdID>
            <MsgRef>1</MsgRef>
            <CmdRef>2</CmdRef>
            <Cmd>Alert</Cmd>
            <Data>401</Data>
        </Status>
        <Status>
            <CmdID>4</CmdID>
            <MsgRef>1</MsgRef>
            <CmdRef>3</CmdRef>
            <Cmd>Replace</Cmd>
            <Data>401</Data>
        </Status>
        <Final></Final>
    </SyncBody>
</SyncML>

any ideas?

5

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

Inner version should be this one:

            <Item>
                <Source>
                    <LocURI>./DevInfo/Ext/InnerV</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>chr
                    </Format>
                </Meta>
                <Data></Data>
            </Item>

but it's empty :\

6

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

@stich86 , what device you try to update?
If it is not MF286D maybe Inner version is not applicable....

7 (edytowany przez frutis 2024-02-07 18:20:35)

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

stich86 napisał/a:

Inner version should be this one:

            <Item>
                <Source>
                    <LocURI>./DevInfo/Ext/InnerV</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>chr
                    </Format>
                </Meta>
                <Data></Data>model_name
            </Item>

but it's empty :\

This is OK. Your first request failed. There are 3 requests sent. Firmware version is sent in last one.

Python script should be working with this model:

model = 'MC7010'

You need to find firmware version before update that can be used in script.

Firmware variable is the integrate_version from device. Model variable is a model_name.

8 (edytowany przez stich86 2024-02-07 21:05:29)

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

frutis napisał/a:
stich86 napisał/a:

Inner version should be this one:

            <Item>
                <Source>
                    <LocURI>./DevInfo/Ext/InnerV</LocURI>
                </Source>
                <Meta>
                    <Format
                        xmlns='syncml:metinf'>chr
                    </Format>
                </Meta>
                <Data></Data>model_name
            </Item>

but it's empty :\

This is OK. Your first request failed. There are 3 requests sent. Firmware version is sent in last one.

Python script should be working with this model:

model = 'MC7010'

You need to find firmware version before update that can be used in script.

Firmware variable is the integrate_version from device. Model variable is a model_name.

That request was done by MC7010 itself. I’ve tried the script putting the correct info, but still not work. I think that ZTE for that device burns the IMEI when it updates.

I’ve tested with MU5120 (the portable one), that has been updated from 1.0.0B04 to 1.0.1B01, but using IMEI+inner+model, doesn’t give any update link

@frutis do you have telegram o google chat?
I think it's better to chat there to speed-up conversation smile

9

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

I just checked the update for MF286D from version B11 and it doesn't work either. Same answer. I guess ZTE has disabled the update for good.

10 (edytowany przez stich86 2024-02-08 07:50:01)

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

frutis napisał/a:

I just checked the update for MF286D from version B11 and it doesn't work either. Same answer. I guess ZTE has disabled the update for good.

I left the script run the whole night, but no good IMEI has been found sad

11

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

Ostatnio zakupiłem MF286d na zanym portalu aukcyjnym od znanego sprzedawcy który ma sporo routerów w sprzedaży. Miałem soft Nordic 08 lub 09. Wyskoczyła mi aktualizacja, zaakceptowałem i ładnie podniosło do 010, po restarcie kolejna, podniosło do 011. Potem do 012. Czyli chyba serwery znowu działają smile Albo router pobrał sobie wszystko wcześniej?

12

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

No to wygląda ,że działają , bo router profilaktycznie to kasuje to co wcześniej pobrał za każdym razem podczas startu ( stąd nie można mu wgrać pliku , zresetować i liczyć ,że się zaktualizuje).

13

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

@dav4dav4 , no ale wg pierwszego posta i słów @frutis:

frutis napisał/a:

Kolejne aktualizacje od wersji B07 do B12 działają prawidłowo

@frutis , czyli już się nie da aktualizować tym skryptem od tych najniższych , ( od B02 do B07 ) ?

14

Odp: Atak MITM zastosowanie praktyczne - ZTE MF286D

dav4dav4 napisał/a:

Ostatnio zakupiłem MF286d na zanym portalu aukcyjnym od znanego sprzedawcy który ma sporo routerów w sprzedaży. Miałem soft Nordic 08 lub 09. Wyskoczyła mi aktualizacja, zaakceptowałem i ładnie podniosło do 010, po restarcie kolejna, podniosło do 011. Potem do 012. Czyli chyba serwery znowu działają smile Albo router pobrał sobie wszystko wcześniej?

Mógłbyś (może być na prywatną wiadomość) podesłać linka do tego sprzedawcy?
Chciałbym kupić jedną (dla mnie dopiero pierwszą) sztukę mf286d ale w wersji która bez problemu da się zaktualizować jeśli ten MITM już nie działa.