Skip to content

Commit 74f9084

Browse files
committed
Merge branch 'testing'
2 parents dc21a46 + 3f62e54 commit 74f9084

3 files changed

Lines changed: 91 additions & 0 deletions

File tree

internal/api/ui/apkauditor/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ <h2 id="appName">App Name</h2>
186186

187187
<section id="panel-overview" class="panel active" role="tabpanel">
188188
<div class="stats-grid" id="overviewStats"></div>
189+
<div class="mitm-readiness" id="mitmReadiness"></div>
189190
<div class="results-section">
190191
<div class="results-header"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>Application</div>
191192
<div id="appInfoGrid" class="results-body"></div>

internal/api/ui/apkauditor/src/main.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,70 @@ function updateBadges(r) {
250250
}
251251
}
252252

253+
// computeMitmReadiness assesses — purely from the static analysis already done in
254+
// the browser — whether the app can be prepped for HTTPS interception with
255+
// apk-mitm. No server-side toolchain (apktool/JRE) is involved; it just reads the
256+
// findings the engine produced (pinning, integrity checks, trust-all) + appInfo.
257+
function computeMitmReadiness(r) {
258+
const ids = new Set((r.findings || []).map(f => f.ruleId));
259+
const pinning = ids.has('cert_pinning'); // CertificatePinner / pin-sha256 / PublicKeyPinning
260+
const antiTamper = ids.has('integrity_check'); // SafetyNet / Play Integrity
261+
const trustAll = ids.has('trust_all'); // app already accepts all certs
262+
const nsc = !!(r.appInfo && r.appInfo.networkSecurityConfig);
263+
const targetSdk = (r.appInfo && r.appInfo.targetSdk) || 0;
264+
265+
let level, verdict, tip;
266+
if (antiTamper) {
267+
level = 'hard';
268+
verdict = 'Integrity / attestation present';
269+
tip = 'SafetyNet / Play Integrity was detected — re-signing with a debug key (what apk-mitm does) is often detected, so the app may refuse to run or fail its requests. You can still try apk-mitm, but you will likely also need to bypass attestation at runtime with Frida.';
270+
} else if (pinning) {
271+
level = 'pinned';
272+
verdict = 'Patchable, but pinned';
273+
tip = 'Certificate pinning was detected. apk-mitm defeats Network-Security-Config / system-trust pinning, but programmatic pinning (OkHttp CertificatePinner, TrustKit) can survive it. Patch with apk-mitm; if interception still fails, disable pinning at runtime with Frida / objection ("android sslpinning disable").';
274+
} else if (trustAll) {
275+
level = 'easy';
276+
verdict = 'Trivially interceptable';
277+
tip = 'The app already accepts all certificates / uses a permissive trust manager — MITM is usually trivial. Installing your CA (or a quick apk-mitm patch) should be enough.';
278+
} else {
279+
level = 'ready';
280+
verdict = 'Likely patchable';
281+
tip = (targetSdk >= 24
282+
? 'Targets Android 7+, so it will not trust user-installed CAs by default — which is exactly what apk-mitm fixes. '
283+
: '') + 'No certificate pinning or integrity checks were detected, so apk-mitm\'s standard patch (trust user CAs + drop NSC pinning) should let you intercept its HTTPS traffic. Patch it locally with "npx apk-mitm <app>.apk", install the patched build, and proxy through Burp/mitmproxy.';
284+
}
285+
return { level, verdict, pinning, antiTamper, trustAll, nsc, tip };
286+
}
287+
288+
function renderMitmReadiness(r) {
289+
const el = document.getElementById('mitmReadiness');
290+
if (!el) return;
291+
const m = computeMitmReadiness(r);
292+
const META = {
293+
ready: { tag: 'READY', ic: '✓' },
294+
easy: { tag: 'EASY', ic: '✓' },
295+
pinned: { tag: 'PINNED', ic: '!' },
296+
hard: { tag: 'HARD', ic: '✕' },
297+
}[m.level];
298+
const chips = [
299+
m.pinning ? 'Cert pinning' : null,
300+
m.antiTamper ? 'Integrity / attestation' : null,
301+
m.trustAll ? 'Accepts all certs' : null,
302+
m.nsc ? 'Has network security config' : 'No network security config',
303+
].filter(Boolean);
304+
el.innerHTML = html`
305+
<div class="mitm-card mitm-${m.level}">
306+
<div class="mitm-head">
307+
<span class="mitm-badge">${META.ic + ' ' + META.tag}</span>
308+
<span class="mitm-title">MITM Readiness — ${m.verdict}</span>
309+
</div>
310+
<div class="mitm-chips">${chips.map(c => ({ __raw: true, html: `<span class="mitm-chip">${esc(c)}</span>` }))}</div>
311+
<div class="mitm-tip">${m.tip}</div>
312+
</div>`;
313+
}
314+
253315
function renderOverview(r) {
316+
renderMitmReadiness(r);
254317
const s = r.summary || { issue: 0, info: 0, secure: 0 };
255318
const issue = s.issue || 0, info = s.info || 0, secure = s.secure || 0;
256319
const score = r.securityScore != null ? r.securityScore : 0;

internal/api/ui/apkauditor/src/styles.css

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,3 +1024,30 @@ input, select { font: inherit; color: inherit; }
10241024
.stats-grid { grid-template-columns: 1fr; }
10251025
.quick-access-list { grid-template-columns: 1fr; }
10261026
}
1027+
1028+
/* ── MITM Readiness card (Overview) ────────────────────────────────────────── */
1029+
.mitm-readiness { margin: 0 0 22px; }
1030+
.mitm-card {
1031+
border: 1px solid var(--lum-30);
1032+
border-left: 4px solid var(--mitm-c, var(--vital));
1033+
border-radius: 14px;
1034+
padding: 14px 16px;
1035+
background: var(--mitm-bg, rgba(52, 211, 153, 0.06));
1036+
}
1037+
.mitm-ready, .mitm-easy { --mitm-c: var(--vital); --mitm-bg: rgba(52, 211, 153, 0.06); }
1038+
.mitm-pinned { --mitm-c: var(--warm); --mitm-bg: rgba(251, 146, 60, 0.06); }
1039+
.mitm-hard { --mitm-c: var(--alert); --mitm-bg: rgba(244, 63, 94, 0.06); }
1040+
.mitm-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
1041+
.mitm-badge {
1042+
background: var(--mitm-c, var(--vital));
1043+
color: var(--depth-1);
1044+
font-size: 11px; font-weight: 800; letter-spacing: 0.04em;
1045+
padding: 3px 9px; border-radius: 6px; white-space: nowrap;
1046+
}
1047+
.mitm-title { font-size: 14px; font-weight: 700; color: var(--lum-90); }
1048+
.mitm-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 11px 0 9px; }
1049+
.mitm-chip {
1050+
font-size: 11px; padding: 2px 9px; border-radius: 999px;
1051+
border: 1px solid var(--lum-30); color: var(--lum-70);
1052+
}
1053+
.mitm-tip { font-size: 12.5px; line-height: 1.55; color: var(--lum-70); }

0 commit comments

Comments
 (0)