Kilala.nl - Personal website of Tess Sluijter

Unimportant background
Login
  RSS feed

About me

Blog archives

2024

2023

2022

2021

2020

2019

2018

2017

2016

2015

2014

2013

2012

2011

2010

2009

2008

2007

2006

2005

2004

2003

> Weblog

> Sysadmin articles

> Maths teaching

<< 9 / 2020 11 / 2020 >>

Understanding pam_unix and unix_chkpwd

2020-10-24 23:49:00

One of the benefits of teaching Linux to a group of young adults, is that it forces me to go back to the books myself. The Linux+ objectives cover a few things I haven't worked with yet (such as MDM), but also touches on things I haven't given much thought yet. Case in point: PAM.

Just about every Linux sysadmin certification exam requires that you can work with Pluggable Authentication Modules. They want you to make your SSHd or SU authenticates correctly, or to include pam_tally. So we learn about /etc/pam.conf and /etc/pam.d/* and how to setup an auth or session stack correctly. 

What led me down a rabbithole was this: what if I want to make a Python app that authenticates users? I found references to python-pam and other modules, but most discussions ended with: "You need to run as root, or add your application user to the shadow group."

Initially this felt odd to me because, aren't we teaching everybody that services shouldn't run as "root"? In the end it does make sense, of course, because if any arbitrary user could (ab)use PAM to verify another user's password that'd be problematic. The process might be very noisy, but you could still try to brute-force the password. 

One source of confusion was the pam_unix documentation, which states:

"A helper binary, unix_chkpwd(8), is provided to check the user's password when it is stored in a read protected database. This binary is very simple and will only check the password of the user invoking it. It is called transparently on behalf of the user by the authenticating component of this module. In this way it is possible for applications like xlock(1) to work without being setuid-root."

Stupidly my brain glossed over the important parts (I need sleep) and latched onto the "without being setuid-root". The important part being that it "will only check the password of the user invoking it". 

What made me finally understand the workings of unix_chkpwd is a project of Marco Bellaccini's that I found on Github -> chkpwd_buddy. It should me the proper way of interacting with unix_chkpwd as a non-root user: FIFO pipes. 

$ mkfifo /tmp/myfifo

$ echo -ne 'testing\0' > /tmp/myfifo &
$ /sbin/unix_chkpwd tess nullok < /tmp/myfifo
$ echo $?
0

$ echo -ne 'testing\0' > /tmp/myfifo &
$ /sbin/unix_chkpwd testaccount nullok < /tmp/myfifo
$ echo $?
7

$ sudo -i
# mkfifo /tmp/rootfifo

# echo -ne 'testing\0' > /tmp/rootfifo &
# /sbin/unix_chkpwd tess nullok < /tmp/rootfifo
# echo $?
0

# echo -ne 'testing\0' > /tmp/rootfifo &
# /sbin/unix_chkpwd testaccount nullok < /tmp/rootfifo
# echo $?
0

Root can verify both my "tess" password and the one on "testaccount", while I could only verify my own password with my normal account. 

What's interesting, is that only the failed validation attempt shows up in journalctl. The successful attempts are not registered:

$ sudo journalctl -t unix_chkpwd
Oct 22 16:08:53 kalivm unix_chkpwd[86131]: check pass; user unknown
Oct 22 16:08:53 kalivm unix_chkpwd[86131]: password check failed for user (test)

To sum it up, if you want a Python app to authenticate the running-user's identity, you can use the python_pam module. But if you want the Python app to authenticate any/every user, then it will need to run as "root". 


kilala.nl tags: , ,

View or add comments (curr. 0)

Running VirtualBox together with Hyper-V on Windows 10

2020-10-06 19:30:00

EDIT: The tweaks outlined in this blog post are no longer needed. Read this update!

Sometimes you just have an odd need or craving! You just have to have some spicy curry udon after midnight! You just have to get an old RAID controller to work in your homelab! Or in this case: you just really have to get VirtualBox and Hyper-V to play nice on Windows 10. 

That's something that just wouldn't fly until recently. But now it'll work!

 

I would like to extend my warmest thanks to my colleage Praveen K-P, who worked with me to figure all of this out. =)

 

Requirements

 

Caveats

These instructions are a work-in-progress and the solution is not 100% rock-solid.

Some mathematical functions, such as SHA2 or CRC, may fail depending on the OS you run in the VM. This means that outright installing an OS from DVD or ISO may fail during extraction: SHA1 or SHA2 checksums won't match up and the installer will refuse to continue. This is likely caused by the layered CPU virtualization and is under research with the VirtualBox team.

Also, please be careful when choosing base images for your VirtualBox VMs! Do not assume that you can trust every VM image on the Vagrant repositories! Only install images from trusted providers such as:

Installing untrusted base images may lead to malware infections or worse.

 

Installation

  1. Enabled the Windows optional feature "Windows Hypervisor Platform".
    1. Go to Add/Remove Programs → Turn Windows Features on/off.
    2. Make sure there are checkmarks at both "Hyper-V" and "Windows Hypervisor Platform".
  2. Install the latest VirtualBox, but at least >=6.1.10.
  3. Install Vagrant.

 

For example: running Kali Linux

Kali Linux is one of the distributions whose installation fails due to the caveat involving mathematical functions. So let's use Vagrant instead, which pulls pre-built images from an online repository. 

Open Powershell. Run the following commands:

        cd $HOME
        mkdir Vagrant; cd Vagrant;
        vagrant init kalilinux/rolling

Before continuing, edit the "vagrantfile" file (e.g. with Notepad) and replace this line:

       config.vm.box = "kalilinux/rolling"

 

With the following configuration. Edit the amount of RAM and CPUs to your liking. Me, I like 6GB and 3 cores.

    config.vm.define "kali" do |kali|
        kali.vm.box = "kalilinux/rolling"
        kali.vm.hostname = "haxor"

        kali.vm.provider "virtualbox" do |vb|
            vb.gui = true
            vb.memory = "6144"
            vb.cpus = 3
            vb.customize [ "modifyvm", :id, "--paravirtprovider", "minimal" ]
        end

        kali.vm.synced_folder '.', '/vagrant', disabled: true

        kali.vm.provision "shell", inline: <<-SHELL
            echo "Here we would install..."
            [[ ! -d /etc/gcrypt ]] && mkdir /etc/gcrypt
            [[ ! -f /etc/gcrypt/hwf.deny ]] && echo "all" >> /etc/gcrypt/hwf.deny
        SHELL
    end

 

Save the configuration file and now run the following in Powershell: 

        vagrant up kali

The init-command sets up your "Vagrant" directory and basic configuration file. By editing the "vagrantfile" we can change a lot of the behavior, including the way Kali perceives the VirtualBox hypervisor. We also tweak GCrypt, so it will refuse to try hardware accellerated cryptography. Both are required to make hashing and other maths work better.

The up-command actually starts the build of the VM, after which it is booted. The first installation will take a few minutes, after that you can just manage the VM using the VirtualBox user interface. 

The Kali Linux Vagrant build includes the full graphical user interface! But you can also ssh -P 2222 vagrant@localhost  to login to the VM. Be sure to create your own account and to change all passwords!

 

GCrypt fix

Your Linux distribution may have problems performing SHA2 calculations correctly. According to this source, it’s “Because apt use sha256 method from libgcrypto20, but optimized too much. We can deny this opt. using configuration file /etc/gcrypt/hwf.deny.” 

        $ sudo bash
        # mkdir /etc/gcrypt
        # echo all >> /etc/gcrypt/hwf.deny
 

In addition, we learned that in our nested situation (VirtualBox on top of Hyper-V) it may be a good idea to change your VM's "paravirtualization interface" from "Normal" to "Minimal". #TIL that this is not about how VBox provides better performance, but about what paravirtualization information is passed to the guest OS. In my case this change did fix hashing problems. This change can be made manually by editing the VM settings in VirtualBox (VM → Settings → System → Acceleration → Paravirtualization interface), or in the Vagrant file:

        vb.customize [ "modifyvm", :id, "--paravirtprovider", "minimal" ]

 

Example Vagrantfile with two VMs 

Vagrant.configure("2") do |config|

  config.vm.define "kali" do |kali|
    kali.vm.box = "kalilinux/rolling"
  kali.vm.hostname = "haxor"
    kali.vm.network "forwarded_port", guest: 22, host: 2222, host_ip: "127.0.0.1"
    kali.vm.network "forwarded_port", guest: 3389, host: 2389, host_ip: "127.0.0.1"

    kali.vm.provider "virtualbox" do |vb|
        vb.gui = true
        vb.memory = "6144"
        vb.cpus = 3
        vb.customize [ "modifyvm", :id, "--paravirtprovider", "minimal" ]
    end

    kali.vm.synced_folder '.', '/vagrant', disabled: true
 
    kali.vm.provision "shell", inline: <<-SHELL
        echo "Here we would install..."
        [[ ! -d /etc/gcrypt ]] && mkdir /etc/gcrypt
        [[ ! -f /etc/gcrypt/hwf.deny ]] && echo "all" >> /etc/gcrypt/hwf.deny
SHELL

  end


  config.vm.define "centos8" do |centos8|
    centos8.vm.box = "centos/8"
    centos8.vm.hostname = "centos8"
    centos8.vm.box_check_update = true

    centos8.vm.network "forwarded_port", guest: 22, host: 2200, host_ip: "127.0.0.1"

    centos8.vm.provider "virtualbox" do |vb|
        vb.gui = false
        vb.memory = "1024"
       vb.cpus = 1
        vb.customize [ "modifyvm", :id, "--paravirtprovider", "minimal" ]
   end

  centos8.vm.provision "shell", inline: <<-SHELL
        echo "Here we would install..."
        [[ ! -d /etc/gcrypt ]] && mkdir /etc/gcrypt
        [[ ! -f /etc/gcrypt/hwf.deny ]] && echo "all" >> /etc/gcrypt/hwf.deny
    SHELL

    centos8.vm.synced_folder '.', '/vagrant', disabled: true

  end

end

kilala.nl tags: , ,

View or add comments (curr. 0)

<< 9 / 2020 11 / 2020 >>