added Spar PoC, added objection and frida guide
This commit is contained in:
46
Spar/pocJava/app/build.gradle.kts
Normal file
46
Spar/pocJava/app/build.gradle.kts
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* This generated file contains a sample Java application project to get you started.
|
||||
* For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.3/userguide/building_java_projects.html in the Gradle documentation.
|
||||
* This project uses @Incubating APIs which are subject to change.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
// Apply the application plugin to add support for building a CLI application in Java.
|
||||
application
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://jitpack.io")
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.github.SAP.gigya-java-sdk:sdk:3.3.2")
|
||||
implementation("com.github.SAP.gigya-java-sdk:auth:3.3.2") // only if needed
|
||||
implementation("org.json:json:20230227") //missing dep declaration in sdk
|
||||
}
|
||||
|
||||
testing {
|
||||
suites {
|
||||
// Configure the built-in test suite
|
||||
val test by getting(JvmTestSuite::class) {
|
||||
// Use JUnit Jupiter test framework
|
||||
useJUnitJupiter("5.9.3")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply a specific Java toolchain to ease working on different environments.
|
||||
java {
|
||||
toolchain {
|
||||
// encoding
|
||||
languageVersion.set(JavaLanguageVersion.of(17))
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
// Define the main class for the application.
|
||||
mainClass.set("poc.App")
|
||||
}
|
||||
173
Spar/pocJava/app/src/main/java/poc/App.java
Normal file
173
Spar/pocJava/app/src/main/java/poc/App.java
Normal file
@@ -0,0 +1,173 @@
|
||||
package poc;
|
||||
|
||||
import com.gigya.auth.GSAnonymousRequest;
|
||||
import com.gigya.socialize.GSKeyNotFoundException;
|
||||
import com.gigya.socialize.GSObject;
|
||||
import com.gigya.socialize.GSRequest;
|
||||
import com.gigya.socialize.GSResponse;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class App {
|
||||
private static final String authHost = "eu2.gigya.com";
|
||||
private static final String authApiKey = "4_NfHE-cJJ9djefjHQU5x97Q";
|
||||
|
||||
private static final String apiProto = "https";
|
||||
private static final String apiHost = "api-scp.spar-ics.com";
|
||||
private static final String apiMount = "/mobile/b2c/apps/spar/at/be/v1/";
|
||||
|
||||
public static void main(String[] args) {
|
||||
var loginProcess = new LoginProcess("", "");
|
||||
loginProcess.perform().join();
|
||||
}
|
||||
|
||||
public static class LoginProcess {
|
||||
private final String username;
|
||||
private final String password;
|
||||
private String sessionToken;
|
||||
private String sessionSecret;
|
||||
private String uid;
|
||||
private String jwt;
|
||||
private Map<String, JSONObject> receiptsByBonId = new HashMap<>();
|
||||
private final Map<String, byte[]> receiptsPdfByBonId = new HashMap<>();
|
||||
|
||||
public LoginProcess(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public CompletableFuture<LoginProcess> perform() {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
login();
|
||||
getJWT();
|
||||
return null;
|
||||
})
|
||||
.thenComposeAsync(v -> receipts())
|
||||
.thenComposeAsync(v -> {
|
||||
var future = CompletableFuture.<Void>completedFuture(null);
|
||||
for (String receiptBonId : receiptsByBonId.keySet()) {
|
||||
future = future.thenCompose(v2 -> receiptById(receiptBonId));
|
||||
}
|
||||
return future;
|
||||
})
|
||||
.thenAccept(v -> dump())
|
||||
.thenApply(v -> this);
|
||||
}
|
||||
|
||||
private void login() {
|
||||
var loginRequest = new GSAnonymousRequest(authApiKey, authHost, "accounts.login");
|
||||
loginRequest.setParam("loginID", username);
|
||||
loginRequest.setParam("password", password);
|
||||
loginRequest.setParam("loginMode", "standard");
|
||||
loginRequest.setParam("targetEnv", "mobile");
|
||||
|
||||
final GSResponse response = loginRequest.send();
|
||||
if (response.getErrorCode() != 0) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
try {
|
||||
sessionToken = response.getData().getObject("sessionInfo").getString("sessionToken");
|
||||
sessionSecret = response.getData().getObject("sessionInfo").getString("sessionSecret");
|
||||
uid = response.getData().getString("UID");
|
||||
} catch (GSKeyNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void getJWT() {
|
||||
var jwtRequest = new GSRequest(authApiKey, sessionSecret, null, "accounts.getJWT", new GSObject(), true);
|
||||
// var jwtRequest = new GSAuthRequest(authApiKey, sessionSecret, sessionToken, "accounts.getJWT", new GSObject(), true);
|
||||
jwtRequest.setAPIDomain(authHost);
|
||||
jwtRequest.setParam("UID", uid);
|
||||
jwtRequest.setParam("oauth_token", sessionToken);
|
||||
jwtRequest.setParam("targetEnv", "mobile");
|
||||
jwtRequest.setParam("fields", "UID,isVerified");
|
||||
final GSResponse response = jwtRequest.send();
|
||||
if (response.getErrorCode() != 0) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
try {
|
||||
this.jwt = response.getData().getString("id_token");
|
||||
} catch (GSKeyNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> receipts() {
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(apiProto + "://" + apiHost + apiMount + "v1/receipts"))
|
||||
.header("Authorization", "Bearer " + this.jwt)
|
||||
.build();
|
||||
return client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
|
||||
.thenApply(res -> {
|
||||
if (res.statusCode() != 200) {
|
||||
throw new RuntimeException("Status code: " + res.statusCode() + "\n" + res.body());
|
||||
}
|
||||
return res;
|
||||
})
|
||||
.thenApply(HttpResponse::body)
|
||||
.thenAccept(body -> {
|
||||
var receipts = new JSONObject(body).getJSONArray("receipt");
|
||||
this.receiptsByBonId = IntStream.range(0, receipts.length())
|
||||
.mapToObj(receipts::getJSONObject)
|
||||
.collect(Collectors.toMap(e -> e.getString("bonId"), e -> e));
|
||||
});
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> receiptById(String bonId) {
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(apiProto + "://" + apiHost + apiMount + "v1/receipt/" + bonId))
|
||||
.header("Authorization", "Bearer " + this.jwt)
|
||||
.build();
|
||||
return client.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray())
|
||||
.thenApply(res -> {
|
||||
if (res.statusCode() != 200) {
|
||||
throw new RuntimeException("Status code: " + res.statusCode() + "\n" + new String(res.body()));
|
||||
}
|
||||
return res;
|
||||
})
|
||||
.thenApply(HttpResponse::body)
|
||||
.thenAccept(body -> this.receiptsPdfByBonId.put(bonId, body));
|
||||
}
|
||||
|
||||
private void dump() {
|
||||
try {
|
||||
new File("dump").mkdirs();
|
||||
|
||||
//dump meta
|
||||
var j = new JSONArray();
|
||||
this.receiptsByBonId.values().forEach(j::put);
|
||||
Files.writeString(Path.of("dump", "receipts.json"), j.toString(2),
|
||||
StandardOpenOption.CREATE,
|
||||
StandardOpenOption.TRUNCATE_EXISTING);
|
||||
|
||||
//dump pdfs
|
||||
for (var e : this.receiptsPdfByBonId.entrySet()) {
|
||||
Files.write(Path.of("dump", e.getKey() + ".pdf"), e.getValue(),
|
||||
StandardOpenOption.CREATE,
|
||||
StandardOpenOption.TRUNCATE_EXISTING);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Spar/pocJava/app/src/test/java/poc/AppTest.java
Normal file
14
Spar/pocJava/app/src/test/java/poc/AppTest.java
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* This Java source file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
package poc;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class AppTest {
|
||||
@Test void appHasAGreeting() {
|
||||
// App classUnderTest = new App();
|
||||
// assertNotNull(classUnderTest.getGreeting(), "app should have a greeting");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user