mirror of
https://github.com/f-droid/fdroidserver.git
synced 2025-11-08 00:10:29 +03:00
dscanner - Drozer based post-build dynamic vulnerability scanner command
* New command `dscanner`, enables one to scan signed APKs with Drozer * Drozer is a dynamic vulnerability scanner for Android * Drozer runs in a emulator or on-device, this new `dscanner` command... * starts a docker image with Drozer and the Android Emulator pre-installed, * loads the signed APK into the emulator * activates Drozer automated tests for the APK * gathers the report output and places it next to the original APK * The Drozer docker image can be: * cached locally for re-use (just don't run --clean*) * retrieved from dockerhub.com for more efficient runtime * or be built from scratch (in the new "./docker" directory) * New "Vulnerability Scanning" documentation section (run gendocs.sh)
This commit is contained in:
parent
f439266303
commit
df27bae6a0
13 changed files with 1063 additions and 1 deletions
180
docker/Dockerfile
Normal file
180
docker/Dockerfile
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
# This image is intended to be used with fdroidserver for the purpose
|
||||
# of dynamic scanning of pre-built APKs during the fdroid build process.
|
||||
|
||||
# Start with ubuntu 12.04 (i386).
|
||||
FROM ubuntu:14.04
|
||||
MAINTAINER fdroid.dscanner <fdroid.dscanner@gmail.com>
|
||||
|
||||
ENV DROZER_URL https://github.com/mwrlabs/drozer/releases/download/2.3.4/drozer_2.3.4.deb
|
||||
ENV DROZER_DEB drozer_2.3.4.deb
|
||||
|
||||
ENV AGENT_URL https://github.com/mwrlabs/drozer/releases/download/2.3.4/drozer-agent-2.3.4.apk
|
||||
ENV AGENT_APK drozer-agent-2.3.4.apk
|
||||
|
||||
# Specially for SSH access and port redirection
|
||||
ENV ROOTPASSWORD android
|
||||
|
||||
# Expose ADB, ADB control and VNC ports
|
||||
EXPOSE 22
|
||||
EXPOSE 5037
|
||||
EXPOSE 5554
|
||||
EXPOSE 5555
|
||||
EXPOSE 5900
|
||||
EXPOSE 5901
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN echo "debconf shared/accepted-oracle-license-v1-1 select true" | debconf-set-selections
|
||||
RUN echo "debconf shared/accepted-oracle-license-v1-1 seen true" | debconf-set-selections
|
||||
|
||||
# Update packages
|
||||
RUN apt-get -y update
|
||||
|
||||
# Drozer packages
|
||||
RUN apt-get install wget python2.7 python-dev python2.7-dev python-openssl python-twisted python-protobuf bash-completion -y
|
||||
|
||||
# First, install add-apt-repository, sshd and bzip2
|
||||
RUN apt-get -y install python-software-properties bzip2 ssh net-tools
|
||||
|
||||
# ubuntu 14.04 needs this too
|
||||
RUN apt-get -y install software-properties-common
|
||||
|
||||
# Add oracle-jdk7 to repositories
|
||||
RUN add-apt-repository ppa:webupd8team/java
|
||||
|
||||
# Make sure the package repository is up to date
|
||||
RUN echo "deb http://archive.ubuntu.com/ubuntu trusty main universe" > /etc/apt/sources.list
|
||||
|
||||
# Update apt
|
||||
RUN apt-get update
|
||||
|
||||
# Add drozer
|
||||
RUN useradd -ms /bin/bash drozer
|
||||
|
||||
# Install oracle-jdk7
|
||||
RUN apt-get -y install oracle-java7-installer
|
||||
|
||||
# Install android sdk
|
||||
RUN wget http://dl.google.com/android/android-sdk_r23-linux.tgz
|
||||
RUN tar -xvzf android-sdk_r23-linux.tgz
|
||||
RUN mv -v android-sdk-linux /usr/local/android-sdk
|
||||
|
||||
# Install apache ant
|
||||
RUN wget http://archive.apache.org/dist/ant/binaries/apache-ant-1.8.4-bin.tar.gz
|
||||
RUN tar -xvzf apache-ant-1.8.4-bin.tar.gz
|
||||
RUN mv -v apache-ant-1.8.4 /usr/local/apache-ant
|
||||
|
||||
# Add android tools and platform tools to PATH
|
||||
ENV ANDROID_HOME /usr/local/android-sdk
|
||||
ENV PATH $PATH:$ANDROID_HOME/tools
|
||||
ENV PATH $PATH:$ANDROID_HOME/platform-tools
|
||||
|
||||
# Add ant to PATH
|
||||
ENV ANT_HOME /usr/local/apache-ant
|
||||
ENV PATH $PATH:$ANT_HOME/bin
|
||||
|
||||
# Export JAVA_HOME variable
|
||||
ENV JAVA_HOME /usr/lib/jvm/java-7-oracle
|
||||
|
||||
# Remove compressed files.
|
||||
RUN cd /; rm android-sdk_r23-linux.tgz && rm apache-ant-1.8.4-bin.tar.gz
|
||||
|
||||
# Some preparation before update
|
||||
RUN chown -R root:root /usr/local/android-sdk/
|
||||
|
||||
# Install latest android tools and system images
|
||||
RUN echo "y" | android update sdk --filter platform-tool --no-ui --force
|
||||
RUN echo "y" | android update sdk --filter platform --no-ui --force
|
||||
RUN echo "y" | android update sdk --filter build-tools-22.0.1 --no-ui -a
|
||||
RUN echo "y" | android update sdk --filter sys-img-x86-android-19 --no-ui -a
|
||||
#RUN echo "y" | android update sdk --filter sys-img-x86-android-21 --no-ui -a
|
||||
#RUN echo "y" | android update sdk --filter sys-img-x86-android-22 --no-ui -a
|
||||
RUN echo "y" | android update sdk --filter sys-img-armeabi-v7a-android-19 --no-ui -a
|
||||
#RUN echo "y" | android update sdk --filter sys-img-armeabi-v7a-android-21 --no-ui -a
|
||||
#RUN echo "y" | android update sdk --filter sys-img-armeabi-v7a-android-22 --no-ui -a
|
||||
|
||||
# Update ADB
|
||||
RUN echo "y" | android update adb
|
||||
|
||||
# Create fake keymap file
|
||||
RUN mkdir /usr/local/android-sdk/tools/keymaps
|
||||
RUN touch /usr/local/android-sdk/tools/keymaps/en-us
|
||||
|
||||
# Run sshd
|
||||
RUN apt-get install -y openssh-server
|
||||
RUN mkdir /var/run/sshd
|
||||
RUN echo "root:$ROOTPASSWORD" | chpasswd
|
||||
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
|
||||
RUN sed -i 's/PermitEmptyPasswords no/PermitEmptyPasswords yes/' /etc/ssh/sshd_config
|
||||
|
||||
# SSH login fix. Otherwise user is kicked off after login
|
||||
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
|
||||
|
||||
ENV NOTVISIBLE "in users profile"
|
||||
RUN echo "export VISIBLE=now" >> /etc/profile
|
||||
|
||||
# Install socat
|
||||
RUN apt-get install -y socat
|
||||
|
||||
# symlink android bins
|
||||
RUN ln -sv /usr/local/android-sdk/tools/android /usr/local/bin/
|
||||
RUN ln -sv /usr/local/android-sdk/tools/emulator /usr/local/bin/
|
||||
RUN ln -sv /usr/local/android-sdk/tools/ddms /usr/local/bin/
|
||||
RUN ln -sv /usr/local/android-sdk/tools/scheenshot2 /usr/local/bin/
|
||||
RUN ln -sv /usr/local/android-sdk/tools/monkeyrunner /usr/local/bin/
|
||||
RUN ln -sv /usr/local/android-sdk/tools/monitor /usr/local/bin/
|
||||
RUN ln -sv /usr/local/android-sdk/tools/mksdcard /usr/local/bin/
|
||||
RUN ln -sv /usr/local/android-sdk/tools/uiautomatorviewer /usr/local/bin/
|
||||
RUN ln -sv /usr/local/android-sdk/tools/traceview /usr/local/bin/
|
||||
RUN ln -sv /usr/local/android-sdk/platform-tools/adb /usr/local/bin/
|
||||
RUN ln -sv /usr/local/android-sdk/platform-tools/fastboot /usr/local/bin/
|
||||
RUN ln -sv /usr/local/android-sdk/platform-tools/sqlite3 /usr/local/bin/
|
||||
|
||||
# Setup DROZER...
|
||||
# https://labs.mwrinfosecurity.com/tools/drozer/
|
||||
|
||||
# Run as drozer user
|
||||
WORKDIR /home/drozer
|
||||
|
||||
# Site lists the shasums, however, I'm not sure the best way to integrate the
|
||||
# checks here. No real idiomatic way for Dockerfile to do that and most of
|
||||
# the examples online use chained commands but we want things to *BREAK* when
|
||||
# the sha doesn't match. So far, I can't seem to reliably make Docker not
|
||||
# finish the image build process.
|
||||
|
||||
# Download the console
|
||||
RUN wget -c $DROZER_URL
|
||||
|
||||
# Install the console
|
||||
RUN dpkg -i $DROZER_DEB
|
||||
|
||||
# Download agent
|
||||
RUN wget -c $AGENT_URL
|
||||
# Keep it version agnostic for other scripts such as install_drozer.py
|
||||
RUN mv -v $AGENT_APK drozer-agent.apk
|
||||
|
||||
# Port forwarding required by drozer
|
||||
RUN echo 'adb forward tcp:31415 tcp:31415' >> /home/drozer/.bashrc
|
||||
|
||||
# Alias for Drozer
|
||||
RUN echo "alias drozer='drozer console connect'" >> /home/drozer/.bashrc
|
||||
|
||||
# add extra scripting
|
||||
COPY install_agent.py /home/drozer/install_agent.py
|
||||
RUN chmod 755 /home/drozer/install_agent.py
|
||||
COPY enable_service.py /home/drozer/enable_service.py
|
||||
RUN chmod 755 /home/drozer/enable_service.py
|
||||
COPY drozer.py /home/drozer/drozer.py
|
||||
RUN chmod 755 /home/drozer/drozer.py
|
||||
|
||||
# fix ownerships
|
||||
RUN chown -R drozer.drozer /home/drozer
|
||||
|
||||
RUN apt-get -y --force-yes install python-pkg-resources=3.3-1ubuntu1
|
||||
RUN apt-get -y install python-pip python-setuptools git
|
||||
RUN pip install "git+https://github.com/dtmilano/AndroidViewClient.git#egg=androidviewclient"
|
||||
RUN apt-get -y install python-pexpect
|
||||
|
||||
# Add entrypoint
|
||||
COPY entrypoint.sh /home/drozer/entrypoint.sh
|
||||
RUN chmod +x /home/drozer/entrypoint.sh
|
||||
ENTRYPOINT ["/home/drozer/entrypoint.sh"]
|
||||
48
docker/Makefile
Normal file
48
docker/Makefile
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
SHELL := /bin/bash
|
||||
ALIAS = "dscanner"
|
||||
EXISTS := $(shell docker ps -a -q -f name=$(ALIAS))
|
||||
RUNNED := $(shell docker ps -q -f name=$(ALIAS))
|
||||
ifneq "$(RUNNED)" ""
|
||||
IP := $(shell docker inspect $(ALIAS) | grep "IPAddress\"" | head -n1 | cut -d '"' -f 4)
|
||||
endif
|
||||
STALE_IMAGES := $(shell docker images | grep "<none>" | awk '{print($$3)}')
|
||||
EMULATOR ?= "android-19"
|
||||
ARCH ?= "armeabi-v7a"
|
||||
|
||||
COLON := :
|
||||
|
||||
.PHONY = build clean kill info
|
||||
|
||||
all: help
|
||||
|
||||
help:
|
||||
@echo "usage: make {help|build|clean|kill|info}"
|
||||
@echo ""
|
||||
@echo " help this help screen"
|
||||
@echo " build create docker image"
|
||||
@echo " clean remove images and containers"
|
||||
@echo " kill stop running containers"
|
||||
@echo " info details of running container"
|
||||
|
||||
build:
|
||||
@docker build -t "dscanner/fdroidserver:latest" .
|
||||
|
||||
clean: kill
|
||||
@docker ps -a -q | xargs -n 1 -I {} docker rm -f {}
|
||||
ifneq "$(STALE_IMAGES)" ""
|
||||
@docker rmi -f $(STALE_IMAGES)
|
||||
endif
|
||||
|
||||
kill:
|
||||
ifneq "$(RUNNED)" ""
|
||||
@docker kill $(ALIAS)
|
||||
endif
|
||||
|
||||
info:
|
||||
@docker ps -a -f name=$(ALIAS)
|
||||
ifneq "$(RUNNED)" ""
|
||||
$(eval ADBPORT := $(shell docker port $(ALIAS) | grep '5555/tcp' | awk '{split($$3,a,"$(COLON)");print a[2]}'))
|
||||
@echo -e "Use:\n adb kill-server\n adb connect $(IP):$(ADBPORT)"
|
||||
else
|
||||
@echo "Run container"
|
||||
endif
|
||||
13
docker/README.md
Normal file
13
docker/README.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# dscanner docker image #
|
||||
|
||||
Use `make help` for up-to-date instructions.
|
||||
|
||||
```
|
||||
usage: make {help|build|clean|kill|info}
|
||||
|
||||
help this help screen
|
||||
build create docker image
|
||||
clean remove images and containers
|
||||
kill stop running containers
|
||||
info details of running container
|
||||
```
|
||||
35
docker/drozer.py
Normal file
35
docker/drozer.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/env python2
|
||||
|
||||
import pexpect
|
||||
import sys
|
||||
|
||||
prompt = "dz>"
|
||||
target = sys.argv[1]
|
||||
|
||||
drozer = pexpect.spawn("drozer console connect")
|
||||
drozer.logfile = open("/tmp/drozer_report.log", "w")
|
||||
|
||||
|
||||
# start
|
||||
drozer.expect(prompt)
|
||||
|
||||
|
||||
def send_command(command, target):
|
||||
cmd = "run {0} -a {1}".format(command, target)
|
||||
drozer.sendline(cmd)
|
||||
drozer.expect(prompt)
|
||||
|
||||
scanners = [
|
||||
"scanner.misc.native", # Find native components included in packages
|
||||
#"scanner.misc.readablefiles", # Find world-readable files in the given folder
|
||||
#"scanner.misc.secretcodes", # Search for secret codes that can be used from the dialer
|
||||
#"scanner.misc.sflagbinaries", # Find suid/sgid binaries in the given folder (default is /system).
|
||||
#"scanner.misc.writablefiles", # Find world-writable files in the given folder
|
||||
"scanner.provider.finduris", # Search for content providers that can be queried.
|
||||
"scanner.provider.injection", # Test content providers for SQL injection vulnerabilities.
|
||||
"scanner.provider.sqltables", # Find tables accessible through SQL injection vulnerabilities.
|
||||
"scanner.provider.traversal" # Test content providers for basic directory traversal
|
||||
]
|
||||
|
||||
for scanner in scanners:
|
||||
send_command(scanner, target)
|
||||
16
docker/enable_service.py
Executable file
16
docker/enable_service.py
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python2
|
||||
|
||||
from com.dtmilano.android.viewclient import ViewClient
|
||||
|
||||
vc = ViewClient(*ViewClient.connectToDeviceOrExit())
|
||||
|
||||
button = vc.findViewWithText("OFF")
|
||||
|
||||
if button:
|
||||
(x, y) = button.getXY()
|
||||
button.touch()
|
||||
else:
|
||||
print("Button not found. Is the app currently running?")
|
||||
exit()
|
||||
|
||||
print("Done!")
|
||||
42
docker/entrypoint.sh
Executable file
42
docker/entrypoint.sh
Executable file
|
|
@ -0,0 +1,42 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [[ $EMULATOR == "" ]]; then
|
||||
EMULATOR="android-19"
|
||||
echo "Using default emulator $EMULATOR"
|
||||
fi
|
||||
|
||||
if [[ $ARCH == "" ]]; then
|
||||
ARCH="x86"
|
||||
echo "Using default arch $ARCH"
|
||||
fi
|
||||
echo EMULATOR = "Requested API: ${EMULATOR} (${ARCH}) emulator."
|
||||
if [[ -n $1 ]]; then
|
||||
echo "Last line of file specified as non-opt/last argument:"
|
||||
tail -1 $1
|
||||
fi
|
||||
|
||||
# Run sshd
|
||||
/usr/sbin/sshd
|
||||
adb start-server
|
||||
|
||||
# Detect ip and forward ADB ports outside to outside interface
|
||||
ip=$(ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}')
|
||||
socat tcp-listen:5037,bind=$ip,fork tcp:127.0.0.1:5037 &
|
||||
socat tcp-listen:5554,bind=$ip,fork tcp:127.0.0.1:5554 &
|
||||
socat tcp-listen:5555,bind=$ip,fork tcp:127.0.0.1:5555 &
|
||||
|
||||
# Set up and run emulator
|
||||
if [[ $ARCH == *"x86"* ]]
|
||||
then
|
||||
EMU="x86"
|
||||
else
|
||||
EMU="arm"
|
||||
fi
|
||||
|
||||
#FASTDROID_VNC_URL="https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/fastdroid-vnc/fastdroid-vnc"
|
||||
#wget -c "${FASTDROID_VNC_URL}"
|
||||
|
||||
export PATH="${PATH}:/usr/local/android-sdk/tools/:/usr/local/android-sdk/platform-tools/"
|
||||
|
||||
echo "no" | android create avd -f -n test -t ${EMULATOR} --abi default/${ARCH}
|
||||
echo "no" | emulator64-${EMU} -avd test -noaudio -no-window -gpu off -verbose -qemu -usbdevice tablet -vnc :0
|
||||
63
docker/install_agent.py
Executable file
63
docker/install_agent.py
Executable file
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env python2
|
||||
|
||||
import os
|
||||
from subprocess import call, check_output
|
||||
from time import sleep
|
||||
|
||||
FNULL = open(os.devnull, 'w')
|
||||
|
||||
print("Ensuring device is online")
|
||||
call("adb wait-for-device", shell=True)
|
||||
|
||||
print("Installing the drozer agent")
|
||||
print("If the device just came online it is likely the package manager hasn't booted.")
|
||||
print("Will try multiple attempts to install.")
|
||||
print("This may need tweaking depending on hardware.")
|
||||
|
||||
|
||||
attempts = 0
|
||||
time_to_sleep = 30
|
||||
|
||||
while attempts < 8:
|
||||
output = check_output('adb shell "pm list packages"', shell=True)
|
||||
print("Checking whether the package manager is up...")
|
||||
if "Could not access the Package Manager" in output:
|
||||
print("Nope. Sleeping for 30 seconds and then trying again.")
|
||||
sleep(time_to_sleep)
|
||||
else:
|
||||
break
|
||||
|
||||
time_to_sleep = 5
|
||||
attempts = 0
|
||||
|
||||
while attempts < 5:
|
||||
sleep(time_to_sleep)
|
||||
try:
|
||||
install_output = check_output("adb install /home/drozer/drozer-agent.apk", shell=True)
|
||||
except Exception:
|
||||
print("Failed. Trying again.")
|
||||
attempts += 1
|
||||
else:
|
||||
attempts += 1
|
||||
if "Error: Could not access the Package Manager" not in install_output:
|
||||
break
|
||||
|
||||
print("Install attempted. Checking everything worked")
|
||||
|
||||
pm_list_output = check_output('adb shell "pm list packages"', shell=True)
|
||||
|
||||
if "com.mwr.dz" not in pm_list_output:
|
||||
print(install_output)
|
||||
exit("APK didn't install properly. Exiting.")
|
||||
|
||||
print("Installed ok.")
|
||||
|
||||
print("Starting the drozer agent main activity: com.mwr.dz/.activities.MainActivity")
|
||||
call('adb shell "am start com.mwr.dz/.activities.MainActivity"', shell=True, stdout=FNULL)
|
||||
|
||||
print("Starting the service")
|
||||
# start the service
|
||||
call("python /home/drozer/enable_service.py", shell=True, stdout=FNULL)
|
||||
|
||||
print("Forward dem ports mon.")
|
||||
call("adb forward tcp:31415 tcp:31415", shell=True, stdout=FNULL)
|
||||
Loading…
Add table
Add a link
Reference in a new issue