Volver
Módulo 6 - Gestión de Archivos INTERMEDIO

Permisos y Propiedades de Archivos

Domina la gestión de permisos y propiedades en sistemas Unix/Linux para mantener la seguridad y control de acceso

Los permisos y propiedades de archivos son fundamentales para la seguridad y administración de sistemas Unix/Linux. En este módulo aprenderás a gestionar permisos, usar ACLs avanzadas y implementar políticas de seguridad robustas.

Sistema de Permisos Unix/Linux

En sistemas Unix/Linux, cada archivo y directorio tiene permisos que determinan quién puede leer, escribir o ejecutar ese archivo. Los permisos se dividen en tres categorías:

Categoría Símbolo Descripción
Propietario (User) u El usuario que posee el archivo
Grupo (Group) g El grupo al que pertenece el archivo
Otros (Others) o Todos los demás usuarios

Tipos de permisos

Permiso Símbolo Valor Octal Para Archivos Para Directorios
Lectura r 4 Ver contenido del archivo Listar archivos del directorio
Escritura w 2 Modificar el archivo Crear/eliminar archivos
Ejecución x 1 Ejecutar el archivo Acceder al directorio
Ejemplo de Permisos

-rwxr-xr-- significa:

  • -: Es un archivo regular (no directorio)
  • rwx: Propietario puede leer, escribir y ejecutar
  • r-x: Grupo puede leer y ejecutar (no escribir)
  • r--: Otros solo pueden leer

En notación octal: 754 (4+2+1=7, 4+1=5, 4=4)

Comandos Básicos de Permisos

1. Cambiar permisos con chmod

Comandos chmod básicos
bash
#!/bin/bash

# Modo simbólico
chmod u+x archivo.sh        # Dar permiso de ejecución al propietario
chmod g-w archivo.txt       # Quitar permiso de escritura al grupo
chmod o+r archivo.txt       # Dar permiso de lectura a otros
chmod a+x script.sh         # Dar permiso de ejecución a todos (all)

# Modo octal
chmod 755 script.sh         # rwxr-xr-x
chmod 644 archivo.txt       # rw-r--r--
chmod 600 archivo_privado   # rw-------
chmod 777 archivo_publico   # rwxrwxrwx

# Aplicar recursivamente
chmod -R 755 directorio/    # Aplicar permisos a directorio y contenido

# Ejemplos combinados
chmod u+x,g+x,o-rwx script.sh    # Solo propietario y grupo pueden ejecutar
chmod u=rwx,g=rx,o=r archivo     # Establecer permisos específicos

2. Cambiar propietario con chown

Comandos chown - Cambiar propietario
bash
#!/bin/bash

# Cambiar propietario
sudo chown usuario archivo.txt

# Cambiar propietario y grupo
sudo chown usuario:grupo archivo.txt

# Solo cambiar grupo
sudo chown :grupo archivo.txt

# Aplicar recursivamente
sudo chown -R usuario:grupo directorio/

# Verificar cambios
ls -la archivo.txt

3. Script de gestión de permisos

Script avanzado - Gestor de permisos
bash
#!/bin/bash
# permission_manager.sh - Gestor avanzado de permisos

show_permissions() {
    local file="$1"
    
    if [[ ! -e "$file" ]]; then
        echo "Error: Archivo no existe - $file"
        return 1
    fi
    
    echo "=== Información de Permisos: $file ==="
    
    # Información básica
    ls -la "$file"
    
    # Desglose detallado
    local perms=$(stat -f%Sp "$file" 2>/dev/null || stat -c%A "$file" 2>/dev/null)
    local owner=$(stat -f%Su "$file" 2>/dev/null || stat -c%U "$file" 2>/dev/null)
    local group=$(stat -f%Sg "$file" 2>/dev/null || stat -c%G "$file" 2>/dev/null)
    local octal=$(stat -f%Lp "$file" 2>/dev/null || stat -c%a "$file" 2>/dev/null)
    
    echo "Propietario: $owner"
    echo "Grupo: $group"
    echo "Permisos simbólicos: $perms"
    echo "Permisos octales: $octal"
    
    # Análisis de permisos
    echo ""
    echo "=== Análisis de Permisos ==="
    
    if [[ -r "$file" ]]; then
        echo "✓ Puedes leer este archivo"
    else
        echo "✗ NO puedes leer este archivo"
    fi
    
    if [[ -w "$file" ]]; then
        echo "✓ Puedes escribir en este archivo"
    else
        echo "✗ NO puedes escribir en este archivo"
    fi
    
    if [[ -x "$file" ]]; then
        echo "✓ Puedes ejecutar este archivo"
    else
        echo "✗ NO puedes ejecutar este archivo"
    fi
}

set_secure_permissions() {
    local file="$1"
    local type="$2"
    
    if [[ ! -e "$file" ]]; then
        echo "Error: Archivo no existe - $file"
        return 1
    fi
    
    case "$type" in
        "script")
            echo "Configurando permisos seguros para script..."
            chmod 750 "$file"  # rwxr-x---
            echo "Permisos establecidos: 750 (rwxr-x---)"
            ;;
        "config")
            echo "Configurando permisos seguros para archivo de configuración..."
            chmod 640 "$file"  # rw-r-----
            echo "Permisos establecidos: 640 (rw-r-----)"
            ;;
        "private")
            echo "Configurando permisos privados..."
            chmod 600 "$file"  # rw-------
            echo "Permisos establecidos: 600 (rw-------)"
            ;;
        "public")
            echo "Configurando permisos públicos de solo lectura..."
            chmod 644 "$file"  # rw-r--r--
            echo "Permisos establecidos: 644 (rw-r--r--)"
            ;;
        "executable")
            echo "Configurando permisos para ejecutable..."
            chmod 755 "$file"  # rwxr-xr-x
            echo "Permisos establecidos: 755 (rwxr-xr-x)"
            ;;
        *)
            echo "Tipos disponibles: script, config, private, public, executable"
            return 1
            ;;
    esac
    
    show_permissions "$file"
}

find_insecure_files() {
    local search_path="${1:-.}"
    
    echo "=== Buscando archivos con permisos inseguros en: $search_path ==="
    
    echo "Archivos escribibles por todos (world-writable):"
    find "$search_path" -type f -perm -002 2>/dev/null | head -10
    
    echo ""
    echo "Directorios escribibles por todos:"
    find "$search_path" -type d -perm -002 2>/dev/null | head -10
    
    echo ""
    echo "Archivos con SUID bit:"
    find "$search_path" -type f -perm -4000 2>/dev/null | head -10
    
    echo ""
    echo "Archivos con SGID bit:"
    find "$search_path" -type f -perm -2000 2>/dev/null | head -10
    
    echo ""
    echo "Archivos sin propietario:"
    find "$search_path" -nouser 2>/dev/null | head -10
    
    echo ""
    echo "Archivos sin grupo:"
    find "$search_path" -nogroup 2>/dev/null | head -10
}

fix_permissions_recursively() {
    local directory="$1"
    local file_perms="${2:-644}"
    local dir_perms="${3:-755}"
    
    if [[ ! -d "$directory" ]]; then
        echo "Error: Directorio no existe - $directory"
        return 1
    fi
    
    echo "Corrigiendo permisos recursivamente en: $directory"
    echo "Permisos para archivos: $file_perms"
    echo "Permisos para directorios: $dir_perms"
    
    read -p "¿Continuar? (y/N): " confirm
    if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
        echo "Operación cancelada"
        return 1
    fi
    
    # Cambiar permisos de directorios
    find "$directory" -type d -exec chmod "$dir_perms" {} \;
    
    # Cambiar permisos de archivos
    find "$directory" -type f -exec chmod "$file_perms" {} \;
    
    echo "Permisos corregidos exitosamente"
}

backup_permissions() {
    local directory="$1"
    local backup_file="${2:-permissions_backup_$(date +%Y%m%d_%H%M%S).txt}"
    
    if [[ ! -e "$directory" ]]; then
        echo "Error: Ruta no existe - $directory"
        return 1
    fi
    
    echo "Creando backup de permisos en: $backup_file"
    
    # Crear backup de permisos
    find "$directory" -exec stat -f "%N %Mp%Lp %Su %Sg" {} \; 2>/dev/null > "$backup_file" || \
    find "$directory" -exec stat -c "%n %a %U %G" {} \; 2>/dev/null > "$backup_file"
    
    echo "Backup creado: $backup_file"
    echo "Archivos incluidos: $(wc -l < "$backup_file")"
}

restore_permissions() {
    local backup_file="$1"
    
    if [[ ! -f "$backup_file" ]]; then
        echo "Error: Archivo de backup no existe - $backup_file"
        return 1
    fi
    
    echo "Restaurando permisos desde: $backup_file"
    
    read -p "¿Continuar con la restauración? (y/N): " confirm
    if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
        echo "Restauración cancelada"
        return 1
    fi
    
    while read -r line; do
        local file=$(echo "$line" | awk '{print $1}')
        local perms=$(echo "$line" | awk '{print $2}')
        local owner=$(echo "$line" | awk '{print $3}')
        local group=$(echo "$line" | awk '{print $4}')
        
        if [[ -e "$file" ]]; then
            chmod "$perms" "$file" 2>/dev/null
            # Solo intentar cambiar propietario si tenemos privilegios
            if [[ $EUID -eq 0 ]]; then
                chown "$owner:$group" "$file" 2>/dev/null
            fi
        fi
    done < "$backup_file"
    
    echo "Restauración completada"
}

# Función principal con menú
main() {
    if [[ $# -eq 0 ]]; then
        echo "=== Gestor de Permisos de Archivos ==="
        echo "1. Mostrar información de permisos"
        echo "2. Establecer permisos seguros"
        echo "3. Buscar archivos inseguros"
        echo "4. Corregir permisos recursivamente"
        echo "5. Crear backup de permisos"
        echo "6. Restaurar permisos desde backup"
        
        read -p "Seleccione opción [1-6]: " option
        
        case "$option" in
            1)
                read -p "Archivo/directorio: " file
                show_permissions "$file"
                ;;
            2)
                read -p "Archivo: " file
                echo "Tipos: script, config, private, public, executable"
                read -p "Tipo: " type
                set_secure_permissions "$file" "$type"
                ;;
            3)
                read -p "Ruta de búsqueda [.]: " path
                find_insecure_files "${path:-.}"
                ;;
            4)
                read -p "Directorio: " dir
                read -p "Permisos archivos [644]: " fperms
                read -p "Permisos directorios [755]: " dperms
                fix_permissions_recursively "$dir" "${fperms:-644}" "${dperms:-755}"
                ;;
            5)
                read -p "Directorio: " dir
                read -p "Archivo backup [auto]: " backup
                backup_permissions "$dir" "$backup"
                ;;
            6)
                read -p "Archivo de backup: " backup
                restore_permissions "$backup"
                ;;
        esac
    else
        case "$1" in
            "show") show_permissions "$2" ;;
            "secure") set_secure_permissions "$2" "$3" ;;
            "scan") find_insecure_files "$2" ;;
            "fix") fix_permissions_recursively "$2" "$3" "$4" ;;
            "backup") backup_permissions "$2" "$3" ;;
            "restore") restore_permissions "$2" ;;
            *) echo "Comandos: show, secure, scan, fix, backup, restore" ;;
        esac
    fi
}

# Ejecutar función principal
main "$@"

Permisos Especiales

1. SUID, SGID y Sticky Bit

Bit Valor Símbolo Descripción Ejemplo
SUID 4000 s/S Se ejecuta con permisos del propietario /usr/bin/passwd
SGID 2000 s/S Se ejecuta con permisos del grupo /usr/bin/wall
Sticky 1000 t/T Solo el propietario puede eliminar /tmp
Permisos especiales - SUID, SGID, Sticky
bash
#!/bin/bash

# Establecer SUID bit
chmod u+s programa
chmod 4755 programa    # También funciona

# Establecer SGID bit
chmod g+s programa
chmod 2755 programa

# Establecer Sticky bit
chmod +t directorio
chmod 1755 directorio

# Combinar permisos especiales
chmod 6755 programa    # SUID + SGID
chmod 7755 programa    # SUID + SGID + Sticky

# Verificar permisos especiales
ls -la /usr/bin/passwd   # Debería mostrar -rwsr-xr-x
ls -ld /tmp              # Debería mostrar drwxrwxrwt
Precaución con Permisos Especiales
Los permisos SUID y SGID pueden ser riesgos de seguridad si se usan incorrectamente. Siempre audita archivos con estos permisos y asegúrate de que sean necesarios.

ACLs - Listas de Control de Acceso

Las ACLs permiten permisos más granulares que el sistema tradicional Unix. Puedes dar permisos específicos a usuarios y grupos individuales.

1. Comandos básicos de ACL

ACLs básicas - Comandos fundamentales
bash
#!/bin/bash

# Ver ACLs actuales
getfacl archivo.txt

# Dar permisos de lectura a un usuario específico
setfacl -m u:usuario:r archivo.txt

# Dar permisos de escritura a un grupo específico
setfacl -m g:grupo:rw archivo.txt

# Establecer ACL por defecto para directorios
setfacl -d -m u:usuario:rwx directorio/

# Eliminar ACL específica
setfacl -x u:usuario archivo.txt

# Eliminar todas las ACLs
setfacl -b archivo.txt

# Aplicar ACLs recursivamente
setfacl -R -m u:usuario:rx directorio/

# Copiar ACLs de un archivo a otro
getfacl archivo1.txt | setfacl --set-file=- archivo2.txt

2. Script de gestión de ACLs

Script avanzado - Gestor de ACLs
bash
#!/bin/bash
# acl_manager.sh - Gestor de ACLs

check_acl_support() {
    # Verificar si el sistema soporta ACLs
    if ! command -v getfacl >/dev/null 2>&1; then
        echo "Error: ACLs no están instaladas"
        echo "Instala con: sudo apt-get install acl (Ubuntu/Debian)"
        echo "o: sudo yum install acl (RHEL/CentOS)"
        return 1
    fi
    
    # Verificar si el filesystem soporta ACLs
    local file="${1:-/tmp/test_acl}"
    touch "$file"
    if ! setfacl -m u:root:r "$file" 2>/dev/null; then
        echo "Warning: El filesystem puede no soportar ACLs"
        echo "Monta con opción 'acl' si es necesario"
    fi
    rm -f "$file"
    
    return 0
}

show_detailed_acl() {
    local file="$1"
    
    if [[ ! -e "$file" ]]; then
        echo "Error: Archivo no existe - $file"
        return 1
    fi
    
    echo "=== ACLs para: $file ==="
    getfacl "$file"
    
    echo ""
    echo "=== Análisis de ACLs ==="
    
    # Verificar si tiene ACLs extendidas
    if getfacl --skip-base "$file" 2>/dev/null | grep -q "^user:\|^group:"; then
        echo "✓ Este archivo tiene ACLs extendidas"
    else
        echo "✗ Este archivo no tiene ACLs extendidas"
    fi
    
    # Mostrar usuarios con acceso
    echo ""
    echo "Usuarios con acceso específico:"
    getfacl "$file" 2>/dev/null | grep "^user:" | sed 's/user://' | while read acl; do
        if [[ "$acl" =~ ^([^:]+):(.+)$ ]]; then
            local user="${BASH_REMATCH[1]}"
            local perms="${BASH_REMATCH[2]}"
            if [[ -n "$user" ]]; then
                echo "  $user: $perms"
            fi
        fi
    done
    
    # Mostrar grupos con acceso
    echo ""
    echo "Grupos con acceso específico:"
    getfacl "$file" 2>/dev/null | grep "^group:" | sed 's/group://' | while read acl; do
        if [[ "$acl" =~ ^([^:]+):(.+)$ ]]; then
            local group="${BASH_REMATCH[1]}"
            local perms="${BASH_REMATCH[2]}"
            if [[ -n "$group" ]]; then
                echo "  $group: $perms"
            fi
        fi
    done
}

set_project_acls() {
    local project_dir="$1"
    local project_group="$2"
    local readonly_group="$3"
    
    if [[ ! -d "$project_dir" ]]; then
        echo "Error: Directorio no existe - $project_dir"
        return 1
    fi
    
    echo "Configurando ACLs para proyecto en: $project_dir"
    echo "Grupo del proyecto: $project_group"
    echo "Grupo de solo lectura: $readonly_group"
    
    # ACLs por defecto para directorios
    setfacl -d -m g:$project_group:rwx "$project_dir"
    setfacl -d -m g:$readonly_group:rx "$project_dir"
    setfacl -d -m o::--- "$project_dir"
    
    # ACLs para el directorio actual
    setfacl -m g:$project_group:rwx "$project_dir"
    setfacl -m g:$readonly_group:rx "$project_dir"
    setfacl -m o::--- "$project_dir"
    
    # Aplicar a contenido existente
    find "$project_dir" -type d -exec setfacl -m g:$project_group:rwx {} \;
    find "$project_dir" -type d -exec setfacl -m g:$readonly_group:rx {} \;
    find "$project_dir" -type f -exec setfacl -m g:$project_group:rw {} \;
    find "$project_dir" -type f -exec setfacl -m g:$readonly_group:r {} \;
    
    echo "ACLs configuradas exitosamente"
    echo ""
    show_detailed_acl "$project_dir"
}

backup_acls() {
    local directory="$1"
    local backup_file="${2:-acls_backup_$(date +%Y%m%d_%H%M%S).txt}"
    
    if [[ ! -e "$directory" ]]; then
        echo "Error: Directorio no existe - $directory"
        return 1
    fi
    
    echo "Creando backup de ACLs en: $backup_file"
    
    # Crear backup de ACLs
    find "$directory" -exec getfacl {} \; > "$backup_file" 2>/dev/null
    
    echo "Backup creado: $backup_file"
    echo "Archivos incluidos: $(grep -c "^# file:" "$backup_file")"
}

restore_acls() {
    local backup_file="$1"
    
    if [[ ! -f "$backup_file" ]]; then
        echo "Error: Archivo de backup no existe - $backup_file"
        return 1
    fi
    
    echo "Restaurando ACLs desde: $backup_file"
    
    read -p "¿Continuar con la restauración? (y/N): " confirm
    if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
        echo "Restauración cancelada"
        return 1
    fi
    
    setfacl --restore="$backup_file"
    
    if [[ $? -eq 0 ]]; then
        echo "ACLs restauradas exitosamente"
    else
        echo "Error al restaurar ACLs"
        return 1
    fi
}

# Función principal
main() {
    # Verificar soporte de ACLs
    if ! check_acl_support; then
        exit 1
    fi
    
    case "$1" in
        "show")
            show_detailed_acl "$2"
            ;;
        "project")
            set_project_acls "$2" "$3" "$4"
            ;;
        "backup")
            backup_acls "$2" "$3"
            ;;
        "restore")
            restore_acls "$2"
            ;;
        *)
            echo "Gestor de ACLs"
            echo "Uso: $0 [comando] [argumentos]"
            echo ""
            echo "Comandos:"
            echo "  show                     - Mostrar ACLs detalladas"
            echo "  project     - Configurar ACLs de proyecto"
            echo "  backup  [archivo]     - Crear backup de ACLs"
            echo "  restore           - Restaurar ACLs"
            ;;
    esac
}

# Ejecutar función principal
main "$@"
Cuándo usar ACLs

Ejercicios Prácticos

Ejercicio 1: Auditor de Seguridad

Crea un script que:

Ejercicio 2: Configurador de Proyecto

Desarrolla una herramienta que:

Ejercicio 3: Monitor de Cambios

Implementa un sistema que: