From ff233090f8a4247cfffcc63eb36d9ffeb0d347d6 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Thu, 30 Nov 2023 21:01:27 +0100 Subject: [PATCH] Add support for importing decrypted Steam JSON blob Some people have managed to snatch the OTP details from Steam using Xposed while it is being decrypted by the app. Aegis still won't be able to do the decryption part, but we can add support for importing the decrypted JSON blob, which only differs slightly from the old format. --- .../aegis/importers/SteamImporter.java | 36 ++++++++++++++----- .../aegis/importers/DatabaseImporterTest.java | 10 ++++++ .../aegis/importers/steam.json | 2 +- .../aegis/importers/steam_old.json | 1 + 4 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 app/src/test/resources/com/beemdevelopment/aegis/importers/steam_old.json diff --git a/app/src/main/java/com/beemdevelopment/aegis/importers/SteamImporter.java b/app/src/main/java/com/beemdevelopment/aegis/importers/SteamImporter.java index 68a5ebc5..bdb550ef 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/importers/SteamImporter.java +++ b/app/src/main/java/com/beemdevelopment/aegis/importers/SteamImporter.java @@ -18,6 +18,10 @@ import org.json.JSONObject; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.sql.Array; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; public class SteamImporter extends DatabaseImporter { private static final String _subDir = "files"; @@ -57,29 +61,43 @@ public class SteamImporter extends DatabaseImporter { try { byte[] bytes = IOUtils.readAll(stream); JSONObject obj = new JSONObject(new String(bytes, StandardCharsets.UTF_8)); - return new State(obj); + + List objs = new ArrayList<>(); + if (obj.has("accounts")) { + JSONObject accounts = obj.getJSONObject("accounts"); + Iterator keys = accounts.keys(); + while (keys.hasNext()) { + String key = keys.next(); + objs.add(accounts.getJSONObject(key)); + } + } else { + objs.add(obj); + } + return new State(objs); } catch (IOException | JSONException e) { throw new DatabaseImporterException(e); } } public static class State extends DatabaseImporter.State { - private JSONObject _obj; + private final List _objs; - private State(JSONObject obj) { + private State(List objs) { super(false); - _obj = obj; + _objs = objs; } @Override public Result convert() { Result result = new Result(); - try { - VaultEntry entry = convertEntry(_obj); - result.addEntry(entry); - } catch (DatabaseImporterEntryException e) { - result.addError(e); + for (JSONObject obj : _objs) { + try { + VaultEntry entry = convertEntry(obj); + result.addEntry(entry); + } catch (DatabaseImporterEntryException e) { + result.addError(e); + } } return result; diff --git a/app/src/test/java/com/beemdevelopment/aegis/importers/DatabaseImporterTest.java b/app/src/test/java/com/beemdevelopment/aegis/importers/DatabaseImporterTest.java index c9f1030a..68ee956a 100644 --- a/app/src/test/java/com/beemdevelopment/aegis/importers/DatabaseImporterTest.java +++ b/app/src/test/java/com/beemdevelopment/aegis/importers/DatabaseImporterTest.java @@ -263,6 +263,16 @@ public class DatabaseImporterTest { } } + @Test + public void testImportSteamOld() throws IOException, DatabaseImporterException, OtpInfoException { + List entries = importPlain(SteamImporter.class, "steam_old.json"); + for (VaultEntry entry : entries) { + VaultEntry entryVector = getEntryVectorBySecret(entry.getInfo().getSecret()); + entryVector.setIssuer("Steam"); + checkImportedEntry(entryVector, entry); + } + } + @Test public void testImportAuthenticatorPlus() throws IOException, DatabaseImporterException, OtpInfoException { List entries = importEncrypted(AuthenticatorPlusImporter.class, "authenticator_plus.zip", encryptedState -> { diff --git a/app/src/test/resources/com/beemdevelopment/aegis/importers/steam.json b/app/src/test/resources/com/beemdevelopment/aegis/importers/steam.json index 126f6e3f..4df35308 100644 --- a/app/src/test/resources/com/beemdevelopment/aegis/importers/steam.json +++ b/app/src/test/resources/com/beemdevelopment/aegis/importers/steam.json @@ -1 +1 @@ -{"steamid":"1234","shared_secret":"THIl8+Jl6ugxr8x0X6eRMg==","serial_number":"12345678901234567890","revocation_code":"R1234","uri":"otpauth:\/\/totp\/Steam:Sophia?secret=JRZCL47CMXVOQMNPZR2F7J4RGI&issuer=Steam","server_time":"0","account_name":"Sophia","token_gid":"894820a474c9","identity_secret":"dGhpcyBpcyBhIHRlc3Qgc3RyaW5n","secret_1":"eWV0IGFub3RoZXIgdGVzdCBzdHJpbmc=","status":1,"steamguard_scheme":"2"} +{"accounts":{"abcdefg":{"steamid":"1234","shared_secret":"THIl8+Jl6ugxr8x0X6eRMg==","serial_number":"12345678901234567890","revocation_code":"R1234","uri":"otpauth:\/\/totp\/Steam:Sophia?secret=JRZCL47CMXVOQMNPZR2F7J4RGI&issuer=Steam","server_time":"0","account_name":"Sophia","token_gid":"894820a474c9","identity_secret":"dGhpcyBpcyBhIHRlc3Qgc3RyaW5n","secret_1":"eWV0IGFub3RoZXIgdGVzdCBzdHJpbmc=","status":1,"steamguard_scheme":"2"}}} diff --git a/app/src/test/resources/com/beemdevelopment/aegis/importers/steam_old.json b/app/src/test/resources/com/beemdevelopment/aegis/importers/steam_old.json new file mode 100644 index 00000000..126f6e3f --- /dev/null +++ b/app/src/test/resources/com/beemdevelopment/aegis/importers/steam_old.json @@ -0,0 +1 @@ +{"steamid":"1234","shared_secret":"THIl8+Jl6ugxr8x0X6eRMg==","serial_number":"12345678901234567890","revocation_code":"R1234","uri":"otpauth:\/\/totp\/Steam:Sophia?secret=JRZCL47CMXVOQMNPZR2F7J4RGI&issuer=Steam","server_time":"0","account_name":"Sophia","token_gid":"894820a474c9","identity_secret":"dGhpcyBpcyBhIHRlc3Qgc3RyaW5n","secret_1":"eWV0IGFub3RoZXIgdGVzdCBzdHJpbmc=","status":1,"steamguard_scheme":"2"}