diff --git a/README.md b/README.md index 478edcb..daeeb36 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This Chromium extensions aims to support the analysis of single sign-on implemen ![Demo Screenshot](demo_screenshot2.png) ## Features -* View request parameters at a glance. +* View request parameters at a glance, either via the *popup* or the *developer tools panel*. * Hover over standardized parameters for background information about parameters. * Manually modify request parameters. * Detailed Analysis of request parameters: @@ -23,11 +23,13 @@ This Chromium extensions aims to support the analysis of single sign-on implemen It is highly recommended to use the latest stable release from [Chrome WebStore](https://chrome.google.com/webstore/detail/clonpaankbndgnciijbiokgjeofjdpeg). -Alternatively, you may either use the latest build published in this repository or directly use the *unpacked sources*. To use the *unpacked sources*, follow these steps: +Alternatively, you may either use the latest build published in this repository or directly use the *unpacked sources*. To use the *unpacked sources*, follow these steps (macOS, Linux): 1. Clone this repository. -2. Visit chrome://extensions/. -3. Enable *Developer mode* (attention, do not enable this option in your "productive" browser!). -4. Specify the cloned folder. +2. Execute `build.sh` script. +3. Unpack created ZIP archive (`auth-request-analyser_submission_chrome_yy-mm-dd-HH-MM-SS.zip`). +4. Visit chrome://extensions/. +5. Enable *Developer mode* (attention, do not enable this option in your "productive" browser!). +6. Specify the cloned folder. ## Privacy diff --git a/popup.html b/application.html similarity index 99% rename from popup.html rename to application.html index e647922..8542841 100644 --- a/popup.html +++ b/application.html @@ -152,6 +152,6 @@

What you should try:

- + \ No newline at end of file diff --git a/popup.js b/application.js similarity index 84% rename from popup.js rename to application.js index f7f3ae9..5b3d27b 100644 --- a/popup.js +++ b/application.js @@ -82,7 +82,7 @@ function processAuthRequest(urlString) { urlParams = new URLSearchParams(url.search); if (!isAuthRequest(urlParams)) { - console.log("Error: The given URL does not include all REQUIRED parameters for Auth. Requests."); + console.log("Error: The given URL does not include all REQUIRED parameters for Auth. Requests. It known that some implementations does not follow the spec and only use client_id or app_id. Thus, there may be a change of the detection rules in the future"); return -1; } else { noAuthRequest.style.display = "none"; @@ -223,7 +223,7 @@ function performAnalysis(params) { // Change PKCE code_challenge_method to plain: https://datatracker.ietf.org/doc/html/rfc7636#section-7.2 if(params.get('code_challenge_method') === "S256") { list_element = document.createElement("li"); - list_element.innerHTML = 'The current flow uses \'S256\' as code_challenge_method, but \'plain\' may also be allowed. The \'plain\' option only exists for compatibility reasons and SHOULD NOT be used´. See literature.'; + list_element.innerHTML = 'The current flow uses \'S256\' as code_challenge_method, but \'plain\' may also be allowed. The \'plain\' option only exists for compatibility reasons and SHOULD NOT be used. See literature.'; attacksList.appendChild(list_element); document.getElementById("attackPkcePlain").addEventListener("click", launchAttackPkcePlain); } @@ -239,8 +239,11 @@ function performAnalysis(params) { // Adjust Redirect URI: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.1.3 if(params.get('redirect_uri')) { list_element = document.createElement("li"); - list_element.innerHTML = 'If the \'redirect_uri\' parameter is present, the authorization server MUST compare it against pre-defined redirection URI values using simple string comparison (RFC3986). Try to fiddle around with different schemes, (sub-)domains, paths, query parameters and fragments. Lax validation may lead to token disclosure. See literature.'; + list_element.innerHTML = 'If the \'redirect_uri\' parameter is present, the authorization server MUST compare it against pre-defined redirection URI values using simple string comparison (RFC3986). Try to fiddle around with different schemes, (sub-)domains, paths, query parameters and fragments. Lax validation may lead to token disclosure. Exemplary attack ideas: See literature.'; attacksList.appendChild(list_element); + Array.from(document.getElementsByClassName("attackRedirectUri")).forEach(function(button) { + button.addEventListener("click", launchAttackRedirectUri, false); + }); } } @@ -360,6 +363,55 @@ function launchAttackResponseMode() { setParameterAndReload("response_mode", "fragment"); } +function launchAttackRedirectUri(event) { + let variant = parseInt(event.target.dataset.variant); + let redirect_uri = new URL(urlParams.get("redirect_uri")); + + // Manipulate redirect_uri depending on the clicked button + switch (variant) { + case 0: + // Use http:// scheme (we assume here that the default is https://) + redirect_uri.protocol = "http:"; + break; + case 1: + // Use aura-test:// scheme (should be non-existent) + // Scenario: If this works, a native app could be used to leak the Auth. Response + redirect_uri.protocol = "aura-test:"; + break; + case 2: + // Append something to path + // Scenario: If this works, a XSS or open redirect can be used to leak the Auth. Response + if(redirect_uri.pathname.slice(-1) === "/") { + redirect_uri.pathname = redirect_uri.pathname + "aura-test"; + } + else { + redirect_uri.pathname = redirect_uri.pathname + "/aura-test"; + } + break; + case 3: + // Use imaginary Subdomain + // Scenario: If this works, a XSS or open redirect or subdomain takeover can be used to leak the Auth. Response on any subdomain + redirect_uri.hostname = "aura-test." + redirect_uri.hostname; + break; + case 4: + // Add arbitrary parameter + // Scenario: If this works, 1) this may enable open redirect or XSS issues, 2) this may allow parameter pollution: https://security.lauritz-holtmann.de/post/sso-security-redirect-uri-ii/ + redirect_uri.searchParams.set("aura-test", 1); + break; + case 5: + // Add arbitrary location hash - variant of 4 + if(redirect_uri.hash) { + redirect_uri.hash = redirect_uri.hash + "&aura-test=1"; + } else { + redirect_uri.hash = "aura-test"; + } + break; + default: + alert("Whoops, something went wrong :("); + } + setParameterAndReload("redirect_uri", redirect_uri.toString()); +} + /**************************************************************************************************/ document.addEventListener("DOMContentLoaded", function() { // Event listeners for UI elements diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..6f5fbac --- /dev/null +++ b/build.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Helper Methods +copy_sources_to_tmp_generic () { + cp -r . /tmp/auth-request-analyser-generic +} + +copy_sources_tmp_chrome () { + cp -r /tmp/auth-request-analyser-generic /tmp/auth-request-analyser-chrome +} + +remove_sources_tmp () { + rm -rf /tmp/auth-request-analyser-generic + rm -rf /tmp/auth-request-analyser-chrome +} + +cleanup_generic_directory () { + echo " [+] Clean source directory... remove screenshot files" + rm /tmp/auth-request-analyser-generic/*screenshot*.png + echo " [+] Clean source directory... remove .git* files and directories" + rm -rf /tmp/auth-request-analyser-generic/.git* + echo " [+] Clean source directory... remove *.md files" + rm /tmp/auth-request-analyser-generic/*.md + echo " [+] Clean source directory... remove .DS_Store" + rm /tmp/auth-request-analyser-generic/.DS_Store* + echo " [+] Clean source directory... remove build script" + rm /tmp/auth-request-analyser-generic/build.sh +} + +pack_extension_chrome () { + zip -r -j "../auth-request-analyser_submission_chrome_$(date '+%Y-%m-%d-%H-%M-%S').zip" /tmp/auth-request-analyser-chrome/ +} + +create_crx_chrome () { + echo " [+] Extension Key path: $EXTENSION_KEY" + echo " [+] Opening headless chrome and pack extension..." + /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --pack-extension=/tmp/auth-request-analyser-chrome --pack-extension-key=$EXTENSION_KEY + cp /tmp/auth-request-analyser-chrome.crx "../auth-request-analyser-$(date '+%Y-%m-%d-%H-%M-%S').crx" +} + +# Main +main () { + echo "[*] Starting the build process..." +############### Generic Setup + echo "[*] Stage 0: Generic Base Etension" + echo " [+] Copy sources to /tmp" + copy_sources_to_tmp_generic + echo " [+] Clean source directory..." + cleanup_generic_directory + echo "[*] Stage 0: Done." +############### Chrome + echo "[*] Stage 1: Chrome Etension" + echo " [+] Copy sources to Chrome folder" + copy_sources_tmp_chrome + echo " [+] Create ZIP archive" + pack_extension_chrome + #echo " [+] Create .crx bundle" + #create_crx_chrome + echo "[*] Stage 1: Done." +############### Generic Cleanup + echo "[*] Stage 3: Cleanup" + echo " [+] Remove temporary directories from /tmp" + remove_sources_tmp + echo "[*] Stage 3: Done." + echo "[>] All done." +} + +main \ No newline at end of file diff --git a/devtools.html b/devtools.html new file mode 100644 index 0000000..36b7bef --- /dev/null +++ b/devtools.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/devtools.js b/devtools.js new file mode 100644 index 0000000..70a9587 --- /dev/null +++ b/devtools.js @@ -0,0 +1,5 @@ +chrome.devtools.panels.create("AuRA (BETA)", + "aura_logo_favicon.png", + "application.html", + function(panel) {} +); \ No newline at end of file diff --git a/manifest.json b/manifest.json index de2ebdd..85ce8d1 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,11 @@ { "manifest_version": 3, "name": "AuRA - Auth. Request Analyser", - "version": "1.0.4", + "version": "1.1", "action": { - "default_popup": "popup.html" + "default_popup": "application.html" }, + "devtools_page": "devtools.html", "background": { "service_worker": "background.js" }, @@ -15,4 +16,4 @@ "icons" : { "128":"aura_logo_favicon.png" } -} \ No newline at end of file +}