Linux Security


User, Group, and Other

Normal Linux file permissions are grouped into three categories: owner, group, and other users access. Permissions can be defined for what the user, group, or anyone else can do to the file. This can be defined with letters or numbers.

  • read (r,4) = Read access.

  • write (w,2) = Write access.

  • execute (x,1) = Executable access.

The addition of these numbers makes up the entire access. For example, “rwx” would equal “777.” [1]

-rwxr-xr--. 1 root bob 0 Oct 22 13:11 example_file.txt
user (root): rwx = 7
group (bob): r-x = 5
other: r-- = 4

These permissions can be modified with the “chmod” command.

Example (numbers):

$ chmod 775

Example (letters):

$ chmod g+w,o+x





Use the passwd to force a password to be changed immediately.

$ sudo passwd --expire <USER>

Or use chage to force a password change on a specified date.

$ sudo chage --lastday <TWO_DIGIT_YEAR>-<TWO_DIGIT_MONTH>-<TWO_DIGIT_DAY> <USER>

Or use chage to force a password change after a specified number of days.

$ sudo chage --maxdays <DAYS> <USER>

View details about password expiration for a user.

$ sudo chage --list <USER>


sudo is a command used to provide elevated privileges in Linux so users can run commands as if they were the root user. It is similar to User Account Control (UAC) on Windows. It is installed by default on many Linux distributions except for a few such as Debian.

A normal user account can run commands as if they were the root user by using the syntax sudo <COMMAND> <ARGUMENTS>.

The main configuration file is /etc/sudoers but it is recommended to create a new file /etc/sudoers.d/<FILE> for additional configurations. The permissions are very strict on these files and the configuration will not load if they are incorrect.

$ sudo touch /etc/sudoers.d/example
$ sudo chmod 0440 /etc/sudoers.d/example
$ sudo chown root:root /etc/sudoers.d/example

Configuration options [12]:

  • <USERNAME> ALL=(ALL) <PATH_TO_COMMAND> = Allow a user to only run the specified command with sudo.

  • <USERNAME> ALL=(ALL) NOPASSWD: ALL = Allow a user to run any command with sudo without entering their password.

  • <USERNAME> ALL=(ALL) ALL = Allow a user to run any command with sudo.

  • %sudo ALL=(ALL) ALL = Allow all users in the sudo group to run any command with sudo.

  • ALL ALL=(ALL) ALL = Allow every user to use sudo.

  • Defaults <KEY1>=<VALUE1>,<KEY2>=<VALUE2> = Configure default settings for all valid sudo users.

  • Defaults:<USERNAME> <KEY1>=<VALUE1>,<KEY2>=<VALUE2> = Configure default settings for a single specified sudo user.

  • Defaults passwd_tries=<VALUE> = Default: 5. The number of times to allow a password to be entered in before locking a user account

  • Defaults timestamp_timeout=<VALUE> = Default: 15. The number of minutes to wait before prompting a user to enter their password again. Set to 0 to always require a password. Set to -1 to only ever require a password once.

  • Defaults timestamp_type=global,timestamp_timeout=<VALUE> = Setting the timestamp type to global makes the settings apply to all TTYs. This means that when a user enters a password in one TTY for sudo, it will be valid for all other logged in sessions of the same user.


Kerberos provides authentication for services over a network. A Kerberos server provides remote users with a “ticket” to use after they log in. This ticket is used to validate authentication with various services including FTP, SSH, NFS, etc. [2]


  • 88 TCP/UDP

  • 464 TCP/UDP

  • 749 TCP/UDP

  • 6620 TCP/UDP

  • 6621 TCP/UDP

  • 6623 TCP/UDP [3]


The Kerberos sever is referred to as the Kerberos Distribution Center (KDC). These packages will need to be installed for the service:


$ sudo yum install krb5-server krb5-workstation pam_krb5


$ sudo apt-get install krb5-kdc krb5-admin-server libpam-krb5

The principal database needs to be generated. First replace “EXAMPLE.COM” with the domain to be used. For this example, the realm “ROOTPAGES.TLD” will be used.

  • /var/kerberos/krb5kdc/kdc.conf

kdc_ports = 88
kdc_tcp_ports = 88
 #master_key_type = aes256-cts
 acl_file = /var/kerberos/krb5kdc/kadm5.acl
 dict_file = /usr/share/dict/words
 admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
 supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
  • /var/kerberos/krb5kdc/adm5.acl

    */admin@ROOTPAGES.TLD   *

The principal is made by running the command below. It will create a new database and associated files for the realm “ROOTPAGES.TLD.”

$ sudo kdb5_util create -s -r ROOTPAGES.TLD

Uncomment all of the lines in /etc/krb5.conf and then replace all references to “” and EXAMPLE.COM” with the server’s domain name/realm. [3] For testing, “rdns=false” and “ignore_acceptor_hostname=true” in the “[libdefaults]” section should be used to prevent DNS issues. [5]

default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log

dns_lookup_realm = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
default_realm = ROOTPAGES.TLD
default_ccache_name = KEYRING:persistent:%{uid}

 kdc = kdc.rootpages.tld
 admin_server = kdc.rootpages.tld

.rootpages.tld = ROOTPAGES.TLD
rootpages.tld = ROOTPAGES.TLD

Start the KDC service.

$ sudo systemctl start krb5kdc

Optionally, the admin authentication service can be started to allow remote management.

$ sudo systemctl start kadmin

Now define the root user and KDC host as allowed principals.

$ sudo kadmin.local -p root/admin
kadmin: addprinc root/admin
kdamin: addprinc -randkey host/kdc.rootpages.tld

Additional Kerberos users can also be created.

kadmin: addprinc <USER>

Allow Kerberos authentication via SSH.

File: /etc/ssh/sshd_config

GSSAPIAuthentication yes
GSSAPICleanupCredentials yes

File: /etc/ssh/ssh_config

Host *
   GSSAPIAuthentication yes
   GSSAPIDelegateCredentials yes
$ sudo systemctl reload sshd

Allow remote authentication through this KDC.

$ sudo authconfig --enablekrb5 --update

Verify that the authentication works.

$ sudo su - <USER>
$ kinit <USER>
$ klist


SSL/TLS Certificates

SSL/TLS certificates provide a symmetric key-pair, similar to SSH keys. SSL is an older protocol that is vulnerable and no longer supported. It was succeeded by TLS.

A TLS cipher suite consist of 4 different algorithms: (1) the key exchange, (2) the authentication, (3) the bulk encyrption, and (4) message authentication code (MAC). A server defines what cipher suite it supports. A client that connects to a server negotiates for a cipher suite that it is compatible with and then uses that for securely connecting. [6]

  • Key exchange = Encrypt both of the symmetric keys.

  • Authentication = Sign and verify certificates.

  • Bulk encyrption = Encrypt data to and from a server. A key generated with this algorithm requires a password.

  • MAC = Checks the integrity of the data being sent and received.

Top algorithms [7]:

  • Key exchange:

    1. ECDHE

    2. RSA

  • Authentication:

    1. ECDSA

    2. RSA

  • Bulk encryption:

    1. AES256-GCM

    2. CHACHA20

    3. AES128-GCM

    4. AES256

    5. AES128

  • MAC:

    1. SHA384

    2. POLY1305

    3. SHA256

Certificate Creation

Self-signed certificates and keys can be manually created. Web browsers and tools will show these as unverified since a trusted certificate authority (CA) did not sign the certificate. The benefit is that secure TLS connections can still be used.

  • Create a CA key.

    $ openssl genrsa -out ca.key 4096
  • Create a root certificate.

    $ openssl req -x509 -new -nodes -key ca.key -days 365 -out ca.crt -subj "/C=<COUNTRY_CODE>/ST=<STATE_NAME>/L=<CITY_NAME>/O=<ORGANIZATION_NAME>/OU=<ORGANIZATIONAL_UNIT_NAME>/CN=<FQDN>"


  • Create a symmetric key-pair. This file will be used as the private key file.

    $ openssl genrsa -out cert.key 4096
  • Optionally, extract the public key from it.

    $ openssl rsa -in cert.key -pubout -out
  • Create a certificate signing request (CSR). This will be used by a CA to sign the certificate.

    $ openssl req -new -key cert.key -out cert.csr -subj "/C=<COUNTRY_CODE>/ST=<STATE_NAME>/L=<CITY_NAME>/O=<ORGANIZATION_NAME>/OU=<ORGANIZATIONAL_UNIT_NAME>/CN=<FQDN>"


  • Create a self-signed certificate signed by the CA.

    $ openssl x509 -req -in cert.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out cert.crt -days 365


  • Verify that the information for the certificate is correct.

    $ openssl x509 -noout -text -in cert.crt


Trusted Certificate Authorities

Custom certificate authorities (CAs) can be added as known trusted CAs.

Arch Linux [10]:

$ sudo cp ca.crt /etc/ca-certificates/trust-source/anchors/
$ sudo update-ca-trust

Debian [11]:

$ sudo cp ca.crt /usr/local/share/ca-certificates/
$ sudo update-ca-certificates

Fedora [11]:

$ sudo cp ca.crt /etc/pki/ca-trust/source/anchors/
$ sudo update-ca-trust


HashiCorp Vault


Install the CLI tool for HashiCorp Vault. [13] It can be used as a client or server.

  • Linux:

    $ export VAULT_VER=1.13.0
    $ wget "${VAULT_VER}/vault_${VAULT_VER}"
    $ unzip vault_${VAULT_VER}
    $ sudo mv ./vault /usr/local/bin/
    $ vault --version
  • macOS:

    $ export VAULT_VER=1.13.0
    $ wget "${VAULT_VER}/vault_${VAULT_VER}"
    $ unzip vault_${VAULT_VER}
    $ sudo mv ./vault /usr/local/bin/
    $ vault --version


For testing purposes, it is recommended to start the server in “dev” mode. This starts the server with the following changes [15]:

  • Unsealed database makes all contents visible via plaintext. [16]

  • Ephemeral RAM storage for database contents.

  • The server URL uses HTTP instead of HTTPS.

  • vault login is not required.

  • The key-value (KV) secrets engine version 2 is enabled by default.

    • On production deployments, this engine is disabled and it defaults to version 1. [17]

Start the server in “dev” mode. By default, a root token will be dynamically generated. The server can also be started with a consistent root token.

$ vault server -dev
$ vault server -dev -dev-root-token-id=root

Verify that the server is working. [14]

$ export VAULT_ADDR=""
$ vault status

Log in manually or by exporting the token as an environment variable.

$ vault login

Secrets Engines


The cubbyhole secrets engine is enabled by default and cannot be disabled. Each user in Vault has their own cubbyhole for storing secrets. Only the owner can access these secrets. Not even the root account has access to them without unsealing the database. [18][19]

  • Create a secret using cubbyhole:

    $ vault write cubbyhole/secret-store foo=bar
    Success! Data written to: cubbyhole/secret-store
    $ vault read cubbyhole/secret-store
    Key    Value
    ---    -----
    foo    bar

The only way to share a secret is to create a wrapper token. This provides a single-use token that expires immediately after it has been used.

  • Create a wrapper token that will last for 5 minutes:

    $ vault kv get -wrap-ttl=300 cubbyhole/secret-store
    Key                              Value
    ---                              -----
    wrapping_token:                  hvs.CAESIIF2lySTD8Xnsps667buHhLatBV9XOc45LJU-8_dVMW6Gh4KHGh2cy5SeWZQaW9lSUE3cDVVdmw4TDc4RnhEYUk
    wrapping_accessor:               5DU2dloysFqLnGDHhwbBaQkg
    wrapping_token_ttl:              5m
    wrapping_token_creation_time:    2023-03-12 13:20:30.283721643 -0600 MDT
    wrapping_token_creation_path:    cubbyhole/secret-store
  • A different user can then use that token to decrypt the secret once. [20]

    $ export VAULT_TOKEN=hvs.CAESIIF2lySTD8Xnsps667buHhLatBV9XOc45LJU-8_dVMW6Gh4KHGh2cy5SeWZQaW9lSUE3cDVVdmw4TDc4RnhEYUk
    $ vault unwrap
    Key    Value
    ---    -----
    foo    bar
    $ vault unwrap
    Error unwrapping: Error making API request.
    URL: PUT
    Code: 400. Errors:
    * wrapping token is not valid or does not exist



  1. “Understanding Linux File Permissions.” May 18, 2010. Accessed October 22, 2016.

  2. “Kerberos.” Ubuntu Documentation. November 18, 2014. Accessed September 25, 2016.

  3. “Configuring Your Firewall to Work With Kerberos V5.” Accessed September 25, 2016.

  4. “CentOS 7 Configure Kerberos KDC and Client.” theurbanpengiun. September 5, 2016. Accessed September 25, 2016.

  5. “Principal names and DNS.” MIT Kerberos Documentation. Accessed October 22, 2016.

  6. “A Beginner’s Guide to TLS Cipher Suites.” Namecheap Blog. December 22, 2020. Accessed March 21, 2021.

  7. “Recommendations for TLS/SSL Cipher Hardening.” The Acunetix Blog. April 10, 2019. Accessed March 21, 2021.

  8. “How to Create Your Own SSL Certificate Authority for Local HTTPS Development.” WP Migrate DB Pro. June 23, 2020. Accessed March 21, 2021.

  9. “OpenSSL Quick Reference Guide.” DigiCert. Accessed March 21, 2021.

  10. “User:Grawity/Adding a trusted CA certificate.” Arch Linux Wiki. June 16, 2020. Accessed April 30, 2021.

  11. “How To Set Up and Configure a Certificate Authority (CA) On Debian 10.” Digital Ocean Community Tutorials. April 2, 2020. Accessed April 30, 2021.

  12. “sudoers(5) - Linux man page.” July 16, 2012. Accessed October 19, 2022.

  13. “Install Vault.” HashiCorp Developer. Accessed March 12, 2023.

  14. “Starting the Server.” HashiCorp Developer. Accessed March 12, 2023.

  15. “”Dev” Server Mode.” HashiCorp Developer. Accessed March 12, 2023.

  16. “Seal/Unseal.” HashiCorp Developer. Accessed March 12, 2023.

  17. “KV Secrets Engine - Version 2.” HashiCorp Developer. Accessed March 12, 2023.

  18. “Cubbyhole Secrets Engine.” HashiCorp Developer. Accessed March 12, 2023.

  19. “Cubbyhole secret backend per user identity #3229.” GitHub hashicorp/vault. February 2, 2023. Accessed March 12, 2023.

  20. “Cubbyhole Response Wrapping.” HashiCorp Developer. Accessed March 12, 2023.