From e1ef5f8f279fb2895381bdb5c7aaca0ab0e95631 Mon Sep 17 00:00:00 2001 From: jesajx Date: Mon, 28 Jun 2021 16:56:56 +0200 Subject: [PATCH 01/10] patriot tests v1 --- .../mal_lang/corelang/test/TestPatriot.java | 2714 +++++++++++++++++ 1 file changed, 2714 insertions(+) create mode 100644 src/test/java/org/mal_lang/corelang/test/TestPatriot.java diff --git a/src/test/java/org/mal_lang/corelang/test/TestPatriot.java b/src/test/java/org/mal_lang/corelang/test/TestPatriot.java new file mode 100644 index 0000000..4acb0de --- /dev/null +++ b/src/test/java/org/mal_lang/corelang/test/TestPatriot.java @@ -0,0 +1,2714 @@ +package org.mal_lang.corelang.test; + +import org.junit.jupiter.api.AfterEach; + +import core.*; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.HashSet; +import java.util.HashMap; + + +public class TestPatriot extends CoreLangTest { + // These tests are based the weaknesses listed in the PATRIOT methodology + // (paper pending). Some of the weaknesses can be found listed here: + // . + // + // In any case, below is an attempt to model each weakness in at least one + // way in coreLang. Note that the weaknesses form a checklist of things to + // look for during a pentest. As such not all weaknesses make sense to + // model. + // + // TODO Some suggestions on changes to coreLang are marked with "TODO". + // + +// @Test +// public void test_t001() { +// // T001 (physical) Sensitive data exposure - Device ID/serial no +// // "An attacker could gather more critical information regarding to internals of the device which makes easy to conduct other various attacks." +// // +// // Interpretation: The device may be physically labeled with IDs (e.g. +// // FCC ID, microchip serial ID). While not sensitive by itself, this +// // information is useful for further attacks and reverse engineering. +// // +// // Probably does not make sense to model in coreLang. +// // +// // See also T002 and T004 on gaining informatino through physical interfaces (e.g. UART, USB, etc). +// } + + @Test + public void test_t002() { + // T002 (physical) Firmware/storage extraction - Insecure external media interfaces + // "An attacker could copy the firmware/storage and even modify firmware if device allows to physically remove the storage media (SD Card, USB)." + // + // Interpretation: An IoT device may have easily accessible physical + // connectors, such as USB. The attacker can use these interfaces to + // gain access to the device. We also model removable storage media + // (e.g. SD-card) the same way. + // + // Examples: + // * The attacker may be able to read firmware. + // * The attacker may be able to read shared credentials (e.g. if the + // same symmetric encryption key is used for all users and + // devices). + // + // How to model this in coreLang: + // * PhysicalZone is used to model physical attacks on a system. + // * Physical interfaces can also be modeled as networks and + // ConnectionRules, see T004. + + var phy = new PhysicalZone("phy"); + var sys = new System("sys"); + var app = new Application("app"); + + containerAdd(phy, sys); + containerAdd(sys, app); + + var sysData = new Data("sysData"); + var appData = new Data("appData"); + + containerAdd(sys, sysData); + containerAdd(app, appData); + + // TODO currently physical exploits are not full implemented in + // coreLang 0.2.0. We will just model this as "anyone" having access. + + var anyone = new Identity("anyone"); + sys.addHighPrivSysIds(anyone); // vulnerability + + attack(phy.gainPhysicalAccess, anyone.assume); + + compromised(1, sysData.read); + compromised(1, appData.read); + } + + @Test + public void test_t003() { + // T003 (physical) Firmware/storage extraction - Download from the Web + // "An attacker could download the firmware from the manufacturer's website if access to the firmware image without authentication is possible." + // + // Interpretation: The firmware used for a particular model of IoT + // device may be publically available on the internet (e.g. can be + // downloaded from the manufacturer's website). The attacker can use + // the firmware to gain information about the device (e.g. reverse + // enginnering, sensitive information contained in the firmware and + // whitebox testing). + // + // Examples: + // * The firmware may contain sensitive information (such as + // credentials) that the attacker can extract. + // * The attacker can reverse engineer the firmware to find + // vulnerabilities faster (as opposed to black-box testing the + // device). + // + // How to model this in coreLang: + // * see test_T001. + // * see test_T001_v2. + + var internet = new Network("internet"); + + var firmwareBlob = new Data("firmwareBlob"); + var sensitiveData = new Data("sensitiveData"); + + transferData(internet, firmwareBlob); + containerAdd(firmwareBlob, sensitiveData); + + attack(internet.access); + + compromised(1, sensitiveData.read); + compromised(1, sensitiveData.write); + } + + @Test + public void test_T003_v2() { + var internet = new Network("internet"); + var cloud = new Application("cloud"); + + var con_internet_cloud = autoconbi("con_internet_cloud", internet, cloud); + + var firmwareBlob = new Data("firmwareBlob"); + var sensitiveData = new Data("sensitiveData"); + + containerAdd(cloud, firmwareBlob); + containerAdd(firmwareBlob, sensitiveData); + + var anyone = new Identity("anyone"); + mkReadApi(cloud, anyone, firmwareBlob); + + attack(internet.access, anyone.attemptAssume); + + + + compromised(1, cloud.specificAccessAuthenticate); + compromised(1, cloud.specificAccess); + + compromised(1, firmwareBlob.attemptAccessFromIdentity); + compromised(1, firmwareBlob.identityRead); + compromised(1, firmwareBlob.attemptRead); + compromised(1, firmwareBlob.read); + + compromised(1, sensitiveData.attemptRead); + compromised(1, sensitiveData.read); + + compromised(0, firmwareBlob.write); + compromised(0, sensitiveData.write); + } + + + @Test + public void test_t004() { + // T004 (physical) Firmware/storage extraction - Insecure SPI interface + // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the serial bus protocol SPI." + // + // Interpretation: An IoT device may have hidden physical connectors. + // The attacker can use these connectors to gain access to the device. + // + // Examples: + // * The attacker may be able to read firmware. + // * The attacker may be able to read shared credentials (e.g. if the + // same symmetric encryption key is used for all users and + // devices). + // * The attacker may desolder the flash component and use SPI to + // extract the contents. + // + // How to model this in coreLang: + // * See test_T002. Basically use PhysicalZone to attach System. TODO not done in coreLang 0.2.0? + // * You can also model SPI as a kind of Network. + + + // SPI as network: + + var spi = new Network("spi"); + var app = new Application("app"); + + var spi_con_app = autocon("spi_con_app", spi, app); + + var appData = new Data("appData"); + containerAdd(app, appData); + + var vuln = vulnerabilityBuilder("vuln").setNetwork().setConfidentiality().build(); + app.addVulnerabilities(vuln); + + var startSet = attack(spi.physicalAccess); + + compromised(1, vuln.abuse); + compromised(1, appData.read); + } + + @Test + public void test_T004_v2() { + // Like test_T004, but with explicit root shell. + + var os = new Application("os"); + var app = new Application("app"); + var shell = new Application("shell"); + + containerAdd(os, app); + containerAdd(os, shell); + + var spi = new Network("spi"); + + var con_shell_spi = autoconbi("con_shell_spi", shell, spi); + + var appData = new Data("appData"); + containerAdd(app, appData); + + var anyone = new Identity("anyone"); + var root = new Identity("root"); + + mkExecApi(shell, anyone); // privilege escalation: anyone -> root + + appExecAs(shell, root); + appExecAs(os, root); + appExecAs(app, root); + + // TODO CoreLang could have an association between PhysicalZone and Network. + attack(spi.physicalAccess, anyone.assume); + + compromised(1, shell.networkConnect); + compromised(1, shell.authenticate); + compromised(1, shell.fullAccess); + compromised(1, os.fullAccess); + compromised(1, app.fullAccess); + compromised(1, appData.read); + } + + @Test + public void test_T004_v3() { + // Attack bootloader. This is perhaps more common with TTL/UART than + // SPI. + + var bootloader = new Application("bootloader"); // e.g. uboot + var os = new Application("os"); + + containerAdd(bootloader, os); + + var spi = new Network("spi"); + + var spi_con_bootloader = autocon("spi_con_bootloader", spi, bootloader); + + var sensitiveData = new Data("sensitiveData"); + containerAdd(os, sensitiveData); + + var anyone = new Identity("anyone"); + + mkExecApi(bootloader, anyone); + + attack(spi.physicalAccess, anyone.assume); + + compromised(1, bootloader.fullAccess); + compromised(1, os.fullAccess); + compromised(1, sensitiveData.read); + } + + + +// @Test +// public void test_t005() { +// // T005 (physical) Firmware/storage extraction - Insecure I2C interface +// // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the serial bus protocol I2C." +// // +// // see T004. +// } +// @Test +// public void test_t006() { +// // T006 (physical) Firmware/storage extraction - Insecure UART interface +// // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the serial interface UART." +// // +// // see T004. +// } +// @Test +// public void test_t007() { +// // T007 (physical) Firmware/storage extraction - Insecure JTAG interface +// // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the debug interface JTAG." +// // +// // see T004. +// } +// @Test +// public void test_t008() { +// // T008 (physical) Firmware/storage extraction - Insecure SWD interface +// // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the debug interface SWD." +// // +// // see T004. +// } + @Test + public void test_t009() { + // T009 (physical) Firmware/storage extraction - Insecure SoC + // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the other SoC (System on Chip) (e.g. Bluetooth)." + // + // Like T004, but we are attacking from another chip. Same idea here: use networks to model internal communication like SPI, etc. + + var chipA = new Application("chipA"); + var chipB = new Application("chipB"); // chipB could for example be a flash component or a chip that provides an API to a flash component. + + var i2c = new Network("i2c"); + var chipA_con_i2c = autocon("chipA_con_i2c", chipA, i2c); // chipA is a "master" + var i2c_con_chipB = autocon("i2c_con_chipB", i2c, chipB); // chipB is a "slave" + + var anyone = new Identity("anyone"); + + var sensitiveData = new Data("sensitiveData"); + mkReadApi(chipB, anyone, sensitiveData); + + attack(chipA.fullAccess, anyone.assume); + compromised(1, sensitiveData.read); + } +// @Test +// public void test_t010() { +// // T010 (physical) Firmware/storage extraction - Insecure eMMC chip +// // "An attacker could dump the firmware by tapping if it is stored an embedded Multi Media Card (eMMC) flash chip (embedded SD card). An attacker could dump the firmware by unsoldering chip then reading it with an adapter if it is stored in an embedded Multi Media Card (eMMC) flash chip (embedded SD card)." +// // +// // Interpretation: Like T004, but we must desolder the eMMC chip +// // first before communicating with it. +// // +// // See T002 and T004. +// } + @Test + public void test_t011() { + // T011 (physical) Backdoor firmware - Insecure UART interface + // "An attacker could modify the firmware if access to the flash/EEPROM chip is not restricted through the serial interface UART." + // + // Interpretation: An IoT device may have hidden physical connectors. + // The attacker may be able to use these connectors to install (and + // run) firmware on the device. + // + // Examples: + // * The attacker is able to upload, install and run firmware. + // + // How to model this in coreLang: + // * See T002 and T004 on modeling physical attacks. Additionally use + // SoftwareProduct to model the attacker overwriting existing + // software via Data. + + + var app = new Application("app"); + + var ttl = new Network("ttl"); + + var ttl_con_app = autocon("ttl_con_app", ttl, app); + + var firmwareBlob = new Data("firmwareBlob"); + containerAdd(app, firmwareBlob); + + var firmwareProduct = new SoftwareProduct("firmwareProduct"); + + execData(firmwareBlob, firmwareProduct, app); + + var anyone = new Identity("anyone"); + + mkWriteApi(app, anyone, firmwareBlob); + + attack(ttl.physicalAccess, anyone.assume); + + + compromised(1, firmwareBlob.write); // By writing to the firmwareblob... + compromised(1, app.fullAccess); // ... we can exec code. + } +// @Test +// public void test_t012() { +// // T012 (physical) Backdoor firmware - Insecure JTAG interface +// // "An attacker could modify the firmware if access to the flash/EEPROM chip is not restricted through the debug interface JTAG." +// // +// // See T011. +// } +// @Test +// public void test_t013() { +// // T013 (physical) Backdoor firmware - Insecure SWD interface +// // "An attacker could modify the firmware if access to the flash/EEPROM chip is not restricted through the debug interface SWD." +// // +// // See T011. +// } +// @Test +// public void test_t014() { +// // T014 (physical) Grant shell access - Insecure UART interface +// // "An attacker could grant a command shell if access to the flash/EEPROM chip is not restricted through the serial interface UART." +// // +// // Interpretation: An IoT device may have hidden physical connectors. +// // The attacker may be able to use these connectors to command the +// // device (e.g. gain root shell access). +// // +// // see test_T004_v2. +// } + @Test + public void test_t015() { + // T015 (physical) Grant shell access - Insecure SPI interface + // "An attacker could grant a command shell if access to the flash/EEPROM chip is not restricted through the serial interface SPI." + // + // See also T004. + + var spi = new Network("spi"); + var flash = new Application("flash"); + var app = new Application("app"); + + var spi_con_app = autocon("spi_con_app", spi, app); + var spi_con_flash = autocon("spi_con_app", spi, flash); + + var filesystem = new Data("filesystem"); + var bootscript = new Data("bootscript"); + containerAdd(flash, filesystem); + containerAdd(filesystem, bootscript); + + var appProduct = new SoftwareProduct("appProduct"); + + execData(bootscript, appProduct, app); + + var anyone = new Identity("anyone"); + mkReadWriteApi(flash, anyone, filesystem); + + var startSet = attack(spi.physicalAccess, anyone.assume); + + compromised(1, filesystem.write); + compromised(1, bootscript.write); + compromised(1, app.fullAccess); + } + +// @Test +// public void test_t016() { +// // T016 (physical) Change code execution flow - Insecure JTAG/SWD interface +// // "An attacker could debug the libraries/binaries and manipulate the execution flow of firmware if access to the flash/EEPROM chip is not restricted through the debug interface JTAG." +// // +// // See T015. +// } +// @Test +// public void test_t017() { +// // T017 (physical) Reset to insecure state +// // "An attacker could misuse reset functionality of the device if resetting results in insecure state." +// // +// // TODO coreLang does not really model state changes. We could +// // potentially model this as two separate models: one showing the +// // scenario leading up to the reset and one shoing the scenario +// // resulting from the reset. The reset can be modeled as the the +// // attacker doing Data.write to a specific Data asset representing the +// // reset API-function. See also T035 on rollback attacks. +// } +// +// @Test +// public void test_t018() { +// // T018 (firmware) Sensitive data exposure - Hardcoded credentials +// // "An attacker could reveal unchangable credentials including password, hash, private certificate, and API key from storage by reverse engineering and source code analysis." +// // +// // Interpretation: The firmware blob of a device may contain hardcoded +// // credentials. If the attacker can obtain the firmware blob they can +// // obtain the credentials. +// // +// // Example: +// // * see T019. +// } + + @Test + public void test_t019() { + // T019 (firmware) Sensitive data exposure - Backdoor accounts + // "An attacker could discover (undocumented) backdoor account from non-volatile data by reverse engineering and source code analysis." + // + // Interpretation: The device may have exposed ports where the + // manufacturer may have preconfigured backdoors. If the attacker was + // to discover these backdoors and obtain the credentials, then they + // could compromise the account. The attacker might learn about the + // backdoor credentials by for example reverse engineering the + // firmware. + // + // See also T004. + // + // Example: + // * The attacker can find the credentials on the internet. + // * The attacker can find the credentials inside a firmwareblob from the internet. + // + // How to model this in coreLang: + // * The attacker needs to Application.networkConnect and Credentials.attemptAccess. + // Link the Application to the Credentials using an Identity. + + var app = new Application("app"); + + var net = new Network("net"); + + var net_con_app = autocon("con_app_net", net, app); + + var identity = new Identity("identity"); + var credentials = new Credentials("credentials"); + identity.addCredentials(credentials); + app.addExecutionPrivIds(identity); + + attack(net.access, credentials.attemptAccess); // assume attacker already has credentials (e.g. from internet) + + compromised(1, app.fullAccess); + } + + @Test + public void test_T019_v2() { + // Gaining creds via physical attack on one device + // and using to gain network-access to another device. + + var app = new Application("app"); + + var net = new Network("net"); + + var appRE = new Application("appRE"); // app for reverse engineering (e.g. attacker bought the device and took it apart) + + + + var net_con_app = autocon("con_app_net", net, app); + + var identity = new Identity("identity"); + var credentials = new Credentials("credentials"); + identity.addCredentials(credentials); + app.addExecutionPrivIds(identity); + + var credStore = new Data("credStore"); + var credStoreRE = new Data("credStoreRE"); + + containerAdd(app, credStore); // optional + containerAdd(credStore, credentials); // optional + + containerAdd(appRE, credStoreRE); + containerAdd(credStoreRE, credentials); + + attack(net.access, appRE.fullAccess); // assume attacker already hacked inside appRE + + compromised(1, appRE.fullAccess); + compromised(1, credStoreRE.read); + compromised(1, credentials.use); + compromised(1, app.networkConnect); + compromised(1, app.authenticate); + compromised(1, app.fullAccess); + } + + +// @Test +// public void test_t020() { +// // T020 (firmware) Sensitive data exposure - Encryption keys and algorithms +// // "An attacker could identify encryption keys from both storage and memory by reverse engineering and source code analysis. An attacker could gain sensitive data if device has encrypted with the discovered keys." +// // +// // See T018. +// } + + @Test + public void test_t021_v1() { + // T021 (firmware) Sensitive data exposure - Other sensitive information + // "An attacker could identify various sensitive data (e.g. URLs) from both storage and memory by reverse engineering and source code analysis. An attacker could gain sensitive data if device lacks of disk encryption." + // + // Interpretation: The device stores data without encrypting it. If + // the attacker can somehow get inside the device (or a copy of the + // firmware) then they can extract that data. + // + // Examples: + // * The device stores sensitive data in plain text in flash. + // + // How to model in coreLang: + // * Use Application.containedData + // * See also test_T003. + + var app = new Application("app"); + + var flash = new Data("flash"); + var sensitiveData = new Data("sensitiveData"); + + containerAdd(app, flash); + containerAdd(flash, sensitiveData); + + attack(app.read); + + compromised(1, flash.read); + compromised(1, sensitiveData.read); + } + + @Test + public void test_T021_v1_defense() { + // Like test_T021_v1, but we encrypt the data. + + var app = new Application("app"); + + var flash = new Data("flash"); + var sensitiveData = new Data("sensitiveData"); + + containerAdd(app, flash); + containerAdd(flash, sensitiveData); + + var enc = new Credentials("enc"); + sensitiveData.addEncryptCreds(enc); + + attack(app.read); + + compromised(1, flash.read); + compromised(0, sensitiveData.read); + } + @Test + public void test_T021_v2() { + // Hardware-based encryption (e.g. keystore on android) can sometimes be circumvented. + + var hardwareCredentials = new Credentials("hardwareCredentials"); // unobtainable in practice + + var keystore = new Data("keystore"); + keystore.addEncryptCreds(hardwareCredentials); + + var key = new Credentials("key"); + containerAdd(keystore, key); + + + var os = new Application("app"); + var app = new Application("app"); + containerAdd(os, app); + + var filesystem = new Data("filesystem"); + containerAdd(filesystem, keystore); + + containerAdd(os, filesystem); + + var appId = new Identity("appId"); + + // TODO CoreLang does not really have a way to express data getting + // copied, but we can abuse Data.containedData to express the + // transformation. + // Similarly, we can not express that the attacker is able to falsely + // sign/encrypt data. + + var decryptApiInput = new Data("externalData"); + + var decryptApiInputPayload = new Data("externalData"); + decryptApiInputPayload.addEncryptCreds(key); + + containerAdd(decryptApiInput, decryptApiInputPayload); + + var decryptApiOutput = new Data("externalData"); + + containerAdd(decryptApiInputPayload, decryptApiOutput); + + appExecAs(app, appId); + + mkReadApi(os, appId, filesystem); + mkWriteApi(os, appId, decryptApiInput); + mkReadApi(os, appId, decryptApiOutput); // decryption as service + + attack(app.fullAccess); + + // Can not access the key: + compromised(1, filesystem.read); + compromised(0, keystore.read); + compromised(0, key.use); + + // but can access the decryption API: + compromised(1, decryptApiInput.write); + compromised(1, decryptApiOutput.read); + } + + @Test + public void test_T021_v3() { + // Like test_T021_v2, but simplified. + + var hardwareCredentials = new Credentials("hardwareCredentials"); // unobtainable in practice + + var keystore = new Data("keystore"); + keystore.addEncryptCreds(hardwareCredentials); + + var keyring = new Data("keyring"); + var key = new Credentials("key"); + containerAdd(keystore, keyring); + containerAdd(keyring, key); + + + var os = new Application("app"); + var app = new Application("app"); + containerAdd(os, app); + + var filesystem = new Data("filesystem"); + containerAdd(os, filesystem); + containerAdd(filesystem, keystore); + + var appId = new Identity("appId"); + appExecAs(app, appId); + + mkReadApi(os, appId, filesystem); + + // While the attacker is not able to access the key directly (see + // test_T021_v2), we can still model it as if they could since they + // can use the key to decrypt data. + mkReadApi(os, appId, keyring); + + var externalData = new Data("externalData"); + externalData.addEncryptCreds(key); + containerAdd(app, externalData); + + + attack(app.fullAccess); + + compromised(1, filesystem.read); + compromised(0, keystore.read); + compromised(1, key.attemptAccess); + compromised(1, key.use); + compromised(1, externalData.read); + } + + @Test + public void test_t022() { + // T022 (firmware) Sensitive data exposure - Static and same encryption keys + // "An attacker could gain sensitive data of other devices if firmware uses static and same encryption keys." + // + // Interpretation: IoT devices of a particular model all use the same + // encryption key. Attacking a single devices is sufficient to access + // the key. + // + // Examples: + // * Data is stored encrypted on the device, but the key is easy to + // obtain. + // * Data is sent over a custom protocol, but the encryption key is + // easy to obtain. + // + // How to model in coreLang: + // * Use Data.encryptCreds and Credentials to model encryption. Use + // for example Application.containedData, Data.containedData and + // Data.containedInformation to model access to the key. + + var app = new Application("app"); + + var flash = new Data("flash"); + var sensitiveData = new Data("sensitiveData"); + var encKey = new Credentials("encKey"); + + containerAdd(app, flash); + containerAdd(flash, sensitiveData); + containerAdd(flash, encKey); + + sensitiveData.addEncryptCreds(encKey); + + attack(app.read); + + compromised(1, flash.read); + compromised(1, encKey.use); + compromised(1, sensitiveData.read); + } + @Test + public void test_T022_v2() { + // Like test_T022, but we use the key on another device. + + var app = new Application("app"); + var flash = new Data("flash"); + var sensitiveData = new Data("sensitiveData"); + var encKey = new Credentials("encKey"); + + var app2 = new Application("app2"); + var flash2 = new Data("flash2"); + var sensitiveData2 = new Data("sensitiveData2"); + + containerAdd(app, flash); + containerAdd(flash, sensitiveData); + containerAdd(flash, encKey); + sensitiveData.addEncryptCreds(encKey); + + + containerAdd(app2, flash2); + containerAdd(flash2, sensitiveData2); + sensitiveData2.addEncryptCreds(encKey); // same key + + attack(app.read, app2.read); + + compromised(1, flash.read); + compromised(1, encKey.use); + compromised(1, sensitiveData.read); + + compromised(1, flash2.read); + compromised(1, sensitiveData2.read); + } + + @Test + public void test_T022_v3() { + // Like test_T022_v1, but the key is hardcoded into the firmware + // (which the attacker can download from the internet). + + var app = new Application("app"); + + var firmwareBlob = new Data("firmwareBlob"); + var encKey = new Credentials("encKey"); + containerAdd(firmwareBlob, encKey); + + var firmwareProduct = new SoftwareProduct("firmwareProduct"); + execData(firmwareBlob, firmwareProduct, app); + + var flash = new Data("flash"); + var sensitiveData = new Data("sensitiveData"); + + + containerAdd(app, flash); + containerAdd(flash, sensitiveData); + + sensitiveData.addEncryptCreds(encKey); + + attack(app.read, firmwareBlob.read); + + compromised(1, flash.read); + compromised(1, encKey.use); + compromised(1, sensitiveData.read); + } + + + +// @Test +// public void test_t023() { +// // T023 (firmware) Configuration - Lack of data integrity checks +// // "An attacker could backdoor the firmware if firmware has insecure or lack of integrity checks." +// // +// // See T035 about signature verification. +// } +// @Test +// public void test_t024() { +// // T024 (firmware) Configuration - Lack of wiping device +// // "Lack of deprovisioning/decomissioning. Inability to wipe device's local data storage … " +// // +// // Interpretation: Factory reset / deprovisioning functionality is missing or +// // imperfect. +// // +// // Example: +// // * Old data is left from previous owner (cloud credentials, wifi passwords, etc.). See also T021. +// // +// // How to model in coreLang: +// // * TODO Corelang does not really model state, see T017 and T040. +// // * Alternative, simply model it as sensitive data/credentials being stored on the device, see e.g. T021. +// } +// @Test +// public void test_t025() { +// // T025 (firmware) Configuration - Insecure customization of OS platforms +// // "Insecure default settings or insufficient ability to harden the system by modifying configurations are the root cause of many vulnerabilities." +// // +// // Interpretation: The OS platform might have been customized in an +// // insecure way, or the default settings are insecure and can't be +// // changed. Basically the device could be more hardened, but is not. +// // +// // This is more like the cause of other vulnerabilities rather than a vulnerability in itself. +// // See for example T031 on modeling generic vulnerabilities. +// } +// @Test +// public void test_t026() { +// // T026 (firmware) Configuration - Lack of security configurability +// // "Insecure default settings or insufficient ability to harden the system by modifying configurations are the root cause of many vulnerabilities." +// // +// // See T025. Does not really make sense to model. Also, It is tricky to define what is and is not a "configuration". +// } + @Test + public void test_t027_v1() { + // T027 (firmware) Configuration - Insecure filesystem permissions + // "Insecure default settings or insufficient ability to harden the system by modifying configurations are the root cause of many vulnerabilities." + // + // Intepretation: Like T044, but specifically about how the filesystem + // is set up. + // + // Examples: + // * Network-connected apps are running as root. + + var os = new Application("os"); + var app = new Application("app"); + containerAdd(os, app); + + var root = new Identity("root"); + appExecAs(os, root); + appExecAs(app, root); + + var filesystem = new Data("filesystem"); + var appData = new Data("appData"); + var nonappData = new Data("nonappData"); + containerAdd(filesystem, appData); + containerAdd(filesystem, nonappData); + + containerAdd(os, filesystem); + containerAdd(app, appData); + + attack(app.fullAccess); + + compromised(1, os.fullAccess); + compromised(1, appData.read); + compromised(1, nonappData.read); + } + @Test + public void test_T027_v1_defense() { + // Like test_T027_v1, but we prevent the attack. + + var os = new Application("os"); + var app = new Application("app"); + containerAdd(os, app); + + var root = new Identity("root"); + appExecAs(os, root); + + var nobody = new Identity("nobody"); + appExecAs(app, nobody); + + aOwnsB(root, nobody); // optional. (root can do everything nobody can do) + + var filesystem = new Data("filesystem"); + var appData = new Data("appData"); + var nonappData = new Data("nonappData"); + + containerAdd(filesystem, appData); + containerAdd(filesystem, nonappData); + + containerAdd(os, filesystem); + containerAdd(app, appData); + + attack(app.fullAccess); + + compromised(0, os.fullAccess); + compromised(1, appData.read); + compromised(0, nonappData.read); + } + + @Test + public void test_T027_v2() { + // appData as OS API + + var os = new Application("os"); + var app = new Application("app"); + containerAdd(os, app); + + var root = new Identity("root"); + appExecAs(os, root); + + var appId = new Identity("appId"); + appExecAs(app, appId); + + aOwnsB(root, appId); // optional. (root can do everything appId can do) + + var filesystem = new Data("filesystem"); + var appData = new Data("appData"); + var nonappData = new Data("nonappData"); + + containerAdd(filesystem, appData); + containerAdd(filesystem, nonappData); + + containerAdd(os, filesystem); + + mkReadApi(os, appId, appData); + mkReadApi(os, appId, nonappData); // vulnerability + + attack(app.fullAccess); + + compromised(0, os.fullAccess); + compromised(1, appData.read); + compromised(1, nonappData.read); + } + + @Test + public void test_T027_v2_defense() { + // Like test_T027_v2, but we prevent the attack. + + var os = new Application("os"); + var app = new Application("app"); + containerAdd(os, app); + + var root = new Identity("root"); + appExecAs(os, root); + + var appId = new Identity("appId"); + appExecAs(app, appId); + + aOwnsB(root, appId); // optional. (root can do everything appId can do) + + var filesystem = new Data("filesystem"); + var appData = new Data("appData"); + var nonappData = new Data("nonappData"); + + containerAdd(filesystem, appData); + containerAdd(filesystem, nonappData); + + containerAdd(os, filesystem); + + mkReadApi(os, appId, appData); + + attack(app.fullAccess); + + compromised(0, os.fullAccess); + compromised(1, appData.read); + compromised(0, nonappData.read); + } + + + @Test + public void test_t028() { + // T028 (firmware) Authentication bypass - Device to device + // "Disclosure or reusing of Sensitive data (session key, token, cookie, etc.) could cause authentication bypass." + // + // Interpretation: The idea is that the attacker could impersonate the + // device to authenticate to other device. For example, the attacker + // takes control of the first device or steals its credentials. + // Alternatively authentication-mechanisms may be missing and the + // attacker just needs to reverse engineer the API. + // + // How to model in coreLang: + // * Just as an API being accessible to the "anyone" Identity. + // * Assume the identity of deviceA. See e.g. T021 on stealing credentials from firmware or local storage. + + + // Just an API accessible to anyone: + + var net = new Network("net"); + var app = new Application("app"); + + var net_con_app = autocon("net_con_app", net, app); + + var anyone = new Identity("anyone"); + + var readData = new Data("readData"); + var writeData = new Data("writeData"); + + mkReadApi(app, anyone, readData); + mkWriteApi(app, anyone, writeData); + + attack(net.access, anyone.assume); + + compromised(1, readData.read); + compromised(1, writeData.write); + + compromised(0, readData.write); + compromised(0, writeData.read); + compromised(0, app.fullAccess); + } + + @Test + public void test_T028_v2() { + // Attacker assumes the identity of device A after hacking device A + // and uses that to access a API on device B. + + var appA = new Application("appA"); + var appB = new Application("appB"); + var net = new Network("net"); + + var appA_con_net = autoconbi("appA_con_net", appA, net); // outgoing connection + var net_con_appB = autoconbi("net_con_appB", net, appB); // open port + + var idA = new Identity("idA"); + + appExecAs(appA, idA); + + var sensitiveData = new Data("sensitiveData"); + var sensitiveCall = new Data("sensitiveCall"); + mkReadApi(appB, idA, sensitiveData); + mkWriteApi(appB, idA, sensitiveCall); + + + var regularCommunication = new Data("regularCommunication"); // optional, just to show m2m + regularCommunication.authenticated.defaultValue = true; + transferData(appA, regularCommunication); + transferData(net, regularCommunication); + transferData(appB, regularCommunication); // TODO coreLang has no way to show that regularCommunication is copied to sensitiveCall. There could perhaps be something like a "copy"-association for Data. + + + attack(appA.fullAccess); + + compromised(1, net.access); + compromised(1, idA.assume); + compromised(1, appB.specificAccess); // assume idA to talk to appB + compromised(1, sensitiveData.read); + compromised(1, sensitiveCall.write); + //compromised(1, regularCommunication.write); // TODO Would work if the authenticated defense was based on credentials instead, like Data.encryptCreds + } + + @Test + public void test_T028_v3() { + // Attacker steals credentials of device C (e.g. physical attack). + // Device A uses the same credentials as device C. + // The attacker uses the credentials from C to assume the identity of + // A to access device B. + + var appA = new Application("appA"); + var appB = new Application("appB"); + var net = new Network("net"); + + var appA_con_net = autoconbi("appA_con_net", appA, net); // outgoing connection + var net_con_appB = autoconbi("net_con_appB", net, appB); // open port + + var idA = new Identity("idA"); + + appExecAs(appA, idA); + + var sensitiveData = new Data("sensitiveData"); + var sensitiveCall = new Data("sensitiveCall"); + mkReadApi(appB, idA, sensitiveData); + mkWriteApi(appB, idA, sensitiveCall); + + + var regularCommunication = new Data("regularCommunication"); // optional, just to show m2m + regularCommunication.authenticated.defaultValue = true; + transferData(appA, regularCommunication); + transferData(net, regularCommunication); + transferData(appB, regularCommunication); // TODO coreLang has no way to show that regularCommunication is calling the API on appB. There could perhaps be something like a "copy"-association for Data. + + + + var appC = new Application("appA"); + var idC = new Identity("idA"); + var credsC = new Credentials("credsC"); + + var storageC = new Data("storageC"); + containerAdd(appC, storageC); + containerAdd(storageC, credsC); + + var credsA = credsC; + idA.addCredentials(credsA); + idC.addCredentials(credsC); + + attack(net.access, appC.fullAccess); + + compromised(1, credsC.use); + compromised(1, idC.assume); + + compromised(1, net.access); + + compromised(1, idA.assume); + compromised(1, appB.specificAccess); // assume idA to talk to appB + compromised(1, sensitiveData.read); + compromised(1, sensitiveCall.write); + //compromised(1, regularCommunication.write); // TODO Would work if the authenticated defense was based on credentials instead, like Data.encryptCreds + } + + @Test + public void test_T028_v4() { + // TODO show server-to-client authentication. i.e. client opens the + // connection, but server is the one authenticating. Not possible in + // CoreLang? + + // Reverse API: appA connects to appB, but appB is the one + // authenticating to appA. + + var appA = new Application("appA"); + var appB = new Application("appB"); + var net = new Network("net"); + + var appA_con_net = autoconbi("appA_con_net", appA, net); // outgoing connection + var net_con_appB = autoconbi("net_con_appB", net, appB); // open port + + var idB = new Identity("idB"); + var credsB = new Credentials("credsB"); + idB.addCredentials(credsB); + + appExecAs(appB, idB); + + var sensitiveData = new Data("sensitiveData"); + var sensitiveCall = new Data("sensitiveCall"); + mkReadApi(appA, idB, sensitiveData); + mkWriteApi(appA, idB, sensitiveCall); + + + var regularCommunicationAB = new Data("regularCommunication"); // optional, just to show m2m + transferData(appA, regularCommunicationAB); + transferData(net, regularCommunicationAB); + transferData(appB, regularCommunicationAB); + + + var regularCommunicationBA = new Data("regularCommunication"); // optional, just to show m2m + regularCommunicationBA.authenticated.defaultValue = true; + transferData(appB, regularCommunicationBA); + transferData(net, regularCommunicationBA); + transferData(appA, regularCommunicationBA); + + attack(net.access, credsB.use); + + compromised(1, sensitiveData.read); + compromised(1, sensitiveCall.write); + //compromised(1, regularCommunicationBA.write); // TODO Would work if the authenticated defense was based on credentials instead, like Data.encryptCreds + } + + +// @Test +// public void test_t029() { +// // T029 (firmware) Authentication bypass - Device to mobile application +// // "Disclosure or reusing of Sensitive data (session key, token, cookie, etc.) could cause authentication bypass." +// // +// // Like T028, but one of the devices is smartphone. +// } +// @Test +// public void test_t030() { +// // T030 (firmware) Authentication bypass - Device to cloud +// // "Disclosure or reusing of Sensitive data (session key, token, cookie, etc.) could cause authentication bypass." +// // +// // Like T028, but with a cloud API. +// } + + @Test + public void test_t031() { + // T031 (firmware) Update mechanism - Missing update mechanism + // "Devices will eventually remain vulnerable as the device does not have the ability to update." + // + // Interpretation: The device firmware may contain vulnerabilities and + // without a update mechanism these vulnerabilities will never get + // fixed. + // + // Example: + // * The device was installed in 2011, in 2013 a CVE is published + // and in 2020 hackers can still use the vulnerability since the + // device was never updated. + // + // How to model in coreLang: + // * Generic vulnerability. + + var app = new Application("app"); + var net = new Network("net"); + + + var con_app_net = autoconbi("con_app_net", app, net); + + // generic network vulnerability + var vuln = vulnerabilityBuilder("vuln").setNetwork().setCIA().build(); + + var prod = new SoftwareProduct("prod"); + prod.addSoftApplications(app); + + prod.addSoftProductVulnerabilities(vuln); // alternatively: vuln in app + + attack(net.access); + + compromised(1, app.networkConnect); + compromised(1, app.fullAccess); + } + @Test + public void test_t032() { + // T032 (firmware) Update mechanism - Lack of manual update + // "Devices will remain vulnerable until an automatic update is triggered, during which time an attacker could compromise the device. (No ability to manually force an update check for the device)" + // + // Interpretation: There is no way for the user to manually update the + // device, so if the manufacturer sending updates, then newer + // vulnerabilities never get fixed. + // + // See also T031. + } + @Test + public void test_t033_v1() { + // T033 (firmware) Update mechanism - Lack of transport encryption + // "An attacker could capture firmware via a transparent proxy if network traffic is unencrypted. (Updates are transmitted over the network without using TLS or encrypting the update file itself)" + // + // Interpretation: The device downloads updates over a network. The + // connection is not encrypted. This means that attacker can MitM the + // download, replacing the update with malicious code. + // + // How to model in coreLang: + // * Use SoftwareProduct.originData. + + var app = new Application("app"); + var net = new Network("lan"); + var cloud = new Application("cloud"); + + var app_con_net = autocon("app_con_net", app, net); + var net_con_cloud = autocon("net_con_cloud", net, cloud); + + var firmwareBlob = new Data("firmwareBlob"); + + var firmwareProduct = new SoftwareProduct("firmwareProduct"); + execData(firmwareBlob, firmwareProduct, app); + + var tcp = new Data("tcp"); + containerAdd(tcp, firmwareBlob); + + transferData(app, tcp); + transferData(net, tcp); // mitm point + transferData(cloud, tcp); + + attack(net.access); + + compromised(1, firmwareBlob.write); // mitm + compromised(1, app.fullAccess); + } + + @Test + public void test_T033_v1_defense() { + // test_T033_v1, but we implement encryption to prevent the + // vulnerability. + + var app = new Application("app"); + var net = new Network("lan"); + var cloud = new Application("cloud"); + + var app_con_net = autocon("app_con_net", app, net); + var net_con_cloud = autocon("net_con_cloud", net, cloud); + + var firmwareBlob = new Data("firmwareBlob"); + + var firmwareProduct = new SoftwareProduct("firmwareProduct"); + execData(firmwareBlob, firmwareProduct, app); + + var tcp = new Data("tcp"); + + var tls = new Data("tls"); + var tlsCreds = new Credentials("tlsCreds"); + tls.addEncryptCreds(tlsCreds); + + containerAdd(tcp, tls); + containerAdd(tls, firmwareBlob); + + transferData(app, tcp); + transferData(net, tcp); // mitm point + transferData(cloud, tcp); + + attack(net.access); + + compromised(0, firmwareBlob.write); // mitm not possible + compromised(0, app.fullAccess); + } + + @Test + public void test_T033_v2() { + // more complicated example + + var sys = new System("sys"); + var app = new Application("app"); + + containerAdd(sys, app); + + var lan = new Network("lan"); + var internet = new Network("internet"); + var cloud = new Application("cloud"); + + var con_app_lan = autocon("con_app_lan", app, lan); + var con_lan_internet = autocon("con_lan_internet", lan, internet); // Note: NAT. + var con_internet_cloud = autoconbi("con_internet_cloud", internet, cloud); + + // The RoutingFirewall is optional. It is just here to show that the + // router may actually be a IoT device (that can be hacked): RoutingFirewall extends Application. + var routerNat = new RoutingFirewall("routerNat"); + con_lan_internet.addRoutingFirewalls(routerNat); + + var routerHardware = new System("routerHardware"); + containerAdd(routerHardware, routerNat); + + var tcp = new Data("tcp"); + + var firmwareBlob = new Data("firmwareBlob"); + + containerAdd(tcp, firmwareBlob); + + var firmwareProduct = new SoftwareProduct("firmwareProduct"); + execData(firmwareBlob, firmwareProduct, app); + + transferData(app, tcp); + transferData(lan, tcp); + transferData(internet, tcp); + transferData(cloud, tcp); + + + var identity = new Identity("identity"); + sys.addHighPrivSysIds(identity); + app.addExecutionPrivIds(identity); // NOTE: You can not gain privileges if there are no privileges defined. + + attack(internet.access); + + compromised(1, firmwareBlob.write); // mitm + compromised(1, app.fullAccess); + } + + @Test + public void test_t034_v1() { + // T034 (firmware) Update mechanism - Lack of signature on update file + // "An attacker could backdoor the firmware if firmware update file has insecure or lack of digital signature." + // + // Interpretation: In some cases IoT device download update files + // without using transport encryption, but still verify the integrity + // of the update file in some other way (e.g. signatures, hashing, + // etc.). If the verification mechanism is missing or not secure, then + // the attacker could install firmware. + // + // How to model in coreLang: + // * In corelang you can use the defense: Data.authenticated. + // * TODO model the attacker overwriting public keys on receiver-end? e.g. overwrite root CA certs and then using mitmproxy. Would require making Credentials/Information writable or have writable-copies used by apps to optain credentials? Alternatively model Identity replacement? + + var app = new Application("app"); + var net = new Network("lan"); + var cloud = new Application("cloud"); + + var app_con_net = autocon("app_con_net", app, net); + var net_con_cloud = autocon("net_con_cloud", net, cloud); + + var firmwareBlob = new Data("firmwareBlob"); + firmwareBlob.authenticated.defaultValue = false; // no signature nor verification + + var sensitiveData = new Data("sensitiveData"); + containerAdd(firmwareBlob, sensitiveData); + + var firmwareProduct = new SoftwareProduct("firmwareProduct"); + execData(firmwareBlob, firmwareProduct, app); + + var tcp = new Data("tcp"); + containerAdd(tcp, firmwareBlob); + + transferData(app, tcp); + transferData(net, tcp); // mitm point + transferData(cloud, tcp); + + attack(net.access); + + + compromised(1, firmwareBlob.read); // can read + compromised(1, sensitiveData.read); + + compromised(1, firmwareBlob.write); + compromised(1, sensitiveData.write); + + compromised(1, app.fullAccess); + } + + @Test + public void test_t034_v1_defense() { + // LIke test_t034_v1, but we defend against the attack. + + var app = new Application("app"); + var net = new Network("lan"); + var cloud = new Application("cloud"); + + var app_con_net = autocon("app_con_net", app, net); + var net_con_cloud = autocon("net_con_cloud", net, cloud); + + var firmwareBlob = new Data("firmwareBlob"); + firmwareBlob.authenticated.defaultValue = true; // signature and verification + + var sensitiveData = new Data("sensitiveData"); + containerAdd(firmwareBlob, sensitiveData); + + var firmwareProduct = new SoftwareProduct("firmwareProduct"); + execData(firmwareBlob, firmwareProduct, app); + + var tcp = new Data("tcp"); + containerAdd(tcp, firmwareBlob); + + transferData(app, tcp); + transferData(net, tcp); // mitm point + transferData(cloud, tcp); + + attack(net.access); + + + compromised(1, firmwareBlob.read); // can read + compromised(1, sensitiveData.read); + + compromised(0, firmwareBlob.write); // but can't write + compromised(0, sensitiveData.write); + + compromised(0, app.fullAccess); + } + +// @Test +// public void test_t035() { +// // T035 (firmware) Update mechanism - Lack of update verification +// // "An attacker could backdoor the firmware if firmware update process has insecure or lack of integrity verification." +// // +// // One form of verification is to verify a signature, see test_T034. +// // +// // More generally we can model lack of verification as "anyone" having +// // access to a write-API. See test_T034. +// } +// @Test +// public void test_t036() { +// // T036 (firmware) Update mechanism - Lack of update authentication +// // "An attacker could download the firmware if firmware update process has insecure or lack of authentication." +// // +// // Interpretation: Basically anyone can download the firmware from the internet +// // without authentication. That is: the authentication here means the +// // IoT authenticating with the cloud to begin downloading the update +// // (not the other way around). +// // +// // See T003. +// } + +// @Test +// public void test_t037() { +// // T037 (firmware) Update mechanism - Intercepting OTA update +// // "An attacker could capture firmware even from encrypted traffic if update mechanism is not secure against MitM attacks." +// // +// // Interpretation: OTA is basically just a fancy way to say that the +// // firmware updates are downloaded over a network (usually from the +// // internet). Those downloads coult be MITMed -- the attacker either +// // just snoops on the data or replaces the firmware on the fly. +// // +// // How to model in coreLang: +// // * See T033 on transport encryption. +// // * See T034 on firmware signatures and verification. +// } +// +// @Test +// public void test_t038() { +// // T038 (firmware) Update mechanism - Backdoor firmware +// // "(Malicious firmware update). An attacker could backdoor the firmware/sensitive data 'on the fly' before reaching the device/hub if update mechanism is not secure against MitM attacks." +// // +// // Interpretation: The attacker can upload and install firmware to the +// // device somehow. This could for example be done via MITM (T037), or the +// // update-mechanism be a world-writable API (T039). +// // +// // How to model in coreLang: +// // * See T037. +// // * See T039. +// } +// + @Test + public void test_t039() { + // T039 (firmware) Update mechanism - World writable update location + // "An attacker could modify firmware if storage location for update files is world writable." + // + // * We can model this as a write-API on the device. See also test_T011 and test_T038. + + var app = new Application("app"); + var net = new Network("net"); + + var net_con_app = autocon("net_con_app", net, app); + + var firmwareStorage = new Data("firmwareStorage"); + var firmwareBlob = new Data("firmwareBlob"); + + var anyone = new Identity("anyone"); + mkWriteApi(app, anyone, firmwareStorage); // alternatively we could use a vulnerability here. + + containerAdd(app, firmwareStorage); + containerAdd(firmwareStorage, firmwareBlob); + + var firmwareProduct = new SoftwareProduct("firmwareProduct"); + execData(firmwareBlob, firmwareProduct, app); + + attack(net.access, anyone.assume); + + compromised(1, firmwareStorage.write); + compromised(1, firmwareBlob.write); + compromised(1, app.fullAccess); + } +// @Test +// public void test_t040() { +// // T040 (firmware) Update mechanism - Lack of anti-rollback mechanism +// // "An attacker could revert firmware back (firmware downgrade) to a vulnerable version if the device lacks of anti-rollback mechanism." +// // +// // TODO CoreLang does not really model multiple versions of the same application. +// // A workaround is to create two models: one model showing the +// // scenario leading up to the rollback and another model showing the +// // situation after the rollback. See also T004. +// } + @Test + public void test_t041() { + // T041 (device network service) Sensitive data exposure + // "Any kind of senstive data that can be accessible." + // + // Intepretation: Sensitive data exposed on network ports. + // + // Examples: + // * MAC-addresses. + // * Unprotected APIs. + // + // See e.g. T003 and T028. + // + // How to model this in coreLang: + // 1. Network-assets may contain "transitData" (Data asset) which can + // be used to model sensitive data being available on the network. + // If the attacker has access to the network they can obtain the + // data through eavesdropping. Note that we consider reading the + // data to be impactful by itself. We do not model the attacker + // using the data for anything. + // 2. We can also model it using APIs (see test_T001_v2). + + + var app = new Application("app"); + + var net = new Network("net"); + + var con_app_net = autocon("con_app_net", app, net); + + var sensitiveData = new Data("sensitiveData"); + + // The app is broadcasting sensitiveData on the network: + //containerAdd(app, sensitiveData); + //transferData(app, sensitiveData); // Not needed, but in larger models this is how we would model the data being transfered around. + transferData(net, sensitiveData); + + attack(net.access); + + compromised(1, sensitiveData.read); + } + @Test + public void test_T041_v2() { + // We can model the sensitive data as being exposed by an API. + + var app = new Application("app"); + + var net = new Network("net"); + + var net_con_app = autocon("net_con_app", net, app); // open port + + var anyone = new Identity("anyone"); + + var sensitiveData = new Data("sensitiveData"); + + mkReadApi(app, anyone, sensitiveData); + + attack(net.access, anyone.assume); + + compromised(1, sensitiveData.read); + } + + +// @Test +// public void test_t042() { +// // T042 (device network service) Lack of transport encryption +// // "Network services are not properly encrypted HTTPS to prevent eavesdropping or tampering senstive data by attackers." +// // +// // See T033. +// } + + @Test + public void test_t043() { + // T043 (device network service) Insecure SSL/TLS issues + // "Encryption is implemented however it is improperly configured or is not being properly updated, (e.g. expired and/or self-signed certificates, same certificate used on multiple devices, deprecated SSL versions)" + // + // Interpretation: The device/cloud may be misconfigured in such a way + // that TLS can be circumvented. + // + // Examples: + // * The TLS certificates are not "pinned". + // * Private keys are reused between device (and might have been leaked on the internet). + // * There might be vulnerabilities in the TLS implementation (e.g. OpenSSL Heartbleed). + // * + // * There is a lack of authentication, so the attacker can just + // connect to the TLS server themselves and extract the information + // without MitM. + // + // How to model this in coreLang: + // * TODO how to model unpinned cert? how to model indirection? how to model spoofing? Simply model as attacker stealing TLS credentials? Maybe combine with signed data somehow? + // * What about overwriting credentials on client-side? or maybe just model as attacker accessing API on client using identity? + + var app = new Application("app"); + var lan = new Network("lan"); + var internet = new Network("internet"); + var cloud = new Application("cloud"); + + var con_app_lan = autocon("con_app_lan", app, lan); + var con_lan_internet = autocon("con_lan_internet", lan, internet); // Note: NAT. + var con_internet_cloud = autoconbi("con_internet_cloud", internet, cloud); + + var routerNat = new RoutingFirewall("routerNat"); + con_lan_internet.addRoutingFirewalls(routerNat); + + var routerHardware = new System("routerHardware"); + containerAdd(routerHardware, routerNat); + + var tlsCredentials = new Credentials("tlsCredentials"); + + var tcp = new Data("tcp"); + var tls = new Data("tls"); + var tlsPayload = new Data("tlsPayload"); + + containerAdd(tcp, tls); + containerAdd(tls, tlsPayload); + tls.addEncryptCreds(tlsCredentials); + + transferData(app, tcp); + transferData(lan, tcp); + transferData(internet, tcp); + transferData(cloud, tcp); + + // Assume the tlsCredentials have been compromised somehow. + attack(internet.access, tlsCredentials.attemptAccess); + + compromised(1, tlsPayload.read); + } + +// @Test +// public void test_t044() { +// // T044 (device network service) Authentication - Username enumeration +// // "Ability to collect a set of valid usernames by interacting with the authentication mechanism" +// // +// // Interpretation: An network service on the device provides a way to +// // enumerate users. +// // +// // Examples: +// // * Different authentication failure error message are returned +// // depending on the cause of the failure. So instead of the +// // attacker having to guess both username and password, they can +// // first guess the correct username (with an empty password) and +// // then guess the password. This saves some time. +// // +// // How to model in corelang: +// // * TODO CoreLang does not really separate usernames from passwords. +// // Username and password form a single Credential. Potentially TTC +// // can be adjusted. +// // * TODO CoreLang also does not model non-credential prerequisites +// // in access/attacks. +// } +// @Test +// public void test_t045() { +// // T045 (device network service) Authentication - Weak credentials +// // "Ability to set account passwords to '1234' or '123456' for example. Usage of pre-programmed default (known) passwords (deffpass.com (Publicly available) - IoT device default password lookup). Easily guessable credentials. Brute-force by dictionaries and rules" +// // +// // * TODO CoreLang does not really distinguish between strong and weak +// // credentials. Maybe TTC can be adjusted differently for different +// // credentials? +// // * See also the defense Credentials.notDisclosed. +// } +// @Test +// public void test_t046() { +// // T046 (device network service) Authentication - Improper account lockout +// // "Ability to continue sending authentication attempts after 3 - 5 failed login attempts" +// // +// // Interpretation: There either is no account lockout mechanism, or +// // the mechanism can be easily bypassed. +// // +// // Examples: +// // * For example, the attacker can keep trying passwords after 3-5 +// // failed attempts. +// // +// // TODO CoreLang does not really seem to model bruteforce attacks. It +// // can sort be done via generic vulnerabilities (if the app also +// // stores the credentials such that the attacker can obtain them), but the ttc will be +// // incorrect. The account lockout mechanism would then be the absence +// // of that vulnerability. +// } + + @Test + public void test_t047() { + // T047 (device network service) Authentication - Weak password recovery + // "Insecure password reset/forgot mechanism could cause authentication bypass." + // + // Interpretation: The device has a mechanism to restore access if the + // user has forgotten their password. This mechanism may have various + // problems. + // + // How to model in coreLang: + // * TODO CoreLang does not really model passwords being "changed", + // only stolen. We can work around this by treating stealing and + // changing as the same thing. + // * TODO Alternatively, we can model this via two Identities. + // + + // We can weak model password reset as the credentials being world + // readable. + var net = new Network("net"); + var app = new Application("app"); + + var net_con_app = autocon("net_con_app", net, app); // open port + + var user = new Identity("user"); + var password = new Credentials("password"); + user.addCredentials(password); + + var sensitiveData = new Data("sensitiveData"); + containerAdd(app, sensitiveData); + mkReadApi(app, user, sensitiveData); + + + var recoverMechanism = new Application("recoverMechanism"); + containerAdd(app, recoverMechanism); + var net_con_recovery = autocon("net_con_recovery", net, recoverMechanism); // open port + + var recoveryApi = new Data("recoveryApi"); + + containerAdd(recoverMechanism, recoveryApi); + containerAdd(recoveryApi, password); + + var vuln = vulnerabilityBuilder("vuln").setNetwork().setConfidentiality().build(); + recoverMechanism.addVulnerabilities(vuln); + + attack(net.access); + + compromised(1, recoveryApi.read); + compromised(1, password.use); + compromised(1, user.assume); + compromised(1, app.specificAccessAuthenticate); + compromised(1, sensitiveData.read); + } + + @Test + public void test_t047_v2() { + var net = new Network("net"); + var app = new Application("app"); + + var net_con_app = autocon("net_con_app", net, app); // open port + + var user = new Identity("user"); + + var sensitiveData = new Data("sensitiveData"); + containerAdd(app, sensitiveData); + mkReadApi(app, user, sensitiveData); + + var recoveryUser = new Identity("recoveryUser"); + aOwnsB(recoveryUser, user); // recoveryUser can assume user + + var recoverMechanism = new Application("recoverMechanism"); + containerAdd(app, recoverMechanism); + appExecAs(recoverMechanism, recoveryUser); + + var net_con_recovery = autocon("net_con_recovery", net, recoverMechanism); // open port + + var vuln = vulnerabilityBuilder("vuln").setNetwork().setCIA().build(); + recoverMechanism.addVulnerabilities(vuln); + + attack(net.access); + + compromised(1, recoverMechanism.fullAccess); + compromised(1, recoveryUser.assume); + compromised(1, user.assume); + compromised(1, app.specificAccessAuthenticate); + compromised(1, sensitiveData.read); + } + + @Test + public void test_t048() { + // T048 (device network service) Privilege escalation + // "For example: Exposed services running as root" + // + // See also T027. + + + // App provides shell access to user A, but the app is running as + // user B. Therefore A can assume B through the app. + + var app = new Application("app"); + + var user = new Identity("user"); + var root = new Identity("root"); + + mkExecApi(app, user); // vulnerability + appExecAs(app, root); + + aOwnsB(root, user); // optional + + // Attacker escalates from user to root: + attack(user.assume, app.networkConnect); + + compromised(1, root.assume); + } + + @Test + public void test_T048_v2() { + // Child app attacks parent app via local Vulnerability. + + var parentApp = new Application("parentApp"); + var childApp = new Application("childApp"); + containerAdd(parentApp, childApp); + + var vuln = vulnerabilityBuilder("vuln").setLocal().setCIA().build(); + parentApp.addVulnerabilities(vuln); + + var root = new Identity("root"); + var user = new Identity("user"); // optional + aOwnsB(root, user); // optional + + appExecAs(parentApp, root); + appExecAs(childApp, user); + + var startSet = attack(childApp.localAccess); // sufficient to use vuln + + compromised(1, parentApp.localConnect); + compromised(1, parentApp.read); // because HXXExploit + compromised(1, parentApp.modify); // because XHXExploit + compromised(1, parentApp.deny); // because XXHExploit + compromised(1, parentApp.fullAccess); // because HHHExploit + compromised(1, root.assume); // because parent fullAccess + compromised(1, user.assume); // because root owns user + } + + @Test + public void test_T048_v3() { + // Child app gains access to parent app via exec API. + + var parentApp = new Application("parentApp"); + var childApp = new Application("childApp"); + containerAdd(parentApp, childApp); + + var root = new Identity("root"); + var user = new Identity("user"); // optional + aOwnsB(root, user); // optional + + mkExecApi(parentApp, user); // privilege escalation: anyone -> root + + appExecAs(parentApp, root); + appExecAs(childApp, user); + + var startSet = attack(childApp.localAccess); // sufficient to use vuln + + compromised(1, parentApp.localConnect); + compromised(1, parentApp.read); // because HXXExploit + compromised(1, parentApp.modify); // because XHXExploit + compromised(1, parentApp.deny); // because XXHExploit + compromised(1, parentApp.fullAccess); // because HHHExploit + compromised(1, root.assume); // because parent fullAccess + compromised(1, user.assume); // because root owns user + } + + @Test + public void test_T048_v4() { + // Low privilege user gains high privilege access via + // network vulnerability. + + var net = new Network("net"); + var app = new Application("ap"); + + var net_con_app = autoconbi("net_con_app", net, app); // open port + + + var admin = new Identity("admin"); + var user = new Identity("user"); + + appExecAs(app, admin); + + var userData = new Data("userData"); + mkReadWriteApi(app, user, userData); + + var adminData = new Data("adminData"); + mkReadWriteApi(app, admin, adminData); + + var vuln = vulnerabilityBuilder("vuln").setNetwork().setPrivLow().setCIA().build(); + app.addVulnerabilities(vuln); + + attack(net.access, user.assume); // sufficient to use vuln + + compromised(1, user.assume); // ok + compromised(1, admin.assume); // escalation + + compromised(1, userData.read); // ok + compromised(1, adminData.read); // escalation + } + + @Test + public void test_T048_v5() { + // Horizontal privilege escalation: access data of other users. + + + var server = new Application("server"); + + var apiA = new Application("apiA"); + var apiB = new Application("apiB"); + + containerAdd(server, apiA); + containerAdd(server, apiB); + + var net = new Network("net"); + var conA = autocon("conA", net, apiA); + var conB = autocon("conB", net, apiB); + + var userA = new Identity("userA"); + var userB = new Identity("userB"); + + var storage = new Data("storage"); + + var dataA = new Data("dataA"); + var dataB = new Data("dataB"); + + containerAdd(storage, dataA); + containerAdd(storage, dataB); // vulnerability + + mkReadApi(apiA, userA, storage); // vulnerability + mkReadApi(apiB, userB, storage); + + attack(net.access, userA.assume); + + compromised(1, dataA.read); + compromised(1, dataB.read); // horizontal privilege escalation. + } + + + + +// @Test +// public void test_t049() { +// // T049 (device network service) Authentication bypass +// // "Disclosure or reusing of Sensitive data (session key, token, cookie, etc.) could cause authentication bypass." +// // +// // Model as generic network vulnerability? test_T031? +// // +// // Alternatively model as multiple APIs (App), where some API can be +// // accessed by Identity("anyone"). +// } + + @Test + public void test_t050() { + // T050 (device network service) Denial of Service (DoS) + // "Service can be attacked in a way that denies service to that service or the entire device" + // + // Basically clog a network. + + var app = new Application("app"); + var net = new Network("net"); + + var con_app_net = autocon("con_app_net", app, net); + + attack(net.access); + + compromised(1, net.denialOfService); + compromised(1, app.deny); + } + +// @Test +// public void test_t051() { +// // T051 (device network service) Buffer overflow +// // "Buffer Overflow is one of the most common vulnerability shown in network services of devices." +// // +// // Generic vulnerability. See for example T031. +// } +// @Test +// public void test_t052() { +// // T052 (device web) Sensitive data exposure +// // "Any kind of senstive data that can be accessible." +// // +// // See T041. +// } +// @Test +// public void test_t053() { +// // T053 (device web) Lack of transport encryption +// // "Web services are not properly encrypted HTTPS to prevent eavesdropping or tampering senstive data by attackers." +// // +// // See T033. +// } +// @Test +// public void test_t054() { +// // T054 (device web) Insecure SSL/TLS issues +// // "Encryption is implemented however it is improperly configured or is not being properly updated, (e.g. expired and/or self-signed certificates, same certificate used on multiple devices, deprecated SSL versions)" +// // +// // See T043. +// } +// @Test +// public void test_t055() { +// // T055 (device web) Authentication - Username enumeration +// // "Ability to collect a set of valid usernames by interacting with the authentication mechanism" +// // +// // See T044. +// } +// @Test +// public void test_t056() { +// // T056 (device web) Authentication - Weak credentials +// // "Ability to set account passwords to '1234' or '123456' for example. Usage of pre-programmed default (known) passwords (deffpass.com (Publicly available) - IoT device default password lookup). Easily guessable credentials. Brute-force by dictionaries and rules" +// // +// // See T045. +// } +// @Test +// public void test_t057() { +// // T057 (device web) Authentication - Improper account lockout +// // "Ability to continue sending authentication attempts after 3 - 5 failed login attempts" +// // +// // See T046. +// } +// @Test +// public void test_t058() { +// // T058 (device web) Authentication - Weak password recovery +// // "Insecure password reset/forgot mechanism could cause authentication bypass." +// // +// // See T047. +// } +// @Test +// public void test_t059() { +// // T059 (device web) Authentication - Lack of two-factor authentication +// // "Lack of two-factor authentication mechanisms such as a security token or fingerprint scanner in senstive APIs." +// // +// // How to model in coreLang: +// // * 2FA is modeled as a defense: Identity.twoFactorAuthentication. Attacks on 2FA include User.steal2FAtoken. +// // * TODO CoreLang could potentially model each factor as a separate Credentials, and have a MultiFactorCredentials that requires all of the Credentials to be assumed. +// } +// @Test +// public void test_t060() { +// // T060 (device web) Authentication bypass - Web application to cloud +// // "Disclosure or reusing of Sensitive data (session key, token, cookie, etc.) could cause authentication bypass." +// // +// // See T028. +// } +// @Test +// public void test_t061() { +// // T061 (device web) Lack of logging options +// // "Lack of logging options or secure logging options. Indetailed logging. It might not a vulnerabilty" +// // +// // TODO lack of intrusion detection. CoreLang does not really model logging. +// } +// @Test +// public void test_t062() { +// // T062 (device web) Command injection +// // "Unsanitized user input can cause arbitrary code execution." +// // +// // How to model in coreLang: +// // * Generic vulnerability. See T031. +// // * XSS can be modeled as stealing credentials in sub-application. +// } +// @Test +// public void test_t063() { +// // T063 (device web) Direct object references +// // "Access to unauthorized data." +// // +// // Interpretation: The attacker can easily guess the ids +// // of objects (e.g. easy to guess url). This is not a vulnerability by +// // itself and there would have to additionally be a vulnerability +// // in the access control of those objects. +// // +// // This does not really make sense to model in coreLang (especially +// // since coreLang does not model indirection, like references and +// // URLs). Rather, just model the data (as APIs) and who has access to +// // it. See also test_T048_v3 on horizontal privilege escalation where +// // one user has access to another user's data. +// } +// @Test +// public void test_t064() { +// // T064 (device web) Business and logic flaws +// // "Any vulnerabilities that cause remote code execution or sensitive data disclosure. OWASP Top 10 and testing guideline." +// // +// // Could be almost anything, so might not make sense to model without +// // being more specific. +// // +// // How to model in coreLang: +// // * Generic vulnerability, see T031. +// // * Access control problems, see T041. +// // +// // Some IoT examples include: +// // * Sibyl attacks. +// } +// @Test +// public void test_t065() { +// // T065 (cloud web) Lack of transport encryption +// // "Insecure network communication. Cloud services are not properly encrypted HTTPS to prevent eavesdropping or tampering senstive data by attackers." +// // +// // See T033. +// } +// @Test +// public void test_t066() { +// // T066 (cloud web) Insecure SSL/TLS issues +// // "Expired and/or self-signed certificates, Same certificate used on multiple devices, Deprecated SSL versions" +// // +// // See T043. +// } +// @Test +// public void test_t067() { +// // T067 (cloud web) Authentication - Username enumeration +// // "Ability to collect a set of valid usernames by interacting with the authentication mechanism" +// // +// // See T044. +// } +// @Test +// public void test_t068() { +// // T068 (cloud web) Authentication - Weak credentials +// // "Ability to set account passwords to '1234' or '123456' for example. Usage of pre-programmed (know) default passwords (deffpass.com (Publicly available) - IoT device default password lookup). Easily guessable credentials. Brute-force by dictionaries and rules" +// // +// // See T045. +// } +// @Test +// public void test_t069() { +// // T069 (cloud web) Authentication - Improper account lockout +// // "Ability to continue sending authentication attempts after 3 - 5 failed login attempts" +// // +// // See T046. +// } +// @Test +// public void test_t070() { +// // T070 (cloud web) Authentication - Weak password recovery +// // "Insecure password reset/forgot mechanism could cause authentication bypass." +// // +// // See T047. +// } +// @Test +// public void test_t071() { +// // T071 (cloud web) Authentication - Lack of two-factor authentication +// // "Lack of two-factor authentication mechanisms such as a security token or fingerprint scanner in senstive APIs." +// // +// // See T059. +// } +// @Test +// public void test_t072() { +// // T072 (cloud API) Vendor APIs - Inherent trust of cloud or mobile application +// // "Vendor or 3rd party APIs" +// // +// // See T064. +// } +// @Test +// public void test_t073() { +// // T073 (cloud API) Vendor APIs - Authentication bypass +// // "Disclosure or reusing of Sensitive data (session key, token, cookie, etc.) could cause authentication bypass." +// // +// // See T028. +// } +// @Test +// public void test_t074() { +// // T074 (cloud API) Vendor APIs - Authorization bypass +// // "Insecure access controls" +// // +// // See T028. +// } +// @Test +// public void test_t075() { +// // T075 (cloud API) Vendor APIs - Undocumented backdoor API calls +// // "Critical API call for testing/debugging purposes left accessible." +// // +// // See T063. +// } +// @Test +// public void test_t076() { +// // T076 (cloud API) Vendor APIs - User data disclosure +// // "Insufficient Privacy Protection: Encrypted PII sent + UnEncrypted PII sent. User’s personal information stored on the device or in the ecosystem that is used insecurely, improperly, or without permission. https://arxiv.org/abs/1705.06805" +// // +// // How to model in coreLang: +// // * TODO CoreLang does not model privacy explicitly, but sensitive +// // information could be modeled as Data/Information. +// // * TODO Combining many small pieces of information (that are +// // otherwise benign) could be used to derive PII (e.g. via +// // statistical analysis). CoreLang does not model this. For +// // example, patterns in traffic could be used to analyze user +// // behavior . +// } +// @Test +// public void test_t077() { +// // T077 (cloud API) Vendor APIs - Device information leakage +// // "User/device location disclosure: Requests to the device’s weather service (API) leaks the exact GPS coordinates of the device, since they were sent as part of unencrypted HTTP communications [EST-1]." +// // +// // See T076. +// } +// @Test +// public void test_t078() { +// // T078 (mobile app) Sensitive data exposure - Hardcoded credentials +// // "An attacker could reveal unchangable credentials including password, hash, private certificate, and API key from storage by reverse engineering and source code analysis." +// // +// // Interpretation: Similarly to firmware, mobile apps packages (e.g. +// // APKs for android) may containing sensitive information. Packages +// // are usually publically available. +// // +// // See T018. +// } +// @Test +// public void test_t079() { +// // T079 (mobile app) Sensitive data exposure - Encryption keys and algorithms +// // "An attacker could identify encryption keys from both storage and memory by reverse engineering and source code analysis." +// // +// // See T018. +// } +// @Test +// public void test_t080() { +// // T080 (mobile app) Sensitive data exposure - Other sensitive information +// // "An attacker could identify various sensitive data (URLs) from both storage and memory by reverse engineering and source code analysis." +// // +// // See T021. +// } +// @Test +// public void test_t081() { +// // T081 (mobile app) Authentication - Username enumeration +// // "Ability to collect a set of valid usernames by interacting with the authentication mechanism" +// // +// // See T044. +// } +// @Test +// public void test_t082() { +// // T082 (mobile app) Authentication - Weak credentials +// // "Ability to set account passwords to '1234' or '123456' for example. Usage of pre-programmed (known) default passwords (deffpass.com (Publicly available) - IoT device default password lookup). Easily guessable credentials. Brute-force by dictionaries and rules" +// // +// // See T045. +// } +// @Test +// public void test_t083() { +// // T083 (mobile app) Authentication - Improper account lockout +// // "Ability to continue sending authentication attempts after 3 - 5 failed login attempts" +// // +// // See T046. +// } +// @Test +// public void test_t084() { +// // T084 (mobile app) Authentication - Weak password recovery +// // "Insecure password reset/forgot mechanism could cause authentication bypass." +// // +// // See T047. +// } +// @Test +// public void test_t085() { +// // T085 (mobile app) Authentication - Lack of two-factor authentication +// // "Lack of two-factor authentication mechanisms such as a security token or fingerprint scanner" +// // +// // See T059. +// } +// @Test +// public void test_t086() { +// // T086 (mobile app) Authentication - Mobile application to cloud system +// // "Disclosure or reusing of sensitive data (session key, token, cookie, etc.) could cause authentication bypass." +// // +// // See T028. +// } +// @Test +// public void test_t087() { +// // T087 (mobile app) Insecure authorization +// // "" +// // +// // Interpretation: See OWASP mobile top ten. Basically access +// // control is broken in some way. +// // +// // See for example T028. +// } +// @Test +// public void test_t088() { +// // T088 (mobile app) Implicitly trusted by device or cloud +// // "" +// // +// // See T064. +// } +// @Test +// public void test_t089() { +// // T089 (mobile app) Lack of transport encryption +// // "Insecure network communication. Mobile applications are not properly encrypted HTTPS to prevent eavesdropping or tampering senstive data by attackers." +// // +// // See T033. +// } +// @Test +// public void test_t090() { +// // T090 (mobile app) Insecure SSL/TLS issues +// // "Expired and/or self-signed certificates, Same certificate used on multiple devices, Deprecated SSL versions" +// // +// // See T043. +// } +// @Test +// public void test_t091() { +// // T091 (mobile app) Insecure data storage +// // "" +// // +// // See T021. +// } +// @Test +// public void test_t092() { +// // T092 (mobile app) Outdated 3rd party libraries and SDKs +// // "Known vulnerabilities in deprecated libraries." +// // +// // Generic vulerability, see T031. +// // In this case it may make sense to attach the vulnerability to a +// // SoftwareProduct rather than directly to an Application. +// } +// @Test +// public void test_t093() { +// // T093 (mobile app) Business and logic flaws +// // "Insecure Device controlling commands" +// // +// // See T064. +// } +// @Test +// public void test_t094() { +// // T094 (mobile app) Lack of health checks +// // "No check whether the device is working as it should. Insecure heartbeats" +// // +// // How to model in coreLang: +// // * For example as dataflow over network that the attacker can +// // manipulate. +// // * Broken authentication/access control. For example heartbeat API +// // accessible to anyone. +// // +// } +// @Test +// public void test_t095() { +// // T095 (radio) Lack of transport encryption +// // "Attacker can extract sensitive information in clear text from radio packets." +// // +// // See T033. +// } +// @Test +// public void test_t096() { +// // T096 (radio) Man in the middle attack +// // "Even TLS connections might be also vulnerable to MitM attacks, since certificate validation is missing. It allows the attackers to conduct additional attacks according to the context [EST-1]." +// // +// // How to model in coreLang: +// // * Just model radio as a regular Network. +// } +// @Test +// public void test_t097() { +// // T097 (radio) Lack of message integrity check +// // "The transmission protocol does not include a mechanism for verifying the integrity of the transmitted data, such as a checksum. Or it does not validate or incorrectly validates the integrity check values or "checksums" of a message (header or payload) which will allow modified or corrupted data in transmission." +// // +// // Examples: +// // * Only part of the packet is encrypted and the unencrypted part +// // of the packet is implicitly trusted. +// // +// // How to model in coreLang: +// // * See T033 on encryption. +// // * See T034 on signatures. +// } +// @Test +// public void test_t098() { +// // T098 (radio) Interception and modification +// // "Attacker can intercept live radio communication and then modify the transmitted packets." +// // +// // See T096. +// } +// @Test +// public void test_t099() { +// // T099 (radio) Replay attack +// // "Attacker can perform bit-flip attacks on encrypted network traffic. The intruder will first intercept an encrypted message and then alter the payload or header and retransmit the data packet. Actually performing replay attack which is possible when there is no verification and captured data can be re-transmitted. Some type of integrity check methods i.e. ICV are known as vulnerable." +// // +// // Intepretation: The attack can record and resend radio waves. +// // Potentially the recorded waves can be interpreted as packets, +// // reverse engineered and more advanced packets can then be sent. +// // +// // How to model in coreLang: +// // * Lack of authentication. +// // * Generic vulnerability in authentication mechanism. +// // * As credentials being sent in plain text over radio. Note that radio can be modeled using Network. +// // * Non-idempotent messages. No sequence numbering. +// // * TODO It may be useful to model replay attacks explicitly in coreLang. For example Data.replay +// } +// @Test +// public void test_t100() { +// // T100 (radio) Jamming attack +// // "Due to some controls such as payload verification, a transmitted packet might not be re-transmitted again. For this cases, it is required jamming the signal first and capturing an "unused" radio packet. Then replay attack can be successfully performed." +// // +// // Interpretation: Jamming can be a form of DoS. It can also be used to block and capture at the same time as a form of MITM attack. This may for example be necessary to perform certain replay attacks. +// // +// // How to model in coreLang: +// // * Model as DoS on network, see T050. +// } +// @Test +// public void test_t101() { +// // T101 (radio) Spoofing attack +// // "Attacker can present itself as a legitamate gateway or sensor in radio communication." +// // +// // See T096. +// // +// // CoreLang does not really model the details of attacks based on +// // redirection and addressing (such as in for example ARP cache +// // poisoning). However, it does model the result -- MITM. +// } +// @Test +// public void test_t102() { +// // T102 (radio) Denial of service (DoS) +// // "Attacker can disrupt radio communication." +// // +// // See T100. +// } + + + + + ////////// util //////////// + + public void con(Application src, ConnectionRule dst) { + // app is client-like (outgoing) + src.addOutgoingAppConnections(dst); + } + public void con(ConnectionRule src, Application dst) { + // app is server-like (incoming) + dst.addIngoingAppConnections(src); + } + + public void con(Network src, ConnectionRule dst) { + // net is client-like (outgoing) + src.addOutgoingNetConnections(dst); + } + public void con(ConnectionRule src, Network dst) { + // net is server-like (incoming) + dst.addIngoingNetConnections(src); + } + + public void con(Application src, ConnectionRule conrule, Network dst) { + con(src, conrule); + con(conrule, dst); + } + public void con(Network src, ConnectionRule conrule, Application dst) { + con(src, conrule); + con(conrule, dst); + } + + public void con(Network src, ConnectionRule conrule, Network dst) { + con(src, conrule); + con(conrule, dst); + } + + public void conbi(Application src, ConnectionRule conrule, Network dst) { + con(src, conrule, dst); + con(dst, conrule, src); + } + public void conbi(Network src, ConnectionRule conrule, Application dst) { + con(src, conrule, dst); + con(dst, conrule, src); + } + + public void conbi(Network src, ConnectionRule conrule, Network dst) { + con(src, conrule, dst); + con(dst, conrule, src); + } + + public void transferData(Network medium, Data data) { + data.addTransitNetwork(medium); + } + public void transferData(Application medium, Data data) { + data.addTransitApp(medium); + } + + public void execData(Data code, SoftwareProduct product, Application app) { + product.addOriginData(code); + product.addSoftApplications(app); + } + + public void aOwnsB(Identity a, Identity b) { + a.addParentId(b); + } + + public void containerAdd(PhysicalZone container, System inside) { + container.addSystems(inside); + } + + public void containerAdd(System container, Application inside) { + container.addSysExecutedApps(inside); + } + + public void containerAdd(System container, Data inside) { + container.addSysData(inside); + } + + public void containerAdd(Application container, Application inside) { + container.addAppExecutedApps(inside); + } + + public void containerAdd(Application container, Data inside) { + container.addContainedData(inside); + } + + public void containerAdd(Data container, Data inside) { + container.addContainedData(inside); + } + + public void containerAdd(Data container, Information inside) { + container.addInformation(inside); + } + + public void addApiData(Application app, Data data) { + containerAdd(app, data); + } + + public void addApiUser(Application app, Identity id) { + id.addLowPrivApps(app); + } + + public void addApiReadAccess(Identity id, Data data) { + id.addReadPrivData(data); + } + + public void addApiWriteAccess(Identity id, Data data) { + id.addWritePrivData(data); + } + + public void mkReadApi(Application app, Identity id, Data data) { + addApiUser(app, id); + addApiData(app, data); + addApiReadAccess(id, data); + } + + public void mkWriteApi(Application app, Identity id, Data data) { + addApiUser(app, id); + addApiData(app, data); + addApiWriteAccess(id, data); + } + + public void mkReadWriteApi(Application app, Identity id, Data data) { + mkReadApi(app, id, data); + mkWriteApi(app, id, data); + } + + public void addApiExecUser(Application app, Identity id) { + id.addHighPrivApps(app); + } + public void mkExecApi(Application app, Identity id) { + addApiExecUser(app, id); + } + + + public HashSet attack(AttackStep... entryPoints) { + var startSet = new HashSet(); + var attacker = new Attacker(); + for (var step : entryPoints) { + if (step == null) { + throw new NullPointerException(); + } + if (!AttackStep.allAttackSteps.contains(step)) { + throw new RuntimeException("missing step " + step); + } + + startSet.add(step); + attacker.addAttackPoint(step); + } + attacker.attack(); + return startSet; // for convenience + } + + public void compromised(int zeroIfUncompromised, AttackStep step) { + boolean isCompromised = (zeroIfUncompromised != 0); + compromised(isCompromised, step); + } + + public void compromised(boolean isCompromised, AttackStep step) { + if (isCompromised) { + assertReached(step); + } else { + assertNotReached(step); + } + } + + public ConnectionRule autocon(String name, Application src, Network dst) { + var connectionRule = new ConnectionRule(name); + con(src, connectionRule, dst); + return connectionRule; + } + public ConnectionRule autocon(String name, Network src, Application dst) { + var connectionRule = new ConnectionRule(name); + con(src, connectionRule, dst); + return connectionRule; + } + + public ConnectionRule autocon(String name, Network src, Network dst) { + var connectionRule = new ConnectionRule(name); + con(src, connectionRule); + con(connectionRule, dst); + return connectionRule; + } + + public ConnectionRule autoconbi(String name, Application src, Network dst) { + var connectionRule = new ConnectionRule(name); + con(src, connectionRule, dst); + con(dst, connectionRule, src); + return connectionRule; + } + + public ConnectionRule autoconbi(String name, Network src, Application dst) { + var connectionRule = new ConnectionRule(name); + con(src, connectionRule, dst); + con(dst, connectionRule, src); + return connectionRule; + } + + public ConnectionRule autoconbi(String name, Network src, Network dst) { + var connectionRule = new ConnectionRule(name); + con(src, connectionRule, dst); + con(dst, connectionRule, src); + return connectionRule; + } + + public void appExecAs(Application app, Identity id) { + id.addExecPrivApps(app); + } + + public static class VulnerabilityBuilder { + String name = ""; + boolean network = false; + boolean local = false; + boolean physical = false; + boolean priv_low = false; + boolean priv_high = false; + boolean user_interact = false; + boolean confidentiality = false; + boolean availability = false; + boolean integrity = false; + boolean complex = false; + + public VulnerabilityBuilder(String name) { + this.name = name; + } + + public VulnerabilityBuilder setNetwork() { + this.network = true; + return this; + } + public VulnerabilityBuilder setLocal() { + this.local = true; + return this; + } + public VulnerabilityBuilder setPhysical() { + this.physical = true; + return this; + } + + public VulnerabilityBuilder setPrivLow() { + this.priv_low = true; + return this; + } + public VulnerabilityBuilder setPrivHigh() { + this.priv_high = true; + return this; + } + + public VulnerabilityBuilder setUserInteract() { + this.user_interact = true; + return this; + } + public VulnerabilityBuilder setComplex() { + this.complex = true; + return this; + } + + public VulnerabilityBuilder setCIA() { + this.confidentiality = true; + this.availability = true; + this.integrity = true; + return this; + } + + public VulnerabilityBuilder setConfidentiality() { + this.confidentiality = true; + return this; + } + public VulnerabilityBuilder setAvailability() { + this.availability = true; + return this; + } + public VulnerabilityBuilder setIntegrity() { + this.integrity = true; + return this; + } + + + public SoftwareVulnerability build() { + var res = new SoftwareVulnerability(name); + res.networkAccessRequired.defaultValue = network; + res.localAccessRequired.defaultValue = local; + res.physicalAccessRequired.defaultValue = physical; + res.lowPrivilegesRequired.defaultValue = priv_low; + res.highPrivilegesRequired.defaultValue = priv_high; + res.userInteractionRequired.defaultValue = user_interact; + res.confidentialityImpactLimitations.defaultValue = !confidentiality; + res.availabilityImpactLimitations.defaultValue = !availability; + res.integrityImpactLimitations.defaultValue = !integrity; + res.highComplexityExploitRequired.defaultValue = complex; + return res; + } + } + + public static VulnerabilityBuilder vulnerabilityBuilder(String name) { + return new VulnerabilityBuilder(name); + } +} From 1817bc5cd546468d26bc7d507f77001510140d80 Mon Sep 17 00:00:00 2001 From: jesajx Date: Tue, 29 Jun 2021 11:51:13 +0200 Subject: [PATCH 02/10] small network restrictions --- .../mal_lang/corelang/test/TestPatriot.java | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/test/java/org/mal_lang/corelang/test/TestPatriot.java b/src/test/java/org/mal_lang/corelang/test/TestPatriot.java index 4acb0de..3c85fbe 100644 --- a/src/test/java/org/mal_lang/corelang/test/TestPatriot.java +++ b/src/test/java/org/mal_lang/corelang/test/TestPatriot.java @@ -125,7 +125,7 @@ public void test_T003_v2() { var internet = new Network("internet"); var cloud = new Application("cloud"); - var con_internet_cloud = autoconbi("con_internet_cloud", internet, cloud); + var con_internet_cloud = autocon("con_internet_cloud", internet, cloud); var firmwareBlob = new Data("firmwareBlob"); var sensitiveData = new Data("sensitiveData"); @@ -209,7 +209,7 @@ public void test_T004_v2() { var spi = new Network("spi"); - var con_shell_spi = autoconbi("con_shell_spi", shell, spi); + var spi_con_shell = autocon("spi_con_shell", spi, shell); var appData = new Data("appData"); containerAdd(app, appData); @@ -1029,8 +1029,8 @@ public void test_T028_v2() { var appB = new Application("appB"); var net = new Network("net"); - var appA_con_net = autoconbi("appA_con_net", appA, net); // outgoing connection - var net_con_appB = autoconbi("net_con_appB", net, appB); // open port + var appA_con_net = autocon("appA_con_net", appA, net); // outgoing connection + var net_con_appB = autocon("net_con_appB", net, appB); // open port var idA = new Identity("idA"); @@ -1070,8 +1070,8 @@ public void test_T028_v3() { var appB = new Application("appB"); var net = new Network("net"); - var appA_con_net = autoconbi("appA_con_net", appA, net); // outgoing connection - var net_con_appB = autoconbi("net_con_appB", net, appB); // open port + var appA_con_net = autocon("appA_con_net", appA, net); // outgoing connection + var net_con_appB = autocon("net_con_appB", net, appB); // open port var idA = new Identity("idA"); @@ -1130,8 +1130,8 @@ public void test_T028_v4() { var appB = new Application("appB"); var net = new Network("net"); - var appA_con_net = autoconbi("appA_con_net", appA, net); // outgoing connection - var net_con_appB = autoconbi("net_con_appB", net, appB); // open port + var appA_con_net = autocon("appA_con_net", appA, net); // outgoing connection + var net_con_appB = autocon("net_con_appB", net, appB); // open port var idB = new Identity("idB"); var credsB = new Credentials("credsB"); @@ -1201,7 +1201,7 @@ public void test_t031() { var net = new Network("net"); - var con_app_net = autoconbi("con_app_net", app, net); + var net_con_app = autocon("net_con_app", net, app); // generic network vulnerability var vuln = vulnerabilityBuilder("vuln").setNetwork().setCIA().build(); @@ -1315,7 +1315,7 @@ public void test_T033_v2() { var con_app_lan = autocon("con_app_lan", app, lan); var con_lan_internet = autocon("con_lan_internet", lan, internet); // Note: NAT. - var con_internet_cloud = autoconbi("con_internet_cloud", internet, cloud); + var con_internet_cloud = autocon("con_internet_cloud", internet, cloud); // The RoutingFirewall is optional. It is just here to show that the // router may actually be a IoT device (that can be hacked): RoutingFirewall extends Application. @@ -1558,7 +1558,7 @@ public void test_t041() { var net = new Network("net"); - var con_app_net = autocon("con_app_net", app, net); + var net_con_app = autocon("net_con_app", net, app); var sensitiveData = new Data("sensitiveData"); @@ -1629,7 +1629,7 @@ public void test_t043() { var con_app_lan = autocon("con_app_lan", app, lan); var con_lan_internet = autocon("con_lan_internet", lan, internet); // Note: NAT. - var con_internet_cloud = autoconbi("con_internet_cloud", internet, cloud); + var con_internet_cloud = autocon("con_internet_cloud", internet, cloud); var routerNat = new RoutingFirewall("routerNat"); con_lan_internet.addRoutingFirewalls(routerNat); @@ -1888,7 +1888,7 @@ public void test_T048_v4() { var net = new Network("net"); var app = new Application("ap"); - var net_con_app = autoconbi("net_con_app", net, app); // open port + var net_con_app = autocon("net_con_app", net, app); // open port var admin = new Identity("admin"); @@ -1975,7 +1975,7 @@ public void test_t050() { var app = new Application("app"); var net = new Network("net"); - var con_app_net = autocon("con_app_net", app, net); + var net_con_app = autocon("net_con_app", app, net); attack(net.access); @@ -2600,22 +2600,19 @@ public ConnectionRule autocon(String name, Network src, Network dst) { public ConnectionRule autoconbi(String name, Application src, Network dst) { var connectionRule = new ConnectionRule(name); - con(src, connectionRule, dst); - con(dst, connectionRule, src); + conbi(src, connectionRule, dst); return connectionRule; } public ConnectionRule autoconbi(String name, Network src, Application dst) { var connectionRule = new ConnectionRule(name); - con(src, connectionRule, dst); - con(dst, connectionRule, src); + conbi(src, connectionRule, dst); return connectionRule; } public ConnectionRule autoconbi(String name, Network src, Network dst) { var connectionRule = new ConnectionRule(name); - con(src, connectionRule, dst); - con(dst, connectionRule, src); + conbi(src, connectionRule, dst); return connectionRule; } From 94d52e0b13436b2caab6fc68a39a653fc95c446f Mon Sep 17 00:00:00 2001 From: jesajx Date: Thu, 1 Jul 2021 17:13:59 +0200 Subject: [PATCH 03/10] Remove unimplemented test cases. --- .../mal_lang/corelang/test/TestPatriot.java | 658 +----------------- 1 file changed, 5 insertions(+), 653 deletions(-) diff --git a/src/test/java/org/mal_lang/corelang/test/TestPatriot.java b/src/test/java/org/mal_lang/corelang/test/TestPatriot.java index 3c85fbe..568508c 100644 --- a/src/test/java/org/mal_lang/corelang/test/TestPatriot.java +++ b/src/test/java/org/mal_lang/corelang/test/TestPatriot.java @@ -23,20 +23,6 @@ public class TestPatriot extends CoreLangTest { // TODO Some suggestions on changes to coreLang are marked with "TODO". // -// @Test -// public void test_t001() { -// // T001 (physical) Sensitive data exposure - Device ID/serial no -// // "An attacker could gather more critical information regarding to internals of the device which makes easy to conduct other various attacks." -// // -// // Interpretation: The device may be physically labeled with IDs (e.g. -// // FCC ID, microchip serial ID). While not sensitive by itself, this -// // information is useful for further attacks and reverse engineering. -// // -// // Probably does not make sense to model in coreLang. -// // -// // See also T002 and T004 on gaining informatino through physical interfaces (e.g. UART, USB, etc). -// } - @Test public void test_t002() { // T002 (physical) Firmware/storage extraction - Insecure external media interfaces @@ -262,36 +248,6 @@ public void test_T004_v3() { compromised(1, sensitiveData.read); } - - -// @Test -// public void test_t005() { -// // T005 (physical) Firmware/storage extraction - Insecure I2C interface -// // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the serial bus protocol I2C." -// // -// // see T004. -// } -// @Test -// public void test_t006() { -// // T006 (physical) Firmware/storage extraction - Insecure UART interface -// // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the serial interface UART." -// // -// // see T004. -// } -// @Test -// public void test_t007() { -// // T007 (physical) Firmware/storage extraction - Insecure JTAG interface -// // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the debug interface JTAG." -// // -// // see T004. -// } -// @Test -// public void test_t008() { -// // T008 (physical) Firmware/storage extraction - Insecure SWD interface -// // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the debug interface SWD." -// // -// // see T004. -// } @Test public void test_t009() { // T009 (physical) Firmware/storage extraction - Insecure SoC @@ -314,16 +270,7 @@ public void test_t009() { attack(chipA.fullAccess, anyone.assume); compromised(1, sensitiveData.read); } -// @Test -// public void test_t010() { -// // T010 (physical) Firmware/storage extraction - Insecure eMMC chip -// // "An attacker could dump the firmware by tapping if it is stored an embedded Multi Media Card (eMMC) flash chip (embedded SD card). An attacker could dump the firmware by unsoldering chip then reading it with an adapter if it is stored in an embedded Multi Media Card (eMMC) flash chip (embedded SD card)." -// // -// // Interpretation: Like T004, but we must desolder the eMMC chip -// // first before communicating with it. -// // -// // See T002 and T004. -// } + @Test public void test_t011() { // T011 (physical) Backdoor firmware - Insecure UART interface @@ -365,31 +312,7 @@ public void test_t011() { compromised(1, firmwareBlob.write); // By writing to the firmwareblob... compromised(1, app.fullAccess); // ... we can exec code. } -// @Test -// public void test_t012() { -// // T012 (physical) Backdoor firmware - Insecure JTAG interface -// // "An attacker could modify the firmware if access to the flash/EEPROM chip is not restricted through the debug interface JTAG." -// // -// // See T011. -// } -// @Test -// public void test_t013() { -// // T013 (physical) Backdoor firmware - Insecure SWD interface -// // "An attacker could modify the firmware if access to the flash/EEPROM chip is not restricted through the debug interface SWD." -// // -// // See T011. -// } -// @Test -// public void test_t014() { -// // T014 (physical) Grant shell access - Insecure UART interface -// // "An attacker could grant a command shell if access to the flash/EEPROM chip is not restricted through the serial interface UART." -// // -// // Interpretation: An IoT device may have hidden physical connectors. -// // The attacker may be able to use these connectors to command the -// // device (e.g. gain root shell access). -// // -// // see test_T004_v2. -// } + @Test public void test_t015() { // T015 (physical) Grant shell access - Insecure SPI interface @@ -423,13 +346,6 @@ public void test_t015() { compromised(1, app.fullAccess); } -// @Test -// public void test_t016() { -// // T016 (physical) Change code execution flow - Insecure JTAG/SWD interface -// // "An attacker could debug the libraries/binaries and manipulate the execution flow of firmware if access to the flash/EEPROM chip is not restricted through the debug interface JTAG." -// // -// // See T015. -// } // @Test // public void test_t017() { // // T017 (physical) Reset to insecure state @@ -441,19 +357,6 @@ public void test_t015() { // // resulting from the reset. The reset can be modeled as the the // // attacker doing Data.write to a specific Data asset representing the // // reset API-function. See also T035 on rollback attacks. -// } -// -// @Test -// public void test_t018() { -// // T018 (firmware) Sensitive data exposure - Hardcoded credentials -// // "An attacker could reveal unchangable credentials including password, hash, private certificate, and API key from storage by reverse engineering and source code analysis." -// // -// // Interpretation: The firmware blob of a device may contain hardcoded -// // credentials. If the attacker can obtain the firmware blob they can -// // obtain the credentials. -// // -// // Example: -// // * see T019. // } @Test @@ -533,15 +436,6 @@ public void test_T019_v2() { compromised(1, app.fullAccess); } - -// @Test -// public void test_t020() { -// // T020 (firmware) Sensitive data exposure - Encryption keys and algorithms -// // "An attacker could identify encryption keys from both storage and memory by reverse engineering and source code analysis. An attacker could gain sensitive data if device has encrypted with the discovered keys." -// // -// // See T018. -// } - @Test public void test_t021_v1() { // T021 (firmware) Sensitive data exposure - Other sensitive information @@ -801,13 +695,6 @@ public void test_T022_v3() { -// @Test -// public void test_t023() { -// // T023 (firmware) Configuration - Lack of data integrity checks -// // "An attacker could backdoor the firmware if firmware has insecure or lack of integrity checks." -// // -// // See T035 about signature verification. -// } // @Test // public void test_t024() { // // T024 (firmware) Configuration - Lack of wiping device @@ -823,25 +710,7 @@ public void test_T022_v3() { // // * TODO Corelang does not really model state, see T017 and T040. // // * Alternative, simply model it as sensitive data/credentials being stored on the device, see e.g. T021. // } -// @Test -// public void test_t025() { -// // T025 (firmware) Configuration - Insecure customization of OS platforms -// // "Insecure default settings or insufficient ability to harden the system by modifying configurations are the root cause of many vulnerabilities." -// // -// // Interpretation: The OS platform might have been customized in an -// // insecure way, or the default settings are insecure and can't be -// // changed. Basically the device could be more hardened, but is not. -// // -// // This is more like the cause of other vulnerabilities rather than a vulnerability in itself. -// // See for example T031 on modeling generic vulnerabilities. -// } -// @Test -// public void test_t026() { -// // T026 (firmware) Configuration - Lack of security configurability -// // "Insecure default settings or insufficient ability to harden the system by modifying configurations are the root cause of many vulnerabilities." -// // -// // See T025. Does not really make sense to model. Also, It is tricky to define what is and is not a "configuration". -// } + @Test public void test_t027_v1() { // T027 (firmware) Configuration - Insecure filesystem permissions @@ -1165,21 +1034,6 @@ public void test_T028_v4() { } -// @Test -// public void test_t029() { -// // T029 (firmware) Authentication bypass - Device to mobile application -// // "Disclosure or reusing of Sensitive data (session key, token, cookie, etc.) could cause authentication bypass." -// // -// // Like T028, but one of the devices is smartphone. -// } -// @Test -// public void test_t030() { -// // T030 (firmware) Authentication bypass - Device to cloud -// // "Disclosure or reusing of Sensitive data (session key, token, cookie, etc.) could cause authentication bypass." -// // -// // Like T028, but with a cloud API. -// } - @Test public void test_t031() { // T031 (firmware) Update mechanism - Missing update mechanism @@ -1439,58 +1293,6 @@ public void test_t034_v1_defense() { compromised(0, app.fullAccess); } -// @Test -// public void test_t035() { -// // T035 (firmware) Update mechanism - Lack of update verification -// // "An attacker could backdoor the firmware if firmware update process has insecure or lack of integrity verification." -// // -// // One form of verification is to verify a signature, see test_T034. -// // -// // More generally we can model lack of verification as "anyone" having -// // access to a write-API. See test_T034. -// } -// @Test -// public void test_t036() { -// // T036 (firmware) Update mechanism - Lack of update authentication -// // "An attacker could download the firmware if firmware update process has insecure or lack of authentication." -// // -// // Interpretation: Basically anyone can download the firmware from the internet -// // without authentication. That is: the authentication here means the -// // IoT authenticating with the cloud to begin downloading the update -// // (not the other way around). -// // -// // See T003. -// } - -// @Test -// public void test_t037() { -// // T037 (firmware) Update mechanism - Intercepting OTA update -// // "An attacker could capture firmware even from encrypted traffic if update mechanism is not secure against MitM attacks." -// // -// // Interpretation: OTA is basically just a fancy way to say that the -// // firmware updates are downloaded over a network (usually from the -// // internet). Those downloads coult be MITMed -- the attacker either -// // just snoops on the data or replaces the firmware on the fly. -// // -// // How to model in coreLang: -// // * See T033 on transport encryption. -// // * See T034 on firmware signatures and verification. -// } -// -// @Test -// public void test_t038() { -// // T038 (firmware) Update mechanism - Backdoor firmware -// // "(Malicious firmware update). An attacker could backdoor the firmware/sensitive data 'on the fly' before reaching the device/hub if update mechanism is not secure against MitM attacks." -// // -// // Interpretation: The attacker can upload and install firmware to the -// // device somehow. This could for example be done via MITM (T037), or the -// // update-mechanism be a world-writable API (T039). -// // -// // How to model in coreLang: -// // * See T037. -// // * See T039. -// } -// @Test public void test_t039() { // T039 (firmware) Update mechanism - World writable update location @@ -1521,6 +1323,7 @@ public void test_t039() { compromised(1, firmwareBlob.write); compromised(1, app.fullAccess); } + // @Test // public void test_t040() { // // T040 (firmware) Update mechanism - Lack of anti-rollback mechanism @@ -1531,6 +1334,7 @@ public void test_t039() { // // scenario leading up to the rollback and another model showing the // // situation after the rollback. See also T004. // } + @Test public void test_t041() { // T041 (device network service) Sensitive data exposure @@ -1593,14 +1397,6 @@ public void test_T041_v2() { } -// @Test -// public void test_t042() { -// // T042 (device network service) Lack of transport encryption -// // "Network services are not properly encrypted HTTPS to prevent eavesdropping or tampering senstive data by attackers." -// // -// // See T033. -// } - @Test public void test_t043() { // T043 (device network service) Insecure SSL/TLS issues @@ -1953,18 +1749,6 @@ public void test_T048_v5() { - -// @Test -// public void test_t049() { -// // T049 (device network service) Authentication bypass -// // "Disclosure or reusing of Sensitive data (session key, token, cookie, etc.) could cause authentication bypass." -// // -// // Model as generic network vulnerability? test_T031? -// // -// // Alternatively model as multiple APIs (App), where some API can be -// // accessed by Identity("anyone"). -// } - @Test public void test_t050() { // T050 (device network service) Denial of Service (DoS) @@ -1983,438 +1767,6 @@ public void test_t050() { compromised(1, app.deny); } -// @Test -// public void test_t051() { -// // T051 (device network service) Buffer overflow -// // "Buffer Overflow is one of the most common vulnerability shown in network services of devices." -// // -// // Generic vulnerability. See for example T031. -// } -// @Test -// public void test_t052() { -// // T052 (device web) Sensitive data exposure -// // "Any kind of senstive data that can be accessible." -// // -// // See T041. -// } -// @Test -// public void test_t053() { -// // T053 (device web) Lack of transport encryption -// // "Web services are not properly encrypted HTTPS to prevent eavesdropping or tampering senstive data by attackers." -// // -// // See T033. -// } -// @Test -// public void test_t054() { -// // T054 (device web) Insecure SSL/TLS issues -// // "Encryption is implemented however it is improperly configured or is not being properly updated, (e.g. expired and/or self-signed certificates, same certificate used on multiple devices, deprecated SSL versions)" -// // -// // See T043. -// } -// @Test -// public void test_t055() { -// // T055 (device web) Authentication - Username enumeration -// // "Ability to collect a set of valid usernames by interacting with the authentication mechanism" -// // -// // See T044. -// } -// @Test -// public void test_t056() { -// // T056 (device web) Authentication - Weak credentials -// // "Ability to set account passwords to '1234' or '123456' for example. Usage of pre-programmed default (known) passwords (deffpass.com (Publicly available) - IoT device default password lookup). Easily guessable credentials. Brute-force by dictionaries and rules" -// // -// // See T045. -// } -// @Test -// public void test_t057() { -// // T057 (device web) Authentication - Improper account lockout -// // "Ability to continue sending authentication attempts after 3 - 5 failed login attempts" -// // -// // See T046. -// } -// @Test -// public void test_t058() { -// // T058 (device web) Authentication - Weak password recovery -// // "Insecure password reset/forgot mechanism could cause authentication bypass." -// // -// // See T047. -// } -// @Test -// public void test_t059() { -// // T059 (device web) Authentication - Lack of two-factor authentication -// // "Lack of two-factor authentication mechanisms such as a security token or fingerprint scanner in senstive APIs." -// // -// // How to model in coreLang: -// // * 2FA is modeled as a defense: Identity.twoFactorAuthentication. Attacks on 2FA include User.steal2FAtoken. -// // * TODO CoreLang could potentially model each factor as a separate Credentials, and have a MultiFactorCredentials that requires all of the Credentials to be assumed. -// } -// @Test -// public void test_t060() { -// // T060 (device web) Authentication bypass - Web application to cloud -// // "Disclosure or reusing of Sensitive data (session key, token, cookie, etc.) could cause authentication bypass." -// // -// // See T028. -// } -// @Test -// public void test_t061() { -// // T061 (device web) Lack of logging options -// // "Lack of logging options or secure logging options. Indetailed logging. It might not a vulnerabilty" -// // -// // TODO lack of intrusion detection. CoreLang does not really model logging. -// } -// @Test -// public void test_t062() { -// // T062 (device web) Command injection -// // "Unsanitized user input can cause arbitrary code execution." -// // -// // How to model in coreLang: -// // * Generic vulnerability. See T031. -// // * XSS can be modeled as stealing credentials in sub-application. -// } -// @Test -// public void test_t063() { -// // T063 (device web) Direct object references -// // "Access to unauthorized data." -// // -// // Interpretation: The attacker can easily guess the ids -// // of objects (e.g. easy to guess url). This is not a vulnerability by -// // itself and there would have to additionally be a vulnerability -// // in the access control of those objects. -// // -// // This does not really make sense to model in coreLang (especially -// // since coreLang does not model indirection, like references and -// // URLs). Rather, just model the data (as APIs) and who has access to -// // it. See also test_T048_v3 on horizontal privilege escalation where -// // one user has access to another user's data. -// } -// @Test -// public void test_t064() { -// // T064 (device web) Business and logic flaws -// // "Any vulnerabilities that cause remote code execution or sensitive data disclosure. OWASP Top 10 and testing guideline." -// // -// // Could be almost anything, so might not make sense to model without -// // being more specific. -// // -// // How to model in coreLang: -// // * Generic vulnerability, see T031. -// // * Access control problems, see T041. -// // -// // Some IoT examples include: -// // * Sibyl attacks. -// } -// @Test -// public void test_t065() { -// // T065 (cloud web) Lack of transport encryption -// // "Insecure network communication. Cloud services are not properly encrypted HTTPS to prevent eavesdropping or tampering senstive data by attackers." -// // -// // See T033. -// } -// @Test -// public void test_t066() { -// // T066 (cloud web) Insecure SSL/TLS issues -// // "Expired and/or self-signed certificates, Same certificate used on multiple devices, Deprecated SSL versions" -// // -// // See T043. -// } -// @Test -// public void test_t067() { -// // T067 (cloud web) Authentication - Username enumeration -// // "Ability to collect a set of valid usernames by interacting with the authentication mechanism" -// // -// // See T044. -// } -// @Test -// public void test_t068() { -// // T068 (cloud web) Authentication - Weak credentials -// // "Ability to set account passwords to '1234' or '123456' for example. Usage of pre-programmed (know) default passwords (deffpass.com (Publicly available) - IoT device default password lookup). Easily guessable credentials. Brute-force by dictionaries and rules" -// // -// // See T045. -// } -// @Test -// public void test_t069() { -// // T069 (cloud web) Authentication - Improper account lockout -// // "Ability to continue sending authentication attempts after 3 - 5 failed login attempts" -// // -// // See T046. -// } -// @Test -// public void test_t070() { -// // T070 (cloud web) Authentication - Weak password recovery -// // "Insecure password reset/forgot mechanism could cause authentication bypass." -// // -// // See T047. -// } -// @Test -// public void test_t071() { -// // T071 (cloud web) Authentication - Lack of two-factor authentication -// // "Lack of two-factor authentication mechanisms such as a security token or fingerprint scanner in senstive APIs." -// // -// // See T059. -// } -// @Test -// public void test_t072() { -// // T072 (cloud API) Vendor APIs - Inherent trust of cloud or mobile application -// // "Vendor or 3rd party APIs" -// // -// // See T064. -// } -// @Test -// public void test_t073() { -// // T073 (cloud API) Vendor APIs - Authentication bypass -// // "Disclosure or reusing of Sensitive data (session key, token, cookie, etc.) could cause authentication bypass." -// // -// // See T028. -// } -// @Test -// public void test_t074() { -// // T074 (cloud API) Vendor APIs - Authorization bypass -// // "Insecure access controls" -// // -// // See T028. -// } -// @Test -// public void test_t075() { -// // T075 (cloud API) Vendor APIs - Undocumented backdoor API calls -// // "Critical API call for testing/debugging purposes left accessible." -// // -// // See T063. -// } -// @Test -// public void test_t076() { -// // T076 (cloud API) Vendor APIs - User data disclosure -// // "Insufficient Privacy Protection: Encrypted PII sent + UnEncrypted PII sent. User’s personal information stored on the device or in the ecosystem that is used insecurely, improperly, or without permission. https://arxiv.org/abs/1705.06805" -// // -// // How to model in coreLang: -// // * TODO CoreLang does not model privacy explicitly, but sensitive -// // information could be modeled as Data/Information. -// // * TODO Combining many small pieces of information (that are -// // otherwise benign) could be used to derive PII (e.g. via -// // statistical analysis). CoreLang does not model this. For -// // example, patterns in traffic could be used to analyze user -// // behavior . -// } -// @Test -// public void test_t077() { -// // T077 (cloud API) Vendor APIs - Device information leakage -// // "User/device location disclosure: Requests to the device’s weather service (API) leaks the exact GPS coordinates of the device, since they were sent as part of unencrypted HTTP communications [EST-1]." -// // -// // See T076. -// } -// @Test -// public void test_t078() { -// // T078 (mobile app) Sensitive data exposure - Hardcoded credentials -// // "An attacker could reveal unchangable credentials including password, hash, private certificate, and API key from storage by reverse engineering and source code analysis." -// // -// // Interpretation: Similarly to firmware, mobile apps packages (e.g. -// // APKs for android) may containing sensitive information. Packages -// // are usually publically available. -// // -// // See T018. -// } -// @Test -// public void test_t079() { -// // T079 (mobile app) Sensitive data exposure - Encryption keys and algorithms -// // "An attacker could identify encryption keys from both storage and memory by reverse engineering and source code analysis." -// // -// // See T018. -// } -// @Test -// public void test_t080() { -// // T080 (mobile app) Sensitive data exposure - Other sensitive information -// // "An attacker could identify various sensitive data (URLs) from both storage and memory by reverse engineering and source code analysis." -// // -// // See T021. -// } -// @Test -// public void test_t081() { -// // T081 (mobile app) Authentication - Username enumeration -// // "Ability to collect a set of valid usernames by interacting with the authentication mechanism" -// // -// // See T044. -// } -// @Test -// public void test_t082() { -// // T082 (mobile app) Authentication - Weak credentials -// // "Ability to set account passwords to '1234' or '123456' for example. Usage of pre-programmed (known) default passwords (deffpass.com (Publicly available) - IoT device default password lookup). Easily guessable credentials. Brute-force by dictionaries and rules" -// // -// // See T045. -// } -// @Test -// public void test_t083() { -// // T083 (mobile app) Authentication - Improper account lockout -// // "Ability to continue sending authentication attempts after 3 - 5 failed login attempts" -// // -// // See T046. -// } -// @Test -// public void test_t084() { -// // T084 (mobile app) Authentication - Weak password recovery -// // "Insecure password reset/forgot mechanism could cause authentication bypass." -// // -// // See T047. -// } -// @Test -// public void test_t085() { -// // T085 (mobile app) Authentication - Lack of two-factor authentication -// // "Lack of two-factor authentication mechanisms such as a security token or fingerprint scanner" -// // -// // See T059. -// } -// @Test -// public void test_t086() { -// // T086 (mobile app) Authentication - Mobile application to cloud system -// // "Disclosure or reusing of sensitive data (session key, token, cookie, etc.) could cause authentication bypass." -// // -// // See T028. -// } -// @Test -// public void test_t087() { -// // T087 (mobile app) Insecure authorization -// // "" -// // -// // Interpretation: See OWASP mobile top ten. Basically access -// // control is broken in some way. -// // -// // See for example T028. -// } -// @Test -// public void test_t088() { -// // T088 (mobile app) Implicitly trusted by device or cloud -// // "" -// // -// // See T064. -// } -// @Test -// public void test_t089() { -// // T089 (mobile app) Lack of transport encryption -// // "Insecure network communication. Mobile applications are not properly encrypted HTTPS to prevent eavesdropping or tampering senstive data by attackers." -// // -// // See T033. -// } -// @Test -// public void test_t090() { -// // T090 (mobile app) Insecure SSL/TLS issues -// // "Expired and/or self-signed certificates, Same certificate used on multiple devices, Deprecated SSL versions" -// // -// // See T043. -// } -// @Test -// public void test_t091() { -// // T091 (mobile app) Insecure data storage -// // "" -// // -// // See T021. -// } -// @Test -// public void test_t092() { -// // T092 (mobile app) Outdated 3rd party libraries and SDKs -// // "Known vulnerabilities in deprecated libraries." -// // -// // Generic vulerability, see T031. -// // In this case it may make sense to attach the vulnerability to a -// // SoftwareProduct rather than directly to an Application. -// } -// @Test -// public void test_t093() { -// // T093 (mobile app) Business and logic flaws -// // "Insecure Device controlling commands" -// // -// // See T064. -// } -// @Test -// public void test_t094() { -// // T094 (mobile app) Lack of health checks -// // "No check whether the device is working as it should. Insecure heartbeats" -// // -// // How to model in coreLang: -// // * For example as dataflow over network that the attacker can -// // manipulate. -// // * Broken authentication/access control. For example heartbeat API -// // accessible to anyone. -// // -// } -// @Test -// public void test_t095() { -// // T095 (radio) Lack of transport encryption -// // "Attacker can extract sensitive information in clear text from radio packets." -// // -// // See T033. -// } -// @Test -// public void test_t096() { -// // T096 (radio) Man in the middle attack -// // "Even TLS connections might be also vulnerable to MitM attacks, since certificate validation is missing. It allows the attackers to conduct additional attacks according to the context [EST-1]." -// // -// // How to model in coreLang: -// // * Just model radio as a regular Network. -// } -// @Test -// public void test_t097() { -// // T097 (radio) Lack of message integrity check -// // "The transmission protocol does not include a mechanism for verifying the integrity of the transmitted data, such as a checksum. Or it does not validate or incorrectly validates the integrity check values or "checksums" of a message (header or payload) which will allow modified or corrupted data in transmission." -// // -// // Examples: -// // * Only part of the packet is encrypted and the unencrypted part -// // of the packet is implicitly trusted. -// // -// // How to model in coreLang: -// // * See T033 on encryption. -// // * See T034 on signatures. -// } -// @Test -// public void test_t098() { -// // T098 (radio) Interception and modification -// // "Attacker can intercept live radio communication and then modify the transmitted packets." -// // -// // See T096. -// } -// @Test -// public void test_t099() { -// // T099 (radio) Replay attack -// // "Attacker can perform bit-flip attacks on encrypted network traffic. The intruder will first intercept an encrypted message and then alter the payload or header and retransmit the data packet. Actually performing replay attack which is possible when there is no verification and captured data can be re-transmitted. Some type of integrity check methods i.e. ICV are known as vulnerable." -// // -// // Intepretation: The attack can record and resend radio waves. -// // Potentially the recorded waves can be interpreted as packets, -// // reverse engineered and more advanced packets can then be sent. -// // -// // How to model in coreLang: -// // * Lack of authentication. -// // * Generic vulnerability in authentication mechanism. -// // * As credentials being sent in plain text over radio. Note that radio can be modeled using Network. -// // * Non-idempotent messages. No sequence numbering. -// // * TODO It may be useful to model replay attacks explicitly in coreLang. For example Data.replay -// } -// @Test -// public void test_t100() { -// // T100 (radio) Jamming attack -// // "Due to some controls such as payload verification, a transmitted packet might not be re-transmitted again. For this cases, it is required jamming the signal first and capturing an "unused" radio packet. Then replay attack can be successfully performed." -// // -// // Interpretation: Jamming can be a form of DoS. It can also be used to block and capture at the same time as a form of MITM attack. This may for example be necessary to perform certain replay attacks. -// // -// // How to model in coreLang: -// // * Model as DoS on network, see T050. -// } -// @Test -// public void test_t101() { -// // T101 (radio) Spoofing attack -// // "Attacker can present itself as a legitamate gateway or sensor in radio communication." -// // -// // See T096. -// // -// // CoreLang does not really model the details of attacks based on -// // redirection and addressing (such as in for example ARP cache -// // poisoning). However, it does model the result -- MITM. -// } -// @Test -// public void test_t102() { -// // T102 (radio) Denial of service (DoS) -// // "Attacker can disrupt radio communication." -// // -// // See T100. -// } - - - ////////// util //////////// From 5663f32cfe024cf001f72882de814dc55d4ff54c Mon Sep 17 00:00:00 2001 From: jesajx Date: Thu, 1 Jul 2021 17:16:49 +0200 Subject: [PATCH 04/10] patriot test folder --- .../org/mal_lang/corelang/test/{ => patriot}/TestPatriot.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/java/org/mal_lang/corelang/test/{ => patriot}/TestPatriot.java (100%) diff --git a/src/test/java/org/mal_lang/corelang/test/TestPatriot.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java similarity index 100% rename from src/test/java/org/mal_lang/corelang/test/TestPatriot.java rename to src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java From 8d4289f56cbeb8151b10cfc4d289d8d29afa860d Mon Sep 17 00:00:00 2001 From: jesajx Date: Thu, 1 Jul 2021 17:17:15 +0200 Subject: [PATCH 05/10] patriot test package --- .../corelang/test/patriot/TestPatriot.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java index 568508c..f8a6369 100644 --- a/src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java @@ -1,7 +1,8 @@ -package org.mal_lang.corelang.test; +package org.mal_lang.corelang.test.patriot; import org.junit.jupiter.api.AfterEach; +import org.mal_lang.corelang.test.*; import core.*; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.fail; @@ -45,7 +46,7 @@ public void test_t002() { // ConnectionRules, see T004. var phy = new PhysicalZone("phy"); - var sys = new System("sys"); + var sys = new org.mal_lang.corelang.test.System("sys"); var app = new Application("app"); containerAdd(phy, sys); @@ -1158,7 +1159,7 @@ public void test_T033_v1_defense() { public void test_T033_v2() { // more complicated example - var sys = new System("sys"); + var sys = new org.mal_lang.corelang.test.System("sys"); var app = new Application("app"); containerAdd(sys, app); @@ -1176,7 +1177,7 @@ public void test_T033_v2() { var routerNat = new RoutingFirewall("routerNat"); con_lan_internet.addRoutingFirewalls(routerNat); - var routerHardware = new System("routerHardware"); + var routerHardware = new org.mal_lang.corelang.test.System("routerHardware"); containerAdd(routerHardware, routerNat); var tcp = new Data("tcp"); @@ -1430,7 +1431,7 @@ public void test_t043() { var routerNat = new RoutingFirewall("routerNat"); con_lan_internet.addRoutingFirewalls(routerNat); - var routerHardware = new System("routerHardware"); + var routerHardware = new org.mal_lang.corelang.test.System("routerHardware"); containerAdd(routerHardware, routerNat); var tlsCredentials = new Credentials("tlsCredentials"); @@ -1832,15 +1833,15 @@ public void aOwnsB(Identity a, Identity b) { a.addParentId(b); } - public void containerAdd(PhysicalZone container, System inside) { + public void containerAdd(PhysicalZone container, org.mal_lang.corelang.test.System inside) { container.addSystems(inside); } - public void containerAdd(System container, Application inside) { + public void containerAdd(org.mal_lang.corelang.test.System container, Application inside) { container.addSysExecutedApps(inside); } - public void containerAdd(System container, Data inside) { + public void containerAdd(org.mal_lang.corelang.test.System container, Data inside) { container.addSysData(inside); } From 69d83ef1ab1e4f4da4d96542ee8ce778ed3cd075 Mon Sep 17 00:00:00 2001 From: jesajx Date: Thu, 1 Jul 2021 17:23:34 +0200 Subject: [PATCH 06/10] add temporary util base class --- .../mal_lang/corelang/test/patriot/Base.java | 306 ++++++++++++++++++ .../corelang/test/patriot/TestPatriot.java | 296 +---------------- 2 files changed, 307 insertions(+), 295 deletions(-) create mode 100644 src/test/java/org/mal_lang/corelang/test/patriot/Base.java diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/Base.java b/src/test/java/org/mal_lang/corelang/test/patriot/Base.java new file mode 100644 index 0000000..05e3d93 --- /dev/null +++ b/src/test/java/org/mal_lang/corelang/test/patriot/Base.java @@ -0,0 +1,306 @@ +package org.mal_lang.corelang.test.patriot; + +import org.junit.jupiter.api.AfterEach; + +import org.mal_lang.corelang.test.*; +import core.*; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.HashSet; +import java.util.HashMap; + + +public class Base extends CoreLangTest { + + public void con(Application src, ConnectionRule dst) { + // app is client-like (outgoing) + src.addOutgoingAppConnections(dst); + } + public void con(ConnectionRule src, Application dst) { + // app is server-like (incoming) + dst.addIngoingAppConnections(src); + } + + public void con(Network src, ConnectionRule dst) { + // net is client-like (outgoing) + src.addOutgoingNetConnections(dst); + } + public void con(ConnectionRule src, Network dst) { + // net is server-like (incoming) + dst.addIngoingNetConnections(src); + } + + public void con(Application src, ConnectionRule conrule, Network dst) { + con(src, conrule); + con(conrule, dst); + } + public void con(Network src, ConnectionRule conrule, Application dst) { + con(src, conrule); + con(conrule, dst); + } + + public void con(Network src, ConnectionRule conrule, Network dst) { + con(src, conrule); + con(conrule, dst); + } + + public void conbi(Application src, ConnectionRule conrule, Network dst) { + con(src, conrule, dst); + con(dst, conrule, src); + } + public void conbi(Network src, ConnectionRule conrule, Application dst) { + con(src, conrule, dst); + con(dst, conrule, src); + } + + public void conbi(Network src, ConnectionRule conrule, Network dst) { + con(src, conrule, dst); + con(dst, conrule, src); + } + + public void transferData(Network medium, Data data) { + data.addTransitNetwork(medium); + } + public void transferData(Application medium, Data data) { + data.addTransitApp(medium); + } + + public void execData(Data code, SoftwareProduct product, Application app) { + product.addOriginData(code); + product.addSoftApplications(app); + } + + public void aOwnsB(Identity a, Identity b) { + a.addParentId(b); + } + + public void containerAdd(PhysicalZone container, org.mal_lang.corelang.test.System inside) { + container.addSystems(inside); + } + + public void containerAdd(org.mal_lang.corelang.test.System container, Application inside) { + container.addSysExecutedApps(inside); + } + + public void containerAdd(org.mal_lang.corelang.test.System container, Data inside) { + container.addSysData(inside); + } + + public void containerAdd(Application container, Application inside) { + container.addAppExecutedApps(inside); + } + + public void containerAdd(Application container, Data inside) { + container.addContainedData(inside); + } + + public void containerAdd(Data container, Data inside) { + container.addContainedData(inside); + } + + public void containerAdd(Data container, Information inside) { + container.addInformation(inside); + } + + public void addApiData(Application app, Data data) { + containerAdd(app, data); + } + + public void addApiUser(Application app, Identity id) { + id.addLowPrivApps(app); + } + + public void addApiReadAccess(Identity id, Data data) { + id.addReadPrivData(data); + } + + public void addApiWriteAccess(Identity id, Data data) { + id.addWritePrivData(data); + } + + public void mkReadApi(Application app, Identity id, Data data) { + addApiUser(app, id); + addApiData(app, data); + addApiReadAccess(id, data); + } + + public void mkWriteApi(Application app, Identity id, Data data) { + addApiUser(app, id); + addApiData(app, data); + addApiWriteAccess(id, data); + } + + public void mkReadWriteApi(Application app, Identity id, Data data) { + mkReadApi(app, id, data); + mkWriteApi(app, id, data); + } + + public void addApiExecUser(Application app, Identity id) { + id.addHighPrivApps(app); + } + public void mkExecApi(Application app, Identity id) { + addApiExecUser(app, id); + } + + + public HashSet attack(AttackStep... entryPoints) { + var startSet = new HashSet(); + var attacker = new Attacker(); + for (var step : entryPoints) { + if (step == null) { + throw new NullPointerException(); + } + if (!AttackStep.allAttackSteps.contains(step)) { + throw new RuntimeException("missing step " + step); + } + + startSet.add(step); + attacker.addAttackPoint(step); + } + attacker.attack(); + return startSet; // for convenience + } + + public void compromised(int zeroIfUncompromised, AttackStep step) { + boolean isCompromised = (zeroIfUncompromised != 0); + compromised(isCompromised, step); + } + + public void compromised(boolean isCompromised, AttackStep step) { + if (isCompromised) { + assertReached(step); + } else { + assertNotReached(step); + } + } + + public ConnectionRule autocon(String name, Application src, Network dst) { + var connectionRule = new ConnectionRule(name); + con(src, connectionRule, dst); + return connectionRule; + } + public ConnectionRule autocon(String name, Network src, Application dst) { + var connectionRule = new ConnectionRule(name); + con(src, connectionRule, dst); + return connectionRule; + } + + public ConnectionRule autocon(String name, Network src, Network dst) { + var connectionRule = new ConnectionRule(name); + con(src, connectionRule); + con(connectionRule, dst); + return connectionRule; + } + + public ConnectionRule autoconbi(String name, Application src, Network dst) { + var connectionRule = new ConnectionRule(name); + conbi(src, connectionRule, dst); + return connectionRule; + } + + public ConnectionRule autoconbi(String name, Network src, Application dst) { + var connectionRule = new ConnectionRule(name); + conbi(src, connectionRule, dst); + return connectionRule; + } + + public ConnectionRule autoconbi(String name, Network src, Network dst) { + var connectionRule = new ConnectionRule(name); + conbi(src, connectionRule, dst); + return connectionRule; + } + + public void appExecAs(Application app, Identity id) { + id.addExecPrivApps(app); + } + + public static class VulnerabilityBuilder { + String name = ""; + boolean network = false; + boolean local = false; + boolean physical = false; + boolean priv_low = false; + boolean priv_high = false; + boolean user_interact = false; + boolean confidentiality = false; + boolean availability = false; + boolean integrity = false; + boolean complex = false; + + public VulnerabilityBuilder(String name) { + this.name = name; + } + + public VulnerabilityBuilder setNetwork() { + this.network = true; + return this; + } + public VulnerabilityBuilder setLocal() { + this.local = true; + return this; + } + public VulnerabilityBuilder setPhysical() { + this.physical = true; + return this; + } + + public VulnerabilityBuilder setPrivLow() { + this.priv_low = true; + return this; + } + public VulnerabilityBuilder setPrivHigh() { + this.priv_high = true; + return this; + } + + public VulnerabilityBuilder setUserInteract() { + this.user_interact = true; + return this; + } + public VulnerabilityBuilder setComplex() { + this.complex = true; + return this; + } + + public VulnerabilityBuilder setCIA() { + this.confidentiality = true; + this.availability = true; + this.integrity = true; + return this; + } + + public VulnerabilityBuilder setConfidentiality() { + this.confidentiality = true; + return this; + } + public VulnerabilityBuilder setAvailability() { + this.availability = true; + return this; + } + public VulnerabilityBuilder setIntegrity() { + this.integrity = true; + return this; + } + + + public SoftwareVulnerability build() { + var res = new SoftwareVulnerability(name); + res.networkAccessRequired.defaultValue = network; + res.localAccessRequired.defaultValue = local; + res.physicalAccessRequired.defaultValue = physical; + res.lowPrivilegesRequired.defaultValue = priv_low; + res.highPrivilegesRequired.defaultValue = priv_high; + res.userInteractionRequired.defaultValue = user_interact; + res.confidentialityImpactLimitations.defaultValue = !confidentiality; + res.availabilityImpactLimitations.defaultValue = !availability; + res.integrityImpactLimitations.defaultValue = !integrity; + res.highComplexityExploitRequired.defaultValue = complex; + return res; + } + } + + public static VulnerabilityBuilder vulnerabilityBuilder(String name) { + return new VulnerabilityBuilder(name); + } +} diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java index f8a6369..36b0a0c 100644 --- a/src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java @@ -11,7 +11,7 @@ import java.util.HashMap; -public class TestPatriot extends CoreLangTest { +public class TestPatriot extends Base { // These tests are based the weaknesses listed in the PATRIOT methodology // (paper pending). Some of the weaknesses can be found listed here: // . @@ -1767,298 +1767,4 @@ public void test_t050() { compromised(1, net.denialOfService); compromised(1, app.deny); } - - - ////////// util //////////// - - public void con(Application src, ConnectionRule dst) { - // app is client-like (outgoing) - src.addOutgoingAppConnections(dst); - } - public void con(ConnectionRule src, Application dst) { - // app is server-like (incoming) - dst.addIngoingAppConnections(src); - } - - public void con(Network src, ConnectionRule dst) { - // net is client-like (outgoing) - src.addOutgoingNetConnections(dst); - } - public void con(ConnectionRule src, Network dst) { - // net is server-like (incoming) - dst.addIngoingNetConnections(src); - } - - public void con(Application src, ConnectionRule conrule, Network dst) { - con(src, conrule); - con(conrule, dst); - } - public void con(Network src, ConnectionRule conrule, Application dst) { - con(src, conrule); - con(conrule, dst); - } - - public void con(Network src, ConnectionRule conrule, Network dst) { - con(src, conrule); - con(conrule, dst); - } - - public void conbi(Application src, ConnectionRule conrule, Network dst) { - con(src, conrule, dst); - con(dst, conrule, src); - } - public void conbi(Network src, ConnectionRule conrule, Application dst) { - con(src, conrule, dst); - con(dst, conrule, src); - } - - public void conbi(Network src, ConnectionRule conrule, Network dst) { - con(src, conrule, dst); - con(dst, conrule, src); - } - - public void transferData(Network medium, Data data) { - data.addTransitNetwork(medium); - } - public void transferData(Application medium, Data data) { - data.addTransitApp(medium); - } - - public void execData(Data code, SoftwareProduct product, Application app) { - product.addOriginData(code); - product.addSoftApplications(app); - } - - public void aOwnsB(Identity a, Identity b) { - a.addParentId(b); - } - - public void containerAdd(PhysicalZone container, org.mal_lang.corelang.test.System inside) { - container.addSystems(inside); - } - - public void containerAdd(org.mal_lang.corelang.test.System container, Application inside) { - container.addSysExecutedApps(inside); - } - - public void containerAdd(org.mal_lang.corelang.test.System container, Data inside) { - container.addSysData(inside); - } - - public void containerAdd(Application container, Application inside) { - container.addAppExecutedApps(inside); - } - - public void containerAdd(Application container, Data inside) { - container.addContainedData(inside); - } - - public void containerAdd(Data container, Data inside) { - container.addContainedData(inside); - } - - public void containerAdd(Data container, Information inside) { - container.addInformation(inside); - } - - public void addApiData(Application app, Data data) { - containerAdd(app, data); - } - - public void addApiUser(Application app, Identity id) { - id.addLowPrivApps(app); - } - - public void addApiReadAccess(Identity id, Data data) { - id.addReadPrivData(data); - } - - public void addApiWriteAccess(Identity id, Data data) { - id.addWritePrivData(data); - } - - public void mkReadApi(Application app, Identity id, Data data) { - addApiUser(app, id); - addApiData(app, data); - addApiReadAccess(id, data); - } - - public void mkWriteApi(Application app, Identity id, Data data) { - addApiUser(app, id); - addApiData(app, data); - addApiWriteAccess(id, data); - } - - public void mkReadWriteApi(Application app, Identity id, Data data) { - mkReadApi(app, id, data); - mkWriteApi(app, id, data); - } - - public void addApiExecUser(Application app, Identity id) { - id.addHighPrivApps(app); - } - public void mkExecApi(Application app, Identity id) { - addApiExecUser(app, id); - } - - - public HashSet attack(AttackStep... entryPoints) { - var startSet = new HashSet(); - var attacker = new Attacker(); - for (var step : entryPoints) { - if (step == null) { - throw new NullPointerException(); - } - if (!AttackStep.allAttackSteps.contains(step)) { - throw new RuntimeException("missing step " + step); - } - - startSet.add(step); - attacker.addAttackPoint(step); - } - attacker.attack(); - return startSet; // for convenience - } - - public void compromised(int zeroIfUncompromised, AttackStep step) { - boolean isCompromised = (zeroIfUncompromised != 0); - compromised(isCompromised, step); - } - - public void compromised(boolean isCompromised, AttackStep step) { - if (isCompromised) { - assertReached(step); - } else { - assertNotReached(step); - } - } - - public ConnectionRule autocon(String name, Application src, Network dst) { - var connectionRule = new ConnectionRule(name); - con(src, connectionRule, dst); - return connectionRule; - } - public ConnectionRule autocon(String name, Network src, Application dst) { - var connectionRule = new ConnectionRule(name); - con(src, connectionRule, dst); - return connectionRule; - } - - public ConnectionRule autocon(String name, Network src, Network dst) { - var connectionRule = new ConnectionRule(name); - con(src, connectionRule); - con(connectionRule, dst); - return connectionRule; - } - - public ConnectionRule autoconbi(String name, Application src, Network dst) { - var connectionRule = new ConnectionRule(name); - conbi(src, connectionRule, dst); - return connectionRule; - } - - public ConnectionRule autoconbi(String name, Network src, Application dst) { - var connectionRule = new ConnectionRule(name); - conbi(src, connectionRule, dst); - return connectionRule; - } - - public ConnectionRule autoconbi(String name, Network src, Network dst) { - var connectionRule = new ConnectionRule(name); - conbi(src, connectionRule, dst); - return connectionRule; - } - - public void appExecAs(Application app, Identity id) { - id.addExecPrivApps(app); - } - - public static class VulnerabilityBuilder { - String name = ""; - boolean network = false; - boolean local = false; - boolean physical = false; - boolean priv_low = false; - boolean priv_high = false; - boolean user_interact = false; - boolean confidentiality = false; - boolean availability = false; - boolean integrity = false; - boolean complex = false; - - public VulnerabilityBuilder(String name) { - this.name = name; - } - - public VulnerabilityBuilder setNetwork() { - this.network = true; - return this; - } - public VulnerabilityBuilder setLocal() { - this.local = true; - return this; - } - public VulnerabilityBuilder setPhysical() { - this.physical = true; - return this; - } - - public VulnerabilityBuilder setPrivLow() { - this.priv_low = true; - return this; - } - public VulnerabilityBuilder setPrivHigh() { - this.priv_high = true; - return this; - } - - public VulnerabilityBuilder setUserInteract() { - this.user_interact = true; - return this; - } - public VulnerabilityBuilder setComplex() { - this.complex = true; - return this; - } - - public VulnerabilityBuilder setCIA() { - this.confidentiality = true; - this.availability = true; - this.integrity = true; - return this; - } - - public VulnerabilityBuilder setConfidentiality() { - this.confidentiality = true; - return this; - } - public VulnerabilityBuilder setAvailability() { - this.availability = true; - return this; - } - public VulnerabilityBuilder setIntegrity() { - this.integrity = true; - return this; - } - - - public SoftwareVulnerability build() { - var res = new SoftwareVulnerability(name); - res.networkAccessRequired.defaultValue = network; - res.localAccessRequired.defaultValue = local; - res.physicalAccessRequired.defaultValue = physical; - res.lowPrivilegesRequired.defaultValue = priv_low; - res.highPrivilegesRequired.defaultValue = priv_high; - res.userInteractionRequired.defaultValue = user_interact; - res.confidentialityImpactLimitations.defaultValue = !confidentiality; - res.availabilityImpactLimitations.defaultValue = !availability; - res.integrityImpactLimitations.defaultValue = !integrity; - res.highComplexityExploitRequired.defaultValue = complex; - return res; - } - } - - public static VulnerabilityBuilder vulnerabilityBuilder(String name) { - return new VulnerabilityBuilder(name); - } } From a127360720956696aff5e72a2ece2f3c0af45cbe Mon Sep 17 00:00:00 2001 From: jesajx Date: Thu, 1 Jul 2021 17:29:25 +0200 Subject: [PATCH 07/10] split into big categories --- .../{TestPatriot.java => TestFirmware.java} | 781 +----------------- .../corelang/test/patriot/TestNetwork.java | 446 ++++++++++ .../corelang/test/patriot/TestPhysical.java | 351 ++++++++ 3 files changed, 798 insertions(+), 780 deletions(-) rename src/test/java/org/mal_lang/corelang/test/patriot/{TestPatriot.java => TestFirmware.java} (54%) create mode 100644 src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java create mode 100644 src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java similarity index 54% rename from src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java rename to src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java index 36b0a0c..600e2ff 100644 --- a/src/test/java/org/mal_lang/corelang/test/patriot/TestPatriot.java +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java @@ -11,354 +11,7 @@ import java.util.HashMap; -public class TestPatriot extends Base { - // These tests are based the weaknesses listed in the PATRIOT methodology - // (paper pending). Some of the weaknesses can be found listed here: - // . - // - // In any case, below is an attempt to model each weakness in at least one - // way in coreLang. Note that the weaknesses form a checklist of things to - // look for during a pentest. As such not all weaknesses make sense to - // model. - // - // TODO Some suggestions on changes to coreLang are marked with "TODO". - // - - @Test - public void test_t002() { - // T002 (physical) Firmware/storage extraction - Insecure external media interfaces - // "An attacker could copy the firmware/storage and even modify firmware if device allows to physically remove the storage media (SD Card, USB)." - // - // Interpretation: An IoT device may have easily accessible physical - // connectors, such as USB. The attacker can use these interfaces to - // gain access to the device. We also model removable storage media - // (e.g. SD-card) the same way. - // - // Examples: - // * The attacker may be able to read firmware. - // * The attacker may be able to read shared credentials (e.g. if the - // same symmetric encryption key is used for all users and - // devices). - // - // How to model this in coreLang: - // * PhysicalZone is used to model physical attacks on a system. - // * Physical interfaces can also be modeled as networks and - // ConnectionRules, see T004. - - var phy = new PhysicalZone("phy"); - var sys = new org.mal_lang.corelang.test.System("sys"); - var app = new Application("app"); - - containerAdd(phy, sys); - containerAdd(sys, app); - - var sysData = new Data("sysData"); - var appData = new Data("appData"); - - containerAdd(sys, sysData); - containerAdd(app, appData); - - // TODO currently physical exploits are not full implemented in - // coreLang 0.2.0. We will just model this as "anyone" having access. - - var anyone = new Identity("anyone"); - sys.addHighPrivSysIds(anyone); // vulnerability - - attack(phy.gainPhysicalAccess, anyone.assume); - - compromised(1, sysData.read); - compromised(1, appData.read); - } - - @Test - public void test_t003() { - // T003 (physical) Firmware/storage extraction - Download from the Web - // "An attacker could download the firmware from the manufacturer's website if access to the firmware image without authentication is possible." - // - // Interpretation: The firmware used for a particular model of IoT - // device may be publically available on the internet (e.g. can be - // downloaded from the manufacturer's website). The attacker can use - // the firmware to gain information about the device (e.g. reverse - // enginnering, sensitive information contained in the firmware and - // whitebox testing). - // - // Examples: - // * The firmware may contain sensitive information (such as - // credentials) that the attacker can extract. - // * The attacker can reverse engineer the firmware to find - // vulnerabilities faster (as opposed to black-box testing the - // device). - // - // How to model this in coreLang: - // * see test_T001. - // * see test_T001_v2. - - var internet = new Network("internet"); - - var firmwareBlob = new Data("firmwareBlob"); - var sensitiveData = new Data("sensitiveData"); - - transferData(internet, firmwareBlob); - containerAdd(firmwareBlob, sensitiveData); - - attack(internet.access); - - compromised(1, sensitiveData.read); - compromised(1, sensitiveData.write); - } - - @Test - public void test_T003_v2() { - var internet = new Network("internet"); - var cloud = new Application("cloud"); - - var con_internet_cloud = autocon("con_internet_cloud", internet, cloud); - - var firmwareBlob = new Data("firmwareBlob"); - var sensitiveData = new Data("sensitiveData"); - - containerAdd(cloud, firmwareBlob); - containerAdd(firmwareBlob, sensitiveData); - - var anyone = new Identity("anyone"); - mkReadApi(cloud, anyone, firmwareBlob); - - attack(internet.access, anyone.attemptAssume); - - - - compromised(1, cloud.specificAccessAuthenticate); - compromised(1, cloud.specificAccess); - - compromised(1, firmwareBlob.attemptAccessFromIdentity); - compromised(1, firmwareBlob.identityRead); - compromised(1, firmwareBlob.attemptRead); - compromised(1, firmwareBlob.read); - - compromised(1, sensitiveData.attemptRead); - compromised(1, sensitiveData.read); - - compromised(0, firmwareBlob.write); - compromised(0, sensitiveData.write); - } - - - @Test - public void test_t004() { - // T004 (physical) Firmware/storage extraction - Insecure SPI interface - // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the serial bus protocol SPI." - // - // Interpretation: An IoT device may have hidden physical connectors. - // The attacker can use these connectors to gain access to the device. - // - // Examples: - // * The attacker may be able to read firmware. - // * The attacker may be able to read shared credentials (e.g. if the - // same symmetric encryption key is used for all users and - // devices). - // * The attacker may desolder the flash component and use SPI to - // extract the contents. - // - // How to model this in coreLang: - // * See test_T002. Basically use PhysicalZone to attach System. TODO not done in coreLang 0.2.0? - // * You can also model SPI as a kind of Network. - - - // SPI as network: - - var spi = new Network("spi"); - var app = new Application("app"); - - var spi_con_app = autocon("spi_con_app", spi, app); - - var appData = new Data("appData"); - containerAdd(app, appData); - - var vuln = vulnerabilityBuilder("vuln").setNetwork().setConfidentiality().build(); - app.addVulnerabilities(vuln); - - var startSet = attack(spi.physicalAccess); - - compromised(1, vuln.abuse); - compromised(1, appData.read); - } - - @Test - public void test_T004_v2() { - // Like test_T004, but with explicit root shell. - - var os = new Application("os"); - var app = new Application("app"); - var shell = new Application("shell"); - - containerAdd(os, app); - containerAdd(os, shell); - - var spi = new Network("spi"); - - var spi_con_shell = autocon("spi_con_shell", spi, shell); - - var appData = new Data("appData"); - containerAdd(app, appData); - - var anyone = new Identity("anyone"); - var root = new Identity("root"); - - mkExecApi(shell, anyone); // privilege escalation: anyone -> root - - appExecAs(shell, root); - appExecAs(os, root); - appExecAs(app, root); - - // TODO CoreLang could have an association between PhysicalZone and Network. - attack(spi.physicalAccess, anyone.assume); - - compromised(1, shell.networkConnect); - compromised(1, shell.authenticate); - compromised(1, shell.fullAccess); - compromised(1, os.fullAccess); - compromised(1, app.fullAccess); - compromised(1, appData.read); - } - - @Test - public void test_T004_v3() { - // Attack bootloader. This is perhaps more common with TTL/UART than - // SPI. - - var bootloader = new Application("bootloader"); // e.g. uboot - var os = new Application("os"); - - containerAdd(bootloader, os); - - var spi = new Network("spi"); - - var spi_con_bootloader = autocon("spi_con_bootloader", spi, bootloader); - - var sensitiveData = new Data("sensitiveData"); - containerAdd(os, sensitiveData); - - var anyone = new Identity("anyone"); - - mkExecApi(bootloader, anyone); - - attack(spi.physicalAccess, anyone.assume); - - compromised(1, bootloader.fullAccess); - compromised(1, os.fullAccess); - compromised(1, sensitiveData.read); - } - - @Test - public void test_t009() { - // T009 (physical) Firmware/storage extraction - Insecure SoC - // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the other SoC (System on Chip) (e.g. Bluetooth)." - // - // Like T004, but we are attacking from another chip. Same idea here: use networks to model internal communication like SPI, etc. - - var chipA = new Application("chipA"); - var chipB = new Application("chipB"); // chipB could for example be a flash component or a chip that provides an API to a flash component. - - var i2c = new Network("i2c"); - var chipA_con_i2c = autocon("chipA_con_i2c", chipA, i2c); // chipA is a "master" - var i2c_con_chipB = autocon("i2c_con_chipB", i2c, chipB); // chipB is a "slave" - - var anyone = new Identity("anyone"); - - var sensitiveData = new Data("sensitiveData"); - mkReadApi(chipB, anyone, sensitiveData); - - attack(chipA.fullAccess, anyone.assume); - compromised(1, sensitiveData.read); - } - - @Test - public void test_t011() { - // T011 (physical) Backdoor firmware - Insecure UART interface - // "An attacker could modify the firmware if access to the flash/EEPROM chip is not restricted through the serial interface UART." - // - // Interpretation: An IoT device may have hidden physical connectors. - // The attacker may be able to use these connectors to install (and - // run) firmware on the device. - // - // Examples: - // * The attacker is able to upload, install and run firmware. - // - // How to model this in coreLang: - // * See T002 and T004 on modeling physical attacks. Additionally use - // SoftwareProduct to model the attacker overwriting existing - // software via Data. - - - var app = new Application("app"); - - var ttl = new Network("ttl"); - - var ttl_con_app = autocon("ttl_con_app", ttl, app); - - var firmwareBlob = new Data("firmwareBlob"); - containerAdd(app, firmwareBlob); - - var firmwareProduct = new SoftwareProduct("firmwareProduct"); - - execData(firmwareBlob, firmwareProduct, app); - - var anyone = new Identity("anyone"); - - mkWriteApi(app, anyone, firmwareBlob); - - attack(ttl.physicalAccess, anyone.assume); - - - compromised(1, firmwareBlob.write); // By writing to the firmwareblob... - compromised(1, app.fullAccess); // ... we can exec code. - } - - @Test - public void test_t015() { - // T015 (physical) Grant shell access - Insecure SPI interface - // "An attacker could grant a command shell if access to the flash/EEPROM chip is not restricted through the serial interface SPI." - // - // See also T004. - - var spi = new Network("spi"); - var flash = new Application("flash"); - var app = new Application("app"); - - var spi_con_app = autocon("spi_con_app", spi, app); - var spi_con_flash = autocon("spi_con_app", spi, flash); - - var filesystem = new Data("filesystem"); - var bootscript = new Data("bootscript"); - containerAdd(flash, filesystem); - containerAdd(filesystem, bootscript); - - var appProduct = new SoftwareProduct("appProduct"); - - execData(bootscript, appProduct, app); - - var anyone = new Identity("anyone"); - mkReadWriteApi(flash, anyone, filesystem); - - var startSet = attack(spi.physicalAccess, anyone.assume); - - compromised(1, filesystem.write); - compromised(1, bootscript.write); - compromised(1, app.fullAccess); - } - -// @Test -// public void test_t017() { -// // T017 (physical) Reset to insecure state -// // "An attacker could misuse reset functionality of the device if resetting results in insecure state." -// // -// // TODO coreLang does not really model state changes. We could -// // potentially model this as two separate models: one showing the -// // scenario leading up to the reset and one shoing the scenario -// // resulting from the reset. The reset can be modeled as the the -// // attacker doing Data.write to a specific Data asset representing the -// // reset API-function. See also T035 on rollback attacks. -// } +public class TestFirmware extends Base { @Test public void test_t019() { @@ -1335,436 +988,4 @@ public void test_t039() { // // scenario leading up to the rollback and another model showing the // // situation after the rollback. See also T004. // } - - @Test - public void test_t041() { - // T041 (device network service) Sensitive data exposure - // "Any kind of senstive data that can be accessible." - // - // Intepretation: Sensitive data exposed on network ports. - // - // Examples: - // * MAC-addresses. - // * Unprotected APIs. - // - // See e.g. T003 and T028. - // - // How to model this in coreLang: - // 1. Network-assets may contain "transitData" (Data asset) which can - // be used to model sensitive data being available on the network. - // If the attacker has access to the network they can obtain the - // data through eavesdropping. Note that we consider reading the - // data to be impactful by itself. We do not model the attacker - // using the data for anything. - // 2. We can also model it using APIs (see test_T001_v2). - - - var app = new Application("app"); - - var net = new Network("net"); - - var net_con_app = autocon("net_con_app", net, app); - - var sensitiveData = new Data("sensitiveData"); - - // The app is broadcasting sensitiveData on the network: - //containerAdd(app, sensitiveData); - //transferData(app, sensitiveData); // Not needed, but in larger models this is how we would model the data being transfered around. - transferData(net, sensitiveData); - - attack(net.access); - - compromised(1, sensitiveData.read); - } - @Test - public void test_T041_v2() { - // We can model the sensitive data as being exposed by an API. - - var app = new Application("app"); - - var net = new Network("net"); - - var net_con_app = autocon("net_con_app", net, app); // open port - - var anyone = new Identity("anyone"); - - var sensitiveData = new Data("sensitiveData"); - - mkReadApi(app, anyone, sensitiveData); - - attack(net.access, anyone.assume); - - compromised(1, sensitiveData.read); - } - - - @Test - public void test_t043() { - // T043 (device network service) Insecure SSL/TLS issues - // "Encryption is implemented however it is improperly configured or is not being properly updated, (e.g. expired and/or self-signed certificates, same certificate used on multiple devices, deprecated SSL versions)" - // - // Interpretation: The device/cloud may be misconfigured in such a way - // that TLS can be circumvented. - // - // Examples: - // * The TLS certificates are not "pinned". - // * Private keys are reused between device (and might have been leaked on the internet). - // * There might be vulnerabilities in the TLS implementation (e.g. OpenSSL Heartbleed). - // * - // * There is a lack of authentication, so the attacker can just - // connect to the TLS server themselves and extract the information - // without MitM. - // - // How to model this in coreLang: - // * TODO how to model unpinned cert? how to model indirection? how to model spoofing? Simply model as attacker stealing TLS credentials? Maybe combine with signed data somehow? - // * What about overwriting credentials on client-side? or maybe just model as attacker accessing API on client using identity? - - var app = new Application("app"); - var lan = new Network("lan"); - var internet = new Network("internet"); - var cloud = new Application("cloud"); - - var con_app_lan = autocon("con_app_lan", app, lan); - var con_lan_internet = autocon("con_lan_internet", lan, internet); // Note: NAT. - var con_internet_cloud = autocon("con_internet_cloud", internet, cloud); - - var routerNat = new RoutingFirewall("routerNat"); - con_lan_internet.addRoutingFirewalls(routerNat); - - var routerHardware = new org.mal_lang.corelang.test.System("routerHardware"); - containerAdd(routerHardware, routerNat); - - var tlsCredentials = new Credentials("tlsCredentials"); - - var tcp = new Data("tcp"); - var tls = new Data("tls"); - var tlsPayload = new Data("tlsPayload"); - - containerAdd(tcp, tls); - containerAdd(tls, tlsPayload); - tls.addEncryptCreds(tlsCredentials); - - transferData(app, tcp); - transferData(lan, tcp); - transferData(internet, tcp); - transferData(cloud, tcp); - - // Assume the tlsCredentials have been compromised somehow. - attack(internet.access, tlsCredentials.attemptAccess); - - compromised(1, tlsPayload.read); - } - -// @Test -// public void test_t044() { -// // T044 (device network service) Authentication - Username enumeration -// // "Ability to collect a set of valid usernames by interacting with the authentication mechanism" -// // -// // Interpretation: An network service on the device provides a way to -// // enumerate users. -// // -// // Examples: -// // * Different authentication failure error message are returned -// // depending on the cause of the failure. So instead of the -// // attacker having to guess both username and password, they can -// // first guess the correct username (with an empty password) and -// // then guess the password. This saves some time. -// // -// // How to model in corelang: -// // * TODO CoreLang does not really separate usernames from passwords. -// // Username and password form a single Credential. Potentially TTC -// // can be adjusted. -// // * TODO CoreLang also does not model non-credential prerequisites -// // in access/attacks. -// } -// @Test -// public void test_t045() { -// // T045 (device network service) Authentication - Weak credentials -// // "Ability to set account passwords to '1234' or '123456' for example. Usage of pre-programmed default (known) passwords (deffpass.com (Publicly available) - IoT device default password lookup). Easily guessable credentials. Brute-force by dictionaries and rules" -// // -// // * TODO CoreLang does not really distinguish between strong and weak -// // credentials. Maybe TTC can be adjusted differently for different -// // credentials? -// // * See also the defense Credentials.notDisclosed. -// } -// @Test -// public void test_t046() { -// // T046 (device network service) Authentication - Improper account lockout -// // "Ability to continue sending authentication attempts after 3 - 5 failed login attempts" -// // -// // Interpretation: There either is no account lockout mechanism, or -// // the mechanism can be easily bypassed. -// // -// // Examples: -// // * For example, the attacker can keep trying passwords after 3-5 -// // failed attempts. -// // -// // TODO CoreLang does not really seem to model bruteforce attacks. It -// // can sort be done via generic vulnerabilities (if the app also -// // stores the credentials such that the attacker can obtain them), but the ttc will be -// // incorrect. The account lockout mechanism would then be the absence -// // of that vulnerability. -// } - - @Test - public void test_t047() { - // T047 (device network service) Authentication - Weak password recovery - // "Insecure password reset/forgot mechanism could cause authentication bypass." - // - // Interpretation: The device has a mechanism to restore access if the - // user has forgotten their password. This mechanism may have various - // problems. - // - // How to model in coreLang: - // * TODO CoreLang does not really model passwords being "changed", - // only stolen. We can work around this by treating stealing and - // changing as the same thing. - // * TODO Alternatively, we can model this via two Identities. - // - - // We can weak model password reset as the credentials being world - // readable. - var net = new Network("net"); - var app = new Application("app"); - - var net_con_app = autocon("net_con_app", net, app); // open port - - var user = new Identity("user"); - var password = new Credentials("password"); - user.addCredentials(password); - - var sensitiveData = new Data("sensitiveData"); - containerAdd(app, sensitiveData); - mkReadApi(app, user, sensitiveData); - - - var recoverMechanism = new Application("recoverMechanism"); - containerAdd(app, recoverMechanism); - var net_con_recovery = autocon("net_con_recovery", net, recoverMechanism); // open port - - var recoveryApi = new Data("recoveryApi"); - - containerAdd(recoverMechanism, recoveryApi); - containerAdd(recoveryApi, password); - - var vuln = vulnerabilityBuilder("vuln").setNetwork().setConfidentiality().build(); - recoverMechanism.addVulnerabilities(vuln); - - attack(net.access); - - compromised(1, recoveryApi.read); - compromised(1, password.use); - compromised(1, user.assume); - compromised(1, app.specificAccessAuthenticate); - compromised(1, sensitiveData.read); - } - - @Test - public void test_t047_v2() { - var net = new Network("net"); - var app = new Application("app"); - - var net_con_app = autocon("net_con_app", net, app); // open port - - var user = new Identity("user"); - - var sensitiveData = new Data("sensitiveData"); - containerAdd(app, sensitiveData); - mkReadApi(app, user, sensitiveData); - - var recoveryUser = new Identity("recoveryUser"); - aOwnsB(recoveryUser, user); // recoveryUser can assume user - - var recoverMechanism = new Application("recoverMechanism"); - containerAdd(app, recoverMechanism); - appExecAs(recoverMechanism, recoveryUser); - - var net_con_recovery = autocon("net_con_recovery", net, recoverMechanism); // open port - - var vuln = vulnerabilityBuilder("vuln").setNetwork().setCIA().build(); - recoverMechanism.addVulnerabilities(vuln); - - attack(net.access); - - compromised(1, recoverMechanism.fullAccess); - compromised(1, recoveryUser.assume); - compromised(1, user.assume); - compromised(1, app.specificAccessAuthenticate); - compromised(1, sensitiveData.read); - } - - @Test - public void test_t048() { - // T048 (device network service) Privilege escalation - // "For example: Exposed services running as root" - // - // See also T027. - - - // App provides shell access to user A, but the app is running as - // user B. Therefore A can assume B through the app. - - var app = new Application("app"); - - var user = new Identity("user"); - var root = new Identity("root"); - - mkExecApi(app, user); // vulnerability - appExecAs(app, root); - - aOwnsB(root, user); // optional - - // Attacker escalates from user to root: - attack(user.assume, app.networkConnect); - - compromised(1, root.assume); - } - - @Test - public void test_T048_v2() { - // Child app attacks parent app via local Vulnerability. - - var parentApp = new Application("parentApp"); - var childApp = new Application("childApp"); - containerAdd(parentApp, childApp); - - var vuln = vulnerabilityBuilder("vuln").setLocal().setCIA().build(); - parentApp.addVulnerabilities(vuln); - - var root = new Identity("root"); - var user = new Identity("user"); // optional - aOwnsB(root, user); // optional - - appExecAs(parentApp, root); - appExecAs(childApp, user); - - var startSet = attack(childApp.localAccess); // sufficient to use vuln - - compromised(1, parentApp.localConnect); - compromised(1, parentApp.read); // because HXXExploit - compromised(1, parentApp.modify); // because XHXExploit - compromised(1, parentApp.deny); // because XXHExploit - compromised(1, parentApp.fullAccess); // because HHHExploit - compromised(1, root.assume); // because parent fullAccess - compromised(1, user.assume); // because root owns user - } - - @Test - public void test_T048_v3() { - // Child app gains access to parent app via exec API. - - var parentApp = new Application("parentApp"); - var childApp = new Application("childApp"); - containerAdd(parentApp, childApp); - - var root = new Identity("root"); - var user = new Identity("user"); // optional - aOwnsB(root, user); // optional - - mkExecApi(parentApp, user); // privilege escalation: anyone -> root - - appExecAs(parentApp, root); - appExecAs(childApp, user); - - var startSet = attack(childApp.localAccess); // sufficient to use vuln - - compromised(1, parentApp.localConnect); - compromised(1, parentApp.read); // because HXXExploit - compromised(1, parentApp.modify); // because XHXExploit - compromised(1, parentApp.deny); // because XXHExploit - compromised(1, parentApp.fullAccess); // because HHHExploit - compromised(1, root.assume); // because parent fullAccess - compromised(1, user.assume); // because root owns user - } - - @Test - public void test_T048_v4() { - // Low privilege user gains high privilege access via - // network vulnerability. - - var net = new Network("net"); - var app = new Application("ap"); - - var net_con_app = autocon("net_con_app", net, app); // open port - - - var admin = new Identity("admin"); - var user = new Identity("user"); - - appExecAs(app, admin); - - var userData = new Data("userData"); - mkReadWriteApi(app, user, userData); - - var adminData = new Data("adminData"); - mkReadWriteApi(app, admin, adminData); - - var vuln = vulnerabilityBuilder("vuln").setNetwork().setPrivLow().setCIA().build(); - app.addVulnerabilities(vuln); - - attack(net.access, user.assume); // sufficient to use vuln - - compromised(1, user.assume); // ok - compromised(1, admin.assume); // escalation - - compromised(1, userData.read); // ok - compromised(1, adminData.read); // escalation - } - - @Test - public void test_T048_v5() { - // Horizontal privilege escalation: access data of other users. - - - var server = new Application("server"); - - var apiA = new Application("apiA"); - var apiB = new Application("apiB"); - - containerAdd(server, apiA); - containerAdd(server, apiB); - - var net = new Network("net"); - var conA = autocon("conA", net, apiA); - var conB = autocon("conB", net, apiB); - - var userA = new Identity("userA"); - var userB = new Identity("userB"); - - var storage = new Data("storage"); - - var dataA = new Data("dataA"); - var dataB = new Data("dataB"); - - containerAdd(storage, dataA); - containerAdd(storage, dataB); // vulnerability - - mkReadApi(apiA, userA, storage); // vulnerability - mkReadApi(apiB, userB, storage); - - attack(net.access, userA.assume); - - compromised(1, dataA.read); - compromised(1, dataB.read); // horizontal privilege escalation. - } - - - - @Test - public void test_t050() { - // T050 (device network service) Denial of Service (DoS) - // "Service can be attacked in a way that denies service to that service or the entire device" - // - // Basically clog a network. - - var app = new Application("app"); - var net = new Network("net"); - - var net_con_app = autocon("net_con_app", app, net); - - attack(net.access); - - compromised(1, net.denialOfService); - compromised(1, app.deny); - } } diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java new file mode 100644 index 0000000..c6b59e1 --- /dev/null +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java @@ -0,0 +1,446 @@ +package org.mal_lang.corelang.test.patriot; + +import org.junit.jupiter.api.AfterEach; + +import org.mal_lang.corelang.test.*; +import core.*; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.HashSet; +import java.util.HashMap; + + +public class TestNetwork extends Base { + @Test + public void test_t041() { + // T041 (device network service) Sensitive data exposure + // "Any kind of senstive data that can be accessible." + // + // Intepretation: Sensitive data exposed on network ports. + // + // Examples: + // * MAC-addresses. + // * Unprotected APIs. + // + // See e.g. T003 and T028. + // + // How to model this in coreLang: + // 1. Network-assets may contain "transitData" (Data asset) which can + // be used to model sensitive data being available on the network. + // If the attacker has access to the network they can obtain the + // data through eavesdropping. Note that we consider reading the + // data to be impactful by itself. We do not model the attacker + // using the data for anything. + // 2. We can also model it using APIs (see test_T001_v2). + + + var app = new Application("app"); + + var net = new Network("net"); + + var net_con_app = autocon("net_con_app", net, app); + + var sensitiveData = new Data("sensitiveData"); + + // The app is broadcasting sensitiveData on the network: + //containerAdd(app, sensitiveData); + //transferData(app, sensitiveData); // Not needed, but in larger models this is how we would model the data being transfered around. + transferData(net, sensitiveData); + + attack(net.access); + + compromised(1, sensitiveData.read); + } + @Test + public void test_T041_v2() { + // We can model the sensitive data as being exposed by an API. + + var app = new Application("app"); + + var net = new Network("net"); + + var net_con_app = autocon("net_con_app", net, app); // open port + + var anyone = new Identity("anyone"); + + var sensitiveData = new Data("sensitiveData"); + + mkReadApi(app, anyone, sensitiveData); + + attack(net.access, anyone.assume); + + compromised(1, sensitiveData.read); + } + + + @Test + public void test_t043() { + // T043 (device network service) Insecure SSL/TLS issues + // "Encryption is implemented however it is improperly configured or is not being properly updated, (e.g. expired and/or self-signed certificates, same certificate used on multiple devices, deprecated SSL versions)" + // + // Interpretation: The device/cloud may be misconfigured in such a way + // that TLS can be circumvented. + // + // Examples: + // * The TLS certificates are not "pinned". + // * Private keys are reused between device (and might have been leaked on the internet). + // * There might be vulnerabilities in the TLS implementation (e.g. OpenSSL Heartbleed). + // * + // * There is a lack of authentication, so the attacker can just + // connect to the TLS server themselves and extract the information + // without MitM. + // + // How to model this in coreLang: + // * TODO how to model unpinned cert? how to model indirection? how to model spoofing? Simply model as attacker stealing TLS credentials? Maybe combine with signed data somehow? + // * What about overwriting credentials on client-side? or maybe just model as attacker accessing API on client using identity? + + var app = new Application("app"); + var lan = new Network("lan"); + var internet = new Network("internet"); + var cloud = new Application("cloud"); + + var con_app_lan = autocon("con_app_lan", app, lan); + var con_lan_internet = autocon("con_lan_internet", lan, internet); // Note: NAT. + var con_internet_cloud = autocon("con_internet_cloud", internet, cloud); + + var routerNat = new RoutingFirewall("routerNat"); + con_lan_internet.addRoutingFirewalls(routerNat); + + var routerHardware = new org.mal_lang.corelang.test.System("routerHardware"); + containerAdd(routerHardware, routerNat); + + var tlsCredentials = new Credentials("tlsCredentials"); + + var tcp = new Data("tcp"); + var tls = new Data("tls"); + var tlsPayload = new Data("tlsPayload"); + + containerAdd(tcp, tls); + containerAdd(tls, tlsPayload); + tls.addEncryptCreds(tlsCredentials); + + transferData(app, tcp); + transferData(lan, tcp); + transferData(internet, tcp); + transferData(cloud, tcp); + + // Assume the tlsCredentials have been compromised somehow. + attack(internet.access, tlsCredentials.attemptAccess); + + compromised(1, tlsPayload.read); + } + +// @Test +// public void test_t044() { +// // T044 (device network service) Authentication - Username enumeration +// // "Ability to collect a set of valid usernames by interacting with the authentication mechanism" +// // +// // Interpretation: An network service on the device provides a way to +// // enumerate users. +// // +// // Examples: +// // * Different authentication failure error message are returned +// // depending on the cause of the failure. So instead of the +// // attacker having to guess both username and password, they can +// // first guess the correct username (with an empty password) and +// // then guess the password. This saves some time. +// // +// // How to model in corelang: +// // * TODO CoreLang does not really separate usernames from passwords. +// // Username and password form a single Credential. Potentially TTC +// // can be adjusted. +// // * TODO CoreLang also does not model non-credential prerequisites +// // in access/attacks. +// } +// @Test +// public void test_t045() { +// // T045 (device network service) Authentication - Weak credentials +// // "Ability to set account passwords to '1234' or '123456' for example. Usage of pre-programmed default (known) passwords (deffpass.com (Publicly available) - IoT device default password lookup). Easily guessable credentials. Brute-force by dictionaries and rules" +// // +// // * TODO CoreLang does not really distinguish between strong and weak +// // credentials. Maybe TTC can be adjusted differently for different +// // credentials? +// // * See also the defense Credentials.notDisclosed. +// } +// @Test +// public void test_t046() { +// // T046 (device network service) Authentication - Improper account lockout +// // "Ability to continue sending authentication attempts after 3 - 5 failed login attempts" +// // +// // Interpretation: There either is no account lockout mechanism, or +// // the mechanism can be easily bypassed. +// // +// // Examples: +// // * For example, the attacker can keep trying passwords after 3-5 +// // failed attempts. +// // +// // TODO CoreLang does not really seem to model bruteforce attacks. It +// // can sort be done via generic vulnerabilities (if the app also +// // stores the credentials such that the attacker can obtain them), but the ttc will be +// // incorrect. The account lockout mechanism would then be the absence +// // of that vulnerability. +// } + + @Test + public void test_t047() { + // T047 (device network service) Authentication - Weak password recovery + // "Insecure password reset/forgot mechanism could cause authentication bypass." + // + // Interpretation: The device has a mechanism to restore access if the + // user has forgotten their password. This mechanism may have various + // problems. + // + // How to model in coreLang: + // * TODO CoreLang does not really model passwords being "changed", + // only stolen. We can work around this by treating stealing and + // changing as the same thing. + // * TODO Alternatively, we can model this via two Identities. + // + + // We can weak model password reset as the credentials being world + // readable. + var net = new Network("net"); + var app = new Application("app"); + + var net_con_app = autocon("net_con_app", net, app); // open port + + var user = new Identity("user"); + var password = new Credentials("password"); + user.addCredentials(password); + + var sensitiveData = new Data("sensitiveData"); + containerAdd(app, sensitiveData); + mkReadApi(app, user, sensitiveData); + + + var recoverMechanism = new Application("recoverMechanism"); + containerAdd(app, recoverMechanism); + var net_con_recovery = autocon("net_con_recovery", net, recoverMechanism); // open port + + var recoveryApi = new Data("recoveryApi"); + + containerAdd(recoverMechanism, recoveryApi); + containerAdd(recoveryApi, password); + + var vuln = vulnerabilityBuilder("vuln").setNetwork().setConfidentiality().build(); + recoverMechanism.addVulnerabilities(vuln); + + attack(net.access); + + compromised(1, recoveryApi.read); + compromised(1, password.use); + compromised(1, user.assume); + compromised(1, app.specificAccessAuthenticate); + compromised(1, sensitiveData.read); + } + + @Test + public void test_t047_v2() { + var net = new Network("net"); + var app = new Application("app"); + + var net_con_app = autocon("net_con_app", net, app); // open port + + var user = new Identity("user"); + + var sensitiveData = new Data("sensitiveData"); + containerAdd(app, sensitiveData); + mkReadApi(app, user, sensitiveData); + + var recoveryUser = new Identity("recoveryUser"); + aOwnsB(recoveryUser, user); // recoveryUser can assume user + + var recoverMechanism = new Application("recoverMechanism"); + containerAdd(app, recoverMechanism); + appExecAs(recoverMechanism, recoveryUser); + + var net_con_recovery = autocon("net_con_recovery", net, recoverMechanism); // open port + + var vuln = vulnerabilityBuilder("vuln").setNetwork().setCIA().build(); + recoverMechanism.addVulnerabilities(vuln); + + attack(net.access); + + compromised(1, recoverMechanism.fullAccess); + compromised(1, recoveryUser.assume); + compromised(1, user.assume); + compromised(1, app.specificAccessAuthenticate); + compromised(1, sensitiveData.read); + } + + @Test + public void test_t048() { + // T048 (device network service) Privilege escalation + // "For example: Exposed services running as root" + // + // See also T027. + + + // App provides shell access to user A, but the app is running as + // user B. Therefore A can assume B through the app. + + var app = new Application("app"); + + var user = new Identity("user"); + var root = new Identity("root"); + + mkExecApi(app, user); // vulnerability + appExecAs(app, root); + + aOwnsB(root, user); // optional + + // Attacker escalates from user to root: + attack(user.assume, app.networkConnect); + + compromised(1, root.assume); + } + + @Test + public void test_T048_v2() { + // Child app attacks parent app via local Vulnerability. + + var parentApp = new Application("parentApp"); + var childApp = new Application("childApp"); + containerAdd(parentApp, childApp); + + var vuln = vulnerabilityBuilder("vuln").setLocal().setCIA().build(); + parentApp.addVulnerabilities(vuln); + + var root = new Identity("root"); + var user = new Identity("user"); // optional + aOwnsB(root, user); // optional + + appExecAs(parentApp, root); + appExecAs(childApp, user); + + var startSet = attack(childApp.localAccess); // sufficient to use vuln + + compromised(1, parentApp.localConnect); + compromised(1, parentApp.read); // because HXXExploit + compromised(1, parentApp.modify); // because XHXExploit + compromised(1, parentApp.deny); // because XXHExploit + compromised(1, parentApp.fullAccess); // because HHHExploit + compromised(1, root.assume); // because parent fullAccess + compromised(1, user.assume); // because root owns user + } + + @Test + public void test_T048_v3() { + // Child app gains access to parent app via exec API. + + var parentApp = new Application("parentApp"); + var childApp = new Application("childApp"); + containerAdd(parentApp, childApp); + + var root = new Identity("root"); + var user = new Identity("user"); // optional + aOwnsB(root, user); // optional + + mkExecApi(parentApp, user); // privilege escalation: anyone -> root + + appExecAs(parentApp, root); + appExecAs(childApp, user); + + var startSet = attack(childApp.localAccess); // sufficient to use vuln + + compromised(1, parentApp.localConnect); + compromised(1, parentApp.read); // because HXXExploit + compromised(1, parentApp.modify); // because XHXExploit + compromised(1, parentApp.deny); // because XXHExploit + compromised(1, parentApp.fullAccess); // because HHHExploit + compromised(1, root.assume); // because parent fullAccess + compromised(1, user.assume); // because root owns user + } + + @Test + public void test_T048_v4() { + // Low privilege user gains high privilege access via + // network vulnerability. + + var net = new Network("net"); + var app = new Application("ap"); + + var net_con_app = autocon("net_con_app", net, app); // open port + + + var admin = new Identity("admin"); + var user = new Identity("user"); + + appExecAs(app, admin); + + var userData = new Data("userData"); + mkReadWriteApi(app, user, userData); + + var adminData = new Data("adminData"); + mkReadWriteApi(app, admin, adminData); + + var vuln = vulnerabilityBuilder("vuln").setNetwork().setPrivLow().setCIA().build(); + app.addVulnerabilities(vuln); + + attack(net.access, user.assume); // sufficient to use vuln + + compromised(1, user.assume); // ok + compromised(1, admin.assume); // escalation + + compromised(1, userData.read); // ok + compromised(1, adminData.read); // escalation + } + + @Test + public void test_T048_v5() { + // Horizontal privilege escalation: access data of other users. + + + var server = new Application("server"); + + var apiA = new Application("apiA"); + var apiB = new Application("apiB"); + + containerAdd(server, apiA); + containerAdd(server, apiB); + + var net = new Network("net"); + var conA = autocon("conA", net, apiA); + var conB = autocon("conB", net, apiB); + + var userA = new Identity("userA"); + var userB = new Identity("userB"); + + var storage = new Data("storage"); + + var dataA = new Data("dataA"); + var dataB = new Data("dataB"); + + containerAdd(storage, dataA); + containerAdd(storage, dataB); // vulnerability + + mkReadApi(apiA, userA, storage); // vulnerability + mkReadApi(apiB, userB, storage); + + attack(net.access, userA.assume); + + compromised(1, dataA.read); + compromised(1, dataB.read); // horizontal privilege escalation. + } + + + + @Test + public void test_t050() { + // T050 (device network service) Denial of Service (DoS) + // "Service can be attacked in a way that denies service to that service or the entire device" + // + // Basically clog a network. + + var app = new Application("app"); + var net = new Network("net"); + + var net_con_app = autocon("net_con_app", app, net); + + attack(net.access); + + compromised(1, net.denialOfService); + compromised(1, app.deny); + } +} diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java new file mode 100644 index 0000000..f8e739f --- /dev/null +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java @@ -0,0 +1,351 @@ +package org.mal_lang.corelang.test.patriot; + +import org.junit.jupiter.api.AfterEach; + +import org.mal_lang.corelang.test.*; +import core.*; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.HashSet; +import java.util.HashMap; + + +public class TestPhysical extends Base { + + @Test + public void test_t002() { + // T002 (physical) Firmware/storage extraction - Insecure external media interfaces + // "An attacker could copy the firmware/storage and even modify firmware if device allows to physically remove the storage media (SD Card, USB)." + // + // Interpretation: An IoT device may have easily accessible physical + // connectors, such as USB. The attacker can use these interfaces to + // gain access to the device. We also model removable storage media + // (e.g. SD-card) the same way. + // + // Examples: + // * The attacker may be able to read firmware. + // * The attacker may be able to read shared credentials (e.g. if the + // same symmetric encryption key is used for all users and + // devices). + // + // How to model this in coreLang: + // * PhysicalZone is used to model physical attacks on a system. + // * Physical interfaces can also be modeled as networks and + // ConnectionRules, see T004. + + var phy = new PhysicalZone("phy"); + var sys = new org.mal_lang.corelang.test.System("sys"); + var app = new Application("app"); + + containerAdd(phy, sys); + containerAdd(sys, app); + + var sysData = new Data("sysData"); + var appData = new Data("appData"); + + containerAdd(sys, sysData); + containerAdd(app, appData); + + // TODO currently physical exploits are not full implemented in + // coreLang 0.2.0. We will just model this as "anyone" having access. + + var anyone = new Identity("anyone"); + sys.addHighPrivSysIds(anyone); // vulnerability + + attack(phy.gainPhysicalAccess, anyone.assume); + + compromised(1, sysData.read); + compromised(1, appData.read); + } + + @Test + public void test_t003() { + // T003 (physical) Firmware/storage extraction - Download from the Web + // "An attacker could download the firmware from the manufacturer's website if access to the firmware image without authentication is possible." + // + // Interpretation: The firmware used for a particular model of IoT + // device may be publically available on the internet (e.g. can be + // downloaded from the manufacturer's website). The attacker can use + // the firmware to gain information about the device (e.g. reverse + // enginnering, sensitive information contained in the firmware and + // whitebox testing). + // + // Examples: + // * The firmware may contain sensitive information (such as + // credentials) that the attacker can extract. + // * The attacker can reverse engineer the firmware to find + // vulnerabilities faster (as opposed to black-box testing the + // device). + // + // How to model this in coreLang: + // * see test_T001. + // * see test_T001_v2. + + var internet = new Network("internet"); + + var firmwareBlob = new Data("firmwareBlob"); + var sensitiveData = new Data("sensitiveData"); + + transferData(internet, firmwareBlob); + containerAdd(firmwareBlob, sensitiveData); + + attack(internet.access); + + compromised(1, sensitiveData.read); + compromised(1, sensitiveData.write); + } + + @Test + public void test_T003_v2() { + var internet = new Network("internet"); + var cloud = new Application("cloud"); + + var con_internet_cloud = autocon("con_internet_cloud", internet, cloud); + + var firmwareBlob = new Data("firmwareBlob"); + var sensitiveData = new Data("sensitiveData"); + + containerAdd(cloud, firmwareBlob); + containerAdd(firmwareBlob, sensitiveData); + + var anyone = new Identity("anyone"); + mkReadApi(cloud, anyone, firmwareBlob); + + attack(internet.access, anyone.attemptAssume); + + + + compromised(1, cloud.specificAccessAuthenticate); + compromised(1, cloud.specificAccess); + + compromised(1, firmwareBlob.attemptAccessFromIdentity); + compromised(1, firmwareBlob.identityRead); + compromised(1, firmwareBlob.attemptRead); + compromised(1, firmwareBlob.read); + + compromised(1, sensitiveData.attemptRead); + compromised(1, sensitiveData.read); + + compromised(0, firmwareBlob.write); + compromised(0, sensitiveData.write); + } + + + @Test + public void test_t004() { + // T004 (physical) Firmware/storage extraction - Insecure SPI interface + // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the serial bus protocol SPI." + // + // Interpretation: An IoT device may have hidden physical connectors. + // The attacker can use these connectors to gain access to the device. + // + // Examples: + // * The attacker may be able to read firmware. + // * The attacker may be able to read shared credentials (e.g. if the + // same symmetric encryption key is used for all users and + // devices). + // * The attacker may desolder the flash component and use SPI to + // extract the contents. + // + // How to model this in coreLang: + // * See test_T002. Basically use PhysicalZone to attach System. TODO not done in coreLang 0.2.0? + // * You can also model SPI as a kind of Network. + + + // SPI as network: + + var spi = new Network("spi"); + var app = new Application("app"); + + var spi_con_app = autocon("spi_con_app", spi, app); + + var appData = new Data("appData"); + containerAdd(app, appData); + + var vuln = vulnerabilityBuilder("vuln").setNetwork().setConfidentiality().build(); + app.addVulnerabilities(vuln); + + var startSet = attack(spi.physicalAccess); + + compromised(1, vuln.abuse); + compromised(1, appData.read); + } + + @Test + public void test_T004_v2() { + // Like test_T004, but with explicit root shell. + + var os = new Application("os"); + var app = new Application("app"); + var shell = new Application("shell"); + + containerAdd(os, app); + containerAdd(os, shell); + + var spi = new Network("spi"); + + var spi_con_shell = autocon("spi_con_shell", spi, shell); + + var appData = new Data("appData"); + containerAdd(app, appData); + + var anyone = new Identity("anyone"); + var root = new Identity("root"); + + mkExecApi(shell, anyone); // privilege escalation: anyone -> root + + appExecAs(shell, root); + appExecAs(os, root); + appExecAs(app, root); + + // TODO CoreLang could have an association between PhysicalZone and Network. + attack(spi.physicalAccess, anyone.assume); + + compromised(1, shell.networkConnect); + compromised(1, shell.authenticate); + compromised(1, shell.fullAccess); + compromised(1, os.fullAccess); + compromised(1, app.fullAccess); + compromised(1, appData.read); + } + + @Test + public void test_T004_v3() { + // Attack bootloader. This is perhaps more common with TTL/UART than + // SPI. + + var bootloader = new Application("bootloader"); // e.g. uboot + var os = new Application("os"); + + containerAdd(bootloader, os); + + var spi = new Network("spi"); + + var spi_con_bootloader = autocon("spi_con_bootloader", spi, bootloader); + + var sensitiveData = new Data("sensitiveData"); + containerAdd(os, sensitiveData); + + var anyone = new Identity("anyone"); + + mkExecApi(bootloader, anyone); + + attack(spi.physicalAccess, anyone.assume); + + compromised(1, bootloader.fullAccess); + compromised(1, os.fullAccess); + compromised(1, sensitiveData.read); + } + + @Test + public void test_t009() { + // T009 (physical) Firmware/storage extraction - Insecure SoC + // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the other SoC (System on Chip) (e.g. Bluetooth)." + // + // Like T004, but we are attacking from another chip. Same idea here: use networks to model internal communication like SPI, etc. + + var chipA = new Application("chipA"); + var chipB = new Application("chipB"); // chipB could for example be a flash component or a chip that provides an API to a flash component. + + var i2c = new Network("i2c"); + var chipA_con_i2c = autocon("chipA_con_i2c", chipA, i2c); // chipA is a "master" + var i2c_con_chipB = autocon("i2c_con_chipB", i2c, chipB); // chipB is a "slave" + + var anyone = new Identity("anyone"); + + var sensitiveData = new Data("sensitiveData"); + mkReadApi(chipB, anyone, sensitiveData); + + attack(chipA.fullAccess, anyone.assume); + compromised(1, sensitiveData.read); + } + + @Test + public void test_t011() { + // T011 (physical) Backdoor firmware - Insecure UART interface + // "An attacker could modify the firmware if access to the flash/EEPROM chip is not restricted through the serial interface UART." + // + // Interpretation: An IoT device may have hidden physical connectors. + // The attacker may be able to use these connectors to install (and + // run) firmware on the device. + // + // Examples: + // * The attacker is able to upload, install and run firmware. + // + // How to model this in coreLang: + // * See T002 and T004 on modeling physical attacks. Additionally use + // SoftwareProduct to model the attacker overwriting existing + // software via Data. + + + var app = new Application("app"); + + var ttl = new Network("ttl"); + + var ttl_con_app = autocon("ttl_con_app", ttl, app); + + var firmwareBlob = new Data("firmwareBlob"); + containerAdd(app, firmwareBlob); + + var firmwareProduct = new SoftwareProduct("firmwareProduct"); + + execData(firmwareBlob, firmwareProduct, app); + + var anyone = new Identity("anyone"); + + mkWriteApi(app, anyone, firmwareBlob); + + attack(ttl.physicalAccess, anyone.assume); + + + compromised(1, firmwareBlob.write); // By writing to the firmwareblob... + compromised(1, app.fullAccess); // ... we can exec code. + } + + @Test + public void test_t015() { + // T015 (physical) Grant shell access - Insecure SPI interface + // "An attacker could grant a command shell if access to the flash/EEPROM chip is not restricted through the serial interface SPI." + // + // See also T004. + + var spi = new Network("spi"); + var flash = new Application("flash"); + var app = new Application("app"); + + var spi_con_app = autocon("spi_con_app", spi, app); + var spi_con_flash = autocon("spi_con_app", spi, flash); + + var filesystem = new Data("filesystem"); + var bootscript = new Data("bootscript"); + containerAdd(flash, filesystem); + containerAdd(filesystem, bootscript); + + var appProduct = new SoftwareProduct("appProduct"); + + execData(bootscript, appProduct, app); + + var anyone = new Identity("anyone"); + mkReadWriteApi(flash, anyone, filesystem); + + var startSet = attack(spi.physicalAccess, anyone.assume); + + compromised(1, filesystem.write); + compromised(1, bootscript.write); + compromised(1, app.fullAccess); + } + +// @Test +// public void test_t017() { +// // T017 (physical) Reset to insecure state +// // "An attacker could misuse reset functionality of the device if resetting results in insecure state." +// // +// // TODO coreLang does not really model state changes. We could +// // potentially model this as two separate models: one showing the +// // scenario leading up to the reset and one shoing the scenario +// // resulting from the reset. The reset can be modeled as the the +// // attacker doing Data.write to a specific Data asset representing the +// // reset API-function. See also T035 on rollback attacks. +// } +} From a6f60c94e39a3734284fb0c572bc47c5c8ca49df Mon Sep 17 00:00:00 2001 From: jesajx Date: Fri, 2 Jul 2021 13:24:07 +0200 Subject: [PATCH 08/10] Give tests overly descriptive names. --- .../corelang/test/patriot/TestFirmware.java | 86 +++++++++---------- .../corelang/test/patriot/TestNetwork.java | 46 +++++----- .../corelang/test/patriot/TestPhysical.java | 46 ++++++---- 3 files changed, 94 insertions(+), 84 deletions(-) diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java index 600e2ff..fb956d7 100644 --- a/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java @@ -11,10 +11,20 @@ import java.util.HashMap; +/** + * Note that most of these tests relate to process of reverse engineering -- + * which can be considered a form of information gathering. + * Since coreLang does not really model information gathering, we only focus on + * two types of data that can be found in a firmware blob: credentials, and + * "inherently" sensitive data. + * + * We also show examples of how the firmware update mechanism can be abused to + * install or otherwise gain access to a device. + */ public class TestFirmware extends Base { @Test - public void test_t019() { + public void hidden_backdoor_found_via_reverse_engineering() { // T019 (firmware) Sensitive data exposure - Backdoor accounts // "An attacker could discover (undocumented) backdoor account from non-volatile data by reverse engineering and source code analysis." // @@ -35,6 +45,9 @@ public void test_t019() { // * The attacker needs to Application.networkConnect and Credentials.attemptAccess. // Link the Application to the Credentials using an Identity. + // NOTE: we only show how the backdoor would be used here, not how it + // was discovered. + var app = new Application("app"); var net = new Network("net"); @@ -52,7 +65,7 @@ public void test_t019() { } @Test - public void test_T019_v2() { + public void shared_hardcoded_credentials() { // Gaining creds via physical attack on one device // and using to gain network-access to another device. @@ -91,7 +104,7 @@ public void test_T019_v2() { } @Test - public void test_t021_v1() { + public void sensitive_data_stored_unencrypted_in_filesystem() { // T021 (firmware) Sensitive data exposure - Other sensitive information // "An attacker could identify various sensitive data (e.g. URLs) from both storage and memory by reverse engineering and source code analysis. An attacker could gain sensitive data if device lacks of disk encryption." // @@ -121,7 +134,7 @@ public void test_t021_v1() { } @Test - public void test_T021_v1_defense() { + public void sensitive_data_stored_encrypted_filesystem() { // Like test_T021_v1, but we encrypt the data. var app = new Application("app"); @@ -141,7 +154,7 @@ public void test_T021_v1_defense() { compromised(0, sensitiveData.read); } @Test - public void test_T021_v2() { + public void hardware_encryption_circumvention_via_app() { // Hardware-based encryption (e.g. keystore on android) can sometimes be circumvented. var hardwareCredentials = new Credentials("hardwareCredentials"); // unobtainable in practice @@ -153,7 +166,7 @@ public void test_T021_v2() { containerAdd(keystore, key); - var os = new Application("app"); + var os = new Application("os"); var app = new Application("app"); containerAdd(os, app); @@ -200,7 +213,7 @@ public void test_T021_v2() { } @Test - public void test_T021_v3() { + public void hardware_encryption_circumvention_via_app_simplified() { // Like test_T021_v2, but simplified. var hardwareCredentials = new Credentials("hardwareCredentials"); // unobtainable in practice @@ -214,7 +227,7 @@ public void test_T021_v3() { containerAdd(keyring, key); - var os = new Application("app"); + var os = new Application("os"); var app = new Application("app"); containerAdd(os, app); @@ -247,7 +260,7 @@ public void test_T021_v3() { } @Test - public void test_t022() { + public void encryption_key_stored_in_filesystem() { // T022 (firmware) Sensitive data exposure - Static and same encryption keys // "An attacker could gain sensitive data of other devices if firmware uses static and same encryption keys." // @@ -285,7 +298,7 @@ public void test_t022() { compromised(1, sensitiveData.read); } @Test - public void test_T022_v2() { + public void shared_stored_credentials() { // Like test_T022, but we use the key on another device. var app = new Application("app"); @@ -318,7 +331,7 @@ public void test_T022_v2() { } @Test - public void test_T022_v3() { + public void shard_hardcoded_downloaded_key() { // Like test_T022_v1, but the key is hardcoded into the firmware // (which the attacker can download from the internet). @@ -347,12 +360,10 @@ public void test_T022_v3() { compromised(1, sensitiveData.read); } - - // @Test // public void test_t024() { // // T024 (firmware) Configuration - Lack of wiping device -// // "Lack of deprovisioning/decomissioning. Inability to wipe device's local data storage … " +// // "Lack of deprovisioning/decomissioning. Inability to wipe device's local data storage " // // // // Interpretation: Factory reset / deprovisioning functionality is missing or // // imperfect. @@ -365,8 +376,9 @@ public void test_T022_v3() { // // * Alternative, simply model it as sensitive data/credentials being stored on the device, see e.g. T021. // } + @Test - public void test_t027_v1() { + public void app_runs_as_root() { // T027 (firmware) Configuration - Insecure filesystem permissions // "Insecure default settings or insufficient ability to harden the system by modifying configurations are the root cause of many vulnerabilities." // @@ -400,7 +412,7 @@ public void test_t027_v1() { compromised(1, nonappData.read); } @Test - public void test_T027_v1_defense() { + public void app_runs_as_nobody() { // Like test_T027_v1, but we prevent the attack. var os = new Application("os"); @@ -433,7 +445,7 @@ public void test_T027_v1_defense() { } @Test - public void test_T027_v2() { + public void os_as_api_to_filesystem_and_app_has_too_much_access() { // appData as OS API var os = new Application("os"); @@ -468,7 +480,7 @@ public void test_T027_v2() { } @Test - public void test_T027_v2_defense() { + public void os_as_api_to_filesystem_and_app_has_restricted_access() { // Like test_T027_v2, but we prevent the attack. var os = new Application("os"); @@ -503,7 +515,7 @@ public void test_T027_v2_defense() { @Test - public void test_t028() { + public void broken_machine_to_machine_access_control() { // T028 (firmware) Authentication bypass - Device to device // "Disclosure or reusing of Sensitive data (session key, token, cookie, etc.) could cause authentication bypass." // @@ -544,7 +556,7 @@ public void test_t028() { } @Test - public void test_T028_v2() { + public void machine_to_machine_identity_theft() { // Attacker assumes the identity of device A after hacking device A // and uses that to access a API on device B. @@ -583,7 +595,7 @@ public void test_T028_v2() { } @Test - public void test_T028_v3() { + public void machine_to_machine_shared_credential_theft() { // Attacker steals credentials of device C (e.g. physical attack). // Device A uses the same credentials as device C. // The attacker uses the credentials from C to assume the identity of @@ -641,11 +653,7 @@ public void test_T028_v3() { } @Test - public void test_T028_v4() { - // TODO show server-to-client authentication. i.e. client opens the - // connection, but server is the one authenticating. Not possible in - // CoreLang? - + public void server_identity_theft_and_mitm() { // Reverse API: appA connects to appB, but appB is the one // authenticating to appA. @@ -689,7 +697,7 @@ public void test_T028_v4() { @Test - public void test_t031() { + public void generic_network_vulnerability() { // T031 (firmware) Update mechanism - Missing update mechanism // "Devices will eventually remain vulnerable as the device does not have the ability to update." // @@ -724,19 +732,9 @@ public void test_t031() { compromised(1, app.networkConnect); compromised(1, app.fullAccess); } + @Test - public void test_t032() { - // T032 (firmware) Update mechanism - Lack of manual update - // "Devices will remain vulnerable until an automatic update is triggered, during which time an attacker could compromise the device. (No ability to manually force an update check for the device)" - // - // Interpretation: There is no way for the user to manually update the - // device, so if the manufacturer sending updates, then newer - // vulnerabilities never get fixed. - // - // See also T031. - } - @Test - public void test_t033_v1() { + public void man_in_the_middle() { // T033 (firmware) Update mechanism - Lack of transport encryption // "An attacker could capture firmware via a transparent proxy if network traffic is unencrypted. (Updates are transmitted over the network without using TLS or encrypting the update file itself)" // @@ -773,7 +771,7 @@ public void test_t033_v1() { } @Test - public void test_T033_v1_defense() { + public void man_in_the_middle_encryption_defense() { // test_T033_v1, but we implement encryption to prevent the // vulnerability. @@ -809,7 +807,7 @@ public void test_T033_v1_defense() { } @Test - public void test_T033_v2() { + public void router_example() { // more complicated example var sys = new org.mal_lang.corelang.test.System("sys"); @@ -859,7 +857,7 @@ public void test_T033_v2() { } @Test - public void test_t034_v1() { + public void firmware_update_man_in_the_middle() { // T034 (firmware) Update mechanism - Lack of signature on update file // "An attacker could backdoor the firmware if firmware update file has insecure or lack of digital signature." // @@ -909,7 +907,7 @@ public void test_t034_v1() { } @Test - public void test_t034_v1_defense() { + public void firmware_update_with_signature_verification() { // LIke test_t034_v1, but we defend against the attack. var app = new Application("app"); @@ -948,7 +946,7 @@ public void test_t034_v1_defense() { } @Test - public void test_t039() { + public void firmware_install_api() { // T039 (firmware) Update mechanism - World writable update location // "An attacker could modify firmware if storage location for update files is world writable." // diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java index c6b59e1..cc3b724 100644 --- a/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java @@ -13,7 +13,7 @@ public class TestNetwork extends Base { @Test - public void test_t041() { + public void sensitive_data_on_network() { // T041 (device network service) Sensitive data exposure // "Any kind of senstive data that can be accessible." // @@ -53,7 +53,7 @@ public void test_t041() { compromised(1, sensitiveData.read); } @Test - public void test_T041_v2() { + public void sensitive_data_via_open_api() { // We can model the sensitive data as being exposed by an API. var app = new Application("app"); @@ -75,7 +75,7 @@ public void test_T041_v2() { @Test - public void test_t043() { + public void bypass_tls_by_stealing_credentials() { // T043 (device network service) Insecure SSL/TLS issues // "Encryption is implemented however it is improperly configured or is not being properly updated, (e.g. expired and/or self-signed certificates, same certificate used on multiple devices, deprecated SSL versions)" // @@ -183,7 +183,7 @@ public void test_t043() { // } @Test - public void test_t047() { + public void weak_password_recovery_as_open_api() { // T047 (device network service) Authentication - Weak password recovery // "Insecure password reset/forgot mechanism could cause authentication bypass." // @@ -236,7 +236,7 @@ public void test_t047() { } @Test - public void test_t047_v2() { + public void weak_password_recovery_as_vulnerability() { var net = new Network("net"); var app = new Application("app"); @@ -270,7 +270,7 @@ public void test_t047_v2() { } @Test - public void test_t048() { + public void privilege_escalation_confused_sheriff() { // T048 (device network service) Privilege escalation // "For example: Exposed services running as root" // @@ -297,7 +297,7 @@ public void test_t048() { } @Test - public void test_T048_v2() { + public void privilege_escalation_child_app_to_parent_app_via_vulnerability() { // Child app attacks parent app via local Vulnerability. var parentApp = new Application("parentApp"); @@ -314,19 +314,19 @@ public void test_T048_v2() { appExecAs(parentApp, root); appExecAs(childApp, user); - var startSet = attack(childApp.localAccess); // sufficient to use vuln + var startSet = attack(childApp.fullAccess); + compromised(1, user.assume); // because child full access compromised(1, parentApp.localConnect); - compromised(1, parentApp.read); // because HXXExploit - compromised(1, parentApp.modify); // because XHXExploit - compromised(1, parentApp.deny); // because XXHExploit - compromised(1, parentApp.fullAccess); // because HHHExploit + compromised(1, parentApp.read); + compromised(1, parentApp.deny); + compromised(1, parentApp.modify); // (always leads to fullAccess) + compromised(1, parentApp.fullAccess); compromised(1, root.assume); // because parent fullAccess - compromised(1, user.assume); // because root owns user } @Test - public void test_T048_v3() { + public void privilege_escalation_child_app_to_parent_app_via_api() { // Child app gains access to parent app via exec API. var parentApp = new Application("parentApp"); @@ -342,19 +342,19 @@ public void test_T048_v3() { appExecAs(parentApp, root); appExecAs(childApp, user); - var startSet = attack(childApp.localAccess); // sufficient to use vuln + var startSet = attack(childApp.fullAccess); + compromised(1, user.assume); compromised(1, parentApp.localConnect); - compromised(1, parentApp.read); // because HXXExploit - compromised(1, parentApp.modify); // because XHXExploit - compromised(1, parentApp.deny); // because XXHExploit - compromised(1, parentApp.fullAccess); // because HHHExploit + compromised(1, parentApp.read); + compromised(1, parentApp.modify); + compromised(1, parentApp.deny); + compromised(1, parentApp.fullAccess); compromised(1, root.assume); // because parent fullAccess - compromised(1, user.assume); // because root owns user } @Test - public void test_T048_v4() { + public void privilege_escalation_app_low_to_high_via_vulnerability() { // Low privilege user gains high privilege access via // network vulnerability. @@ -388,7 +388,7 @@ public void test_T048_v4() { } @Test - public void test_T048_v5() { + public void horizontal_privilege_escalation_user_to_user() { // Horizontal privilege escalation: access data of other users. @@ -427,7 +427,7 @@ public void test_T048_v5() { @Test - public void test_t050() { + public void network_dos() { // T050 (device network service) Denial of Service (DoS) // "Service can be attacked in a way that denies service to that service or the entire device" // diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java index f8e739f..057ca0a 100644 --- a/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java @@ -11,10 +11,22 @@ import java.util.HashMap; +/** + * Note that most of these tests relate to process of access firmware with the + * intent of performing reverse engineering. So it can usually be assumed that + * the attacker are "attacking" a device that they themselves own (and would + * then use the information gained to exploit other devices on the internet). + * + * As such there is a lot of focus on modeling the access method itself. Since + * coreLang does not really model information gathering, these tests may or + * may not be of interest. (Except perhaps to help companies protect their + * intellectual property via hardware defenses?). + * + */ public class TestPhysical extends Base { @Test - public void test_t002() { + public void hardware_vulnerability() { // T002 (physical) Firmware/storage extraction - Insecure external media interfaces // "An attacker could copy the firmware/storage and even modify firmware if device allows to physically remove the storage media (SD Card, USB)." // @@ -48,10 +60,11 @@ public void test_t002() { containerAdd(app, appData); // TODO currently physical exploits are not full implemented in - // coreLang 0.2.0. We will just model this as "anyone" having access. - + // coreLang 0.2.0. For now we will just model this as "anyone" having access. + // In coreLang 0.1.0 this was modeled as a UnknownVulnerability in the + // system itself. var anyone = new Identity("anyone"); - sys.addHighPrivSysIds(anyone); // vulnerability + sys.addHighPrivSysIds(anyone); attack(phy.gainPhysicalAccess, anyone.assume); @@ -60,9 +73,8 @@ public void test_t002() { } @Test - public void test_t003() { + public void firmware_is_available_on_the_internet() { // T003 (physical) Firmware/storage extraction - Download from the Web - // "An attacker could download the firmware from the manufacturer's website if access to the firmware image without authentication is possible." // // Interpretation: The firmware used for a particular model of IoT // device may be publically available on the internet (e.g. can be @@ -97,7 +109,7 @@ public void test_t003() { } @Test - public void test_T003_v2() { + public void firmware_is_available_via_cloud_api() { var internet = new Network("internet"); var cloud = new Application("cloud"); @@ -133,7 +145,7 @@ public void test_T003_v2() { @Test - public void test_t004() { + public void hardware_interfaces_as_networks_example1() { // T004 (physical) Firmware/storage extraction - Insecure SPI interface // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the serial bus protocol SPI." // @@ -173,8 +185,8 @@ public void test_t004() { } @Test - public void test_T004_v2() { - // Like test_T004, but with explicit root shell. + public void root_shell_via_hardware_interface() { + // Like test_T004, but shows something that looks more like linux. var os = new Application("os"); var app = new Application("app"); @@ -183,9 +195,9 @@ public void test_T004_v2() { containerAdd(os, app); containerAdd(os, shell); - var spi = new Network("spi"); + var ttl = new Network("ttl"); - var spi_con_shell = autocon("spi_con_shell", spi, shell); + var ttl_con_shell = autocon("ttl_con_shell", ttl, shell); var appData = new Data("appData"); containerAdd(app, appData); @@ -200,7 +212,7 @@ public void test_T004_v2() { appExecAs(app, root); // TODO CoreLang could have an association between PhysicalZone and Network. - attack(spi.physicalAccess, anyone.assume); + attack(ttl.physicalAccess, anyone.assume); compromised(1, shell.networkConnect); compromised(1, shell.authenticate); @@ -211,7 +223,7 @@ public void test_T004_v2() { } @Test - public void test_T004_v3() { + public void bootloader_shell_via_hardware_interface() { // Attack bootloader. This is perhaps more common with TTL/UART than // SPI. @@ -239,7 +251,7 @@ public void test_T004_v3() { } @Test - public void test_t009() { + public void read_flash_from_adjacant_microprocessor() { // T009 (physical) Firmware/storage extraction - Insecure SoC // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the other SoC (System on Chip) (e.g. Bluetooth)." // @@ -262,7 +274,7 @@ public void test_t009() { } @Test - public void test_t011() { + public void install_firmware_via_hardware_interface() { // T011 (physical) Backdoor firmware - Insecure UART interface // "An attacker could modify the firmware if access to the flash/EEPROM chip is not restricted through the serial interface UART." // @@ -304,7 +316,7 @@ public void test_t011() { } @Test - public void test_t015() { + public void root_shell_via_spi_flash_filesystem_access() { // T015 (physical) Grant shell access - Insecure SPI interface // "An attacker could grant a command shell if access to the flash/EEPROM chip is not restricted through the serial interface SPI." // From d5efb840a85d546d50e4a2126720f51fe29e5e34 Mon Sep 17 00:00:00 2001 From: jesajx Date: Fri, 2 Jul 2021 13:45:29 +0200 Subject: [PATCH 09/10] clean up a bit --- .../corelang/test/patriot/TestFirmware.java | 42 ++++++++----------- .../corelang/test/patriot/TestNetwork.java | 42 ++++++++++++++++--- .../corelang/test/patriot/TestPhysical.java | 23 ++-------- 3 files changed, 59 insertions(+), 48 deletions(-) diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java index fb956d7..e0f8451 100644 --- a/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java @@ -35,8 +35,6 @@ public void hidden_backdoor_found_via_reverse_engineering() { // backdoor credentials by for example reverse engineering the // firmware. // - // See also T004. - // // Example: // * The attacker can find the credentials on the internet. // * The attacker can find the credentials inside a firmwareblob from the internet. @@ -114,10 +112,6 @@ public void sensitive_data_stored_unencrypted_in_filesystem() { // // Examples: // * The device stores sensitive data in plain text in flash. - // - // How to model in coreLang: - // * Use Application.containedData - // * See also test_T003. var app = new Application("app"); @@ -135,7 +129,7 @@ public void sensitive_data_stored_unencrypted_in_filesystem() { @Test public void sensitive_data_stored_encrypted_filesystem() { - // Like test_T021_v1, but we encrypt the data. + // Like sensitive_data_stored_unencrypted_in_filesystem(), but we encrypt the data. var app = new Application("app"); @@ -214,7 +208,7 @@ public void hardware_encryption_circumvention_via_app() { @Test public void hardware_encryption_circumvention_via_app_simplified() { - // Like test_T021_v2, but simplified. + // Like hardware_encryption_circumvention_via_app(), but simplified. var hardwareCredentials = new Credentials("hardwareCredentials"); // unobtainable in practice @@ -240,9 +234,9 @@ public void hardware_encryption_circumvention_via_app_simplified() { mkReadApi(os, appId, filesystem); - // While the attacker is not able to access the key directly (see - // test_T021_v2), we can still model it as if they could since they - // can use the key to decrypt data. + // While the attacker is not able to access the key directly + // (hardware_encryption_circumvention_via_app), we can still model it + // as if they could since they can use the key to decrypt data. mkReadApi(os, appId, keyring); var externalData = new Data("externalData"); @@ -297,9 +291,10 @@ public void encryption_key_stored_in_filesystem() { compromised(1, encKey.use); compromised(1, sensitiveData.read); } + @Test public void shared_stored_credentials() { - // Like test_T022, but we use the key on another device. + // Like encryption_key_stored_in_filesystem(), but we use the key on another device. var app = new Application("app"); var flash = new Data("flash"); @@ -331,8 +326,8 @@ public void shared_stored_credentials() { } @Test - public void shard_hardcoded_downloaded_key() { - // Like test_T022_v1, but the key is hardcoded into the firmware + public void shared_hardcoded_downloaded_key() { + // Like shared_stored_credentials(), but the key is hardcoded into the firmware // (which the attacker can download from the internet). var app = new Application("app"); @@ -369,11 +364,11 @@ public void shard_hardcoded_downloaded_key() { // // imperfect. // // // // Example: -// // * Old data is left from previous owner (cloud credentials, wifi passwords, etc.). See also T021. +// // * Old data is left from previous owner (cloud credentials, wifi passwords, etc.). // // // // How to model in coreLang: -// // * TODO Corelang does not really model state, see T017 and T040. -// // * Alternative, simply model it as sensitive data/credentials being stored on the device, see e.g. T021. +// // * TODO Corelang does not really model state. +// // * Alternative, simply model it as sensitive data/credentials being stored on the device. // } @@ -382,8 +377,7 @@ public void app_runs_as_root() { // T027 (firmware) Configuration - Insecure filesystem permissions // "Insecure default settings or insufficient ability to harden the system by modifying configurations are the root cause of many vulnerabilities." // - // Intepretation: Like T044, but specifically about how the filesystem - // is set up. + // Intepretation: Broken access control on the filesystem. // // Examples: // * Network-connected apps are running as root. @@ -413,7 +407,7 @@ public void app_runs_as_root() { } @Test public void app_runs_as_nobody() { - // Like test_T027_v1, but we prevent the attack. + // Like app_runs_as_root(), but we prevent the attack. var os = new Application("os"); var app = new Application("app"); @@ -481,7 +475,7 @@ public void os_as_api_to_filesystem_and_app_has_too_much_access() { @Test public void os_as_api_to_filesystem_and_app_has_restricted_access() { - // Like test_T027_v2, but we prevent the attack. + // Like os_as_api_to_filesystem_and_app_has_too_much_access(), but we prevent the attack. var os = new Application("os"); var app = new Application("app"); @@ -527,7 +521,7 @@ public void broken_machine_to_machine_access_control() { // // How to model in coreLang: // * Just as an API being accessible to the "anyone" Identity. - // * Assume the identity of deviceA. See e.g. T021 on stealing credentials from firmware or local storage. + // * Assume the identity of deviceA. // Just an API accessible to anyone: @@ -950,7 +944,7 @@ public void firmware_install_api() { // T039 (firmware) Update mechanism - World writable update location // "An attacker could modify firmware if storage location for update files is world writable." // - // * We can model this as a write-API on the device. See also test_T011 and test_T038. + // We can model this as a write-API on the device. var app = new Application("app"); var net = new Network("net"); @@ -984,6 +978,6 @@ public void firmware_install_api() { // // TODO CoreLang does not really model multiple versions of the same application. // // A workaround is to create two models: one model showing the // // scenario leading up to the rollback and another model showing the -// // situation after the rollback. See also T004. +// // situation after the rollback. // } } diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java index cc3b724..6f9014a 100644 --- a/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java @@ -11,7 +11,43 @@ import java.util.HashMap; +/** + * Note that I in many cases use data to model "APIs" here. + * This provides more granularity than SoftwareVulnerability. + * + */ public class TestNetwork extends Base { + + @Test + public void api() { + var app = new Application("app"); + var net = new Network("net"); + + var net_con_app = autocon("net_con_app", net, app); + + + var readApi = new Data("readApi"); + var writeApi = new Data("writeApi"); + var readWriteApi = new Data("readWriteApi"); + + var id = new Identity("id"); + + mkReadApi(app, id, readApi); + mkWriteApi(app, id, writeApi); + mkReadWriteApi(app, id, readWriteApi); + + attack(net.access, id.assume); + + compromised(1, readApi.read); + compromised(0, readApi.write); + + compromised(0, writeApi.read); + compromised(1, writeApi.write); + + compromised(1, readWriteApi.read); + compromised(1, readWriteApi.write); + } + @Test public void sensitive_data_on_network() { // T041 (device network service) Sensitive data exposure @@ -23,8 +59,6 @@ public void sensitive_data_on_network() { // * MAC-addresses. // * Unprotected APIs. // - // See e.g. T003 and T028. - // // How to model this in coreLang: // 1. Network-assets may contain "transitData" (Data asset) which can // be used to model sensitive data being available on the network. @@ -32,7 +66,7 @@ public void sensitive_data_on_network() { // data through eavesdropping. Note that we consider reading the // data to be impactful by itself. We do not model the attacker // using the data for anything. - // 2. We can also model it using APIs (see test_T001_v2). + // 2. We can also model it using APIs. var app = new Application("app"); @@ -273,8 +307,6 @@ public void weak_password_recovery_as_vulnerability() { public void privilege_escalation_confused_sheriff() { // T048 (device network service) Privilege escalation // "For example: Exposed services running as root" - // - // See also T027. // App provides shell access to user A, but the app is running as diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java index 057ca0a..2f92cc6 100644 --- a/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java @@ -44,7 +44,7 @@ public void hardware_vulnerability() { // How to model this in coreLang: // * PhysicalZone is used to model physical attacks on a system. // * Physical interfaces can also be modeled as networks and - // ConnectionRules, see T004. + // ConnectionRules. var phy = new PhysicalZone("phy"); var sys = new org.mal_lang.corelang.test.System("sys"); @@ -89,10 +89,6 @@ public void firmware_is_available_on_the_internet() { // * The attacker can reverse engineer the firmware to find // vulnerabilities faster (as opposed to black-box testing the // device). - // - // How to model this in coreLang: - // * see test_T001. - // * see test_T001_v2. var internet = new Network("internet"); @@ -159,10 +155,6 @@ public void hardware_interfaces_as_networks_example1() { // devices). // * The attacker may desolder the flash component and use SPI to // extract the contents. - // - // How to model this in coreLang: - // * See test_T002. Basically use PhysicalZone to attach System. TODO not done in coreLang 0.2.0? - // * You can also model SPI as a kind of Network. // SPI as network: @@ -186,7 +178,7 @@ public void hardware_interfaces_as_networks_example1() { @Test public void root_shell_via_hardware_interface() { - // Like test_T004, but shows something that looks more like linux. + // Like hardware_interfaces_as_networks_example1(), but shows something that looks more like linux. var os = new Application("os"); var app = new Application("app"); @@ -255,7 +247,7 @@ public void read_flash_from_adjacant_microprocessor() { // T009 (physical) Firmware/storage extraction - Insecure SoC // "An attacker could dump the firmware if access to the flash/EEPROM chip is not restricted through the other SoC (System on Chip) (e.g. Bluetooth)." // - // Like T004, but we are attacking from another chip. Same idea here: use networks to model internal communication like SPI, etc. + // Like hardware_interfaces_as_networks_example1(), but we are attacking from another chip. Same idea here: use networks to model internal communication like SPI, etc. var chipA = new Application("chipA"); var chipB = new Application("chipB"); // chipB could for example be a flash component or a chip that provides an API to a flash component. @@ -284,11 +276,6 @@ public void install_firmware_via_hardware_interface() { // // Examples: // * The attacker is able to upload, install and run firmware. - // - // How to model this in coreLang: - // * See T002 and T004 on modeling physical attacks. Additionally use - // SoftwareProduct to model the attacker overwriting existing - // software via Data. var app = new Application("app"); @@ -319,8 +306,6 @@ public void install_firmware_via_hardware_interface() { public void root_shell_via_spi_flash_filesystem_access() { // T015 (physical) Grant shell access - Insecure SPI interface // "An attacker could grant a command shell if access to the flash/EEPROM chip is not restricted through the serial interface SPI." - // - // See also T004. var spi = new Network("spi"); var flash = new Application("flash"); @@ -358,6 +343,6 @@ public void root_shell_via_spi_flash_filesystem_access() { // // scenario leading up to the reset and one shoing the scenario // // resulting from the reset. The reset can be modeled as the the // // attacker doing Data.write to a specific Data asset representing the -// // reset API-function. See also T035 on rollback attacks. +// // reset API-function. See also rollback attacks. // } } From 3d63f649a0e99721c79644b6db86776d304e80cc Mon Sep 17 00:00:00 2001 From: jesajx Date: Mon, 5 Jul 2021 14:12:45 +0200 Subject: [PATCH 10/10] inline patriot Base class - prepare for con(x,y) inlining - inline con(x,y) - inline con(x,y,z) - inline conbi(x,y,z) - inline transferData(x,y) - remove final commented out tests - inline execCode(x,y,z) - inline aOwnsB(x,y) - prepare inline of API helpers - inline mkReadWriteApi(x,y,z) - inline mkExecApi(x,y) - inline mkReadApi(x,y,z) - inline mkWriteApi(x,y,z) - fix indent - remove debug code remainder - move functionality out of attack(...) - make attack(attacker, ...) take one attack step - inline attack(x,y) - inline compromised(x,y) - inline appExecAs - inline class VulnerabilityBuilder - remove autoconbi(x,y,z) - move functionality out of autocon - rename autocon overloads - inline autocon1 - inline autocon2 - inline autocon - inline containerAdd(x,y) - inline class Base - fix indentation - remove spurious spaces --- .../mal_lang/corelang/test/patriot/Base.java | 306 -------- .../corelang/test/patriot/TestFirmware.java | 706 ++++++++++-------- .../corelang/test/patriot/TestNetwork.java | 396 +++++----- .../corelang/test/patriot/TestPhysical.java | 237 +++--- 4 files changed, 770 insertions(+), 875 deletions(-) delete mode 100644 src/test/java/org/mal_lang/corelang/test/patriot/Base.java diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/Base.java b/src/test/java/org/mal_lang/corelang/test/patriot/Base.java deleted file mode 100644 index 05e3d93..0000000 --- a/src/test/java/org/mal_lang/corelang/test/patriot/Base.java +++ /dev/null @@ -1,306 +0,0 @@ -package org.mal_lang.corelang.test.patriot; - -import org.junit.jupiter.api.AfterEach; - -import org.mal_lang.corelang.test.*; -import core.*; -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.fail; - -import java.util.HashSet; -import java.util.HashMap; - - -public class Base extends CoreLangTest { - - public void con(Application src, ConnectionRule dst) { - // app is client-like (outgoing) - src.addOutgoingAppConnections(dst); - } - public void con(ConnectionRule src, Application dst) { - // app is server-like (incoming) - dst.addIngoingAppConnections(src); - } - - public void con(Network src, ConnectionRule dst) { - // net is client-like (outgoing) - src.addOutgoingNetConnections(dst); - } - public void con(ConnectionRule src, Network dst) { - // net is server-like (incoming) - dst.addIngoingNetConnections(src); - } - - public void con(Application src, ConnectionRule conrule, Network dst) { - con(src, conrule); - con(conrule, dst); - } - public void con(Network src, ConnectionRule conrule, Application dst) { - con(src, conrule); - con(conrule, dst); - } - - public void con(Network src, ConnectionRule conrule, Network dst) { - con(src, conrule); - con(conrule, dst); - } - - public void conbi(Application src, ConnectionRule conrule, Network dst) { - con(src, conrule, dst); - con(dst, conrule, src); - } - public void conbi(Network src, ConnectionRule conrule, Application dst) { - con(src, conrule, dst); - con(dst, conrule, src); - } - - public void conbi(Network src, ConnectionRule conrule, Network dst) { - con(src, conrule, dst); - con(dst, conrule, src); - } - - public void transferData(Network medium, Data data) { - data.addTransitNetwork(medium); - } - public void transferData(Application medium, Data data) { - data.addTransitApp(medium); - } - - public void execData(Data code, SoftwareProduct product, Application app) { - product.addOriginData(code); - product.addSoftApplications(app); - } - - public void aOwnsB(Identity a, Identity b) { - a.addParentId(b); - } - - public void containerAdd(PhysicalZone container, org.mal_lang.corelang.test.System inside) { - container.addSystems(inside); - } - - public void containerAdd(org.mal_lang.corelang.test.System container, Application inside) { - container.addSysExecutedApps(inside); - } - - public void containerAdd(org.mal_lang.corelang.test.System container, Data inside) { - container.addSysData(inside); - } - - public void containerAdd(Application container, Application inside) { - container.addAppExecutedApps(inside); - } - - public void containerAdd(Application container, Data inside) { - container.addContainedData(inside); - } - - public void containerAdd(Data container, Data inside) { - container.addContainedData(inside); - } - - public void containerAdd(Data container, Information inside) { - container.addInformation(inside); - } - - public void addApiData(Application app, Data data) { - containerAdd(app, data); - } - - public void addApiUser(Application app, Identity id) { - id.addLowPrivApps(app); - } - - public void addApiReadAccess(Identity id, Data data) { - id.addReadPrivData(data); - } - - public void addApiWriteAccess(Identity id, Data data) { - id.addWritePrivData(data); - } - - public void mkReadApi(Application app, Identity id, Data data) { - addApiUser(app, id); - addApiData(app, data); - addApiReadAccess(id, data); - } - - public void mkWriteApi(Application app, Identity id, Data data) { - addApiUser(app, id); - addApiData(app, data); - addApiWriteAccess(id, data); - } - - public void mkReadWriteApi(Application app, Identity id, Data data) { - mkReadApi(app, id, data); - mkWriteApi(app, id, data); - } - - public void addApiExecUser(Application app, Identity id) { - id.addHighPrivApps(app); - } - public void mkExecApi(Application app, Identity id) { - addApiExecUser(app, id); - } - - - public HashSet attack(AttackStep... entryPoints) { - var startSet = new HashSet(); - var attacker = new Attacker(); - for (var step : entryPoints) { - if (step == null) { - throw new NullPointerException(); - } - if (!AttackStep.allAttackSteps.contains(step)) { - throw new RuntimeException("missing step " + step); - } - - startSet.add(step); - attacker.addAttackPoint(step); - } - attacker.attack(); - return startSet; // for convenience - } - - public void compromised(int zeroIfUncompromised, AttackStep step) { - boolean isCompromised = (zeroIfUncompromised != 0); - compromised(isCompromised, step); - } - - public void compromised(boolean isCompromised, AttackStep step) { - if (isCompromised) { - assertReached(step); - } else { - assertNotReached(step); - } - } - - public ConnectionRule autocon(String name, Application src, Network dst) { - var connectionRule = new ConnectionRule(name); - con(src, connectionRule, dst); - return connectionRule; - } - public ConnectionRule autocon(String name, Network src, Application dst) { - var connectionRule = new ConnectionRule(name); - con(src, connectionRule, dst); - return connectionRule; - } - - public ConnectionRule autocon(String name, Network src, Network dst) { - var connectionRule = new ConnectionRule(name); - con(src, connectionRule); - con(connectionRule, dst); - return connectionRule; - } - - public ConnectionRule autoconbi(String name, Application src, Network dst) { - var connectionRule = new ConnectionRule(name); - conbi(src, connectionRule, dst); - return connectionRule; - } - - public ConnectionRule autoconbi(String name, Network src, Application dst) { - var connectionRule = new ConnectionRule(name); - conbi(src, connectionRule, dst); - return connectionRule; - } - - public ConnectionRule autoconbi(String name, Network src, Network dst) { - var connectionRule = new ConnectionRule(name); - conbi(src, connectionRule, dst); - return connectionRule; - } - - public void appExecAs(Application app, Identity id) { - id.addExecPrivApps(app); - } - - public static class VulnerabilityBuilder { - String name = ""; - boolean network = false; - boolean local = false; - boolean physical = false; - boolean priv_low = false; - boolean priv_high = false; - boolean user_interact = false; - boolean confidentiality = false; - boolean availability = false; - boolean integrity = false; - boolean complex = false; - - public VulnerabilityBuilder(String name) { - this.name = name; - } - - public VulnerabilityBuilder setNetwork() { - this.network = true; - return this; - } - public VulnerabilityBuilder setLocal() { - this.local = true; - return this; - } - public VulnerabilityBuilder setPhysical() { - this.physical = true; - return this; - } - - public VulnerabilityBuilder setPrivLow() { - this.priv_low = true; - return this; - } - public VulnerabilityBuilder setPrivHigh() { - this.priv_high = true; - return this; - } - - public VulnerabilityBuilder setUserInteract() { - this.user_interact = true; - return this; - } - public VulnerabilityBuilder setComplex() { - this.complex = true; - return this; - } - - public VulnerabilityBuilder setCIA() { - this.confidentiality = true; - this.availability = true; - this.integrity = true; - return this; - } - - public VulnerabilityBuilder setConfidentiality() { - this.confidentiality = true; - return this; - } - public VulnerabilityBuilder setAvailability() { - this.availability = true; - return this; - } - public VulnerabilityBuilder setIntegrity() { - this.integrity = true; - return this; - } - - - public SoftwareVulnerability build() { - var res = new SoftwareVulnerability(name); - res.networkAccessRequired.defaultValue = network; - res.localAccessRequired.defaultValue = local; - res.physicalAccessRequired.defaultValue = physical; - res.lowPrivilegesRequired.defaultValue = priv_low; - res.highPrivilegesRequired.defaultValue = priv_high; - res.userInteractionRequired.defaultValue = user_interact; - res.confidentialityImpactLimitations.defaultValue = !confidentiality; - res.availabilityImpactLimitations.defaultValue = !availability; - res.integrityImpactLimitations.defaultValue = !integrity; - res.highComplexityExploitRequired.defaultValue = complex; - return res; - } - } - - public static VulnerabilityBuilder vulnerabilityBuilder(String name) { - return new VulnerabilityBuilder(name); - } -} diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java index e0f8451..f707495 100644 --- a/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestFirmware.java @@ -21,7 +21,7 @@ * We also show examples of how the firmware update mechanism can be abused to * install or otherwise gain access to a device. */ -public class TestFirmware extends Base { +public class TestFirmware extends CoreLangTest { @Test public void hidden_backdoor_found_via_reverse_engineering() { @@ -50,16 +50,21 @@ public void hidden_backdoor_found_via_reverse_engineering() { var net = new Network("net"); - var net_con_app = autocon("con_app_net", net, app); + var net_con_app = new ConnectionRule("con_app_net"); + net.addOutgoingNetConnections(net_con_app); + app.addIngoingAppConnections(net_con_app); var identity = new Identity("identity"); var credentials = new Credentials("credentials"); identity.addCredentials(credentials); app.addExecutionPrivIds(identity); - attack(net.access, credentials.attemptAccess); // assume attacker already has credentials (e.g. from internet) + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.addAttackPoint(credentials.attemptAccess); + attacker.attack(); // assume attacker already has credentials (e.g. from internet) - compromised(1, app.fullAccess); + assertReached(app.fullAccess); } @Test @@ -75,7 +80,9 @@ public void shared_hardcoded_credentials() { - var net_con_app = autocon("con_app_net", net, app); + var net_con_app = new ConnectionRule("con_app_net"); + net.addOutgoingNetConnections(net_con_app); + app.addIngoingAppConnections(net_con_app); var identity = new Identity("identity"); var credentials = new Credentials("credentials"); @@ -85,20 +92,23 @@ public void shared_hardcoded_credentials() { var credStore = new Data("credStore"); var credStoreRE = new Data("credStoreRE"); - containerAdd(app, credStore); // optional - containerAdd(credStore, credentials); // optional + app.addContainedData(credStore); // optional + credStore.addInformation(credentials); // optional - containerAdd(appRE, credStoreRE); - containerAdd(credStoreRE, credentials); + appRE.addContainedData(credStoreRE); + credStoreRE.addInformation(credentials); - attack(net.access, appRE.fullAccess); // assume attacker already hacked inside appRE + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.addAttackPoint(appRE.fullAccess); + attacker.attack(); // assume attacker already hacked inside appRE - compromised(1, appRE.fullAccess); - compromised(1, credStoreRE.read); - compromised(1, credentials.use); - compromised(1, app.networkConnect); - compromised(1, app.authenticate); - compromised(1, app.fullAccess); + assertReached(appRE.fullAccess); + assertReached(credStoreRE.read); + assertReached(credentials.use); + assertReached(app.networkConnect); + assertReached(app.authenticate); + assertReached(app.fullAccess); } @Test @@ -118,13 +128,15 @@ public void sensitive_data_stored_unencrypted_in_filesystem() { var flash = new Data("flash"); var sensitiveData = new Data("sensitiveData"); - containerAdd(app, flash); - containerAdd(flash, sensitiveData); + app.addContainedData(flash); + flash.addContainedData(sensitiveData); - attack(app.read); + var attacker = new Attacker(); + attacker.addAttackPoint(app.read); + attacker.attack(); - compromised(1, flash.read); - compromised(1, sensitiveData.read); + assertReached(flash.read); + assertReached(sensitiveData.read); } @Test @@ -136,16 +148,18 @@ public void sensitive_data_stored_encrypted_filesystem() { var flash = new Data("flash"); var sensitiveData = new Data("sensitiveData"); - containerAdd(app, flash); - containerAdd(flash, sensitiveData); + app.addContainedData(flash); + flash.addContainedData(sensitiveData); var enc = new Credentials("enc"); sensitiveData.addEncryptCreds(enc); - attack(app.read); + var attacker = new Attacker(); + attacker.addAttackPoint(app.read); + attacker.attack(); - compromised(1, flash.read); - compromised(0, sensitiveData.read); + assertReached(flash.read); + assertNotReached(sensitiveData.read); } @Test public void hardware_encryption_circumvention_via_app() { @@ -157,17 +171,17 @@ public void hardware_encryption_circumvention_via_app() { keystore.addEncryptCreds(hardwareCredentials); var key = new Credentials("key"); - containerAdd(keystore, key); + keystore.addInformation(key); var os = new Application("os"); var app = new Application("app"); - containerAdd(os, app); + os.addAppExecutedApps(app); var filesystem = new Data("filesystem"); - containerAdd(filesystem, keystore); + filesystem.addContainedData(keystore); - containerAdd(os, filesystem); + os.addContainedData(filesystem); var appId = new Identity("appId"); @@ -182,28 +196,36 @@ public void hardware_encryption_circumvention_via_app() { var decryptApiInputPayload = new Data("externalData"); decryptApiInputPayload.addEncryptCreds(key); - containerAdd(decryptApiInput, decryptApiInputPayload); + decryptApiInput.addContainedData(decryptApiInputPayload); var decryptApiOutput = new Data("externalData"); - containerAdd(decryptApiInputPayload, decryptApiOutput); + decryptApiInputPayload.addContainedData(decryptApiOutput); - appExecAs(app, appId); + appId.addExecPrivApps(app); - mkReadApi(os, appId, filesystem); - mkWriteApi(os, appId, decryptApiInput); - mkReadApi(os, appId, decryptApiOutput); // decryption as service + appId.addLowPrivApps(os); + os.addContainedData(filesystem); + appId.addReadPrivData(filesystem); + appId.addLowPrivApps(os); + os.addContainedData(decryptApiInput); + appId.addWritePrivData(decryptApiInput); + appId.addLowPrivApps(os); + os.addContainedData(decryptApiOutput); + appId.addReadPrivData(decryptApiOutput); // decryption as service - attack(app.fullAccess); + var attacker = new Attacker(); + attacker.addAttackPoint(app.fullAccess); + attacker.attack(); // Can not access the key: - compromised(1, filesystem.read); - compromised(0, keystore.read); - compromised(0, key.use); + assertReached(filesystem.read); + assertNotReached(keystore.read); + assertNotReached(key.use); // but can access the decryption API: - compromised(1, decryptApiInput.write); - compromised(1, decryptApiOutput.read); + assertReached(decryptApiInput.write); + assertReached(decryptApiOutput.read); } @Test @@ -217,40 +239,46 @@ public void hardware_encryption_circumvention_via_app_simplified() { var keyring = new Data("keyring"); var key = new Credentials("key"); - containerAdd(keystore, keyring); - containerAdd(keyring, key); + keystore.addContainedData(keyring); + keyring.addInformation(key); var os = new Application("os"); var app = new Application("app"); - containerAdd(os, app); + os.addAppExecutedApps(app); var filesystem = new Data("filesystem"); - containerAdd(os, filesystem); - containerAdd(filesystem, keystore); + os.addContainedData(filesystem); + filesystem.addContainedData(keystore); var appId = new Identity("appId"); - appExecAs(app, appId); + appId.addExecPrivApps(app); - mkReadApi(os, appId, filesystem); + appId.addLowPrivApps(os); + os.addContainedData(filesystem); + appId.addReadPrivData(filesystem); // While the attacker is not able to access the key directly // (hardware_encryption_circumvention_via_app), we can still model it // as if they could since they can use the key to decrypt data. - mkReadApi(os, appId, keyring); + appId.addLowPrivApps(os); + os.addContainedData(keyring); + appId.addReadPrivData(keyring); var externalData = new Data("externalData"); externalData.addEncryptCreds(key); - containerAdd(app, externalData); + app.addContainedData(externalData); - attack(app.fullAccess); + var attacker = new Attacker(); + attacker.addAttackPoint(app.fullAccess); + attacker.attack(); - compromised(1, filesystem.read); - compromised(0, keystore.read); - compromised(1, key.attemptAccess); - compromised(1, key.use); - compromised(1, externalData.read); + assertReached(filesystem.read); + assertNotReached(keystore.read); + assertReached(key.attemptAccess); + assertReached(key.use); + assertReached(externalData.read); } @Test @@ -279,17 +307,19 @@ public void encryption_key_stored_in_filesystem() { var sensitiveData = new Data("sensitiveData"); var encKey = new Credentials("encKey"); - containerAdd(app, flash); - containerAdd(flash, sensitiveData); - containerAdd(flash, encKey); + app.addContainedData(flash); + flash.addContainedData(sensitiveData); + flash.addInformation(encKey); sensitiveData.addEncryptCreds(encKey); - attack(app.read); + var attacker = new Attacker(); + attacker.addAttackPoint(app.read); + attacker.attack(); - compromised(1, flash.read); - compromised(1, encKey.use); - compromised(1, sensitiveData.read); + assertReached(flash.read); + assertReached(encKey.use); + assertReached(sensitiveData.read); } @Test @@ -305,24 +335,27 @@ public void shared_stored_credentials() { var flash2 = new Data("flash2"); var sensitiveData2 = new Data("sensitiveData2"); - containerAdd(app, flash); - containerAdd(flash, sensitiveData); - containerAdd(flash, encKey); + app.addContainedData(flash); + flash.addContainedData(sensitiveData); + flash.addInformation(encKey); sensitiveData.addEncryptCreds(encKey); - containerAdd(app2, flash2); - containerAdd(flash2, sensitiveData2); + app2.addContainedData(flash2); + flash2.addContainedData(sensitiveData2); sensitiveData2.addEncryptCreds(encKey); // same key - attack(app.read, app2.read); + var attacker = new Attacker(); + attacker.addAttackPoint(app.read); + attacker.addAttackPoint(app2.read); + attacker.attack(); - compromised(1, flash.read); - compromised(1, encKey.use); - compromised(1, sensitiveData.read); + assertReached(flash.read); + assertReached(encKey.use); + assertReached(sensitiveData.read); - compromised(1, flash2.read); - compromised(1, sensitiveData2.read); + assertReached(flash2.read); + assertReached(sensitiveData2.read); } @Test @@ -334,44 +367,31 @@ public void shared_hardcoded_downloaded_key() { var firmwareBlob = new Data("firmwareBlob"); var encKey = new Credentials("encKey"); - containerAdd(firmwareBlob, encKey); + firmwareBlob.addInformation(encKey); var firmwareProduct = new SoftwareProduct("firmwareProduct"); - execData(firmwareBlob, firmwareProduct, app); + firmwareProduct.addOriginData(firmwareBlob); + firmwareProduct.addSoftApplications(app); var flash = new Data("flash"); var sensitiveData = new Data("sensitiveData"); - containerAdd(app, flash); - containerAdd(flash, sensitiveData); + app.addContainedData(flash); + flash.addContainedData(sensitiveData); sensitiveData.addEncryptCreds(encKey); - attack(app.read, firmwareBlob.read); + var attacker = new Attacker(); + attacker.addAttackPoint(app.read); + attacker.addAttackPoint(firmwareBlob.read); + attacker.attack(); - compromised(1, flash.read); - compromised(1, encKey.use); - compromised(1, sensitiveData.read); + assertReached(flash.read); + assertReached(encKey.use); + assertReached(sensitiveData.read); } -// @Test -// public void test_t024() { -// // T024 (firmware) Configuration - Lack of wiping device -// // "Lack of deprovisioning/decomissioning. Inability to wipe device's local data storage " -// // -// // Interpretation: Factory reset / deprovisioning functionality is missing or -// // imperfect. -// // -// // Example: -// // * Old data is left from previous owner (cloud credentials, wifi passwords, etc.). -// // -// // How to model in coreLang: -// // * TODO Corelang does not really model state. -// // * Alternative, simply model it as sensitive data/credentials being stored on the device. -// } - - @Test public void app_runs_as_root() { // T027 (firmware) Configuration - Insecure filesystem permissions @@ -384,26 +404,28 @@ public void app_runs_as_root() { var os = new Application("os"); var app = new Application("app"); - containerAdd(os, app); + os.addAppExecutedApps(app); var root = new Identity("root"); - appExecAs(os, root); - appExecAs(app, root); + root.addExecPrivApps(os); + root.addExecPrivApps(app); var filesystem = new Data("filesystem"); var appData = new Data("appData"); var nonappData = new Data("nonappData"); - containerAdd(filesystem, appData); - containerAdd(filesystem, nonappData); + filesystem.addContainedData(appData); + filesystem.addContainedData(nonappData); - containerAdd(os, filesystem); - containerAdd(app, appData); + os.addContainedData(filesystem); + app.addContainedData(appData); - attack(app.fullAccess); + var attacker = new Attacker(); + attacker.addAttackPoint(app.fullAccess); + attacker.attack(); - compromised(1, os.fullAccess); - compromised(1, appData.read); - compromised(1, nonappData.read); + assertReached(os.fullAccess); + assertReached(appData.read); + assertReached(nonappData.read); } @Test public void app_runs_as_nobody() { @@ -411,31 +433,33 @@ public void app_runs_as_nobody() { var os = new Application("os"); var app = new Application("app"); - containerAdd(os, app); + os.addAppExecutedApps(app); var root = new Identity("root"); - appExecAs(os, root); + root.addExecPrivApps(os); var nobody = new Identity("nobody"); - appExecAs(app, nobody); + nobody.addExecPrivApps(app); - aOwnsB(root, nobody); // optional. (root can do everything nobody can do) + root.addParentId(nobody); // optional. (root can do everything nobody can do) var filesystem = new Data("filesystem"); var appData = new Data("appData"); var nonappData = new Data("nonappData"); - containerAdd(filesystem, appData); - containerAdd(filesystem, nonappData); + filesystem.addContainedData(appData); + filesystem.addContainedData(nonappData); - containerAdd(os, filesystem); - containerAdd(app, appData); + os.addContainedData(filesystem); + app.addContainedData(appData); - attack(app.fullAccess); + var attacker = new Attacker(); + attacker.addAttackPoint(app.fullAccess); + attacker.attack(); - compromised(0, os.fullAccess); - compromised(1, appData.read); - compromised(0, nonappData.read); + assertNotReached(os.fullAccess); + assertReached(appData.read); + assertNotReached(nonappData.read); } @Test @@ -444,33 +468,39 @@ public void os_as_api_to_filesystem_and_app_has_too_much_access() { var os = new Application("os"); var app = new Application("app"); - containerAdd(os, app); + os.addAppExecutedApps(app); var root = new Identity("root"); - appExecAs(os, root); + root.addExecPrivApps(os); var appId = new Identity("appId"); - appExecAs(app, appId); + appId.addExecPrivApps(app); - aOwnsB(root, appId); // optional. (root can do everything appId can do) + root.addParentId(appId); // optional. (root can do everything appId can do) var filesystem = new Data("filesystem"); var appData = new Data("appData"); var nonappData = new Data("nonappData"); - containerAdd(filesystem, appData); - containerAdd(filesystem, nonappData); + filesystem.addContainedData(appData); + filesystem.addContainedData(nonappData); - containerAdd(os, filesystem); + os.addContainedData(filesystem); - mkReadApi(os, appId, appData); - mkReadApi(os, appId, nonappData); // vulnerability + appId.addLowPrivApps(os); + os.addContainedData(appData); + appId.addReadPrivData(appData); + appId.addLowPrivApps(os); + os.addContainedData(nonappData); + appId.addReadPrivData(nonappData); // vulnerability - attack(app.fullAccess); + var attacker = new Attacker(); + attacker.addAttackPoint(app.fullAccess); + attacker.attack(); - compromised(0, os.fullAccess); - compromised(1, appData.read); - compromised(1, nonappData.read); + assertNotReached(os.fullAccess); + assertReached(appData.read); + assertReached(nonappData.read); } @Test @@ -479,32 +509,36 @@ public void os_as_api_to_filesystem_and_app_has_restricted_access() { var os = new Application("os"); var app = new Application("app"); - containerAdd(os, app); + os.addAppExecutedApps(app); var root = new Identity("root"); - appExecAs(os, root); + root.addExecPrivApps(os); var appId = new Identity("appId"); - appExecAs(app, appId); + appId.addExecPrivApps(app); - aOwnsB(root, appId); // optional. (root can do everything appId can do) + root.addParentId(appId); // optional. (root can do everything appId can do) var filesystem = new Data("filesystem"); var appData = new Data("appData"); var nonappData = new Data("nonappData"); - containerAdd(filesystem, appData); - containerAdd(filesystem, nonappData); + filesystem.addContainedData(appData); + filesystem.addContainedData(nonappData); - containerAdd(os, filesystem); + os.addContainedData(filesystem); - mkReadApi(os, appId, appData); + appId.addLowPrivApps(os); + os.addContainedData(appData); + appId.addReadPrivData(appData); - attack(app.fullAccess); + var attacker = new Attacker(); + attacker.addAttackPoint(app.fullAccess); + attacker.attack(); - compromised(0, os.fullAccess); - compromised(1, appData.read); - compromised(0, nonappData.read); + assertNotReached(os.fullAccess); + assertReached(appData.read); + assertNotReached(nonappData.read); } @@ -529,24 +563,33 @@ public void broken_machine_to_machine_access_control() { var net = new Network("net"); var app = new Application("app"); - var net_con_app = autocon("net_con_app", net, app); + var net_con_app = new ConnectionRule("net_con_app"); + net.addOutgoingNetConnections(net_con_app); + app.addIngoingAppConnections(net_con_app); var anyone = new Identity("anyone"); var readData = new Data("readData"); var writeData = new Data("writeData"); - mkReadApi(app, anyone, readData); - mkWriteApi(app, anyone, writeData); + anyone.addLowPrivApps(app); + app.addContainedData(readData); + anyone.addReadPrivData(readData); + anyone.addLowPrivApps(app); + app.addContainedData(writeData); + anyone.addWritePrivData(writeData); - attack(net.access, anyone.assume); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.addAttackPoint(anyone.assume); + attacker.attack(); - compromised(1, readData.read); - compromised(1, writeData.write); + assertReached(readData.read); + assertReached(writeData.write); - compromised(0, readData.write); - compromised(0, writeData.read); - compromised(0, app.fullAccess); + assertNotReached(readData.write); + assertNotReached(writeData.read); + assertNotReached(app.fullAccess); } @Test @@ -558,34 +601,44 @@ public void machine_to_machine_identity_theft() { var appB = new Application("appB"); var net = new Network("net"); - var appA_con_net = autocon("appA_con_net", appA, net); // outgoing connection - var net_con_appB = autocon("net_con_appB", net, appB); // open port + var appA_con_net = new ConnectionRule("appA_con_net"); + appA.addOutgoingAppConnections(appA_con_net); + net.addIngoingNetConnections(appA_con_net); // outgoing connection + var net_con_appB = new ConnectionRule("net_con_appB"); + net.addOutgoingNetConnections(net_con_appB); + appB.addIngoingAppConnections(net_con_appB); // open port var idA = new Identity("idA"); - appExecAs(appA, idA); + idA.addExecPrivApps(appA); var sensitiveData = new Data("sensitiveData"); var sensitiveCall = new Data("sensitiveCall"); - mkReadApi(appB, idA, sensitiveData); - mkWriteApi(appB, idA, sensitiveCall); + idA.addLowPrivApps(appB); + appB.addContainedData(sensitiveData); + idA.addReadPrivData(sensitiveData); + idA.addLowPrivApps(appB); + appB.addContainedData(sensitiveCall); + idA.addWritePrivData(sensitiveCall); var regularCommunication = new Data("regularCommunication"); // optional, just to show m2m regularCommunication.authenticated.defaultValue = true; - transferData(appA, regularCommunication); - transferData(net, regularCommunication); - transferData(appB, regularCommunication); // TODO coreLang has no way to show that regularCommunication is copied to sensitiveCall. There could perhaps be something like a "copy"-association for Data. + regularCommunication.addTransitApp(appA); + regularCommunication.addTransitNetwork(net); + regularCommunication.addTransitApp(appB); // TODO coreLang has no way to show that regularCommunication is copied to sensitiveCall. There could perhaps be something like a "copy"-association for Data. - attack(appA.fullAccess); + var attacker = new Attacker(); + attacker.addAttackPoint(appA.fullAccess); + attacker.attack(); - compromised(1, net.access); - compromised(1, idA.assume); - compromised(1, appB.specificAccess); // assume idA to talk to appB - compromised(1, sensitiveData.read); - compromised(1, sensitiveCall.write); - //compromised(1, regularCommunication.write); // TODO Would work if the authenticated defense was based on credentials instead, like Data.encryptCreds + assertReached(net.access); + assertReached(idA.assume); + assertReached(appB.specificAccess); // assume idA to talk to appB + assertReached(sensitiveData.read); + assertReached(sensitiveCall.write); + //assertReached(regularCommunication.write); // TODO Would work if the authenticated defense was based on credentials instead, like Data.encryptCreds } @Test @@ -599,24 +652,32 @@ public void machine_to_machine_shared_credential_theft() { var appB = new Application("appB"); var net = new Network("net"); - var appA_con_net = autocon("appA_con_net", appA, net); // outgoing connection - var net_con_appB = autocon("net_con_appB", net, appB); // open port + var appA_con_net = new ConnectionRule("appA_con_net"); + appA.addOutgoingAppConnections(appA_con_net); + net.addIngoingNetConnections(appA_con_net); // outgoing connection + var net_con_appB = new ConnectionRule("net_con_appB"); + net.addOutgoingNetConnections(net_con_appB); + appB.addIngoingAppConnections(net_con_appB); // open port var idA = new Identity("idA"); - appExecAs(appA, idA); + idA.addExecPrivApps(appA); var sensitiveData = new Data("sensitiveData"); var sensitiveCall = new Data("sensitiveCall"); - mkReadApi(appB, idA, sensitiveData); - mkWriteApi(appB, idA, sensitiveCall); + idA.addLowPrivApps(appB); + appB.addContainedData(sensitiveData); + idA.addReadPrivData(sensitiveData); + idA.addLowPrivApps(appB); + appB.addContainedData(sensitiveCall); + idA.addWritePrivData(sensitiveCall); var regularCommunication = new Data("regularCommunication"); // optional, just to show m2m regularCommunication.authenticated.defaultValue = true; - transferData(appA, regularCommunication); - transferData(net, regularCommunication); - transferData(appB, regularCommunication); // TODO coreLang has no way to show that regularCommunication is calling the API on appB. There could perhaps be something like a "copy"-association for Data. + regularCommunication.addTransitApp(appA); + regularCommunication.addTransitNetwork(net); + regularCommunication.addTransitApp(appB); // TODO coreLang has no way to show that regularCommunication is calling the API on appB. There could perhaps be something like a "copy"-association for Data. @@ -625,25 +686,28 @@ public void machine_to_machine_shared_credential_theft() { var credsC = new Credentials("credsC"); var storageC = new Data("storageC"); - containerAdd(appC, storageC); - containerAdd(storageC, credsC); + appC.addContainedData(storageC); + storageC.addInformation(credsC); var credsA = credsC; idA.addCredentials(credsA); idC.addCredentials(credsC); - attack(net.access, appC.fullAccess); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.addAttackPoint(appC.fullAccess); + attacker.attack(); - compromised(1, credsC.use); - compromised(1, idC.assume); + assertReached(credsC.use); + assertReached(idC.assume); - compromised(1, net.access); + assertReached(net.access); - compromised(1, idA.assume); - compromised(1, appB.specificAccess); // assume idA to talk to appB - compromised(1, sensitiveData.read); - compromised(1, sensitiveCall.write); - //compromised(1, regularCommunication.write); // TODO Would work if the authenticated defense was based on credentials instead, like Data.encryptCreds + assertReached(idA.assume); + assertReached(appB.specificAccess); // assume idA to talk to appB + assertReached(sensitiveData.read); + assertReached(sensitiveCall.write); + //assertReached(regularCommunication.write); // TODO Would work if the authenticated defense was based on credentials instead, like Data.encryptCreds } @Test @@ -655,38 +719,49 @@ public void server_identity_theft_and_mitm() { var appB = new Application("appB"); var net = new Network("net"); - var appA_con_net = autocon("appA_con_net", appA, net); // outgoing connection - var net_con_appB = autocon("net_con_appB", net, appB); // open port + var appA_con_net = new ConnectionRule("appA_con_net"); + appA.addOutgoingAppConnections(appA_con_net); + net.addIngoingNetConnections(appA_con_net); // outgoing connection + var net_con_appB = new ConnectionRule("net_con_appB"); + net.addOutgoingNetConnections(net_con_appB); + appB.addIngoingAppConnections(net_con_appB); // open port var idB = new Identity("idB"); var credsB = new Credentials("credsB"); idB.addCredentials(credsB); - appExecAs(appB, idB); + idB.addExecPrivApps(appB); var sensitiveData = new Data("sensitiveData"); var sensitiveCall = new Data("sensitiveCall"); - mkReadApi(appA, idB, sensitiveData); - mkWriteApi(appA, idB, sensitiveCall); + idB.addLowPrivApps(appA); + appA.addContainedData(sensitiveData); + idB.addReadPrivData(sensitiveData); + idB.addLowPrivApps(appA); + appA.addContainedData(sensitiveCall); + idB.addWritePrivData(sensitiveCall); var regularCommunicationAB = new Data("regularCommunication"); // optional, just to show m2m - transferData(appA, regularCommunicationAB); - transferData(net, regularCommunicationAB); - transferData(appB, regularCommunicationAB); + regularCommunicationAB.addTransitApp(appA); + regularCommunicationAB.addTransitNetwork(net); + regularCommunicationAB.addTransitApp(appB); var regularCommunicationBA = new Data("regularCommunication"); // optional, just to show m2m regularCommunicationBA.authenticated.defaultValue = true; - transferData(appB, regularCommunicationBA); - transferData(net, regularCommunicationBA); - transferData(appA, regularCommunicationBA); - - attack(net.access, credsB.use); - - compromised(1, sensitiveData.read); - compromised(1, sensitiveCall.write); - //compromised(1, regularCommunicationBA.write); // TODO Would work if the authenticated defense was based on credentials instead, like Data.encryptCreds + regularCommunicationBA.addTransitApp(appB); + regularCommunicationBA.addTransitNetwork(net); + regularCommunicationBA.addTransitApp(appA); + + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.addAttackPoint(credsB.use); + attacker.attack(); + + assertReached(sensitiveData.read); + assertReached(sensitiveCall.write); + //assertReached(regularCommunicationBA.write); // TODO Would work if the authenticated defense was based on credentials instead, like Data.encryptCreds } @@ -711,20 +786,25 @@ public void generic_network_vulnerability() { var net = new Network("net"); - var net_con_app = autocon("net_con_app", net, app); + var net_con_app = new ConnectionRule("net_con_app"); + net.addOutgoingNetConnections(net_con_app); + app.addIngoingAppConnections(net_con_app); // generic network vulnerability - var vuln = vulnerabilityBuilder("vuln").setNetwork().setCIA().build(); + var vuln = new SoftwareVulnerability("vuln"); + vuln.networkAccessRequired.defaultValue = true; var prod = new SoftwareProduct("prod"); prod.addSoftApplications(app); prod.addSoftProductVulnerabilities(vuln); // alternatively: vuln in app - attack(net.access); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.attack(); - compromised(1, app.networkConnect); - compromised(1, app.fullAccess); + assertReached(app.networkConnect); + assertReached(app.fullAccess); } @Test @@ -743,25 +823,32 @@ public void man_in_the_middle() { var net = new Network("lan"); var cloud = new Application("cloud"); - var app_con_net = autocon("app_con_net", app, net); - var net_con_cloud = autocon("net_con_cloud", net, cloud); + var app_con_net = new ConnectionRule("app_con_net"); + app.addOutgoingAppConnections(app_con_net); + net.addIngoingNetConnections(app_con_net); + var net_con_cloud = new ConnectionRule("net_con_cloud"); + net.addOutgoingNetConnections(net_con_cloud); + cloud.addIngoingAppConnections(net_con_cloud); var firmwareBlob = new Data("firmwareBlob"); var firmwareProduct = new SoftwareProduct("firmwareProduct"); - execData(firmwareBlob, firmwareProduct, app); + firmwareProduct.addOriginData(firmwareBlob); + firmwareProduct.addSoftApplications(app); var tcp = new Data("tcp"); - containerAdd(tcp, firmwareBlob); + tcp.addContainedData(firmwareBlob); - transferData(app, tcp); - transferData(net, tcp); // mitm point - transferData(cloud, tcp); + tcp.addTransitApp(app); + tcp.addTransitNetwork(net); // mitm point + tcp.addTransitApp(cloud); - attack(net.access); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.attack(); - compromised(1, firmwareBlob.write); // mitm - compromised(1, app.fullAccess); + assertReached(firmwareBlob.write); // mitm + assertReached(app.fullAccess); } @Test @@ -773,13 +860,18 @@ public void man_in_the_middle_encryption_defense() { var net = new Network("lan"); var cloud = new Application("cloud"); - var app_con_net = autocon("app_con_net", app, net); - var net_con_cloud = autocon("net_con_cloud", net, cloud); + var app_con_net = new ConnectionRule("app_con_net"); + app.addOutgoingAppConnections(app_con_net); + net.addIngoingNetConnections(app_con_net); + var net_con_cloud = new ConnectionRule("net_con_cloud"); + net.addOutgoingNetConnections(net_con_cloud); + cloud.addIngoingAppConnections(net_con_cloud); var firmwareBlob = new Data("firmwareBlob"); var firmwareProduct = new SoftwareProduct("firmwareProduct"); - execData(firmwareBlob, firmwareProduct, app); + firmwareProduct.addOriginData(firmwareBlob); + firmwareProduct.addSoftApplications(app); var tcp = new Data("tcp"); @@ -787,17 +879,19 @@ public void man_in_the_middle_encryption_defense() { var tlsCreds = new Credentials("tlsCreds"); tls.addEncryptCreds(tlsCreds); - containerAdd(tcp, tls); - containerAdd(tls, firmwareBlob); + tcp.addContainedData(tls); + tls.addContainedData(firmwareBlob); - transferData(app, tcp); - transferData(net, tcp); // mitm point - transferData(cloud, tcp); + tcp.addTransitApp(app); + tcp.addTransitNetwork(net); // mitm point + tcp.addTransitApp(cloud); - attack(net.access); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.attack(); - compromised(0, firmwareBlob.write); // mitm not possible - compromised(0, app.fullAccess); + assertNotReached(firmwareBlob.write); // mitm not possible + assertNotReached(app.fullAccess); } @Test @@ -807,15 +901,21 @@ public void router_example() { var sys = new org.mal_lang.corelang.test.System("sys"); var app = new Application("app"); - containerAdd(sys, app); + sys.addSysExecutedApps(app); var lan = new Network("lan"); var internet = new Network("internet"); var cloud = new Application("cloud"); - var con_app_lan = autocon("con_app_lan", app, lan); - var con_lan_internet = autocon("con_lan_internet", lan, internet); // Note: NAT. - var con_internet_cloud = autocon("con_internet_cloud", internet, cloud); + var con_app_lan = new ConnectionRule("con_app_lan"); + app.addOutgoingAppConnections(con_app_lan); + lan.addIngoingNetConnections(con_app_lan); + var con_lan_internet = new ConnectionRule("con_lan_internet"); + lan.addOutgoingNetConnections(con_lan_internet); + internet.addIngoingNetConnections(con_lan_internet); // Note: NAT. + var con_internet_cloud = new ConnectionRule("con_internet_cloud"); + internet.addOutgoingNetConnections(con_internet_cloud); + cloud.addIngoingAppConnections(con_internet_cloud); // The RoutingFirewall is optional. It is just here to show that the // router may actually be a IoT device (that can be hacked): RoutingFirewall extends Application. @@ -823,31 +923,34 @@ public void router_example() { con_lan_internet.addRoutingFirewalls(routerNat); var routerHardware = new org.mal_lang.corelang.test.System("routerHardware"); - containerAdd(routerHardware, routerNat); + routerHardware.addSysExecutedApps(routerNat); var tcp = new Data("tcp"); var firmwareBlob = new Data("firmwareBlob"); - containerAdd(tcp, firmwareBlob); + tcp.addContainedData(firmwareBlob); var firmwareProduct = new SoftwareProduct("firmwareProduct"); - execData(firmwareBlob, firmwareProduct, app); + firmwareProduct.addOriginData(firmwareBlob); + firmwareProduct.addSoftApplications(app); - transferData(app, tcp); - transferData(lan, tcp); - transferData(internet, tcp); - transferData(cloud, tcp); + tcp.addTransitApp(app); + tcp.addTransitNetwork(lan); + tcp.addTransitNetwork(internet); + tcp.addTransitApp(cloud); var identity = new Identity("identity"); sys.addHighPrivSysIds(identity); app.addExecutionPrivIds(identity); // NOTE: You can not gain privileges if there are no privileges defined. - attack(internet.access); + var attacker = new Attacker(); + attacker.addAttackPoint(internet.access); + attacker.attack(); - compromised(1, firmwareBlob.write); // mitm - compromised(1, app.fullAccess); + assertReached(firmwareBlob.write); // mitm + assertReached(app.fullAccess); } @Test @@ -869,35 +972,42 @@ public void firmware_update_man_in_the_middle() { var net = new Network("lan"); var cloud = new Application("cloud"); - var app_con_net = autocon("app_con_net", app, net); - var net_con_cloud = autocon("net_con_cloud", net, cloud); + var app_con_net = new ConnectionRule("app_con_net"); + app.addOutgoingAppConnections(app_con_net); + net.addIngoingNetConnections(app_con_net); + var net_con_cloud = new ConnectionRule("net_con_cloud"); + net.addOutgoingNetConnections(net_con_cloud); + cloud.addIngoingAppConnections(net_con_cloud); var firmwareBlob = new Data("firmwareBlob"); firmwareBlob.authenticated.defaultValue = false; // no signature nor verification var sensitiveData = new Data("sensitiveData"); - containerAdd(firmwareBlob, sensitiveData); + firmwareBlob.addContainedData(sensitiveData); var firmwareProduct = new SoftwareProduct("firmwareProduct"); - execData(firmwareBlob, firmwareProduct, app); + firmwareProduct.addOriginData(firmwareBlob); + firmwareProduct.addSoftApplications(app); var tcp = new Data("tcp"); - containerAdd(tcp, firmwareBlob); + tcp.addContainedData(firmwareBlob); - transferData(app, tcp); - transferData(net, tcp); // mitm point - transferData(cloud, tcp); + tcp.addTransitApp(app); + tcp.addTransitNetwork(net); // mitm point + tcp.addTransitApp(cloud); - attack(net.access); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.attack(); - compromised(1, firmwareBlob.read); // can read - compromised(1, sensitiveData.read); + assertReached(firmwareBlob.read); // can read + assertReached(sensitiveData.read); - compromised(1, firmwareBlob.write); - compromised(1, sensitiveData.write); + assertReached(firmwareBlob.write); + assertReached(sensitiveData.write); - compromised(1, app.fullAccess); + assertReached(app.fullAccess); } @Test @@ -908,35 +1018,42 @@ public void firmware_update_with_signature_verification() { var net = new Network("lan"); var cloud = new Application("cloud"); - var app_con_net = autocon("app_con_net", app, net); - var net_con_cloud = autocon("net_con_cloud", net, cloud); + var app_con_net = new ConnectionRule("app_con_net"); + app.addOutgoingAppConnections(app_con_net); + net.addIngoingNetConnections(app_con_net); + var net_con_cloud = new ConnectionRule("net_con_cloud"); + net.addOutgoingNetConnections(net_con_cloud); + cloud.addIngoingAppConnections(net_con_cloud); var firmwareBlob = new Data("firmwareBlob"); firmwareBlob.authenticated.defaultValue = true; // signature and verification var sensitiveData = new Data("sensitiveData"); - containerAdd(firmwareBlob, sensitiveData); + firmwareBlob.addContainedData(sensitiveData); var firmwareProduct = new SoftwareProduct("firmwareProduct"); - execData(firmwareBlob, firmwareProduct, app); + firmwareProduct.addOriginData(firmwareBlob); + firmwareProduct.addSoftApplications(app); var tcp = new Data("tcp"); - containerAdd(tcp, firmwareBlob); + tcp.addContainedData(firmwareBlob); - transferData(app, tcp); - transferData(net, tcp); // mitm point - transferData(cloud, tcp); + tcp.addTransitApp(app); + tcp.addTransitNetwork(net); // mitm point + tcp.addTransitApp(cloud); - attack(net.access); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.attack(); - compromised(1, firmwareBlob.read); // can read - compromised(1, sensitiveData.read); + assertReached(firmwareBlob.read); // can read + assertReached(sensitiveData.read); - compromised(0, firmwareBlob.write); // but can't write - compromised(0, sensitiveData.write); + assertNotReached(firmwareBlob.write); // but can't write + assertNotReached(sensitiveData.write); - compromised(0, app.fullAccess); + assertNotReached(app.fullAccess); } @Test @@ -949,35 +1066,32 @@ public void firmware_install_api() { var app = new Application("app"); var net = new Network("net"); - var net_con_app = autocon("net_con_app", net, app); + var net_con_app = new ConnectionRule("net_con_app"); + net.addOutgoingNetConnections(net_con_app); + app.addIngoingAppConnections(net_con_app); var firmwareStorage = new Data("firmwareStorage"); var firmwareBlob = new Data("firmwareBlob"); var anyone = new Identity("anyone"); - mkWriteApi(app, anyone, firmwareStorage); // alternatively we could use a vulnerability here. + anyone.addLowPrivApps(app); + app.addContainedData(firmwareStorage); + anyone.addWritePrivData(firmwareStorage); // alternatively we could use a vulnerability here. - containerAdd(app, firmwareStorage); - containerAdd(firmwareStorage, firmwareBlob); + app.addContainedData(firmwareStorage); + firmwareStorage.addContainedData(firmwareBlob); var firmwareProduct = new SoftwareProduct("firmwareProduct"); - execData(firmwareBlob, firmwareProduct, app); + firmwareProduct.addOriginData(firmwareBlob); + firmwareProduct.addSoftApplications(app); - attack(net.access, anyone.assume); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.addAttackPoint(anyone.assume); + attacker.attack(); - compromised(1, firmwareStorage.write); - compromised(1, firmwareBlob.write); - compromised(1, app.fullAccess); + assertReached(firmwareStorage.write); + assertReached(firmwareBlob.write); + assertReached(app.fullAccess); } - -// @Test -// public void test_t040() { -// // T040 (firmware) Update mechanism - Lack of anti-rollback mechanism -// // "An attacker could revert firmware back (firmware downgrade) to a vulnerable version if the device lacks of anti-rollback mechanism." -// // -// // TODO CoreLang does not really model multiple versions of the same application. -// // A workaround is to create two models: one model showing the -// // scenario leading up to the rollback and another model showing the -// // situation after the rollback. -// } } diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java index 6f9014a..87e8e51 100644 --- a/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestNetwork.java @@ -16,14 +16,16 @@ * This provides more granularity than SoftwareVulnerability. * */ -public class TestNetwork extends Base { +public class TestNetwork extends CoreLangTest { @Test public void api() { var app = new Application("app"); var net = new Network("net"); - var net_con_app = autocon("net_con_app", net, app); + var net_con_app = new ConnectionRule("net_con_app"); + net.addOutgoingNetConnections(net_con_app); + app.addIngoingAppConnections(net_con_app); var readApi = new Data("readApi"); @@ -32,20 +34,32 @@ public void api() { var id = new Identity("id"); - mkReadApi(app, id, readApi); - mkWriteApi(app, id, writeApi); - mkReadWriteApi(app, id, readWriteApi); - - attack(net.access, id.assume); - - compromised(1, readApi.read); - compromised(0, readApi.write); - - compromised(0, writeApi.read); - compromised(1, writeApi.write); - - compromised(1, readWriteApi.read); - compromised(1, readWriteApi.write); + id.addLowPrivApps(app); + app.addContainedData(readApi); + id.addReadPrivData(readApi); + id.addLowPrivApps(app); + app.addContainedData(writeApi); + id.addWritePrivData(writeApi); + id.addLowPrivApps(app); + app.addContainedData(readWriteApi); + id.addReadPrivData(readWriteApi); + id.addLowPrivApps(app); + app.addContainedData(readWriteApi); + id.addWritePrivData(readWriteApi); + + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.addAttackPoint(id.assume); + attacker.attack(); + + assertReached(readApi.read); + assertNotReached(readApi.write); + + assertNotReached(writeApi.read); + assertReached(writeApi.write); + + assertReached(readWriteApi.read); + assertReached(readWriteApi.write); } @Test @@ -73,18 +87,22 @@ public void sensitive_data_on_network() { var net = new Network("net"); - var net_con_app = autocon("net_con_app", net, app); + var net_con_app = new ConnectionRule("net_con_app"); + net.addOutgoingNetConnections(net_con_app); + app.addIngoingAppConnections(net_con_app); var sensitiveData = new Data("sensitiveData"); // The app is broadcasting sensitiveData on the network: - //containerAdd(app, sensitiveData); - //transferData(app, sensitiveData); // Not needed, but in larger models this is how we would model the data being transfered around. - transferData(net, sensitiveData); + //app.addContainedData(sensitiveData); + //sensitiveData.addTransitNetwork(app); // Not needed, but in larger models this is how we would model the data being transfered around. + sensitiveData.addTransitNetwork(net); - attack(net.access); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.attack(); - compromised(1, sensitiveData.read); + assertReached(sensitiveData.read); } @Test public void sensitive_data_via_open_api() { @@ -94,17 +112,24 @@ public void sensitive_data_via_open_api() { var net = new Network("net"); - var net_con_app = autocon("net_con_app", net, app); // open port + var net_con_app = new ConnectionRule("net_con_app"); + net.addOutgoingNetConnections(net_con_app); + app.addIngoingAppConnections(net_con_app); // open port var anyone = new Identity("anyone"); var sensitiveData = new Data("sensitiveData"); - mkReadApi(app, anyone, sensitiveData); + anyone.addLowPrivApps(app); + app.addContainedData(sensitiveData); + anyone.addReadPrivData(sensitiveData); - attack(net.access, anyone.assume); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.addAttackPoint(anyone.assume); + attacker.attack(); - compromised(1, sensitiveData.read); + assertReached(sensitiveData.read); } @@ -134,15 +159,21 @@ public void bypass_tls_by_stealing_credentials() { var internet = new Network("internet"); var cloud = new Application("cloud"); - var con_app_lan = autocon("con_app_lan", app, lan); - var con_lan_internet = autocon("con_lan_internet", lan, internet); // Note: NAT. - var con_internet_cloud = autocon("con_internet_cloud", internet, cloud); + var con_app_lan = new ConnectionRule("con_app_lan"); + app.addOutgoingAppConnections(con_app_lan); + lan.addIngoingNetConnections(con_app_lan); + var con_lan_internet = new ConnectionRule("con_lan_internet"); + lan.addOutgoingNetConnections(con_lan_internet); + internet.addIngoingNetConnections(con_lan_internet); // Note: NAT. + var con_internet_cloud = new ConnectionRule("con_internet_cloud"); + internet.addOutgoingNetConnections(con_internet_cloud); + cloud.addIngoingAppConnections(con_internet_cloud); var routerNat = new RoutingFirewall("routerNat"); con_lan_internet.addRoutingFirewalls(routerNat); var routerHardware = new org.mal_lang.corelang.test.System("routerHardware"); - containerAdd(routerHardware, routerNat); + routerHardware.addSysExecutedApps(routerNat); var tlsCredentials = new Credentials("tlsCredentials"); @@ -150,72 +181,24 @@ public void bypass_tls_by_stealing_credentials() { var tls = new Data("tls"); var tlsPayload = new Data("tlsPayload"); - containerAdd(tcp, tls); - containerAdd(tls, tlsPayload); + tcp.addContainedData(tls); + tls.addContainedData(tlsPayload); tls.addEncryptCreds(tlsCredentials); - transferData(app, tcp); - transferData(lan, tcp); - transferData(internet, tcp); - transferData(cloud, tcp); + tcp.addTransitApp(app); + tcp.addTransitNetwork(lan); + tcp.addTransitNetwork(internet); + tcp.addTransitApp(cloud); // Assume the tlsCredentials have been compromised somehow. - attack(internet.access, tlsCredentials.attemptAccess); + var attacker = new Attacker(); + attacker.addAttackPoint(internet.access); + attacker.addAttackPoint(tlsCredentials.attemptAccess); + attacker.attack(); - compromised(1, tlsPayload.read); + assertReached(tlsPayload.read); } -// @Test -// public void test_t044() { -// // T044 (device network service) Authentication - Username enumeration -// // "Ability to collect a set of valid usernames by interacting with the authentication mechanism" -// // -// // Interpretation: An network service on the device provides a way to -// // enumerate users. -// // -// // Examples: -// // * Different authentication failure error message are returned -// // depending on the cause of the failure. So instead of the -// // attacker having to guess both username and password, they can -// // first guess the correct username (with an empty password) and -// // then guess the password. This saves some time. -// // -// // How to model in corelang: -// // * TODO CoreLang does not really separate usernames from passwords. -// // Username and password form a single Credential. Potentially TTC -// // can be adjusted. -// // * TODO CoreLang also does not model non-credential prerequisites -// // in access/attacks. -// } -// @Test -// public void test_t045() { -// // T045 (device network service) Authentication - Weak credentials -// // "Ability to set account passwords to '1234' or '123456' for example. Usage of pre-programmed default (known) passwords (deffpass.com (Publicly available) - IoT device default password lookup). Easily guessable credentials. Brute-force by dictionaries and rules" -// // -// // * TODO CoreLang does not really distinguish between strong and weak -// // credentials. Maybe TTC can be adjusted differently for different -// // credentials? -// // * See also the defense Credentials.notDisclosed. -// } -// @Test -// public void test_t046() { -// // T046 (device network service) Authentication - Improper account lockout -// // "Ability to continue sending authentication attempts after 3 - 5 failed login attempts" -// // -// // Interpretation: There either is no account lockout mechanism, or -// // the mechanism can be easily bypassed. -// // -// // Examples: -// // * For example, the attacker can keep trying passwords after 3-5 -// // failed attempts. -// // -// // TODO CoreLang does not really seem to model bruteforce attacks. It -// // can sort be done via generic vulnerabilities (if the app also -// // stores the credentials such that the attacker can obtain them), but the ttc will be -// // incorrect. The account lockout mechanism would then be the absence -// // of that vulnerability. -// } - @Test public void weak_password_recovery_as_open_api() { // T047 (device network service) Authentication - Weak password recovery @@ -237,36 +220,46 @@ public void weak_password_recovery_as_open_api() { var net = new Network("net"); var app = new Application("app"); - var net_con_app = autocon("net_con_app", net, app); // open port + var net_con_app = new ConnectionRule("net_con_app"); + net.addOutgoingNetConnections(net_con_app); + app.addIngoingAppConnections(net_con_app); // open port var user = new Identity("user"); var password = new Credentials("password"); user.addCredentials(password); var sensitiveData = new Data("sensitiveData"); - containerAdd(app, sensitiveData); - mkReadApi(app, user, sensitiveData); + app.addContainedData(sensitiveData); + user.addLowPrivApps(app); + app.addContainedData(sensitiveData); + user.addReadPrivData(sensitiveData); var recoverMechanism = new Application("recoverMechanism"); - containerAdd(app, recoverMechanism); - var net_con_recovery = autocon("net_con_recovery", net, recoverMechanism); // open port + app.addAppExecutedApps(recoverMechanism); + var net_con_recovery = new ConnectionRule("net_con_recovery"); + net.addOutgoingNetConnections(net_con_recovery); + recoverMechanism.addIngoingAppConnections(net_con_recovery); // open port var recoveryApi = new Data("recoveryApi"); - containerAdd(recoverMechanism, recoveryApi); - containerAdd(recoveryApi, password); + recoverMechanism.addContainedData(recoveryApi); + recoveryApi.addInformation(password); - var vuln = vulnerabilityBuilder("vuln").setNetwork().setConfidentiality().build(); + var vuln = new SoftwareVulnerability("vuln"); + vuln.networkAccessRequired.defaultValue = true; + vuln.confidentialityImpactLimitations.defaultValue = false; recoverMechanism.addVulnerabilities(vuln); - attack(net.access); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.attack(); - compromised(1, recoveryApi.read); - compromised(1, password.use); - compromised(1, user.assume); - compromised(1, app.specificAccessAuthenticate); - compromised(1, sensitiveData.read); + assertReached(recoveryApi.read); + assertReached(password.use); + assertReached(user.assume); + assertReached(app.specificAccessAuthenticate); + assertReached(sensitiveData.read); } @Test @@ -274,33 +267,42 @@ public void weak_password_recovery_as_vulnerability() { var net = new Network("net"); var app = new Application("app"); - var net_con_app = autocon("net_con_app", net, app); // open port + var net_con_app = new ConnectionRule("net_con_app"); + net.addOutgoingNetConnections(net_con_app); + app.addIngoingAppConnections(net_con_app); // open port var user = new Identity("user"); var sensitiveData = new Data("sensitiveData"); - containerAdd(app, sensitiveData); - mkReadApi(app, user, sensitiveData); + app.addContainedData(sensitiveData); + user.addLowPrivApps(app); + app.addContainedData(sensitiveData); + user.addReadPrivData(sensitiveData); var recoveryUser = new Identity("recoveryUser"); - aOwnsB(recoveryUser, user); // recoveryUser can assume user + recoveryUser.addParentId(user); // recoveryUser can assume user var recoverMechanism = new Application("recoverMechanism"); - containerAdd(app, recoverMechanism); - appExecAs(recoverMechanism, recoveryUser); + app.addAppExecutedApps(recoverMechanism); + recoveryUser.addExecPrivApps(recoverMechanism); - var net_con_recovery = autocon("net_con_recovery", net, recoverMechanism); // open port + var net_con_recovery = new ConnectionRule("net_con_recovery"); + net.addOutgoingNetConnections(net_con_recovery); + recoverMechanism.addIngoingAppConnections(net_con_recovery); // open port - var vuln = vulnerabilityBuilder("vuln").setNetwork().setCIA().build(); + var vuln = new SoftwareVulnerability("vuln"); + vuln.networkAccessRequired.defaultValue = true; recoverMechanism.addVulnerabilities(vuln); - attack(net.access); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.attack(); - compromised(1, recoverMechanism.fullAccess); - compromised(1, recoveryUser.assume); - compromised(1, user.assume); - compromised(1, app.specificAccessAuthenticate); - compromised(1, sensitiveData.read); + assertReached(recoverMechanism.fullAccess); + assertReached(recoveryUser.assume); + assertReached(user.assume); + assertReached(app.specificAccessAuthenticate); + assertReached(sensitiveData.read); } @Test @@ -317,15 +319,18 @@ public void privilege_escalation_confused_sheriff() { var user = new Identity("user"); var root = new Identity("root"); - mkExecApi(app, user); // vulnerability - appExecAs(app, root); + user.addHighPrivApps(app); // vulnerability + root.addExecPrivApps(app); - aOwnsB(root, user); // optional + root.addParentId(user); // optional // Attacker escalates from user to root: - attack(user.assume, app.networkConnect); + var attacker = new Attacker(); + attacker.addAttackPoint(user.assume); + attacker.addAttackPoint(app.networkConnect); + attacker.attack(); - compromised(1, root.assume); + assertReached(root.assume); } @Test @@ -334,27 +339,30 @@ public void privilege_escalation_child_app_to_parent_app_via_vulnerability() { var parentApp = new Application("parentApp"); var childApp = new Application("childApp"); - containerAdd(parentApp, childApp); + parentApp.addAppExecutedApps(childApp); - var vuln = vulnerabilityBuilder("vuln").setLocal().setCIA().build(); + var vuln = new SoftwareVulnerability("vuln"); + vuln.localAccessRequired.defaultValue = true; parentApp.addVulnerabilities(vuln); var root = new Identity("root"); var user = new Identity("user"); // optional - aOwnsB(root, user); // optional - - appExecAs(parentApp, root); - appExecAs(childApp, user); - - var startSet = attack(childApp.fullAccess); - - compromised(1, user.assume); // because child full access - compromised(1, parentApp.localConnect); - compromised(1, parentApp.read); - compromised(1, parentApp.deny); - compromised(1, parentApp.modify); // (always leads to fullAccess) - compromised(1, parentApp.fullAccess); - compromised(1, root.assume); // because parent fullAccess + root.addParentId(user); // optional + + root.addExecPrivApps(parentApp); + user.addExecPrivApps(childApp); + + var attacker = new Attacker(); + attacker.addAttackPoint(childApp.fullAccess); + attacker.attack(); + + assertReached(user.assume); // because child full access + assertReached(parentApp.localConnect); + assertReached(parentApp.read); + assertReached(parentApp.deny); + assertReached(parentApp.modify); // (always leads to fullAccess) + assertReached(parentApp.fullAccess); + assertReached(root.assume); // because parent fullAccess } @Test @@ -363,26 +371,28 @@ public void privilege_escalation_child_app_to_parent_app_via_api() { var parentApp = new Application("parentApp"); var childApp = new Application("childApp"); - containerAdd(parentApp, childApp); + parentApp.addAppExecutedApps(childApp); var root = new Identity("root"); var user = new Identity("user"); // optional - aOwnsB(root, user); // optional + root.addParentId(user); // optional - mkExecApi(parentApp, user); // privilege escalation: anyone -> root + user.addHighPrivApps(parentApp); // privilege escalation: anyone -> root - appExecAs(parentApp, root); - appExecAs(childApp, user); + root.addExecPrivApps(parentApp); + user.addExecPrivApps(childApp); - var startSet = attack(childApp.fullAccess); + var attacker = new Attacker(); + attacker.addAttackPoint(childApp.fullAccess); + attacker.attack(); - compromised(1, user.assume); - compromised(1, parentApp.localConnect); - compromised(1, parentApp.read); - compromised(1, parentApp.modify); - compromised(1, parentApp.deny); - compromised(1, parentApp.fullAccess); - compromised(1, root.assume); // because parent fullAccess + assertReached(user.assume); + assertReached(parentApp.localConnect); + assertReached(parentApp.read); + assertReached(parentApp.modify); + assertReached(parentApp.deny); + assertReached(parentApp.fullAccess); + assertReached(root.assume); // because parent fullAccess } @Test @@ -393,30 +403,47 @@ public void privilege_escalation_app_low_to_high_via_vulnerability() { var net = new Network("net"); var app = new Application("ap"); - var net_con_app = autocon("net_con_app", net, app); // open port + var net_con_app = new ConnectionRule("net_con_app"); + net.addOutgoingNetConnections(net_con_app); + app.addIngoingAppConnections(net_con_app); // open port var admin = new Identity("admin"); var user = new Identity("user"); - appExecAs(app, admin); + admin.addExecPrivApps(app); var userData = new Data("userData"); - mkReadWriteApi(app, user, userData); + user.addLowPrivApps(app); + app.addContainedData(userData); + user.addReadPrivData(userData); + user.addLowPrivApps(app); + app.addContainedData(userData); + user.addWritePrivData(userData); var adminData = new Data("adminData"); - mkReadWriteApi(app, admin, adminData); - - var vuln = vulnerabilityBuilder("vuln").setNetwork().setPrivLow().setCIA().build(); + admin.addLowPrivApps(app); + app.addContainedData(adminData); + admin.addReadPrivData(adminData); + admin.addLowPrivApps(app); + app.addContainedData(adminData); + admin.addWritePrivData(adminData); + + var vuln = new SoftwareVulnerability("vuln"); + vuln.networkAccessRequired.defaultValue = true; + vuln.lowPrivilegesRequired.defaultValue = true; app.addVulnerabilities(vuln); - attack(net.access, user.assume); // sufficient to use vuln + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.addAttackPoint(user.assume); + attacker.attack(); // sufficient to use vuln - compromised(1, user.assume); // ok - compromised(1, admin.assume); // escalation + assertReached(user.assume); // ok + assertReached(admin.assume); // escalation - compromised(1, userData.read); // ok - compromised(1, adminData.read); // escalation + assertReached(userData.read); // ok + assertReached(adminData.read); // escalation } @Test @@ -429,12 +456,16 @@ public void horizontal_privilege_escalation_user_to_user() { var apiA = new Application("apiA"); var apiB = new Application("apiB"); - containerAdd(server, apiA); - containerAdd(server, apiB); + server.addAppExecutedApps(apiA); + server.addAppExecutedApps(apiB); var net = new Network("net"); - var conA = autocon("conA", net, apiA); - var conB = autocon("conB", net, apiB); + var conA = new ConnectionRule("conA"); + net.addOutgoingNetConnections(conA); + apiA.addIngoingAppConnections(conA); + var conB = new ConnectionRule("conB"); + net.addOutgoingNetConnections(conB); + apiB.addIngoingAppConnections(conB); var userA = new Identity("userA"); var userB = new Identity("userB"); @@ -444,16 +475,23 @@ public void horizontal_privilege_escalation_user_to_user() { var dataA = new Data("dataA"); var dataB = new Data("dataB"); - containerAdd(storage, dataA); - containerAdd(storage, dataB); // vulnerability + storage.addContainedData(dataA); + storage.addContainedData(dataB); // vulnerability - mkReadApi(apiA, userA, storage); // vulnerability - mkReadApi(apiB, userB, storage); + userA.addLowPrivApps(apiA); + apiA.addContainedData(storage); + userA.addReadPrivData(storage); // vulnerability + userB.addLowPrivApps(apiB); + apiB.addContainedData(storage); + userB.addReadPrivData(storage); - attack(net.access, userA.assume); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.addAttackPoint(userA.assume); + attacker.attack(); - compromised(1, dataA.read); - compromised(1, dataB.read); // horizontal privilege escalation. + assertReached(dataA.read); + assertReached(dataB.read); // horizontal privilege escalation. } @@ -468,11 +506,15 @@ public void network_dos() { var app = new Application("app"); var net = new Network("net"); - var net_con_app = autocon("net_con_app", app, net); + var net_con_app = new ConnectionRule("net_con_app"); + app.addOutgoingAppConnections(net_con_app); + net.addIngoingNetConnections(net_con_app); - attack(net.access); + var attacker = new Attacker(); + attacker.addAttackPoint(net.access); + attacker.attack(); - compromised(1, net.denialOfService); - compromised(1, app.deny); + assertReached(net.denialOfService); + assertReached(app.deny); } } diff --git a/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java b/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java index 2f92cc6..958ec94 100644 --- a/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java +++ b/src/test/java/org/mal_lang/corelang/test/patriot/TestPhysical.java @@ -23,7 +23,7 @@ * intellectual property via hardware defenses?). * */ -public class TestPhysical extends Base { +public class TestPhysical extends CoreLangTest { @Test public void hardware_vulnerability() { @@ -50,14 +50,14 @@ public void hardware_vulnerability() { var sys = new org.mal_lang.corelang.test.System("sys"); var app = new Application("app"); - containerAdd(phy, sys); - containerAdd(sys, app); + phy.addSystems(sys); + sys.addSysExecutedApps(app); var sysData = new Data("sysData"); var appData = new Data("appData"); - containerAdd(sys, sysData); - containerAdd(app, appData); + sys.addSysData(sysData); + app.addContainedData(appData); // TODO currently physical exploits are not full implemented in // coreLang 0.2.0. For now we will just model this as "anyone" having access. @@ -66,10 +66,13 @@ public void hardware_vulnerability() { var anyone = new Identity("anyone"); sys.addHighPrivSysIds(anyone); - attack(phy.gainPhysicalAccess, anyone.assume); + var attacker = new Attacker(); + attacker.addAttackPoint(phy.gainPhysicalAccess); + attacker.addAttackPoint(anyone.assume); + attacker.attack(); - compromised(1, sysData.read); - compromised(1, appData.read); + assertReached(sysData.read); + assertReached(appData.read); } @Test @@ -95,13 +98,15 @@ public void firmware_is_available_on_the_internet() { var firmwareBlob = new Data("firmwareBlob"); var sensitiveData = new Data("sensitiveData"); - transferData(internet, firmwareBlob); - containerAdd(firmwareBlob, sensitiveData); + firmwareBlob.addTransitNetwork(internet); + firmwareBlob.addContainedData(sensitiveData); - attack(internet.access); + var attacker = new Attacker(); + attacker.addAttackPoint(internet.access); + attacker.attack(); - compromised(1, sensitiveData.read); - compromised(1, sensitiveData.write); + assertReached(sensitiveData.read); + assertReached(sensitiveData.write); } @Test @@ -109,34 +114,41 @@ public void firmware_is_available_via_cloud_api() { var internet = new Network("internet"); var cloud = new Application("cloud"); - var con_internet_cloud = autocon("con_internet_cloud", internet, cloud); + var con_internet_cloud = new ConnectionRule("con_internet_cloud"); + internet.addOutgoingNetConnections(con_internet_cloud); + cloud.addIngoingAppConnections(con_internet_cloud); var firmwareBlob = new Data("firmwareBlob"); var sensitiveData = new Data("sensitiveData"); - containerAdd(cloud, firmwareBlob); - containerAdd(firmwareBlob, sensitiveData); + cloud.addContainedData(firmwareBlob); + firmwareBlob.addContainedData(sensitiveData); var anyone = new Identity("anyone"); - mkReadApi(cloud, anyone, firmwareBlob); + anyone.addLowPrivApps(cloud); + cloud.addContainedData(firmwareBlob); + anyone.addReadPrivData(firmwareBlob); - attack(internet.access, anyone.attemptAssume); + var attacker = new Attacker(); + attacker.addAttackPoint(internet.access); + attacker.addAttackPoint(anyone.attemptAssume); + attacker.attack(); - compromised(1, cloud.specificAccessAuthenticate); - compromised(1, cloud.specificAccess); + assertReached(cloud.specificAccessAuthenticate); + assertReached(cloud.specificAccess); - compromised(1, firmwareBlob.attemptAccessFromIdentity); - compromised(1, firmwareBlob.identityRead); - compromised(1, firmwareBlob.attemptRead); - compromised(1, firmwareBlob.read); + assertReached(firmwareBlob.attemptAccessFromIdentity); + assertReached(firmwareBlob.identityRead); + assertReached(firmwareBlob.attemptRead); + assertReached(firmwareBlob.read); - compromised(1, sensitiveData.attemptRead); - compromised(1, sensitiveData.read); + assertReached(sensitiveData.attemptRead); + assertReached(sensitiveData.read); - compromised(0, firmwareBlob.write); - compromised(0, sensitiveData.write); + assertNotReached(firmwareBlob.write); + assertNotReached(sensitiveData.write); } @@ -162,18 +174,24 @@ public void hardware_interfaces_as_networks_example1() { var spi = new Network("spi"); var app = new Application("app"); - var spi_con_app = autocon("spi_con_app", spi, app); + var spi_con_app = new ConnectionRule("spi_con_app"); + spi.addOutgoingNetConnections(spi_con_app); + app.addIngoingAppConnections(spi_con_app); var appData = new Data("appData"); - containerAdd(app, appData); + app.addContainedData(appData); - var vuln = vulnerabilityBuilder("vuln").setNetwork().setConfidentiality().build(); + var vuln = new SoftwareVulnerability("vuln"); + vuln.networkAccessRequired.defaultValue = true; + vuln.confidentialityImpactLimitations.defaultValue = false; app.addVulnerabilities(vuln); - var startSet = attack(spi.physicalAccess); + var attacker = new Attacker(); + attacker.addAttackPoint(spi.physicalAccess); + attacker.attack(); - compromised(1, vuln.abuse); - compromised(1, appData.read); + assertReached(vuln.abuse); + assertReached(appData.read); } @Test @@ -184,34 +202,39 @@ public void root_shell_via_hardware_interface() { var app = new Application("app"); var shell = new Application("shell"); - containerAdd(os, app); - containerAdd(os, shell); + os.addAppExecutedApps(app); + os.addAppExecutedApps(shell); var ttl = new Network("ttl"); - var ttl_con_shell = autocon("ttl_con_shell", ttl, shell); + var ttl_con_shell = new ConnectionRule("ttl_con_shell"); + ttl.addOutgoingNetConnections(ttl_con_shell); + shell.addIngoingAppConnections(ttl_con_shell); var appData = new Data("appData"); - containerAdd(app, appData); + app.addContainedData(appData); var anyone = new Identity("anyone"); var root = new Identity("root"); - mkExecApi(shell, anyone); // privilege escalation: anyone -> root + anyone.addHighPrivApps(shell); // privilege escalation: anyone -> root - appExecAs(shell, root); - appExecAs(os, root); - appExecAs(app, root); + root.addExecPrivApps(shell); + root.addExecPrivApps(os); + root.addExecPrivApps(app); // TODO CoreLang could have an association between PhysicalZone and Network. - attack(ttl.physicalAccess, anyone.assume); - - compromised(1, shell.networkConnect); - compromised(1, shell.authenticate); - compromised(1, shell.fullAccess); - compromised(1, os.fullAccess); - compromised(1, app.fullAccess); - compromised(1, appData.read); + var attacker = new Attacker(); + attacker.addAttackPoint(ttl.physicalAccess); + attacker.addAttackPoint(anyone.assume); + attacker.attack(); + + assertReached(shell.networkConnect); + assertReached(shell.authenticate); + assertReached(shell.fullAccess); + assertReached(os.fullAccess); + assertReached(app.fullAccess); + assertReached(appData.read); } @Test @@ -222,24 +245,29 @@ public void bootloader_shell_via_hardware_interface() { var bootloader = new Application("bootloader"); // e.g. uboot var os = new Application("os"); - containerAdd(bootloader, os); + bootloader.addAppExecutedApps(os); var spi = new Network("spi"); - var spi_con_bootloader = autocon("spi_con_bootloader", spi, bootloader); + var spi_con_bootloader = new ConnectionRule("spi_con_bootloader"); + spi.addOutgoingNetConnections(spi_con_bootloader); + bootloader.addIngoingAppConnections(spi_con_bootloader); var sensitiveData = new Data("sensitiveData"); - containerAdd(os, sensitiveData); + os.addContainedData(sensitiveData); var anyone = new Identity("anyone"); - mkExecApi(bootloader, anyone); + anyone.addHighPrivApps(bootloader); - attack(spi.physicalAccess, anyone.assume); + var attacker = new Attacker(); + attacker.addAttackPoint(spi.physicalAccess); + attacker.addAttackPoint(anyone.assume); + attacker.attack(); - compromised(1, bootloader.fullAccess); - compromised(1, os.fullAccess); - compromised(1, sensitiveData.read); + assertReached(bootloader.fullAccess); + assertReached(os.fullAccess); + assertReached(sensitiveData.read); } @Test @@ -253,16 +281,25 @@ public void read_flash_from_adjacant_microprocessor() { var chipB = new Application("chipB"); // chipB could for example be a flash component or a chip that provides an API to a flash component. var i2c = new Network("i2c"); - var chipA_con_i2c = autocon("chipA_con_i2c", chipA, i2c); // chipA is a "master" - var i2c_con_chipB = autocon("i2c_con_chipB", i2c, chipB); // chipB is a "slave" + var chipA_con_i2c = new ConnectionRule("chipA_con_i2c"); + chipA.addOutgoingAppConnections(chipA_con_i2c); + i2c.addIngoingNetConnections(chipA_con_i2c); // chipA is a "master" + var i2c_con_chipB = new ConnectionRule("i2c_con_chipB"); + i2c.addOutgoingNetConnections(i2c_con_chipB); + chipB.addIngoingAppConnections(i2c_con_chipB); // chipB is a "slave" var anyone = new Identity("anyone"); var sensitiveData = new Data("sensitiveData"); - mkReadApi(chipB, anyone, sensitiveData); - - attack(chipA.fullAccess, anyone.assume); - compromised(1, sensitiveData.read); + anyone.addLowPrivApps(chipB); + chipB.addContainedData(sensitiveData); + anyone.addReadPrivData(sensitiveData); + + var attacker = new Attacker(); + attacker.addAttackPoint(chipA.fullAccess); + attacker.addAttackPoint(anyone.assume); + attacker.attack(); + assertReached(sensitiveData.read); } @Test @@ -282,24 +319,32 @@ public void install_firmware_via_hardware_interface() { var ttl = new Network("ttl"); - var ttl_con_app = autocon("ttl_con_app", ttl, app); + var ttl_con_app = new ConnectionRule("ttl_con_app"); + ttl.addOutgoingNetConnections(ttl_con_app); + app.addIngoingAppConnections(ttl_con_app); var firmwareBlob = new Data("firmwareBlob"); - containerAdd(app, firmwareBlob); + app.addContainedData(firmwareBlob); var firmwareProduct = new SoftwareProduct("firmwareProduct"); - execData(firmwareBlob, firmwareProduct, app); + firmwareProduct.addOriginData(firmwareBlob); + firmwareProduct.addSoftApplications(app); var anyone = new Identity("anyone"); - mkWriteApi(app, anyone, firmwareBlob); + anyone.addLowPrivApps(app); + app.addContainedData(firmwareBlob); + anyone.addWritePrivData(firmwareBlob); - attack(ttl.physicalAccess, anyone.assume); + var attacker = new Attacker(); + attacker.addAttackPoint(ttl.physicalAccess); + attacker.addAttackPoint(anyone.assume); + attacker.attack(); - compromised(1, firmwareBlob.write); // By writing to the firmwareblob... - compromised(1, app.fullAccess); // ... we can exec code. + assertReached(firmwareBlob.write); // By writing to the firmwareblob... + assertReached(app.fullAccess); // ... we can exec code. } @Test @@ -311,38 +356,38 @@ public void root_shell_via_spi_flash_filesystem_access() { var flash = new Application("flash"); var app = new Application("app"); - var spi_con_app = autocon("spi_con_app", spi, app); - var spi_con_flash = autocon("spi_con_app", spi, flash); + var spi_con_app = new ConnectionRule("spi_con_app"); + spi.addOutgoingNetConnections(spi_con_app); + app.addIngoingAppConnections(spi_con_app); + var spi_con_flash = new ConnectionRule("spi_con_app"); + spi.addOutgoingNetConnections(spi_con_flash); + flash.addIngoingAppConnections(spi_con_flash); var filesystem = new Data("filesystem"); var bootscript = new Data("bootscript"); - containerAdd(flash, filesystem); - containerAdd(filesystem, bootscript); + flash.addContainedData(filesystem); + filesystem.addContainedData(bootscript); var appProduct = new SoftwareProduct("appProduct"); - execData(bootscript, appProduct, app); + appProduct.addOriginData(bootscript); + appProduct.addSoftApplications(app); var anyone = new Identity("anyone"); - mkReadWriteApi(flash, anyone, filesystem); - - var startSet = attack(spi.physicalAccess, anyone.assume); - - compromised(1, filesystem.write); - compromised(1, bootscript.write); - compromised(1, app.fullAccess); + anyone.addLowPrivApps(flash); + flash.addContainedData(filesystem); + anyone.addReadPrivData(filesystem); + anyone.addLowPrivApps(flash); + flash.addContainedData(filesystem); + anyone.addWritePrivData(filesystem); + + var attacker = new Attacker(); + attacker.addAttackPoint(spi.physicalAccess); + attacker.addAttackPoint(anyone.assume); + attacker.attack(); + + assertReached(filesystem.write); + assertReached(bootscript.write); + assertReached(app.fullAccess); } - -// @Test -// public void test_t017() { -// // T017 (physical) Reset to insecure state -// // "An attacker could misuse reset functionality of the device if resetting results in insecure state." -// // -// // TODO coreLang does not really model state changes. We could -// // potentially model this as two separate models: one showing the -// // scenario leading up to the reset and one shoing the scenario -// // resulting from the reset. The reset can be modeled as the the -// // attacker doing Data.write to a specific Data asset representing the -// // reset API-function. See also rollback attacks. -// } }