From 43ca3dcf17538c557397eeb52f1de395bc830ee2 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Sun, 28 Jul 2019 15:42:57 -0400 Subject: [PATCH 01/23] chfiles optional default. fix immutable in template. --- vm-boot-protect.sh | 57 ++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 27 deletions(-) mode change 100644 => 100755 vm-boot-protect.sh diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh old mode 100644 new mode 100755 index b707bc4..4d307fe --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -25,10 +25,10 @@ # Define sh, bash, X and desktop init scripts in /home/user # to be protected -chfiles=".bashrc .bash_profile .bash_login .bash_logout .profile \ -.xprofile .xinitrc .xserverrc .xsession" -chdirs="bin .local/bin .config/autostart .config/plasma-workspace/env \ -.config/plasma-workspace/shutdown .config/autostart-scripts .config/systemd" +chfiles=${chfiles:-".bashrc .bash_profile .bash_login .bash_logout .profile \ +.xprofile .xinitrc .xserverrc .xsession"} +chdirs=${chdirs:-"bin .local/bin .config/autostart .config/plasma-workspace/env \ +.config/plasma-workspace/shutdown .config/autostart-scripts .config/systemd"} vmname=`qubesdb-read /name` dev=/dev/xvdb @@ -39,8 +39,20 @@ defdir=/etc/default/vms version="0.8.5" +# Remount fs as read-write +remount_rw() { + # Begin write operations + if [ -e $dev ] && mount -o remount,rw $dev $rw ; then + echo Good rw remount. + else + abort_startup RELOCATE "Remount failed!" + fi +} + + # Function: Make user scripts immutable. make_immutable() { + remount_rw #initialize_home $rw/home ifneeded cd $rw/home/user mkdir -p $chdirs @@ -49,6 +61,7 @@ make_immutable() { cd /root } + # Start rescue shell then exit/fail abort_startup() { type="$1" @@ -85,19 +98,6 @@ abort_startup() { } -# Don't bother with root protections in template or standalone -if ! is_rwonly_persistent; then - if qsvc vm-boot-protect; then - make_immutable - fi - if ! is_templatevm; then - # Keep configs invisible for standalone vms - rm -rf "$defdir" - fi - exit 0 - # cannot use abort_startup() before this point -fi - echo >$errlog # Clear if qsvc vm-boot-protect-cli; then @@ -120,6 +120,15 @@ if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then abort_startup RELOCATE "Mount failed; BAD private volume!" fi fi + + # Don't bother with root protections in template or standalone + if ! is_rwonly_persistent; then + if qsvc vm-boot-protect; then + make_immutable + fi + exit 0 + fi + fi @@ -157,12 +166,7 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then abort_startup RELOCATE "Hash check failed!" fi - # Begin write operations - if [ -e $dev ] && mount -o remount,rw $dev $rw ; then - echo Good rw remount. - else - abort_startup RELOCATE "Remount failed!" - fi + remount_rw # Files mutable for del/copy operations cd $rw/home/user @@ -224,13 +228,12 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then fi +# Keep configs invisible at runtime... +rm -rf "$defdir" + if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then make_immutable umount $rw fi -# Keep configs invisible at runtime... -rm -rf "$defdir" - - exit 0 From 302c96831315b4471ca16f00111b33879d24d4c8 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Tue, 30 Jul 2019 17:19:11 -0400 Subject: [PATCH 02/23] begin rc, chfiles as user, process etc/skel --- vm-boot-protect.sh | 55 +++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index 4d307fe..750ed0d 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -23,13 +23,6 @@ # Source Qubes library. . /usr/lib/qubes/init/functions -# Define sh, bash, X and desktop init scripts in /home/user -# to be protected -chfiles=${chfiles:-".bashrc .bash_profile .bash_login .bash_logout .profile \ -.xprofile .xinitrc .xserverrc .xsession"} -chdirs=${chdirs:-"bin .local/bin .config/autostart .config/plasma-workspace/env \ -.config/plasma-workspace/shutdown .config/autostart-scripts .config/systemd"} - vmname=`qubesdb-read /name` dev=/dev/xvdb rw=/mnt/rwtmp @@ -38,6 +31,27 @@ errlog=/var/run/vm-protect-error defdir=/etc/default/vms version="0.8.5" +# Define sh, bash, X and desktop init scripts in /home/user +# to be protected +chfiles=${chfiles:-".bashrc .bash_profile .bash_login .bash_logout .profile \ +.xprofile .xinitrc .xserverrc .xsession"} +chfiles_add="" +chdirs=${chdirs:-"bin .local/bin .config/autostart .config/plasma-workspace/env \ +.config/plasma-workspace/shutdown .config/autostart-scripts .config/systemd"} +chdirs_add="" + +# Define dirs to apply quarrantine / whitelists +privdirs=${privdirs:-"/rw/config /rw/usrlocal /rw/bind-dirs"} +privdirs_add="" + +# Run rc file commands if they exist +if [ -e $defdir/vms.all.rc ]; then + . $defdir/vms.all.rc +fi +if [ -e $defdir/$vmname.rc ]; then + . $defdir/$vmname.rc +fi + # Remount fs as read-write remount_rw() { @@ -55,9 +69,8 @@ make_immutable() { remount_rw #initialize_home $rw/home ifneeded cd $rw/home/user - mkdir -p $chdirs - touch $chfiles - chattr -R -f +i $chfiles $chdirs + su user -c "mkdir -p $chdirs $chdirs_add; touch $chfiles $chfiles_add" + chattr -R -f +i $chfiles $chfiles_add $chdirs $chdirs_add cd /root } @@ -122,11 +135,9 @@ if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then fi # Don't bother with root protections in template or standalone - if ! is_rwonly_persistent; then - if qsvc vm-boot-protect; then - make_immutable - fi - exit 0 + if ! is_rwonly_persistent; then + make_immutable + exit 0 fi fi @@ -137,7 +148,6 @@ fi # * Hashes in vms/vms.all.SHA and vms/$vmname.SHA files will be checked. # * Remove /rw root startup files (config, usrlocal, bind-dirs). # * Contents of vms/vms.all and vms/$vmname folders will be copied. -privdirs=${privdirs:-"/rw/config /rw/usrlocal /rw/bind-dirs"} if qsvc vm-boot-protect-root && is_rwonly_persistent; then @@ -170,13 +180,13 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then # Files mutable for del/copy operations cd $rw/home/user - chattr -R -f -i $chfiles $chdirs $privdirs + chattr -R -f -i $chfiles $chfiles_add $chdirs $chdirs_add $privdirs $privdirs_add cd /root # Deactivate private.img config dirs mkdir -p $rwbak - for dir in $privdirs; do # maybe use 'eval' for privdirs quotes/escaping + for dir in $privdirs $privdirs_add; do # maybe use 'eval' for privdirs quotes/escaping echo "Deactivate $dir" subdir=`echo $dir |sed -r 's|^/rw/||'` bakdir="$rwbak/BAK-$subdir" @@ -187,6 +197,15 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then rm -rf "$bakdir" mv "$rw/$subdir" "$bakdir" mkdir -p "$rw/$subdir" + + # Populate /home/user w skel files if it was in privdirs + case "$subdir" in + "home"|"home/"|"home/user"|"home/user/") + mkdir -p $rw/home/user + cp -aT /etc/skel $rw/home/user + chown -R user:user $rw/home/user + ;; + esac done for vmset in vms.all $vmname; do From 55181dc2dd997072313ed4e30e747c2e3587db5a Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Tue, 30 Jul 2019 23:25:35 -0400 Subject: [PATCH 03/23] mutable for rm, use mkhomedir_helper --- ibrowse.whitelist | 3 +++ vm-boot-protect.sh | 23 ++++++++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 ibrowse.whitelist diff --git a/ibrowse.whitelist b/ibrowse.whitelist new file mode 100644 index 0000000..9f17a0f --- /dev/null +++ b/ibrowse.whitelist @@ -0,0 +1,3 @@ +/rw/home/user/.mozilla/firefox/profile.default/places.sqlite +/rw/home/user/.mozilla/firefox/profile.default/places.sqlite-shm +/rw/home/user/.mozilla/firefox/profile.default/places.sqlite-wal diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index 750ed0d..c8da300 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -134,11 +134,11 @@ if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then fi fi - # Don't bother with root protections in template or standalone + # Don't bother with root protections in template or standalone if ! is_rwonly_persistent; then - make_immutable - exit 0 - fi + make_immutable + exit 0 + fi fi @@ -191,19 +191,24 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then subdir=`echo $dir |sed -r 's|^/rw/||'` bakdir="$rwbak/BAK-$subdir" origdir="$rwbak/ORIG-$subdir" - if [ -d "$bakdir" ] && [ ! -d "$origdir" ]; then + if [ -e "$bakdir" ] && [ ! -e "$origdir" ]; then mv "$bakdir" "$origdir" fi - rm -rf "$bakdir" + if [ -e "$bakdir" ]; then + chattr -R -i "$bakdir" + rm -rf "$bakdir" + fi mv "$rw/$subdir" "$bakdir" mkdir -p "$rw/$subdir" # Populate /home/user w skel files if it was in privdirs case "$subdir" in "home"|"home/"|"home/user"|"home/user/") - mkdir -p $rw/home/user - cp -aT /etc/skel $rw/home/user - chown -R user:user $rw/home/user + echo "Populating home dir" + #chown user:user $rw/home/user + rm -rf /home/user $rw/home/user + mkhomedir_helper user + mv /home/user $rw/home ;; esac done From d8770854942d36fe2675ee7cdb8b869a76503464 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Tue, 30 Jul 2019 23:43:32 -0400 Subject: [PATCH 04/23] add vm_boot_finish hook --- vm-boot-protect.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index c8da300..c5d111e 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -44,6 +44,11 @@ chdirs_add="" privdirs=${privdirs:-"/rw/config /rw/usrlocal /rw/bind-dirs"} privdirs_add="" + +# Placeholder function: Runs at end +vm_boot_finish() { } + + # Run rc file commands if they exist if [ -e $defdir/vms.all.rc ]; then . $defdir/vms.all.rc @@ -136,6 +141,7 @@ if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then # Don't bother with root protections in template or standalone if ! is_rwonly_persistent; then + vm_boot_finish make_immutable exit 0 fi @@ -256,6 +262,7 @@ fi rm -rf "$defdir" if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then + vm_boot_finish make_immutable umount $rw fi From 850843e7c081637b110e550eeb51ba24ef918d2f Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Thu, 1 Aug 2019 18:50:20 -0400 Subject: [PATCH 05/23] fix placeholder func, faster home populate --- vm-boot-protect.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index c5d111e..1f09362 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -46,7 +46,7 @@ privdirs_add="" # Placeholder function: Runs at end -vm_boot_finish() { } +vm_boot_finish() { return; } # Run rc file commands if they exist @@ -211,10 +211,11 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then case "$subdir" in "home"|"home/"|"home/user"|"home/user/") echo "Populating home dir" - #chown user:user $rw/home/user rm -rf /home/user $rw/home/user + mount --bind $rw/home /home mkhomedir_helper user - mv /home/user $rw/home + #mv /home/user $rw/home + umount /home ;; esac done From 204e90a6260bf4815e778566201cc16298210354 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Sat, 3 Aug 2019 00:15:21 -0400 Subject: [PATCH 06/23] add 3 rc files, add tagging feature, simplify issue #9, issue #35 --- vm-boot-protect.sh | 52 ++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index 1f09362..ab1b1c5 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -29,12 +29,12 @@ rw=/mnt/rwtmp rwbak=$rw/vm-boot-protect errlog=/var/run/vm-protect-error defdir=/etc/default/vms -version="0.8.5" +version="0.9.0b" # Define sh, bash, X and desktop init scripts in /home/user # to be protected chfiles=${chfiles:-".bashrc .bash_profile .bash_login .bash_logout .profile \ -.xprofile .xinitrc .xserverrc .xsession"} +.pam_environment .xprofile .xinitrc .xserverrc .Xsession .xsession .xsessionrc"} chfiles_add="" chdirs=${chdirs:-"bin .local/bin .config/autostart .config/plasma-workspace/env \ .config/plasma-workspace/shutdown .config/autostart-scripts .config/systemd"} @@ -44,20 +44,15 @@ chdirs_add="" privdirs=${privdirs:-"/rw/config /rw/usrlocal /rw/bind-dirs"} privdirs_add="" +# Get list of enabled tags from Qubes services +tags=`find /var/run/qubes-service -name 'vm-boot-tag-*' -type f -printf '%f\n' \ + | sort | sed -E 's|^vm-boot-tag-|\@tags/|'` + # Placeholder function: Runs at end vm_boot_finish() { return; } -# Run rc file commands if they exist -if [ -e $defdir/vms.all.rc ]; then - . $defdir/vms.all.rc -fi -if [ -e $defdir/$vmname.rc ]; then - . $defdir/$vmname.rc -fi - - # Remount fs as read-write remount_rw() { # Begin write operations @@ -71,10 +66,11 @@ remount_rw() { # Function: Make user scripts immutable. make_immutable() { + echo "Making files IMMUTABLE" remount_rw #initialize_home $rw/home ifneeded cd $rw/home/user - su user -c "mkdir -p $chdirs $chdirs_add; touch $chfiles $chfiles_add" + su user -c "mkdir -p $chdirs $chdirs_add; touch $chfiles $chfiles_add 2>/dev/null" chattr -R -f +i $chfiles $chfiles_add $chdirs $chdirs_add cd /root } @@ -116,6 +112,14 @@ abort_startup() { } +# Run rc file commands if they exist +for rcbase in vms.all $tags $vmname; do + if [ -e "$defdir/$rcbase.rc" ]; then + . "$defdir/$rcbase.rc" + fi +done + + echo >$errlog # Clear if qsvc vm-boot-protect-cli; then @@ -159,21 +163,18 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then # Check hashes checkcode=0 - if [ -e $defdir/$vmname.SHA ]; then - # remove padding and add number field - sed 's/^ *//; s/ *$//; /^$/d; s/^/1 /' $defdir/$vmname.SHA \ - >/tmp/vm-boot-protect-sha - fi - if [ -e $defdir/vms.all.SHA ]; then - sed 's/^ *//; s/ *$//; /^$/d; s/^/2 /' $defdir/vms.all.SHA \ - >>/tmp/vm-boot-protect-sha - fi + for sha_base in $vmname $tags vms.all; do + if [ -e "$defdir/$sha_base.SHA" ]; then + cat "$defdir/$sha_base.SHA" >>/tmp/vm-boot-protect-sha + fi + done if [ -e /tmp/vm-boot-protect-sha ]; then echo "Checking file hashes." |tee $errlog - # Get unique paths, remove field and switch path to $rw before check; + # Strip padding, get unique paths and switch path to $rw before check; # this allows hashes in $vmname.SHA to override ones in vms.all.SHA. - sort --unique --key=3 /tmp/vm-boot-protect-sha \ - | sed -r 's|^[1-2] (.*[[:space:]]*)/rw|\1'$rw'|' \ + sed 's/^ *//; s/ *$//; /^$/d;' /tmp/vm-boot-protect-sha \ + | sort -u -k2,2 \ + | sed -r 's|^(\S+\s+)/rw|\1'$rw'|' \ | sha256sum --strict -c >>$errlog; checkcode=$? fi @@ -220,7 +221,7 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then esac done - for vmset in vms.all $vmname; do + for vmset in vms.all $tags $vmname; do # Process whitelists... cat $defdir/$vmset.whitelist \ @@ -263,6 +264,7 @@ fi rm -rf "$defdir" if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then + echo "Preparing for unmount" vm_boot_finish make_immutable umount $rw From ca67ef7fe323bb6fbe4fcd1a219af6f0a1958fda Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Sun, 11 Aug 2019 06:26:26 -0400 Subject: [PATCH 07/23] var and rc tweaks, add tag files --- README.md | 7 +++++++ default/vms/@tags/ibrowse.rc | 1 + default/vms/@tags/ibrowse.whitelist | 3 +++ default/vms/@tags/network.whitelist | 2 ++ default/vms/@tags/usb.rc | 1 + default/vms/sys-net.whitelist | 3 +-- vm-boot-protect.sh | 31 ++++++++++++++--------------- 7 files changed, 30 insertions(+), 18 deletions(-) create mode 100644 default/vms/@tags/ibrowse.rc create mode 100644 default/vms/@tags/ibrowse.whitelist create mode 100644 default/vms/@tags/network.whitelist create mode 100644 default/vms/@tags/usb.rc mode change 100644 => 120000 default/vms/sys-net.whitelist diff --git a/README.md b/README.md index ff862a9..b6300b0 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,10 @@ Leverage Qubes template non-persistence to fend off malware at VM startup: Lock- **Deployment** files are copied _recursively_ from ../vms/vms.all/rw/ and ../vms/$vmname/rw/ dirs. Example is to place the .bashrc file in /etc/default/vms/vms.all/rw/home/user/.bashrc for deployment to /rw/home/user/.bashrc. Once copying is complete, the /etc/defaults/vms folder is deleted from the running VM (this has no effect on the original in the template). + **rc files** are sh script fragments sourced from ../vms/vms.all.rc and ../vms/$vmname.rc. They run near the beginning of the vm-boot-protect service before mounting /rw, and can be used to override variable definitions like `privdirs` as well as the `vm_boot_finish` function which runs near the end before dismount. Another use for rc files is to run threat detection tools such as antivirus. + + **Tags** may be defined with all of the above features so that you are not limited to specifying them for either all VMs or specifically-named VMs. Simply configure them as you would acccording to the above directions, but place the files under the '@tags' subdir instead. For example '/etc/default/vms/@tags/special.whitelist' defines a whitelist for the tag 'special'. A tag can be activated for one or more VMs by adding a Qubes service prefixed with `vm-boot-tag-` (i.e. vm-boot-tag-special) to the VMs. + ### Where to use: Basic examples After installing into a template, simply enable `vm-boot-protect-root` service without configuration. Recommended for the following types of VMs: @@ -82,6 +86,8 @@ Examples where -root should *not* be enabled: ### Notes + * The /rw/home directory can be added to `privdirs` so it is quarrantined much like /rw/config, /rw/binddirs and /rw/usrlocal. The easiest way to configure this is to define `privdirs_add=/rw/home` in an rc file or a drop-in for the vm-boot-protect.service. But in the case of /rw/home, the /rw/home/user folder will be repopulated automatically from OS defaults (usually in /etc/skel) before whitelists are applied. For an example, see the `ibrowse` tag which quarrantines home while whitelisting Firefox bookmarks. + * A bug in v0.8.4 will erase anything in '/etc/default/vms' when booting into the template. For proper future operation with sys-net or other VMs you may have customized in that path, updating Qubes-VM-hardening to the latest version (using the install script) is recommended, along with restoring any custom files @@ -98,6 +104,7 @@ Examples where -root should *not* be enabled: * Currently the service cannot seamlessly handle 'first boot' when the private volume must be initialized. If you enabled the service on a VM before its first startup, on first start the shell will display a notice telling you to restart the VM. Subsequent starts will proceed normally. ## Releases + - v0.9.0 Add tags and rc files, protect more home scripts, support home quarrantine - v0.8.5 Fix template detection, /etc/default/vms erasure - v0.8.4 Add protection to /home/user/.config/systemd - v0.8.3 Fix for install script copying to /etc/default/vms diff --git a/default/vms/@tags/ibrowse.rc b/default/vms/@tags/ibrowse.rc new file mode 100644 index 0000000..b26ec82 --- /dev/null +++ b/default/vms/@tags/ibrowse.rc @@ -0,0 +1 @@ +privdirs_add="/rw/home" diff --git a/default/vms/@tags/ibrowse.whitelist b/default/vms/@tags/ibrowse.whitelist new file mode 100644 index 0000000..9f17a0f --- /dev/null +++ b/default/vms/@tags/ibrowse.whitelist @@ -0,0 +1,3 @@ +/rw/home/user/.mozilla/firefox/profile.default/places.sqlite +/rw/home/user/.mozilla/firefox/profile.default/places.sqlite-shm +/rw/home/user/.mozilla/firefox/profile.default/places.sqlite-wal diff --git a/default/vms/@tags/network.whitelist b/default/vms/@tags/network.whitelist new file mode 100644 index 0000000..dbd0208 --- /dev/null +++ b/default/vms/@tags/network.whitelist @@ -0,0 +1,2 @@ +/rw/config/NM-system-connections/ +/rw/config/suspend-module-blacklist diff --git a/default/vms/@tags/usb.rc b/default/vms/@tags/usb.rc new file mode 100644 index 0000000..b26ec82 --- /dev/null +++ b/default/vms/@tags/usb.rc @@ -0,0 +1 @@ +privdirs_add="/rw/home" diff --git a/default/vms/sys-net.whitelist b/default/vms/sys-net.whitelist deleted file mode 100644 index dbd0208..0000000 --- a/default/vms/sys-net.whitelist +++ /dev/null @@ -1,2 +0,0 @@ -/rw/config/NM-system-connections/ -/rw/config/suspend-module-blacklist diff --git a/default/vms/sys-net.whitelist b/default/vms/sys-net.whitelist new file mode 120000 index 0000000..0fec9b6 --- /dev/null +++ b/default/vms/sys-net.whitelist @@ -0,0 +1 @@ +@tags/network.whitelist \ No newline at end of file diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index ab1b1c5..bee816b 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -29,16 +29,16 @@ rw=/mnt/rwtmp rwbak=$rw/vm-boot-protect errlog=/var/run/vm-protect-error defdir=/etc/default/vms -version="0.9.0b" +version="0.9.0" # Define sh, bash, X and desktop init scripts in /home/user # to be protected chfiles=${chfiles:-".bashrc .bash_profile .bash_login .bash_logout .profile \ .pam_environment .xprofile .xinitrc .xserverrc .Xsession .xsession .xsessionrc"} -chfiles_add="" +chfiles_add=${chfiles_add:-""} chdirs=${chdirs:-"bin .local/bin .config/autostart .config/plasma-workspace/env \ .config/plasma-workspace/shutdown .config/autostart-scripts .config/systemd"} -chdirs_add="" +chdirs_add=${chdirs_add:-""} # Define dirs to apply quarrantine / whitelists privdirs=${privdirs:-"/rw/config /rw/usrlocal /rw/bind-dirs"} @@ -112,14 +112,6 @@ abort_startup() { } -# Run rc file commands if they exist -for rcbase in vms.all $tags $vmname; do - if [ -e "$defdir/$rcbase.rc" ]; then - . "$defdir/$rcbase.rc" - fi -done - - echo >$errlog # Clear if qsvc vm-boot-protect-cli; then @@ -145,7 +137,6 @@ if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then # Don't bother with root protections in template or standalone if ! is_rwonly_persistent; then - vm_boot_finish make_immutable exit 0 fi @@ -161,6 +152,13 @@ fi if qsvc vm-boot-protect-root && is_rwonly_persistent; then + # Run rc file commands if they exist + for rcbase in vms.all $tags $vmname; do + if [ -e "$defdir/$rcbase.rc" ]; then + . "$defdir/$rcbase.rc" + fi + done + # Check hashes checkcode=0 for sha_base in $vmname $tags vms.all; do @@ -187,7 +185,8 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then # Files mutable for del/copy operations cd $rw/home/user - chattr -R -f -i $chfiles $chfiles_add $chdirs $chdirs_add $privdirs $privdirs_add + chattr -R -f -i $chfiles $chfiles_add $chdirs $chdirs_add $privdirs $privdirs_add \ + $rwbak/BAK-* cd /root @@ -202,7 +201,7 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then mv "$bakdir" "$origdir" fi if [ -e "$bakdir" ]; then - chattr -R -i "$bakdir" + #chattr -R -i "$bakdir" rm -rf "$bakdir" fi mv "$rw/$subdir" "$bakdir" @@ -215,7 +214,6 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then rm -rf /home/user $rw/home/user mount --bind $rw/home /home mkhomedir_helper user - #mv /home/user $rw/home umount /home ;; esac @@ -258,6 +256,8 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then fi done + vm_boot_finish + fi # Keep configs invisible at runtime... @@ -265,7 +265,6 @@ rm -rf "$defdir" if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then echo "Preparing for unmount" - vm_boot_finish make_immutable umount $rw fi From ebe40e1391c49a849ec51fa0197a4fddfb040983 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Sun, 11 Aug 2019 06:28:22 -0400 Subject: [PATCH 08/23] tweaks to log, tags and cleanup --- vm-boot-protect.sh | 69 ++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index bee816b..a28c610 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -28,6 +28,7 @@ dev=/dev/xvdb rw=/mnt/rwtmp rwbak=$rw/vm-boot-protect errlog=/var/run/vm-protect-error +servicedir=/var/run/qubes-service defdir=/etc/default/vms version="0.9.0" @@ -44,10 +45,6 @@ chdirs_add=${chdirs_add:-""} privdirs=${privdirs:-"/rw/config /rw/usrlocal /rw/bind-dirs"} privdirs_add="" -# Get list of enabled tags from Qubes services -tags=`find /var/run/qubes-service -name 'vm-boot-tag-*' -type f -printf '%f\n' \ - | sort | sed -E 's|^vm-boot-tag-|\@tags/|'` - # Placeholder function: Runs at end vm_boot_finish() { return; } @@ -152,6 +149,10 @@ fi if qsvc vm-boot-protect-root && is_rwonly_persistent; then + # Get list of enabled tags from Qubes services + tags=`find $servicedir -name 'vm-boot-tag-*' -type f -printf '%f\n' \ + | sort | sed -E 's|^vm-boot-tag-|\@tags/|'` + # Run rc file commands if they exist for rcbase in vms.all $tags $vmname; do if [ -e "$defdir/$rcbase.rc" ]; then @@ -222,36 +223,38 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then for vmset in vms.all $tags $vmname; do # Process whitelists... - cat $defdir/$vmset.whitelist \ - | while read wlfile; do - # Must begin with '/rw/' - if echo $wlfile |grep -q "^\/rw\/"; then - srcfile="`echo $wlfile |sed -r \"s|^/rw/(.+)$|$rwbak/BAK-\1|\"`" - dstfile="`echo $wlfile |sed -r \"s|^/rw/(.+)$|$rw/\1|\"`" - dstdir="`dirname \"$dstfile\"`" - if [ ! -e "$srcfile" ]; then - echo "Whitelist entry not present in filesystem:" - echo "$srcfile" - continue - # For very large dirs: mv whole dir when entry ends with '/' - elif echo $wlfile |grep -q "\/$"; then - echo "Whitelist mv $srcfile" - echo "to $dstfile" - mkdir -p "$dstdir" - mv -T "$srcfile" "$dstfile" - else - echo "Whitelist cp $srcfile" - mkdir -p "$dstdir" - cp -a --link "$srcfile" "$dstdir" + if [ -e $defdir/$vmset.whitelist ]; then + cat $defdir/$vmset.whitelist \ + | while read wlfile; do + # Must begin with '/rw/' + if echo $wlfile |grep -q "^\/rw\/"; then + srcfile="`echo $wlfile |sed -r \"s|^/rw/(.+)$|$rwbak/BAK-\1|\"`" + dstfile="`echo $wlfile |sed -r \"s|^/rw/(.+)$|$rw/\1|\"`" + dstdir="`dirname \"$dstfile\"`" + if [ ! -e "$srcfile" ]; then + echo "Whitelist entry not present in filesystem:" + echo "$srcfile" + continue + # For very large dirs: mv whole dir when entry ends with '/' + elif echo $wlfile |grep -q "\/$"; then + # echo "Whitelist mv $srcfile" + # echo "to $dstfile" + mkdir -p "$dstdir" + mv -T "$srcfile" "$dstfile" + else + # echo "Whitelist cp $srcfile" + mkdir -p "$dstdir" + cp -a --link "$srcfile" "$dstdir" + fi + elif [ -n "$wlfile" ]; then + echo "Whitelist path must begin with /rw/. Skipped." fi - elif [ -n "$wlfile" ]; then - echo "Whitelist path must begin with /rw/. Skipped." - fi - done + done + fi # Copy default files... if [ -d $defdir/$vmset/rw ]; then - echo "Copy files from $defdir/$vmset/rw" + # echo "Copy files from $defdir/$vmset/rw" cp -af $defdir/$vmset/rw/* $rw fi done @@ -260,13 +263,13 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then fi -# Keep configs invisible at runtime... -rm -rf "$defdir" - if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then echo "Preparing for unmount" make_immutable umount $rw fi +# Keep configs invisible at runtime... +rm -rf "$defdir" $servicedir/vm-boot-tag* $servicedir/vm-boot-protect* $errlog + exit 0 From 8f8e7e6595677a22f8171c301566cb3b4450c0e5 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Tue, 13 Aug 2019 13:46:52 -0400 Subject: [PATCH 09/23] add uninstall, refine ibrowse --- README.md | 25 +++++++---- .../.mozilla/firefox/profile.default/user.js | 6 +++ .../home/user/.mozilla/firefox/profiles.ini | 9 ++++ default/vms/@tags/{usb.rc => qhome.rc} | 0 ibrowse.whitelist | 3 -- install | 42 +++++++++++++++++-- vm-boot-protect.sh | 9 +++- 7 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 default/vms/@tags/ibrowse/rw/home/user/.mozilla/firefox/profile.default/user.js create mode 100644 default/vms/@tags/ibrowse/rw/home/user/.mozilla/firefox/profiles.ini rename default/vms/@tags/{usb.rc => qhome.rc} (100%) delete mode 100644 ibrowse.whitelist diff --git a/README.md b/README.md index b6300b0..8846fbf 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@ Leverage Qubes template non-persistence to fend off malware at VM startup: Lock- * Acts at VM startup before private volume /rw mounts * User: Protect /home desktop & shell startup executables * Root: Quarantine all /rw configs & scripts, with whitelisting - * Re-deploy custom or default files to /rw on each boot + * Organize configurations with named tags + * Deploy trusted custom files to /rw on each boot * SHA256 hash checking against unwanted changes * Provides rescue shell on error or request * Works with template-based AppVMs, sys-net and sys-vpn @@ -32,7 +33,7 @@ Leverage Qubes template non-persistence to fend off malware at VM startup: Lock- For Debian-based templates the installer will launch `configure-sudo-prompt` automatically to enable a sudo [yes/no prompt](https://www.qubes-os.org/doc/vm-sudo/#replacing-password-less-root-access-with-dom0-user-prompt) that appears in dom0. This handles the template configuration then displays several commands to manually configure dom0 (the dom0 step is required only once, regardless of how many templates you configure). You may test the `configure-sudo-prompt` script in a regular template-based appVM to see if it works, although the effect will be temporary. Alternately, you can uninstall the `qubes-core-agent-passwordless-root` package from the template. After doing this, you will have to use `qvm-run -u root` from dom0 to run any VM commands as root. - + --- ### Usage @@ -48,7 +49,7 @@ Leverage Qubes template non-persistence to fend off malware at VM startup: Lock- ### Configuration - Files can be added to /etc/default/vms in the template to enable the following features... + Files can be added to /etc/default/vms in the template to configure the following `vm-boot-protect-root` features... **Hashes/Checksums** are checked in ../vms/vms.all.SHA and ../vms/$vmname.SHA files. File paths contained in them must be absolute, and references to '/home' must be prefixed with '/rw/'. Hashes in $vmname.SHA will override hashes specified for the same paths in vms.all.SHA. See also man page for `sha256sum -c`. @@ -59,7 +60,7 @@ the /etc/defaults/vms folder is deleted from the running VM (this has no effect **rc files** are sh script fragments sourced from ../vms/vms.all.rc and ../vms/$vmname.rc. They run near the beginning of the vm-boot-protect service before mounting /rw, and can be used to override variable definitions like `privdirs` as well as the `vm_boot_finish` function which runs near the end before dismount. Another use for rc files is to run threat detection tools such as antivirus. - **Tags** may be defined with all of the above features so that you are not limited to specifying them for either all VMs or specifically-named VMs. Simply configure them as you would acccording to the above directions, but place the files under the '@tags' subdir instead. For example '/etc/default/vms/@tags/special.whitelist' defines a whitelist for the tag 'special'. A tag can be activated for one or more VMs by adding a Qubes service prefixed with `vm-boot-tag-` (i.e. vm-boot-tag-special) to the VMs. + **Tags** may be defined with all of the above features so that you are not limited to specifying them for either all VMs or specifically-named VMs. Simply configure them as you would acccording to the above directions, but place the files under the '@tags' subdir instead. For example '/etc/default/vms/@tags/special.whitelist' defines a whitelist for the tag 'special'. A tag can be activated for one or more VMs by adding a Qubes service prefixed with `vm-boot-tag-` (i.e. vm-boot-tag-special) to the VMs. Also, multiple tags may be activated for a VM. ### Where to use: Basic examples @@ -75,18 +76,26 @@ Examples where -root should *not* be enabled: * Standalone VMs. Plain `vm-boot-protect` makes more sense for these. * Non-Linux VMs (currently unsupported for any mode) +### Example configs + +Some usefull configurations have been supplied in /etc/default/vms: + + * vm-boot-tag-network: Contains a whitelist for Network Manager connections and the module blacklist which is often used with network interfaces in Qubes. By default, this config also activates for any VM named 'sys-net'. + * vm-boot-tag-qhome: Quarrantines /home in addition to the /rw system dirs. Useful for 'sys-usb' and DispVM-like functionality. + * vm-boot-tag-ibrowse: Preserves Firefox bookmarks while quarantining the rest of /home folder. (To preserve pre-existing bookmarks, existing Firefox profile folder must be renamed to "profile.default" before activating this tag.) + ### Scope and Limitations The *vm-boot-protect* concept enhances the guest operating system's own defenses by using the *root volume non-persistence* provided by the Qubes template system; thus a relatively pristine startup state may be achieved if the *private* volume is brought online in a controlled manner. Protecting the init/autostart files should result in Qubes template-based VMs that boot 'cleanly' with much less chance of being affected by malware initially. Even if malware persists in a VM, it should be possible to run other apps and terminals without interference if the malware has not escalated to root (admittedly, a big 'if'). Conversely, attacks which damage/exploit the Ext4 private filesystem itself or quickly re-exploit network vulnerabilities could conceivably still persist at startup. Further, repeated running of some apps such as Firefox, Chrome, LibreOffice, PDF viewers, online games, etc. may reactivate malware; this is not only because of the complexity of the formats handled by such apps, but also because of settings contained in javascript or which specify commands to be executed by the app. Therefore, setting apps to autostart can diminish protection of the startup environment. - + Note that as vulnerabilities are patched via system updates, malware that used those vulns to gain entry may cease to function without the kind of loopholes that *vm-boot-protect* closes. ### Notes - * The /rw/home directory can be added to `privdirs` so it is quarrantined much like /rw/config, /rw/binddirs and /rw/usrlocal. The easiest way to configure this is to define `privdirs_add=/rw/home` in an rc file or a drop-in for the vm-boot-protect.service. But in the case of /rw/home, the /rw/home/user folder will be repopulated automatically from OS defaults (usually in /etc/skel) before whitelists are applied. For an example, see the `ibrowse` tag which quarrantines home while whitelisting Firefox bookmarks. + * The /rw/home directory can be added to `privdirs` so it is quarrantined much like the other /rw dirs. The easiest way to configure this is to define `privdirs_add=/rw/home` in an rc file; see 'qhome.rc' for an exmaple. * A bug in v0.8.4 will erase anything in '/etc/default/vms' when booting into the template. For proper future operation with sys-net or other VMs you may have customized in that path, updating Qubes-VM-hardening @@ -95,8 +104,6 @@ Examples where -root should *not* be enabled: * All the user-writable startup files in /home should be protected by the immutable flag; See issue #9 if you notice an omission or other problem. An extra step of disabling the flag using `sudo chattr -i` is required whenever the user wants to modify these startup files. - * Adding /home or subdirs of it to $privdirs is possible. This would quarantine everything there to set the stage for applying whitelists on /home contents. The $privdirs variable can be changed via the service file, for example adding a .conf file in /lib/systemd/system/vm-boot-protect.d. - * The sys-net VM should work 'out of the box' with the vm-boot-protect-root service via the included whitelist file. Additional network VMs may require configuration, such as `cp sys-net.whitelist sys-net2.whitelist`. * Using the -root service with a [VPN VM](https://github.com/tasket/Qubes-vpn-support) requires manual configuration in the template and can be approached different ways: Whitelist (optionally with SHA) can be made for the appropriate files. Alternately, all VPN configs can be added under /etc/default/vms/vmname/rw so they'll be automatically deployed. @@ -104,7 +111,7 @@ Examples where -root should *not* be enabled: * Currently the service cannot seamlessly handle 'first boot' when the private volume must be initialized. If you enabled the service on a VM before its first startup, on first start the shell will display a notice telling you to restart the VM. Subsequent starts will proceed normally. ## Releases - - v0.9.0 Add tags and rc files, protect more home scripts, support home quarrantine + - v0.9.0 Add tags and rc files, protect more home scripts, reinitialize home - v0.8.5 Fix template detection, /etc/default/vms erasure - v0.8.4 Add protection to /home/user/.config/systemd - v0.8.3 Fix for install script copying to /etc/default/vms diff --git a/default/vms/@tags/ibrowse/rw/home/user/.mozilla/firefox/profile.default/user.js b/default/vms/@tags/ibrowse/rw/home/user/.mozilla/firefox/profile.default/user.js new file mode 100644 index 0000000..abeef9c --- /dev/null +++ b/default/vms/@tags/ibrowse/rw/home/user/.mozilla/firefox/profile.default/user.js @@ -0,0 +1,6 @@ +// Remove history from places.sqlite +user_pref("privacy.history.custom",true); +user_pref("privacy.sanitize.sanitizeOnShutdown",true); +user_pref("privacy.clearOnShutdown.downloads",true); +user_pref("privacy.clearOnShutdown.history",true); +user_pref("browser.search.suggest.enabled",false); diff --git a/default/vms/@tags/ibrowse/rw/home/user/.mozilla/firefox/profiles.ini b/default/vms/@tags/ibrowse/rw/home/user/.mozilla/firefox/profiles.ini new file mode 100644 index 0000000..726d784 --- /dev/null +++ b/default/vms/@tags/ibrowse/rw/home/user/.mozilla/firefox/profiles.ini @@ -0,0 +1,9 @@ +[General] +StartWithLastProfile=1 + +[Profile0] +Name=default +IsRelative=1 +Path=profile.default +Default=1 + diff --git a/default/vms/@tags/usb.rc b/default/vms/@tags/qhome.rc similarity index 100% rename from default/vms/@tags/usb.rc rename to default/vms/@tags/qhome.rc diff --git a/ibrowse.whitelist b/ibrowse.whitelist deleted file mode 100644 index 9f17a0f..0000000 --- a/ibrowse.whitelist +++ /dev/null @@ -1,3 +0,0 @@ -/rw/home/user/.mozilla/firefox/profile.default/places.sqlite -/rw/home/user/.mozilla/firefox/profile.default/places.sqlite-shm -/rw/home/user/.mozilla/firefox/profile.default/places.sqlite-wal diff --git a/install b/install index 45be4da..423bdb3 100644 --- a/install +++ b/install @@ -1,12 +1,24 @@ #!/bin/bash # From https://github.com/tasket/Qubes-VM-hardening -# installer version 0.8.4 +# installer version 0.9.0 set -e [ `id -u` -eq 0 ] || exit -echo "Disabling the pre-release service (if present)..." -systemctl disable vm-sudo-protect.service || true +if [ "$1" = "--uninstall" ]; then + echo "Removing vm-boot-protect.service..." + echo "Warning: This will remove any custom files added to /etc/default/vms!" + read -p "Proceed [y/N]? " ans + if [[ $ans == @(Y|y) ]]; then + systemctl disable vm-boot-protect.service + rm -r /lib/systemd/system/vm-boot-protect.service /usr/lib/qubes/init/vm-boot-protect.sh /etc/default/vms + systemctl daemon-reload + echo "Done." + else + echo "Aborted." + fi +fi + echo "Installing vm-boot-protect.service..." cp vm-boot-protect.sh /usr/lib/qubes/init @@ -20,6 +32,30 @@ mkdir -p /etc/default/vms # Careful... ownership & mode are not preserved here! cp -riv default/vms/* /etc/default/vms + +# echo +# echo "Setup empty Firefox default profile in /etc/skel..." +# echo "A fixed-name profile will be defined in the /home/user folder" +# echo "whenever home is reset/initialized. This is required when" +# echo "using vm-boot-protect features (such as ibrowse) to" +# echo "whitelist parts of the browser configuration." +# echo +# read -p "Add Firefox default profile [y/N]? " ans +# if [[ $ans == @(Y|y) ]]; then +# mkdir -p /etc/skel/.mozilla/firefox/profile.default +# cat <<__END1__ >/etc/skel/.mozilla/firefox/profiles.ini +# [General] +# StartWithLastProfile=1 +# +# [Profile0] +# Name=default +# IsRelative=1 +# Path=profile.default +# Default=1 +# __END1__ +# +# fi + echo -e "\nvm-boot-protect installed!\n" bash ./configure-sudo-prompt diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index a28c610..73d4411 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -30,7 +30,8 @@ rwbak=$rw/vm-boot-protect errlog=/var/run/vm-protect-error servicedir=/var/run/qubes-service defdir=/etc/default/vms -version="0.9.0" +save_backup=${save_backup:-1} +version="0.9.0b" # Define sh, bash, X and desktop init scripts in /home/user # to be protected @@ -272,4 +273,10 @@ fi # Keep configs invisible at runtime... rm -rf "$defdir" $servicedir/vm-boot-tag* $servicedir/vm-boot-protect* $errlog +# Remove backups if indicated +if [ $save_backup = 0 ]; then + chattr -R -f -i $rwbak + rm -rf $rwbak +fi + exit 0 From 876491ceee366c4d815241b6f094ed77d5bea222 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Tue, 13 Aug 2019 14:46:03 -0400 Subject: [PATCH 10/23] fix backup rm sequence --- vm-boot-protect.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index 73d4411..95e4330 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -30,7 +30,6 @@ rwbak=$rw/vm-boot-protect errlog=/var/run/vm-protect-error servicedir=/var/run/qubes-service defdir=/etc/default/vms -save_backup=${save_backup:-1} version="0.9.0b" # Define sh, bash, X and desktop init scripts in /home/user @@ -44,7 +43,8 @@ chdirs_add=${chdirs_add:-""} # Define dirs to apply quarrantine / whitelists privdirs=${privdirs:-"/rw/config /rw/usrlocal /rw/bind-dirs"} -privdirs_add="" +privdirs_add=${privdirs_add:-""} +save_backup=${save_backup:-1} # Placeholder function: Runs at end @@ -264,12 +264,6 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then fi -if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then - echo "Preparing for unmount" - make_immutable - umount $rw -fi - # Keep configs invisible at runtime... rm -rf "$defdir" $servicedir/vm-boot-tag* $servicedir/vm-boot-protect* $errlog @@ -279,4 +273,10 @@ if [ $save_backup = 0 ]; then rm -rf $rwbak fi +if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then + echo "Preparing for unmount" + make_immutable + umount $rw +fi + exit 0 From 700016197ec8aaf037e1af647612abdaa087f1d3 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Tue, 13 Aug 2019 15:55:13 -0400 Subject: [PATCH 11/23] fix spelling, add tag noqbackup --- README.md | 9 ++++----- default/vms/@tags/ibrowse.rc | 1 + default/vms/@tags/noqbackup.rc | 2 ++ default/vms/@tags/qhome.rc | 1 + vm-boot-protect.sh | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 default/vms/@tags/noqbackup.rc diff --git a/README.md b/README.md index 8846fbf..ec8a416 100644 --- a/README.md +++ b/README.md @@ -78,10 +78,11 @@ Examples where -root should *not* be enabled: ### Example configs -Some usefull configurations have been supplied in /etc/default/vms: +Some useful configurations have been supplied in /etc/default/vms: * vm-boot-tag-network: Contains a whitelist for Network Manager connections and the module blacklist which is often used with network interfaces in Qubes. By default, this config also activates for any VM named 'sys-net'. - * vm-boot-tag-qhome: Quarrantines /home in addition to the /rw system dirs. Useful for 'sys-usb' and DispVM-like functionality. + * vm-boot-tag-qhome: Quarantines /home in addition to the /rw system dirs. Useful for 'sys-usb' and DispVM-like functionality. + * vm-boot-tag-noqbackup: Deletes all quarantined files that are not whitelisted. * vm-boot-tag-ibrowse: Preserves Firefox bookmarks while quarantining the rest of /home folder. (To preserve pre-existing bookmarks, existing Firefox profile folder must be renamed to "profile.default" before activating this tag.) @@ -95,7 +96,7 @@ Some usefull configurations have been supplied in /etc/default/vms: ### Notes - * The /rw/home directory can be added to `privdirs` so it is quarrantined much like the other /rw dirs. The easiest way to configure this is to define `privdirs_add=/rw/home` in an rc file; see 'qhome.rc' for an exmaple. + * The /rw/home directory can be added to `privdirs` so it is quarantined much like the other /rw dirs. The easiest way to configure this is to define `privdirs_add=/rw/home` in an rc file; see 'qhome.rc' for an exmaple. * A bug in v0.8.4 will erase anything in '/etc/default/vms' when booting into the template. For proper future operation with sys-net or other VMs you may have customized in that path, updating Qubes-VM-hardening @@ -118,5 +119,3 @@ Some usefull configurations have been supplied in /etc/default/vms: - v0.8.2 Working rescue shell. Add sys-net whitelist, sudo config, fixes. - v0.8.0 Adds protection to /rw, file SHA checksums, whitelists, deployment - v0.2.0 Protects /home/user files and dirs - - diff --git a/default/vms/@tags/ibrowse.rc b/default/vms/@tags/ibrowse.rc index b26ec82..f61377b 100644 --- a/default/vms/@tags/ibrowse.rc +++ b/default/vms/@tags/ibrowse.rc @@ -1 +1,2 @@ +# Browser-focused config that saves only bookmarks, starts with /home quarantine privdirs_add="/rw/home" diff --git a/default/vms/@tags/noqbackup.rc b/default/vms/@tags/noqbackup.rc new file mode 100644 index 0000000..53f0302 --- /dev/null +++ b/default/vms/@tags/noqbackup.rc @@ -0,0 +1,2 @@ +# Removes any files that were quarantined under /rw/vm-boot-protect/ +save_backup=0 diff --git a/default/vms/@tags/qhome.rc b/default/vms/@tags/qhome.rc index b26ec82..3549057 100644 --- a/default/vms/@tags/qhome.rc +++ b/default/vms/@tags/qhome.rc @@ -1 +1,2 @@ +# Quarantine entire /home directory privdirs_add="/rw/home" diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index 95e4330..6f7bf92 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -41,7 +41,7 @@ chdirs=${chdirs:-"bin .local/bin .config/autostart .config/plasma-workspace/env .config/plasma-workspace/shutdown .config/autostart-scripts .config/systemd"} chdirs_add=${chdirs_add:-""} -# Define dirs to apply quarrantine / whitelists +# Define dirs to apply quarantine / whitelists privdirs=${privdirs:-"/rw/config /rw/usrlocal /rw/bind-dirs"} privdirs_add=${privdirs_add:-""} save_backup=${save_backup:-1} From b203c69a3c502c36bd14a08a9bc776b1349ef79c Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Tue, 13 Aug 2019 16:22:27 -0400 Subject: [PATCH 12/23] fix uninstall exit --- README.md | 6 ++++-- install | 24 +----------------------- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index ec8a416..fa633b6 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Leverage Qubes template non-persistence to fend off malware at VM startup: Lock- 1. In a template VM, install the service files ``` cd Qubes-VM-hardening - sudo sh ./install + sudo bash install ``` 2. Activate by specifying one of the following Qubes services for your VM(s)... @@ -110,7 +110,9 @@ Some useful configurations have been supplied in /etc/default/vms: * Using the -root service with a [VPN VM](https://github.com/tasket/Qubes-vpn-support) requires manual configuration in the template and can be approached different ways: Whitelist (optionally with SHA) can be made for the appropriate files. Alternately, all VPN configs can be added under /etc/default/vms/vmname/rw so they'll be automatically deployed. * Currently the service cannot seamlessly handle 'first boot' when the private volume must be initialized. If you enabled the service on a VM before its first startup, on first start the shell will display a notice telling you to restart the VM. Subsequent starts will proceed normally. - + + * The service can be removed from the system with `cd Qubes-VM-hardening; sudo bash install --uninstall` + ## Releases - v0.9.0 Add tags and rc files, protect more home scripts, reinitialize home - v0.8.5 Fix template detection, /etc/default/vms erasure diff --git a/install b/install index 423bdb3..662c620 100644 --- a/install +++ b/install @@ -17,6 +17,7 @@ if [ "$1" = "--uninstall" ]; then else echo "Aborted." fi + exit 0 fi @@ -33,29 +34,6 @@ mkdir -p /etc/default/vms cp -riv default/vms/* /etc/default/vms -# echo -# echo "Setup empty Firefox default profile in /etc/skel..." -# echo "A fixed-name profile will be defined in the /home/user folder" -# echo "whenever home is reset/initialized. This is required when" -# echo "using vm-boot-protect features (such as ibrowse) to" -# echo "whitelist parts of the browser configuration." -# echo -# read -p "Add Firefox default profile [y/N]? " ans -# if [[ $ans == @(Y|y) ]]; then -# mkdir -p /etc/skel/.mozilla/firefox/profile.default -# cat <<__END1__ >/etc/skel/.mozilla/firefox/profiles.ini -# [General] -# StartWithLastProfile=1 -# -# [Profile0] -# Name=default -# IsRelative=1 -# Path=profile.default -# Default=1 -# __END1__ -# -# fi - echo -e "\nvm-boot-protect installed!\n" bash ./configure-sudo-prompt From e385fa995b0bc88dd95f5e432652c85eb23b7dd0 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Wed, 14 Aug 2019 01:18:54 -0400 Subject: [PATCH 13/23] fix template exit condition --- vm-boot-protect.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index 6f7bf92..0241a45 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -133,13 +133,16 @@ if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then fi fi - # Don't bother with root protections in template or standalone + # Begin exit if in template or standalone if ! is_rwonly_persistent; then make_immutable - exit 0 fi fi +# Exit if in template or standalone +if ! is_rwonly_persistent; then + exit 0 +fi # Protection measures for /rw dirs: From 8327e1e10664cd2819c3fd0a7ea5cb5bd74de7dc Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Wed, 14 Aug 2019 01:34:39 -0400 Subject: [PATCH 14/23] umount in template --- vm-boot-protect.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index 0241a45..3c64cc3 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -136,6 +136,7 @@ if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then # Begin exit if in template or standalone if ! is_rwonly_persistent; then make_immutable + umount $rw fi fi @@ -268,7 +269,9 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then fi # Keep configs invisible at runtime... -rm -rf "$defdir" $servicedir/vm-boot-tag* $servicedir/vm-boot-protect* $errlog +if ! is_templatevm; then + rm -rf "$defdir" $servicedir/vm-boot-tag* $servicedir/vm-boot-protect* $errlog +fi # Remove backups if indicated if [ $save_backup = 0 ]; then From 9bff232683c7a241b4b3471bab1b8ac88afb0439 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Thu, 15 Aug 2019 15:08:44 -0400 Subject: [PATCH 15/23] version 0.9.0 --- README.md | 4 ++-- vm-boot-protect.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fa633b6..88902c6 100644 --- a/README.md +++ b/README.md @@ -76,14 +76,14 @@ Examples where -root should *not* be enabled: * Standalone VMs. Plain `vm-boot-protect` makes more sense for these. * Non-Linux VMs (currently unsupported for any mode) -### Example configs +### Example tags Some useful configurations have been supplied in /etc/default/vms: * vm-boot-tag-network: Contains a whitelist for Network Manager connections and the module blacklist which is often used with network interfaces in Qubes. By default, this config also activates for any VM named 'sys-net'. * vm-boot-tag-qhome: Quarantines /home in addition to the /rw system dirs. Useful for 'sys-usb' and DispVM-like functionality. * vm-boot-tag-noqbackup: Deletes all quarantined files that are not whitelisted. - * vm-boot-tag-ibrowse: Preserves Firefox bookmarks while quarantining the rest of /home folder. (To preserve pre-existing bookmarks, existing Firefox profile folder must be renamed to "profile.default" before activating this tag.) + * vm-boot-tag-ibrowse: Preserves Firefox bookmarks while quarantining the /home folder. [Currently](https://github.com/tasket/Qubes-VM-hardening/issues/39) works with Firefox ESR. ### Scope and Limitations diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index 3c64cc3..3a28d47 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -30,7 +30,7 @@ rwbak=$rw/vm-boot-protect errlog=/var/run/vm-protect-error servicedir=/var/run/qubes-service defdir=/etc/default/vms -version="0.9.0b" +version="0.9.0" # Define sh, bash, X and desktop init scripts in /home/user # to be protected From 67315b0119fe9f4472559c112d6c6b4529bbf919 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Thu, 15 Aug 2019 15:44:21 -0400 Subject: [PATCH 16/23] add note --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 88902c6..af3ee73 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ the /etc/defaults/vms folder is deleted from the running VM (this has no effect **rc files** are sh script fragments sourced from ../vms/vms.all.rc and ../vms/$vmname.rc. They run near the beginning of the vm-boot-protect service before mounting /rw, and can be used to override variable definitions like `privdirs` as well as the `vm_boot_finish` function which runs near the end before dismount. Another use for rc files is to run threat detection tools such as antivirus. - **Tags** may be defined with all of the above features so that you are not limited to specifying them for either all VMs or specifically-named VMs. Simply configure them as you would acccording to the above directions, but place the files under the '@tags' subdir instead. For example '/etc/default/vms/@tags/special.whitelist' defines a whitelist for the tag 'special'. A tag can be activated for one or more VMs by adding a Qubes service prefixed with `vm-boot-tag-` (i.e. vm-boot-tag-special) to the VMs. Also, multiple tags may be activated for a VM. + **Tags:** Any of the above configs may be defined as tags so that you are not limited to specifying them for either all VMs or specifically-named VMs. Simply configure them as you would acccording to the above directions, but place the files under the '@tags' subdir instead. For example '/etc/default/vms/@tags/special.whitelist' defines a whitelist for the tag 'special'. A tag can be activated for one or more VMs by adding a Qubes service prefixed with `vm-boot-tag-` (i.e. vm-boot-tag-special) to the VMs. Also, multiple tags may be activated for a VM. ### Where to use: Basic examples @@ -83,21 +83,25 @@ Some useful configurations have been supplied in /etc/default/vms: * vm-boot-tag-network: Contains a whitelist for Network Manager connections and the module blacklist which is often used with network interfaces in Qubes. By default, this config also activates for any VM named 'sys-net'. * vm-boot-tag-qhome: Quarantines /home in addition to the /rw system dirs. Useful for 'sys-usb' and DispVM-like functionality. * vm-boot-tag-noqbackup: Deletes all quarantined files that are not whitelisted. - * vm-boot-tag-ibrowse: Preserves Firefox bookmarks while quarantining the /home folder. [Currently](https://github.com/tasket/Qubes-VM-hardening/issues/39) works with Firefox ESR. + * vm-boot-tag-ibrowse: Preserves Firefox bookmarks while quarantining the /home folder. [Currently](https://github.com/tasket/Qubes-VM-hardening/issues/39) works with Firefox ESR. See Notes below. ### Scope and Limitations The *vm-boot-protect* concept enhances the guest operating system's own defenses by using the *root volume non-persistence* provided by the Qubes template system; thus a relatively pristine startup state may be achieved if the *private* volume is brought online in a controlled manner. Protecting the init/autostart files should result in Qubes template-based VMs that boot 'cleanly' with much less chance of being affected by malware initially. Even if malware persists in a VM, it should be possible to run other apps and terminals without interference if the malware has not escalated to root (admittedly, a big 'if'). - Conversely, attacks which damage/exploit the Ext4 private filesystem itself or quickly re-exploit network vulnerabilities could conceivably still persist at startup. Further, repeated running of some apps such as Firefox, Chrome, LibreOffice, PDF viewers, online games, etc. may reactivate malware; this is not only because of the complexity of the formats handled by such apps, but also because of settings contained in javascript or which specify commands to be executed by the app. Therefore, setting apps to autostart can diminish protection of the startup environment. + Conversely, attacks which damage/exploit the Ext4 private filesystem itself or quickly re-exploit network vulnerabilities could conceivably still persist at startup. Further, repeated running of complex apps, games, and programming environments may reactivate malware; this is because of the complexity of the formats and settings handled by such apps. Therefore, setting apps to autostart can diminish protection of the startup environment. - Note that as vulnerabilities are patched via system updates, malware that used those vulns to gain entry may cease to function without the kind of loopholes that *vm-boot-protect* closes. + Note that as system and app vulnerabilities are patched via system updates, malware that used those vulns to gain entry may cease to function without the kind of loopholes that *vm-boot-protect* closes. + + Efficient template re-use is another aspect of using *vm-boot-protect-root* features, since a single template can be customized for various roles. However, note that some customizations may not be appropriate to run during VM startup. ### Notes * The /rw/home directory can be added to `privdirs` so it is quarantined much like the other /rw dirs. The easiest way to configure this is to define `privdirs_add=/rw/home` in an rc file; see 'qhome.rc' for an exmaple. + * The ibrowse tag works with Firefox versions up to 66 and uses a generic profile named 'profile.default'. If you wish to carry over existing bookmarks for use with ibrowse, rename the current profile folder in '.mozilla/firefox' to 'profile.default' before enabling the ibrowse tag. + * A bug in v0.8.4 will erase anything in '/etc/default/vms' when booting into the template. For proper future operation with sys-net or other VMs you may have customized in that path, updating Qubes-VM-hardening to the latest version (using the install script) is recommended, along with restoring any custom files From bbdc5b711b1cf20782bec6966d61116e5e5173ac Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Sat, 17 Aug 2019 13:28:36 -0400 Subject: [PATCH 17/23] move rc back before mount --- .vm-boot-protect.sh.kate-swp | Bin 0 -> 911 bytes vm-boot-protect.sh | 29 ++++++++++++++++------------- 2 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 .vm-boot-protect.sh.kate-swp diff --git a/.vm-boot-protect.sh.kate-swp b/.vm-boot-protect.sh.kate-swp new file mode 100644 index 0000000000000000000000000000000000000000..1b6a07c1734bbbf117977b2bc067ebab04efc8be GIT binary patch literal 911 zcmZ9L?Mebc6o$vL?+?qQZ(*;X)bdZ_PlE{mxJ3Okp^Y|V6<1iio^B}U3c8IT=sdeS zozVk>^UQf?_C0e(V@&yeFbzCE8H~N#a2R-vi<&W}@-(`Mo?G3Iug|1f`R@MyyuTd! zkCM5RVLE=tzms32L?Kizz^}?nu&2B%TnXd;BpF4+S$`Z%;xL{D(NrZzY-uSUFC1|K zJNi@jP4#DRpnMKTozy>;tJZ&AfUy4H)PL?5cKyTnclAYhl6{Q)3Y;jf!XxE1Sj=#L z=-1()@&-Ip-h}(gTku$U8_tX6ydBu_vkS+nFTqZIdvIIx`wRIpT+c3#^A9pE-6d!s+Ga=HT>lr5IisT(q6K5+JN|*zFYTb_#Yo1=FdL^X$B~ zCw28?m26o?UYo^2Evw{OQiOfhaQbm+D^B4hoIc2;nH_00vQDQh@=uxD0yJe9+5ZQE CV`?`5 literal 0 HcmV?d00001 diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index 3a28d47..586f3a6 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -30,7 +30,7 @@ rwbak=$rw/vm-boot-protect errlog=/var/run/vm-protect-error servicedir=/var/run/qubes-service defdir=/etc/default/vms -version="0.9.0" +version="0.9.1" # Define sh, bash, X and desktop init scripts in /home/user # to be protected @@ -111,11 +111,25 @@ abort_startup() { echo >$errlog # Clear - if qsvc vm-boot-protect-cli; then abort_startup RELOCATE "CLI requested." fi + +# Run rc file commands if they exist +if qsvc vm-boot-protect-root && is_rwonly_persistent; then + # Get list of enabled tags from Qubes services + tags=`find $servicedir -name 'vm-boot-tag-*' -type f -printf '%f\n' \ + | sort | sed -E 's|^vm-boot-tag-|\@tags/|'` + + for rcbase in vms.all $tags $vmname; do + if [ -e "$defdir/$rcbase.rc" ]; then + . "$defdir/$rcbase.rc" + fi + done +fi + + if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then # Mount private volume in temp location mkdir -p $rw @@ -154,17 +168,6 @@ fi if qsvc vm-boot-protect-root && is_rwonly_persistent; then - # Get list of enabled tags from Qubes services - tags=`find $servicedir -name 'vm-boot-tag-*' -type f -printf '%f\n' \ - | sort | sed -E 's|^vm-boot-tag-|\@tags/|'` - - # Run rc file commands if they exist - for rcbase in vms.all $tags $vmname; do - if [ -e "$defdir/$rcbase.rc" ]; then - . "$defdir/$rcbase.rc" - fi - done - # Check hashes checkcode=0 for sha_base in $vmname $tags vms.all; do From 13d5c5d2deec4ecf427f36d802915bb45f5272ea Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Sat, 17 Aug 2019 15:12:13 -0400 Subject: [PATCH 18/23] optimize, add tag wiperw --- .vm-boot-protect.sh.kate-swp | Bin 911 -> 0 bytes README.md | 4 +++- default/vms/@tags/wiperw.rc | 4 ++++ vm-boot-protect.sh | 14 ++++++++++---- 4 files changed, 17 insertions(+), 5 deletions(-) delete mode 100644 .vm-boot-protect.sh.kate-swp create mode 100644 default/vms/@tags/wiperw.rc diff --git a/.vm-boot-protect.sh.kate-swp b/.vm-boot-protect.sh.kate-swp deleted file mode 100644 index 1b6a07c1734bbbf117977b2bc067ebab04efc8be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 911 zcmZ9L?Mebc6o$vL?+?qQZ(*;X)bdZ_PlE{mxJ3Okp^Y|V6<1iio^B}U3c8IT=sdeS zozVk>^UQf?_C0e(V@&yeFbzCE8H~N#a2R-vi<&W}@-(`Mo?G3Iug|1f`R@MyyuTd! zkCM5RVLE=tzms32L?Kizz^}?nu&2B%TnXd;BpF4+S$`Z%;xL{D(NrZzY-uSUFC1|K zJNi@jP4#DRpnMKTozy>;tJZ&AfUy4H)PL?5cKyTnclAYhl6{Q)3Y;jf!XxE1Sj=#L z=-1()@&-Ip-h}(gTku$U8_tX6ydBu_vkS+nFTqZIdvIIx`wRIpT+c3#^A9pE-6d!s+Ga=HT>lr5IisT(q6K5+JN|*zFYTb_#Yo1=FdL^X$B~ zCw28?m26o?UYo^2Evw{OQiOfhaQbm+D^B4hoIc2;nH_00vQDQh@=uxD0yJe9+5ZQE CV`?`5 diff --git a/README.md b/README.md index af3ee73..549b8d9 100644 --- a/README.md +++ b/README.md @@ -84,8 +84,9 @@ Some useful configurations have been supplied in /etc/default/vms: * vm-boot-tag-qhome: Quarantines /home in addition to the /rw system dirs. Useful for 'sys-usb' and DispVM-like functionality. * vm-boot-tag-noqbackup: Deletes all quarantined files that are not whitelisted. * vm-boot-tag-ibrowse: Preserves Firefox bookmarks while quarantining the /home folder. [Currently](https://github.com/tasket/Qubes-VM-hardening/issues/39) works with Firefox ESR. See Notes below. + * vm-boot-wiperw: Completely wipe and reformat the /rw partition. - + ### Scope and Limitations The *vm-boot-protect* concept enhances the guest operating system's own defenses by using the *root volume non-persistence* provided by the Qubes template system; thus a relatively pristine startup state may be achieved if the *private* volume is brought online in a controlled manner. Protecting the init/autostart files should result in Qubes template-based VMs that boot 'cleanly' with much less chance of being affected by malware initially. Even if malware persists in a VM, it should be possible to run other apps and terminals without interference if the malware has not escalated to root (admittedly, a big 'if'). @@ -118,6 +119,7 @@ Some useful configurations have been supplied in /etc/default/vms: * The service can be removed from the system with `cd Qubes-VM-hardening; sudo bash install --uninstall` ## Releases + - v0.9.1 Optimized, fix rc order, new "wiperw" tag - v0.9.0 Add tags and rc files, protect more home scripts, reinitialize home - v0.8.5 Fix template detection, /etc/default/vms erasure - v0.8.4 Add protection to /home/user/.config/systemd diff --git a/default/vms/@tags/wiperw.rc b/default/vms/@tags/wiperw.rc new file mode 100644 index 0000000..3879af7 --- /dev/null +++ b/default/vms/@tags/wiperw.rc @@ -0,0 +1,4 @@ +# Completely wipes private volume contents + +blkdiscard $dev +mkfs.ext4 $dev diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index 586f3a6..d19772a 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -46,6 +46,12 @@ privdirs=${privdirs:-"/rw/config /rw/usrlocal /rw/bind-dirs"} privdirs_add=${privdirs_add:-""} save_backup=${save_backup:-1} +if is_rwonly_persistent; then + rwonly_pers=1 +else + rwonly_pers=0 +fi + # Placeholder function: Runs at end vm_boot_finish() { return; } @@ -117,7 +123,7 @@ fi # Run rc file commands if they exist -if qsvc vm-boot-protect-root && is_rwonly_persistent; then +if qsvc vm-boot-protect-root && [ $rwonly_pers = 1 ]; then # Get list of enabled tags from Qubes services tags=`find $servicedir -name 'vm-boot-tag-*' -type f -printf '%f\n' \ | sort | sed -E 's|^vm-boot-tag-|\@tags/|'` @@ -148,14 +154,14 @@ if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then fi # Begin exit if in template or standalone - if ! is_rwonly_persistent; then + if [ $rwonly_pers = 0 ]; then make_immutable umount $rw fi fi # Exit if in template or standalone -if ! is_rwonly_persistent; then +if [ $rwonly_pers = 0 ]; then exit 0 fi @@ -166,7 +172,7 @@ fi # * Remove /rw root startup files (config, usrlocal, bind-dirs). # * Contents of vms/vms.all and vms/$vmname folders will be copied. -if qsvc vm-boot-protect-root && is_rwonly_persistent; then +if qsvc vm-boot-protect-root && [ $rwonly_pers = 1 ]; then # Check hashes checkcode=0 From 47b42547d188e3b2d051cc7547a15c0c686e2467 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Sun, 18 Aug 2019 15:49:10 -0400 Subject: [PATCH 19/23] fix vm-boot-protect mode issue #40 --- README.md | 1 + vm-boot-protect.sh | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 549b8d9..15e66ea 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,7 @@ Some useful configurations have been supplied in /etc/default/vms: * The service can be removed from the system with `cd Qubes-VM-hardening; sudo bash install --uninstall` ## Releases + - v0.9.2 Fix vm-boot-protect mode - v0.9.1 Optimized, fix rc order, new "wiperw" tag - v0.9.0 Add tags and rc files, protect more home scripts, reinitialize home - v0.8.5 Fix template detection, /etc/default/vms erasure diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index d19772a..af192b7 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -30,7 +30,7 @@ rwbak=$rw/vm-boot-protect errlog=/var/run/vm-protect-error servicedir=/var/run/qubes-service defdir=/etc/default/vms -version="0.9.1" +version=0.9.2 # Define sh, bash, X and desktop init scripts in /home/user # to be protected @@ -277,11 +277,6 @@ if qsvc vm-boot-protect-root && [ $rwonly_pers = 1 ]; then fi -# Keep configs invisible at runtime... -if ! is_templatevm; then - rm -rf "$defdir" $servicedir/vm-boot-tag* $servicedir/vm-boot-protect* $errlog -fi - # Remove backups if indicated if [ $save_backup = 0 ]; then chattr -R -f -i $rwbak @@ -294,4 +289,8 @@ if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then umount $rw fi +# Keep configs invisible at runtime... +if ! is_templatevm; then + rm -rf "$defdir" $servicedir/vm-boot-tag* $servicedir/vm-boot-protect* $errlog +fi exit 0 From 05d8649e05f3ae85a75202a33891666e338e4ad7 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Tue, 27 Aug 2019 21:13:20 -0400 Subject: [PATCH 20/23] add nosuid,nodev protection --- README.md | 1 + configure-sudo-prompt | 20 ++++++++++++++++++-- install | 7 ++++++- vm-boot-protect.sh | 16 ++++++++-------- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 15e66ea..9b3f1ec 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,7 @@ Some useful configurations have been supplied in /etc/default/vms: * The service can be removed from the system with `cd Qubes-VM-hardening; sudo bash install --uninstall` ## Releases + - v0.9.3 Protect against suid and device nodes - v0.9.2 Fix vm-boot-protect mode - v0.9.1 Optimized, fix rc order, new "wiperw" tag - v0.9.0 Add tags and rc files, protect more home scripts, reinitialize home diff --git a/configure-sudo-prompt b/configure-sudo-prompt index fd28f8b..9888cf0 100644 --- a/configure-sudo-prompt +++ b/configure-sudo-prompt @@ -17,11 +17,27 @@ See https://qubes-os.org/doc/vm-sudo for manual instructions." exit 1 fi + +if [ "$1" = "--force" ]; then + force=1 +else + force=0 +fi + +if grep -q '^auth .* dom0\squbes\.VMAuth' /etc/pam.d/common-auth && [ $force = 0 ]; then + echo "System appears already configured for sudo prompts." + echo "To force re-configuration run 'configure-sudo-prompt --force'." + exit 0 +fi + + echo -e "\n--+ Enable yes/no authentication prompt for sudo +-- Warning: Before opting for this change a backup or clone should me made of this template!" -read -p "Configure sudo authentication prompt now? (y/n): " answer -if [[ $answer == @(y|Y) ]]; then +if [ $force = 0 ]; then + read -p "Configure sudo authentication prompt now? (y/n): " answer +fi +if [[ $answer == @(y|Y) ]] || [ $force = 1 ]; then mv -fb /etc/pam.d/common-auth /etc/pam.d/common-auth~ cat >/etc/pam.d/common-auth <<_EOF diff --git a/install b/install index 662c620..632c0f4 100644 --- a/install +++ b/install @@ -1,6 +1,6 @@ #!/bin/bash # From https://github.com/tasket/Qubes-VM-hardening -# installer version 0.9.0 +# installer version 0.9.3 set -e [ `id -u` -eq 0 ] || exit @@ -33,6 +33,11 @@ mkdir -p /etc/default/vms # Careful... ownership & mode are not preserved here! cp -riv default/vms/* /etc/default/vms +echo "Adding nosuid,nodev options to /etc/fstab..." +cp /etc/fstab /etc/fstab.bak +awk '($1~"^/rw/" || $2~"^/rw$") && ($4!~"nosuid" || $4!~"nodev") {$4=$4",nosuid,nodev"}1' \ + /etc/fstab.bak >/etc/fstab + echo -e "\nvm-boot-protect installed!\n" diff --git a/vm-boot-protect.sh b/vm-boot-protect.sh index af192b7..de861b5 100755 --- a/vm-boot-protect.sh +++ b/vm-boot-protect.sh @@ -30,7 +30,7 @@ rwbak=$rw/vm-boot-protect errlog=/var/run/vm-protect-error servicedir=/var/run/qubes-service defdir=/etc/default/vms -version=0.9.2 +version=0.9.3 # Define sh, bash, X and desktop init scripts in /home/user # to be protected @@ -60,7 +60,7 @@ vm_boot_finish() { return; } # Remount fs as read-write remount_rw() { # Begin write operations - if [ -e $dev ] && mount -o remount,rw $dev $rw ; then + if [ -e $dev ] && mount -o remount,rw,nosuid,nodev $dev $rw ; then echo Good rw remount. else abort_startup RELOCATE "Remount failed!" @@ -139,7 +139,7 @@ fi if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then # Mount private volume in temp location mkdir -p $rw - if [ -e $dev ] && mount -o ro $dev $rw ; then + if [ -e $dev ] && mount -o ro,nosuid,nodev $dev $rw ; then echo "Good read-only mount." else echo "Mount failed." @@ -208,7 +208,7 @@ if qsvc vm-boot-protect-root && [ $rwonly_pers = 1 ]; then # Deactivate private.img config dirs mkdir -p $rwbak for dir in $privdirs $privdirs_add; do # maybe use 'eval' for privdirs quotes/escaping - echo "Deactivate $dir" + # echo "Deactivate $dir" subdir=`echo $dir |sed -r 's|^/rw/||'` bakdir="$rwbak/BAK-$subdir" origdir="$rwbak/ORIG-$subdir" @@ -225,9 +225,9 @@ if qsvc vm-boot-protect-root && [ $rwonly_pers = 1 ]; then # Populate /home/user w skel files if it was in privdirs case "$subdir" in "home"|"home/"|"home/user"|"home/user/") - echo "Populating home dir" + # echo "Populating home dir" rm -rf /home/user $rw/home/user - mount --bind $rw/home /home + mount --bind -o nosuid,nodev $rw/home /home mkhomedir_helper user umount /home ;; @@ -246,8 +246,8 @@ if qsvc vm-boot-protect-root && [ $rwonly_pers = 1 ]; then dstfile="`echo $wlfile |sed -r \"s|^/rw/(.+)$|$rw/\1|\"`" dstdir="`dirname \"$dstfile\"`" if [ ! -e "$srcfile" ]; then - echo "Whitelist entry not present in filesystem:" - echo "$srcfile" + # echo "Whitelist entry not present in filesystem:" + # echo "$srcfile" continue # For very large dirs: mv whole dir when entry ends with '/' elif echo $wlfile |grep -q "\/$"; then From bcd840c318f4a8dc891934e4196de43b56e798fc Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Mon, 2 Sep 2019 08:50:18 -0400 Subject: [PATCH 21/23] makefile and debian --- Makefile | 7 +++++++ README.md | 3 ++- debian/changelog | 5 +++++ debian/compat | 1 + debian/control | 18 +++++++++++++++++ debian/copyright | 18 +++++++++++++++++ debian/install | 1 + debian/postinst | 48 ++++++++++++++++++++++++++++++++++++++++++++ debian/rules | 25 +++++++++++++++++++++++ debian/source/format | 1 + install | 2 +- 11 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 Makefile create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/install create mode 100644 debian/postinst create mode 100755 debian/rules create mode 100644 debian/source/format diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..64e8636 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +VERSION := $(shell cat version) + +install: install-vm + +install-vm: + bash ./install + bash ./configure-sudo-prompt --force diff --git a/README.md b/README.md index 9b3f1ec..fdc37af 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,11 @@ Leverage Qubes template non-persistence to fend off malware at VM startup: Lock- ### Installing -1. In a template VM, install the service files +1. In a template VM, install and configure ``` cd Qubes-VM-hardening sudo bash install + sudo bash configure-sudo-prompt ``` 2. Activate by specifying one of the following Qubes services for your VM(s)... diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..0f42418 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +qubes-vm-hardening (0.9.3-1) unstable; urgency=medium + + * Initial release + + -- Christopher Laprise Mon, 2 Sep 2018 08:01:15 -0400 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +10 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..5db6eea --- /dev/null +++ b/debian/control @@ -0,0 +1,18 @@ +Source: Qubes-VM-hardening +Section: admin +Priority: optional +Maintainer: Christopher Laprise +Build-Depends: debhelper (>= 10) +Standards-Version: 4.1.2 +Homepage: https://www.qubes-os.org + +Package: qubes-vm-hardening +Architecture: all +Depends: ${misc:Depends} qubes-core-agent +Description: Prevent malware persistence in Qubes virtual machines. + Reconfigures Qubes VM templates to block casual sudo access, + protects user startup scripts, and includes a service that can + quarantine, whitelist and check file hashes at startup before + the /rw volume comes online. + + See https://www.github.com/tasket/Qubes-VM-hardening for more info. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..2aac0ca --- /dev/null +++ b/debian/copyright @@ -0,0 +1,18 @@ +Files: debian/* +Copyright: 2018-2019 Christopher Laprise +License: GPL-3 + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see + . + On Debian systems, the complete text of the GNU General + Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". diff --git a/debian/install b/debian/install new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/debian/install @@ -0,0 +1 @@ + diff --git a/debian/postinst b/debian/postinst new file mode 100644 index 0000000..8d04b00 --- /dev/null +++ b/debian/postinst @@ -0,0 +1,48 @@ +#!/bin/sh +# postinst script for qubes-tunnel +# +# see: dh_installdeb(1) + + + +### TODO: +### Fix postinst and install files in 'debian' folder. + + + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + systemctl daemon-reload + systemctl enable vm-boot-protect.service + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..e1c367c --- /dev/null +++ b/debian/rules @@ -0,0 +1,25 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#export DH_VERBOSE = 1 + + +# see FEATURE AREAS in dpkg-buildflags(1) +#export DEB_BUILD_MAINT_OPTIONS = hardening=+all + +# see ENVIRONMENT in dpkg-buildflags(1) +# package maintainers to append CFLAGS +#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic +# package maintainers to append LDFLAGS +#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed + + +%: + dh $@ + + +# dh_make generated override targets +# This is example for Cmake (See https://bugs.debian.org/641051 ) +#override_dh_auto_configure: +# dh_auto_configure -- # -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH) + diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/install b/install index 632c0f4..5503a3b 100644 --- a/install +++ b/install @@ -41,6 +41,6 @@ awk '($1~"^/rw/" || $2~"^/rw$") && ($4!~"nosuid" || $4!~"nodev") {$4=$4",nosuid, echo -e "\nvm-boot-protect installed!\n" -bash ./configure-sudo-prompt +#bash ./configure-sudo-prompt exit 0 From 1b9b0ce5298178a4a55cc25599b1bf0dcf3c8f1c Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Mon, 1 May 2023 13:28:02 -0400 Subject: [PATCH 22/23] Revise dom0 instructions for sudo prompt --- README.md | 26 +++++++++++++++++--------- configure-sudo-prompt | 4 +++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index fdc37af..5269584 100644 --- a/README.md +++ b/README.md @@ -16,24 +16,31 @@ Leverage Qubes template non-persistence to fend off malware at VM startup: Lock- ### Installing -1. In a template VM, install and configure - ``` + 1. In dom0, enter the following commands to [enable](https://www.qubes-os.org/doc/vm-sudo/#replacing-password-less-root-access-with-dom0-user-prompt) `sudo` prompts: + +``` + sudo su - + echo "/usr/bin/echo 1" >/etc/qubes-rpc/qubes.VMAuth + chmod +x /etc/qubes-rpc/qubes.VMAuth + echo "@anyvm dom0 ask,default_target=dom0" >/etc/qubes-rpc/policy/qubes.VMAuth +``` + + 2. In a template VM, install and configure +``` cd Qubes-VM-hardening sudo bash install sudo bash configure-sudo-prompt - ``` +``` -2. Activate by specifying one of the following Qubes services for your VM(s)... +As an alternative, you can skip _'configure-sudo-prompt'_ and Step 1 and instead uninstall the `qubes-core-agent-passwordless-root` package from the template. After doing this, you will have to use `qvm-run -u root` from dom0 to run any VM commands as root. + + + 3. Activate by specifying one of the following Qubes services for your VM(s)... - `vm-boot-protect` - Protects executables/scripts within /home/user and may be used with wide array of Qubes VMs including standalone, appVMs, netVMs, Whonix, etc. - `vm-boot-protect-root` - Protects /home/user as above, automatic /rw executable deactivation, whitelisting, checksumming, deployment. Works with appVMs, netVMs, etc. that are _template-based_. CAUTION: The -root option by default **removes** prior copies of /rw/config, /rw/usrlocal and /rw/bind-dirs. This can delete data! -3. Disable Qubes default passwordless-root. This is necessary for the above measures to work effectively... - - For Debian-based templates the installer will launch `configure-sudo-prompt` automatically to enable a sudo [yes/no prompt](https://www.qubes-os.org/doc/vm-sudo/#replacing-password-less-root-access-with-dom0-user-prompt) that appears in dom0. This handles the template configuration then displays several commands to manually configure dom0 (the dom0 step is required only once, regardless of how many templates you configure). You may test the `configure-sudo-prompt` script in a regular template-based appVM to see if it works, although the effect will be temporary. - - Alternately, you can uninstall the `qubes-core-agent-passwordless-root` package from the template. After doing this, you will have to use `qvm-run -u root` from dom0 to run any VM commands as root. --- @@ -120,6 +127,7 @@ Some useful configurations have been supplied in /etc/default/vms: * The service can be removed from the system with `cd Qubes-VM-hardening; sudo bash install --uninstall` ## Releases + - v0.9.4 Revise dom0 instructions for sudo prompt - v0.9.3 Protect against suid and device nodes - v0.9.2 Fix vm-boot-protect mode - v0.9.1 Optimized, fix rc order, new "wiperw" tag diff --git a/configure-sudo-prompt b/configure-sudo-prompt index 9888cf0..4b67852 100644 --- a/configure-sudo-prompt +++ b/configure-sudo-prompt @@ -1,5 +1,6 @@ #!/bin/bash # From https://github.com/tasket/Qubes-VM-hardening +# installer version 0.9.4 set -e [ `id -u` -eq 0 ] || exit @@ -64,7 +65,8 @@ _EOF Next.... Enable auth prompts in dom0 with the following commands: [user@dom0 ~]$ sudo su - [root@dom0 /]# echo "/usr/bin/echo 1" >/etc/qubes-rpc/qubes.VMAuth - [root@dom0 /]# echo "\$anyvm dom0 ask,default_target=dom0" \ + [root@dom0 /]# chmod +x /etc/qubes-rpc/qubes.VMAuth + [root@dom0 /]# echo "@anyvm dom0 ask,default_target=dom0" \ >/etc/qubes-rpc/policy/qubes.VMAuth ' From b85fac02828c0b732723e441a4344942fa55b3b8 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Mon, 1 May 2023 13:39:26 -0400 Subject: [PATCH 23/23] Fix formatting --- README.md | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 5269584..3ad357b 100644 --- a/README.md +++ b/README.md @@ -16,28 +16,26 @@ Leverage Qubes template non-persistence to fend off malware at VM startup: Lock- ### Installing - 1. In dom0, enter the following commands to [enable](https://www.qubes-os.org/doc/vm-sudo/#replacing-password-less-root-access-with-dom0-user-prompt) `sudo` prompts: +``` +1. In dom0, enter the following commands to enable `sudo` prompts: -``` - sudo su - - echo "/usr/bin/echo 1" >/etc/qubes-rpc/qubes.VMAuth - chmod +x /etc/qubes-rpc/qubes.VMAuth - echo "@anyvm dom0 ask,default_target=dom0" >/etc/qubes-rpc/policy/qubes.VMAuth -``` + sudo su - + echo "/usr/bin/echo 1" >/etc/qubes-rpc/qubes.VMAuth + chmod +x /etc/qubes-rpc/qubes.VMAuth + echo "@anyvm dom0 ask,default_target=dom0" >/etc/qubes-rpc/policy/qubes.VMAuth - 2. In a template VM, install and configure -``` - cd Qubes-VM-hardening - sudo bash install - sudo bash configure-sudo-prompt -``` +2. In a template VM, install and configure + + cd Qubes-VM-hardening + sudo bash install + sudo bash configure-sudo-prompt As an alternative, you can skip _'configure-sudo-prompt'_ and Step 1 and instead uninstall the `qubes-core-agent-passwordless-root` package from the template. After doing this, you will have to use `qvm-run -u root` from dom0 to run any VM commands as root. - - 3. Activate by specifying one of the following Qubes services for your VM(s)... +3. Activate by specifying one of the following Qubes services for your VM(s)... - `vm-boot-protect` - Protects executables/scripts within /home/user and may be used with wide array of Qubes VMs including standalone, appVMs, netVMs, Whonix, etc. - `vm-boot-protect-root` - Protects /home/user as above, automatic /rw executable deactivation, whitelisting, checksumming, deployment. Works with appVMs, netVMs, etc. that are _template-based_. +``` CAUTION: The -root option by default **removes** prior copies of /rw/config, /rw/usrlocal and /rw/bind-dirs. This can delete data! @@ -126,6 +124,10 @@ Some useful configurations have been supplied in /etc/default/vms: * The service can be removed from the system with `cd Qubes-VM-hardening; sudo bash install --uninstall` +### Links + +- Qubes VM sudo [page](https://www.qubes-os.org/doc/vm-sudo/#replacing-password-less-root-access-with-dom0-user-prompt) + ## Releases - v0.9.4 Revise dom0 instructions for sudo prompt - v0.9.3 Protect against suid and device nodes