Potentially Command Injection

Description

Command injection is an attack in which the goal is execution of arbitrary commands on the Android operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to the system shell. In this attack, the attacker-supplied operating system commands are usually executed with the privileges of the vulnerable application. Command injection attacks are possible largely due to insufficient input validation.

Recommendation

The application should allow the users to use either the Wi-Fi or a mobile network connection. A common strategy for apps is to only fetch large data if a Wi-Fi network is available.

References
Technical details
[TAINT] String 'chmod 666 ' ==>>> Sink '['Ljava/lang/Runtime;', 'exec', '(Ljava/lang/String;)Ljava/lang/Process;', '0', 'COMMAND_SINK']' [[('Landroid_serialport_api/HDXPosPrinter;', 'onHandleIntent', '(Landroid/content/Intent;)V'), ('Lmpay/apps/mpayconnect/MPAYApplication;', 'getSerialPort', '()Landroid_serialport_api/SerialPort;'), ('Landroid_serialport_api/SerialPort;', '<init>', '(Ljava/io/File; I I)V'), ('Ljava/lang/Runtime;', 'exec', '(Ljava/lang/String;)Ljava/lang/Process;')]]

The application executes a dangerous command

Method android_serialport_api.HDXPosPrinter.onHandleIntent():


    protected void onHandleIntent(android.content.Intent p4)
    {
        android.util.Log.i(android_serialport_api.HDXPosPrinter.TAG, "onHandleIntent");
        this.processTransactionType();
        this.lock = ((android.os.PowerManager) this.getApplicationContext().getSystemService("power")).newWakeLock(1, android_serialport_api.HDXPosPrinter.TAG);
        this.mApplication = ((mpay.apps.mpayconnect.MPAYApplication) this.getApplication());
        try {
            this.mSerialPort = this.mApplication.getSerialPort();
            this.mOutputStream = this.mSerialPort.getOutputStream();
            this.mInputStream = this.mSerialPort.getInputStream();
            this.mReadThread = new android_serialport_api.HDXPosPrinter$ReadThread(this);
            this.mReadThread.start();
        } catch (int v0_42) {
            v0_42.printStackTrace();
        }
        hdx.HdxUtil.SwitchSerialFunction(0);
        if (!p4.getExtras().containsKey("ACTION")) {
            if (p4.getExtras().get("CURRENCY") != null) {
                this.currencyCode = p4.getExtras().getString("CURRENCY");
            }
            if (p4.getExtras().get("COMPANYNAME") != null) {
                this.companyName = p4.getExtras().getString("COMPANYNAME");
            }
            if (p4.getExtras().get("BANKMID") != null) {
                this.bankMID = p4.getExtras().getString("BANKMID");
            }
            if (p4.getExtras().get("COPYTYPE") != null) {
                this.trxnCopyType = p4.getExtras().getString("COPYTYPE");
            }
            if (p4.getExtras().get("TERMINALUID") != null) {
                this.terminalUID = p4.getExtras().getString("TERMINALUID");
            }
            if (p4.getExtras().get("CURRENCY") != null) {
                this.currencyCode = p4.getExtras().getString("CURRENCY");
            }
            if (this.transObj != null) {
                if (this.transObj.getTranNameType() <= 0) {
                    if (!this.transObj.isAlipay()) {
                        this.printEMVReceipt();
                    } else {
                        this.printAlipayReceipt();
                    }
                } else {
                    if (this.transObj.getTranNameType() != 2) {
                        if (this.transObj.getTranNameType() != 1) {
                            if (this.transObj.getTranNameType() == 3) {
                                this.printMPayVoucherReceipt();
                            }
                        } else {
                            this.printBoostReceipt();
                        }
                    } else {
                        this.printWechatReceipt();
                    }
                }
            } else {
                new android.os.Handler(android.os.Looper.getMainLooper()).post(new android_serialport_api.HDXPosPrinter$1(this));
            }
        } else {
            if (p4.getExtras().get("ACTION").toString().equalsIgnoreCase("DAILY_SETTLEMENT_REPORT")) {
                if (p4.getExtras().containsKey("DAILY_SETTLEMENT_DATA")) {
                    this.droList = ((java.util.ArrayList) p4.getExtras().get("DAILY_SETTLEMENT_DATA"));
                }
                this.printDailySettlementReport();
            }
        }
        return;
    }

Method mpay.apps.mpayconnect.MPAYApplication.getSerialPort():


    public android_serialport_api.SerialPort getSerialPort()
    {
        if ((this.mSerialPort == null) && (mpay.apps.util.Util.isHDXPOSTerminal)) {
            android.util.Log.i("", "YES");
            this.mSerialPort = new android_serialport_api.SerialPort(new java.io.File(hdx.HdxUtil.GetPrinterPort()), 115200, 0);
        }
        return this.mSerialPort;
    }

Method android_serialport_api.SerialPort.<init>():


    public SerialPort(java.io.File p5, int p6, int p7)
    {
        if ((!p5.canRead()) || (!p5.canWrite())) {
            try {
                android.util.Log.e("SerialPort", "1============================");
                java.io.FileOutputStream v0_5 = new StringBuilder().append("chmod 666 ").append(p5.getAbsolutePath()).toString();
                android.util.Log.e("SerialPort", new StringBuilder().append("cmd=====================").append(v0_5).toString());
                Runtime.getRuntime().exec(v0_5);
            } catch (java.io.FileOutputStream v0_22) {
                android.util.Log.e("SerialPort", "3=================");
                v0_22.printStackTrace();
                throw new SecurityException();
            }
            if ((!p5.canRead()) || (!p5.canWrite())) {
                android.util.Log.e("SerialPort", "2=====================");
                throw new SecurityException();
            }
        }
        this.mFd = android_serialport_api.SerialPort.open(p5.getAbsolutePath(), p6, p7);
        if (this.mFd != null) {
            this.mFileInputStream = new java.io.FileInputStream(this.mFd);
            this.mFileOutputStream = new java.io.FileOutputStream(this.mFd);
            return;
        } else {
            android.util.Log.e("SerialPort", "native open returns null");
            throw new java.io.IOException();
        }
    }

Method java.lang.Runtime.exec() not found.

[TAINT] String 'chmod 666 ' ==>>> Sink '['Ljava/lang/Runtime;', 'exec', '(Ljava/lang/String;)Ljava/lang/Process;', '0', 'COMMAND_SINK']' [[('Landroid_serialport_api/SerialPort;', '<init>', '(Ljava/io/File; I I)V'), ('Ljava/lang/Runtime;', 'exec', '(Ljava/lang/String;)Ljava/lang/Process;')]]

The application executes a dangerous command

Method android_serialport_api.SerialPort.<init>():


    public SerialPort(java.io.File p5, int p6, int p7)
    {
        if ((!p5.canRead()) || (!p5.canWrite())) {
            try {
                android.util.Log.e("SerialPort", "1============================");
                java.io.FileOutputStream v0_5 = new StringBuilder().append("chmod 666 ").append(p5.getAbsolutePath()).toString();
                android.util.Log.e("SerialPort", new StringBuilder().append("cmd=====================").append(v0_5).toString());
                Runtime.getRuntime().exec(v0_5);
            } catch (java.io.FileOutputStream v0_22) {
                android.util.Log.e("SerialPort", "3=================");
                v0_22.printStackTrace();
                throw new SecurityException();
            }
            if ((!p5.canRead()) || (!p5.canWrite())) {
                android.util.Log.e("SerialPort", "2=====================");
                throw new SecurityException();
            }
        }
        this.mFd = android_serialport_api.SerialPort.open(p5.getAbsolutePath(), p6, p7);
        if (this.mFd != null) {
            this.mFileInputStream = new java.io.FileInputStream(this.mFd);
            this.mFileOutputStream = new java.io.FileOutputStream(this.mFd);
            return;
        } else {
            android.util.Log.e("SerialPort", "native open returns null");
            throw new java.io.IOException();
        }
    }

Method java.lang.Runtime.exec() not found.