Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ Instructions for AI coding agents working on this repository.

## Project overview

OWASP Security Shepherd is a web and mobile application security training platform. The web app is a Java servlet application built with Maven, deployed as a WAR on Tomcat. The mobile challenges are independent Android apps under `mobile/MobileShepherd/`.
OWASP Security Shepherd is a web and mobile application security training platform. The web app is a Java servlet application built with Maven, deployed as a WAR on Tomcat. The mobile challenges are an Android app under `mobile/`.

## Intentionally vulnerable code — DO NOT FIX

The following paths contain **deliberately insecure code** used for security training. Do not fix, refactor, or flag security vulnerabilities in these files:

- `src/main/java/servlets/module/lesson/` — lesson servlets with intentional vulnerabilities
- `src/main/java/servlets/module/challenge/` — challenge servlets with intentional vulnerabilities
- `mobile/MobileShepherd/` — mobile challenge apps with intentional vulnerabilities
- `mobile/` — Android app with the mobile challenges and intentional vulnerabilities

Security improvements should only be made to the **platform infrastructure** (authentication, session management, admin functions, DB layer, etc.), never to the training content.

Expand Down Expand Up @@ -206,7 +206,7 @@ The hostname must be the **Docker container name** (e.g. `secshep_mariadb`), not
- `src/main/resources/` — config and challenge properties files
- `src/test/java/` — unit tests
- `src/it/java/` — integration tests (require running DB containers)
- `mobile/MobileShepherd/` — independent Android apps (Gradle-based, not part of Maven build)
- `mobile/` — Android app (Gradle-based, not part of Maven build)
- `docs/` — documentation, published to https://owasp.github.io/SecurityShepherd/ (see "Documentation site" below)

### Documentation site
Expand Down
44 changes: 16 additions & 28 deletions mobile/.gitignore
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
# built application files
*.apk
*.ap_

# files for the dex VM
*.dex

# Java class files
*.class

# generated files
bin/
gen/

# Local configuration file (sdk path, etc)
local.properties

# Eclipse project files
.classpath
.project

# Proguard folder generated by Eclipse
proguard/

# Intellij project files
*.iml
*.ipr
*.iws
.idea/
.gradle
/local.properties
# Ignore all IDE project files
.idea/
/.idea/
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
# Local dev notes and planning docs
*.md
# Environment / secrets
.env
.env.*
1 change: 1 addition & 0 deletions mobile/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
79 changes: 79 additions & 0 deletions mobile/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
plugins {
id 'com.android.application'
}

android {
namespace 'org.owasp.mobileshepherd'
compileSdk 34

defaultConfig {
applicationId "org.owasp.mobileshepherd"
minSdk 21
targetSdk 34
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
testOptions {
unitTests {
returnDefaultValues = true
includeAndroidResources = true
}
}
sourceSets {
test {
java {
// These test files reference unimplemented modules — exclude from compilation
// until the corresponding fragments/models are implemented.
exclude 'org/owasp/mobileshepherd/InsecureData3Test.java'
exclude 'org/owasp/mobileshepherd/ReverseEngineering2Test.java'
exclude 'org/owasp/mobileshepherd/ReverseEngineeringChallenge3Test.java'
exclude 'org/owasp/mobileshepherd/SecurityMisconfigChallenge3Test.java'
exclude 'org/owasp/mobileshepherd/SupplyChainChallengeTest.java'
}
}
}
buildFeatures {
viewBinding true
}
}

dependencies {

implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.preference:preference:1.2.1'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.2'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
implementation 'androidx.navigation:navigation-fragment:2.7.7'
implementation 'androidx.navigation:navigation-ui:2.7.7'
implementation 'androidx.exifinterface:exifinterface:1.3.7'
implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'net.zetetic:android-database-sqlcipher:4.5.4'
implementation 'androidx.sqlite:sqlite:2.3.1'

// Unit testing
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.10'

// Instrumented testing
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
97 changes: 97 additions & 0 deletions mobile/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# ===================================
# REVERSE ENGINEERING LESSONS/CHALLENGES
# Keep these unobfuscated for educational purposes
# ===================================

# Reverse Engineering Lesson - meant to be reverse engineered
-keep class org.owasp.mobileshepherd.ui.lessons.** { *; }

# Reverse Engineering Challenges 1-3 - meant to be reverse engineered
-keep class org.owasp.mobileshepherd.ui.challenges.** { *; }

# ===================================
# OBFUSCATE EVERYTHING ELSE
# These should be protected from reverse engineering
# ===================================

# Keep names for ViewBinding and ViewModels to avoid runtime issues
-keep class org.owasp.mobileshepherd.databinding.** { *; }
-keep class * extends androidx.lifecycle.ViewModel { *; }

# Keep MainActivity and navigation infrastructure
-keep class org.owasp.mobileshepherd.MainActivity { *; }
-keep class org.owasp.mobileshepherd.LandingActivity { *; }
-keep class org.owasp.mobileshepherd.Preferences { *; }

# Keep Fragment classes but obfuscate their internals
-keepnames class * extends androidx.fragment.app.Fragment

# Keep these challenge/lesson packages OBFUSCATED (not in RE category)
# Insecure Data Storage - should be obfuscated
-keepnames class org.owasp.mobileshepherd.ui.lessons.insecuredata.**
-keepnames class org.owasp.mobileshepherd.ui.challenges.insecuredata1.**
-keepnames class org.owasp.mobileshepherd.ui.challenges.insecuredata3.**

# Poor Authentication - should be obfuscated
-keepnames class org.owasp.mobileshepherd.ui.lessons.poorauth.**
-keepnames class org.owasp.mobileshepherd.ui.challenges.poorauth.**

# Supply Chain Security - should be obfuscated
-keepnames class org.owasp.mobileshepherd.ui.lessons.supplychain.**
-keepnames class org.owasp.mobileshepherd.ui.challenges.supplychain.**

# Cryptography - should be obfuscated
-keepnames class org.owasp.mobileshepherd.ui.lessons.crypto.**
-keepnames class org.owasp.mobileshepherd.ui.challenges.crypto.**

# Security Misconfiguration - should be obfuscated
-keepnames class org.owasp.mobileshepherd.ui.lessons.securitymisconfig.**
-keepnames class org.owasp.mobileshepherd.ui.challenges.securitymisconfig.**

# Input Validation - should be obfuscated
-keepnames class org.owasp.mobileshepherd.ui.lessons.inputvalidation.**
-keepnames class org.owasp.mobileshepherd.ui.challenges.inputvalidation.**

# Insecure Authorization - should be obfuscated
-keepnames class org.owasp.mobileshepherd.ui.lessons.insecureauthorization.**

# Home fragment
-keepnames class org.owasp.mobileshepherd.ui.home.**

# Aggressive obfuscation settings
-optimizationpasses 5
-overloadaggressively
-repackageclasses ''
-allowaccessmodification

# Obfuscate string constants (except in RE packages)
-adaptclassstrings

# Remove logging for non-RE packages
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
public static *** i(...);
}

# Keep source file and line numbers for debugging
-keepattributes SourceFile,LineNumberTable
-renamesourcefileattribute SourceFile

# AndroidX and Material Components
-keep class androidx.** { *; }
-keep interface androidx.** { *; }
-keep class com.google.android.material.** { *; }

# Navigation component
-keep class androidx.navigation.** { *; }

# Prevent stripping of enum classes
-keepclassmembers enum * { *; }
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.owasp.mobileshepherd;

import android.content.Context;

import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.*;

/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("org.owasp.mobileshepherd", appContext.getPackageName());
}
}
70 changes: 70 additions & 0 deletions mobile/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />

<application
android:networkSecurityConfig="@xml/network_security_config"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Comment on lines +11 to +13
android:icon="@drawable/icon"
android:label="@string/app_name"
android:roundIcon="@drawable/icon"
android:supportsRtl="true"
android:theme="@style/Theme.Reverser"
tools:targetApi="31">
<activity
android:name=".LandingActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.Reverser.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity
android:name=".MainActivity"
android:exported="false"
android:label="@string/app_name"
android:theme="@style/Theme.Reverser.NoActionBar" />

<activity
android:name=".LoginActivity"
android:exported="false"
android:label="@string/app_name"
android:theme="@style/Theme.Reverser.NoActionBar">
</activity>

<activity android:name="Preferences"
android:label="@string/action_settings"
android:exported="true">
<intent-filter>
<action android:name="org.owasp.mobileshepherd.Preferences" />

<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>



<!-- FileProvider for camera image capture -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="org.owasp.mobileshepherd.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>

</application>

</manifest>
Loading
Loading