This shows you the differences between two versions of the page.
isc:labs:03 [2023/03/19 21:29] florin.stancu |
isc:labs:03 [2025/01/23 12:36] (current) radu.mantu [03. [15p] Password Hashing] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | /* ~~SHOWSOLUTION~~ */ | + | ===== Lab 03 - Authentication in Linux ===== |
- | + | ||
- | ====== Lab 03 - Hardware Security ====== | + | |
===== Objectives ===== | ===== Objectives ===== | ||
- | * Hardware Security Basics | ||
- | * Side Channel Attacks | ||
- | * HSMs: Java Card & Simulator | ||
- | ===== Basics ====== | + | * Hashing |
+ | * Linux PAM | ||
+ | * Multi-Factor Authentication | ||
- | For a long time, hardware had a central role in computer security. Take, for example, the CPU's protection rings model (on x86): they realize a privilege separation between a hypervisor / Operating System kernel and the user applications and is enforced at hardware-level for efficiency. | + | ===== Preparation ===== |
- | Nowadays, the security requirements of certain applications has led to the implementation of additional access control or cryptographic functions directly into the hardware, e.g., AES-NI / SHA SSE-based instructions, the Trusted Platform Module cryptoprocessor, Smart Cards or Trusted Execution Environments (ARM TrustZone, Intel SGX, memory encryption etc.). | + | You may use the UPB's [[https://cloud.grid.pub.ro|OpenStack]] cloud to instantiate a Virtual Machine. |
+ | Read these [[:isc:info:virtualmachine|instructions]] if you wanna know how! | ||
- | On a different note, hardware is also susceptible to security bugs: side channel attacks, cryptographic vulnerabilities (e.g., cache or timing attacks or the much recent Spectre / Meltdown speculative execution bugs), hardcoded credentials or even manufacturer-introduced backdoors. | + | ===== Overview ===== |
- | These are very difficult (or even impossible) to fix without re-designing the chip and replacing the faulty products. | + | |
- | ===== Side Channel Attacks ====== | + | Hashing is the process of converting data — text, numbers, files, or anything, really — into a fixed-length string of letters and numbers. Data is converted into these fixed-length strings, or hash values, by using a special algorithm called a hash function. |
- | A side-channel attack is a type of cyber-attack that targets the unintended //side effects// of a software application / hardware component in a computer system, rather than attacking it directly. These side effects may include signals or data that are generated by the system's physical components, such as its power consumption, electromagnetic emissions, or even sound. | + | Linux Pluggable Authentication Modules (PAM) is a suite of libraries that allow a Linux system administrator to configure methods to authenticate users. |
- | By analyzing these side effects, an attacker can gain information about the system's operations, such as encryption keys or other sensitive data, without directly accessing the system. Side-channel attacks can be executed remotely or locally and are often used to target cryptographic systems that use secret keys. | + | "pam_exec" is a PAM module that can be used to run an external command. |
- | ===== Java Smart Cards ====== | + | Multi-factor authentication (MFA) is a multi-step account login process that requires users to enter more information than just a password. For example, along with the password, users might be asked to enter a code sent to their email, answer a secret question, or scan a fingerprint. A second form of authentication can help prevent unauthorized account access if a system password has been compromised. |
- | Java smart cards are small electronic devices that have an embedded microprocessor and memory, which can be programmed with Java Card technology to perform secure transactions and store sensitive information. Java Card technology is a subset of Java that has been designed specifically for smart card environments. | + | ===== Tasks ===== |
- | Java smart cards can be found in various forms, such as SIM cards in mobile phones, banking cards, e-passports, and employee ID cards. They can be purchased from smart card manufacturers or vendors, or provided by organizations to their customers or employees. | + | In the current security lab, we'll explore the fundamentals of Linux authentication. |
- | To program and manage Java smart cards, specialized software development kits and tools are needed, such as Java Card Development Kit (JCDK), Global Platform Card Specification, and Smart Card Integrated Development Environment (IDE). Developers can use these tools to create and test Java Card applets that run on the smart cards and perform various secure operations. | + | We'll start by examining how the OS performs hashing. First, we'll crack it and then we'll replicate it using Python. |
- | ===== Preparation ===== | + | Then, we'll utilize the "pam_exec" module to set up a custom Python script for user authentication. By exploiting a weak password vulnerability, we will be able to perform a successful login. |
- | ==== Instance Creation ==== | + | Finally, we'll enhance security measures by implementing Multi-Factor Authentication (MFA) with Google Authenticator. |
- | Ideally, you should solve this laboratory on [[https://cloud.grid.pub.ro|openstack]]. As in the first week, create an **m1.small** instance from the **ISC 2022** image. | + | ==== 01. [5p] Setup ==== |
+ | |||
+ | We use Docker: | ||
- | If you have configured your **PC**'s keypair on openstack (not the one you generated on fep), you can connect directly this way (using SSH Jump Hosts): | ||
<code bash> | <code bash> | ||
- | $ ssh -J ${LDAP_ID}@fep.grid.pub.ro student@${VM_IP} | + | |
+ | docker pull ghcr.io/cs-pub-ro/isc-auth-pam:latest | ||
+ | mkdir ~/auth-lab | ||
+ | docker run --rm --name auth-lab -v $(pwd)/auth-lab/:/home/hacker/auth-lab -it ghcr.io/cs-pub-ro/isc-auth-pam | ||
</code> | </code> | ||
- | Otherwise, you must first connect to ''fep.grid.pub.ro'', then connect to your VM: | + | <note> |
- | <code bash> | + | The ''~/auth-lab'' folder is used as persistent volume so you won't lose + sync your work inside the container! |
- | Your-PC$ ssh ${LDAP_ID}@fep.grid.pub.ro | + | </note> |
- | # if you haven't enabled public key authentication, yet: | + | |
- | # you will need to do a two-factor login | + | Download the {{:isc:labs:lab03-pam.zip|lab archive}} inside the ''~/auth-lab'' directory and unzip it. |
- | fep.grid.pub.ro$ ssh student@${VM_IP} | + | |
+ | Analyse the users and groups on the system. What user are we interested in? | ||
+ | |||
+ | <solution -hidden> | ||
+ | <code> | ||
+ | |||
+ | User "dani.mocanu", member of group "top_10_manelisti". | ||
</code> | </code> | ||
+ | </solution> | ||
- | NOTE: you can have more than one keypair configured (both for your localhost, and for fep). Select the one you want from the //Key Pair// tab during the instance creation. | ||
- | ===== Tasks ==== | + | ==== 02. [15p] Password Cracking ==== |
- | ==== [40p] 1. Python timing side channel attack ==== | + | Use John the Ripper to crack our user's password. You need to run it as super user on the file that contains the passwords. |
- | Download the {{isc:labs:lab03-sidechannel.zip|side channel demo}} archive here. | + | We want to use the default mode "wordlist" with the default location ''/usr/share/john/password.lst''. |
- | Implement the TODOs and crack the password via a timing attack ;) | + | If you are getting an error "No password hashes loaded (see FAQ)", you need to specify the format of the hash. It is named the same as the Linux password hashing function ;) |
- | <note> | + | **References:** |
- | Hint: you have LunarVim installed on the VM, use ''lvim ${file}'' to start it! | + | * https://www.openwall.com/john/doc/OPTIONS.shtml |
- | </note> | + | |
<solution -hidden> | <solution -hidden> | ||
- | {{isc:labs:lab-3-sidechannel-solved.zip|Solved attack.py here}}. | + | <code> |
+ | |||
+ | $ sudo john /etc/shadow --format=crypt | ||
+ | dani.mocanu:snoopdog | ||
+ | |||
+ | </code> | ||
</solution> | </solution> | ||
- | ==== [60p] 2. Java Card Simulator ==== | + | ==== 03. [15p] Password Hashing ==== |
- | {{ :isc:labs:lab03.png?direct&600 |}} | + | Fill in the TODOs in ''gen_hash.py'' to generate a new password hash. Using your super user privileges, manually overwrite the old password of our user. |
- | First, we must download & install all components for developing and simulating Java Cards: | + | Test if you were successful by trying to log in (''su'') using the new password. |
- | <hidden> | + | <note warning> |
- | Dacă nu se descurcă fraierii, dați-le link-ul ăsta: | + | **crypt** was deprecated in PEP 594. See [[https://docs.python.org/3/library/crypt.html|this]] for alternatives. **legacycrypt** works.</note> |
- | https://github.com/cs-pub-ro/ISC-lab-vm/blob/master/labvm/scripts/tasks/31-javacard.sh#L14 | + | <solution -hidden> |
- | </hidden> | + | <code> |
+ | |||
+ | TODO(1): | ||
+ | password = 'parolanoua' | ||
+ | |||
+ | TODO(2): | ||
+ | salt = crypt.mksalt(crypt.METHOD_SHA512) | ||
+ | |||
+ | TODO(3): | ||
+ | hash = crypt.crypt(password, salt) | ||
- | * First, download the [[https://github.com/martinpaljak/oracle_javacard_sdks|Oracle JavaCard SDKs]]: | ||
- | <code bash> | ||
- | git clone https://github.com/martinpaljak/oracle_javacard_sdks.git "$HOME/oracle_javacard_sdks" | ||
- | export JC_HOME="$HOME/oracle_javacard_sdks/jc222_kit" | ||
- | export JC_CLASSIC_HOME="$HOME/oracle_javacard_sdks/jc305u3_kit" | ||
</code> | </code> | ||
- | * Since we don't have a physical smart card, we need a simulator: download & install [[https://github.com/arekinath/jcardsim|JCardSim]]: | + | </solution> |
- | <code bash> | + | |
- | git clone https://github.com/arekinath/jcardsim.git "$HOME/jcardsim" | + | ==== 04. [5p] Account Locking ==== |
- | cd "$HOME/jcardsim"; mvn initialize && mvn clean install | + | |
+ | As we want to use a Python script to log in to the user account we worked on so far, you need to delete and lock its password so that password-based authentication is disabled for this user account. | ||
+ | |||
+ | **Reference:** | ||
+ | * https://linux.die.net/man/1/passwd | ||
+ | |||
+ | <solution -hidden> | ||
+ | <code> | ||
+ | |||
+ | sudo passwd -dl dani.mocanu | ||
</code> | </code> | ||
- | * We now need an applet to install on our (emulated) Smart Card. [[https://github.com/philipWendland/IsoApplet|IsoApplet]] is an open source applet implementing Public Key cryptography operations (with OpenSC integration): | + | </solution> |
- | <code bash> | + | |
- | git clone -b main-javacard-v2.2.2 https://github.com/philipWendland/IsoApplet.git "$HOME/IsoApplet" | + | ==== 05. [10p] Linux PAM ==== |
- | cd "$HOME/IsoApplet" | + | |
- | # install dependencies (fortunately, this project uses git submodules) | + | We wish to write our own authentication module in Python. |
- | git submodule init && git submodule update | + | |
- | # unfortunately, jCardSim cannot simulate CAPs (compiled applet firmwares)... | + | For this, we must modify the ''common-auth'' Linux PAM configuration file (look in ''/etc/pam.d'') and add this as the **first** rule: <code> |
- | # so we directly compile the Java files (make sure to have the card simulator's SDK in Java Path): | + | auth sufficient pam_exec.so expose_authtok stdout quiet <path-to-auth.py> |
- | javac -classpath "$HOME/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar" "$HOME/IsoApplet/src/xyz/wendland/javacard/pki/isoapplet/"*.java | + | |
</code> | </code> | ||
- | * Finally, note that we need a Card Reader to interface with the smart cards. So, with our simulated card, we will have to use a virtual card reader software (''vpcd'' from [[https://frankmorgner.github.io/vsmartcard/virtualsmartcard/README.html|vsmartcard]]): | + | |
+ | As we want to use the script to authenticate only our special user, and because it will be called for all users, it should be //sufficient// to authenticate using it, but not //required//. | ||
+ | |||
+ | In order for authentication to be successfully performed using Python, we need 3 features, which can be achieved by passing the proper options to the ''pam_exec.so'' module: | ||
+ | * perform reads in the Python script, | ||
+ | * perform prints from the Python script, | ||
+ | * do not print anything else. | ||
+ | |||
+ | <note tip> | ||
+ | If you need to debug your //auth.py// script, delete the ''quiet'' parameter from the PAM config. Now, your stdout and stderr are no longer suppressed. | ||
+ | |||
+ | ---- | ||
+ | |||
+ | The PAM module may return different error codes depending on the nature of the error. Use the **errno** tool to check their meaning. | ||
<code bash> | <code bash> | ||
- | git clone https://github.com/frankmorgner/vsmartcard.git "$HOME/vsmartcard" | + | $ apt install errno |
- | cd "$HOME/vsmartcard/virtualsmartcard" | + | $ errno 13 |
- | autoreconf -vis && ./configure && sudo make install | + | EACCES 13 Permission denied |
- | # Restart PCSC daemon to load our new vcard driver | + | |
- | sudo systemctl restart pcscd | + | |
- | cd ~ # go back to home | + | |
</code> | </code> | ||
- | Before we can run our simulators, we must create a configuration file: | + | ---- |
+ | Remember that ''^?'' sequences (where ''?'' certain upper-case letters) represents a control character. If you get an error that contains such a sequence, take a look at the hexdump. | ||
+ | </note> | ||
+ | |||
+ | **References:** | ||
+ | * https://linux.die.net/man/5/pam.d | ||
+ | * https://man7.org/linux/man-pages/man8/pam_exec.8.html | ||
+ | |||
+ | <solution -hidden> | ||
<code> | <code> | ||
- | $ cat $HOME/jcardsim.cfg # <-- yes, create this file ! | + | $ cat /etc/pam.d/common-auth |
- | com.licel.jcardsim.card.applet.0.AID=F276A288BCFBA69D34F31001 | + | ... |
- | com.licel.jcardsim.card.applet.0.Class=xyz.wendland.javacard.pki.isoapplet.IsoApplet | + | # here are the local modules |
- | com.licel.jcardsim.card.ATR=3B80800101 | + | auth sufficient pam_exec.so expose_authtok stdout quiet /home/hacker/auth-lab/auth.py |
- | com.licel.jcardsim.vsmartcard.host=localhost | + | ... |
- | com.licel.jcardsim.vsmartcard.port=35963 | + | |
</code> | </code> | ||
+ | </solution> | ||
+ | |||
+ | ==== 06. [20p] Python Script ==== | ||
+ | |||
+ | Edit ''auth.py'' and fill in TODOs(6.*). | ||
+ | |||
+ | When you're done, [[http://crackstation.net|crack the new password hash]] and try to log in ;) | ||
- | Now we can start our simulator: | + | <note hint> |
- | <note important> | + | Note that the password hash is hardcoded in Python (you will also find the algorithm by cracking it!) without any salt. |
- | use separate terminals or ''tmux'', since this command is blocking: | + | Once you figure it out, use Python's ''hashlib'' to compute the input's ''user_hash'' and compare them! |
</note> | </note> | ||
- | <code bash> | + | <solution -hidden> |
- | java -classpath "$HOME/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar:$HOME/IsoApplet/src" com.licel.jcardsim.remote.VSmartCard "$HOME/jcardsim.cfg" | + | <code> |
+ | TODO(6.1): | ||
+ | if "top_10_manelisti" not in user_groups: | ||
+ | return False | ||
+ | |||
+ | TODO(6.2): | ||
+ | hash_object = hashlib.sha256() | ||
+ | hash_object.update(user_password.encode("utf-8")) | ||
+ | user_hash = hash_object.hexdigest() | ||
+ | |||
+ | 13412ffd6149204f40e546ffa9fbd7124b410198a6ba3924f788622b929c8eb2 ---crackstation.net---> poochiedontsurf | ||
</code> | </code> | ||
+ | </solution> | ||
+ | |||
+ | ==== 07. [30p] Multi-Factor Authentication ==== | ||
+ | |||
+ | Finally, let's add two-factor authentication to our script! | ||
+ | |||
+ | Edit ''setup_mfa.py'', input a 32-byte secret and print its QR enrollment code to the console. | ||
+ | After this, run the script and enroll the key inside a [[https://www.rfc-editor.org/rfc/rfc6238|RFC 6238 (TOTP)]] compatible (e.g.: Google Authenticator, TOTP Authenticator, KeePassXC etc.). | ||
- | All right, it's time to use our Smart Card: | + | Solve the remaining TODOs(7.*) in ''auth.py'' to integrate your MFA (note: the TOTP's secret key should be the same!). |
<note> | <note> | ||
- | The APDU [[https://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit|Smart Card Application Protocol Data Unit]] is a communication protocol used for interfacing with smart cards, standardized in ISO/IEC 7816-4. | + | **Hint / workaround:** PAM only gives you one ''input()'' with the user-typed password (then closes stdin, any following reads will get EOF). |
+ | So, in order to read both a password and a numeric TOTP code, you must read them all at once (use whatever convention you desire, e.g.: password then 6-digit code either concatenated or split by space, then parse/extract it in Python). | ||
- | We use an [[https://jcardsim.org/docs/quick-start-guide-using-in-cli-mode|initial APDU script]] to install & execute the IsoApplet into the emulated smart card. | + | Custom ''.so'' PAM plugins have no such limitations (but you must then write them in a system programming language). |
</note> | </note> | ||
- | <code bash> | + | <note important>If you're getting an error (e.g., invalid padding) while scanning QR / verifying the TOTP, make sure ''TOTP_SECRET'' is 32 bytes in length!</note> |
- | # install IsoApplet usign a APDU script | + | |
- | opensc-tool --card-driver default --send-apdu 80b800001a0cf276a288bcfba69d34f310010cf276a288bcfba69d34f3100100 | + | |
- | opensc-tool -n | + | |
- | # create PKCS#15 structure on our smart card (also set a PIN and a PUK, for security purposes) | + | **References:** |
- | pkcs15-init --create-pkcs15 --so-pin 123456 --so-puk 0123456789abcdef | + | * https://pyauth.github.io/pyotp/#module-pyotp |
- | # generate an RSA key pair to use for signing (note: auth-id is a PIN slot) | + | * https://pyqrcode.readthedocs.io |
- | pkcs15-init --generate-key rsa/2048 --id 1 --key-usage decrypt,sign --label MyRSAKey --auth-id FF --pin 123456 | + | |
- | # download the generated public key to your machine | + | |
- | pkcs15-tool --read-public-key "1" --output "smartcard-pubkey.pem" | + | |
- | echo "Sunt de acord să cedez toată averea mea asistenților de ISC. Adevăraaat!" > textToSign.txt | + | <solution -hidden> |
- | openssl dgst -engine pkcs11 -sign "pkcs11:object=MyRSAKey;type=private;pin-value=123456" -keyform ENGINE -sha256 -out textSignature.sig textToSign.txt | + | <code> |
- | # now everyone can check whether the document is correctly signed using the public key: | + | setup_mfa.py: |
- | openssl dgst -sha256 -verify smartcard-pubkey.pem -keyform PEM -signature textSignature.sig textToSign.txt | + | |
- | # modificați fișierul textToSign.txt și re-verificați semnătura digitală... ce se întâmplă? | + | |
- | </code> | + | |
- | Finally, here's one last challenge: use ''openssl'' to encrypt / decrypt a file using this key! | + | TODO(1): |
+ | TOTP_SECRET = "NeverGonnaGiveYouUpNeverGonnaLet" | ||
- | Bonus: [[https://access.redhat.com/articles/1523343|You can configure OpenSSH to use a private key stored inside a smart card for authentication]]! | + | TODO(2): |
+ | qr_code = pyqrcode.create(totp_auth) | ||
+ | print(qr_code.terminal(quiet_zone=1)) | ||
- | ==== 6. Feedback ==== | + | auth.py: |
+ | |||
+ | TODO(7.1): | ||
+ | TOTP_SECRET = "NeverGonnaGiveYouUpNeverGonnaLet" | ||
+ | |||
+ | TODO(7.2): | ||
+ | user_password = user_secret[:-6] | ||
+ | user_totp = user_secret[-6:] | ||
+ | |||
+ | TODO(7.3): | ||
+ | totp = pyotp.TOTP(TOTP_SECRET) | ||
+ | totp_correct = totp.verify(user_totp) | ||
+ | |||
+ | </code> | ||
+ | </solution> | ||
- | Please take a minute to fill in the [[https://forms.gle/5Lu1mFa63zptk2ox9|feedback form]] for this lab. | + | ===== Feedback ===== |
+ | Please take a minute to fill in the [[https://docs.google.com/forms/d/e/1FAIpQLSeMrKoWY6UKe1N_BASUARA-HixTuvSfrEnx_FKstT-RW464NQ/viewform |feedback form]] for this lab. | ||