BashTex | Linux
2.5K subscribers
72 photos
13 videos
456 links
Авторский канал для тех, кто хочет глубже погрузиться в мир Linux.

Подойдет для разработчиков, системных администраторов и DevOps

Реклама: @dad_admin
Download Telegram
Проверка недавно созданных пользователей: UID, shell и следы активности

На сервере часто важно быстро понять, появлялись ли новые пользователи и насколько они “нормальные”.

Один из базовых источников - /etc/passwd, но там нет явной даты создания. Поэтому анализ строится через косвенные признаки.

▪️Поиск пользователей с обычным UID диапазоном
getent passwd | awk -F: '$3 >= 1000 {print $1, $3, $7}'

Обычно реальные пользователи находятся начиная с UID 1000.

Системные - ниже.

Смотрим shell: /bin/bash, /bin/zsh чаще у людей, /usr/sbin/nologin или /bin/false - сервисные аккаунты.

▪️Быстрый срез через lastlog

lastlog -t 30


Показывает пользователей, которые логинились за последние 30 дней. Новые аккаунты без активности сразу заметны.

▪️Проверка событий создания пользователей

journalctl _COMM=useradd --since "7 days ago"


или через auth лог:

grep useradd /var/log/auth.log


Здесь видны факты создания аккаунтов и изменения групп.

▪️Косвенная проверка “новизны”

Можно оценить свежесть через системные изменения:

stat /etc/passwd


или изменения shadow:

stat /etc/shadow


Если недавно был добавлен пользователь, эти файлы будут обновлены в тот же период.

▪️Дополнительная проверка активности

faillog -a


и

last


Позволяют понять, пытался ли пользователь входить в систему и с каких хостов.

▪️Почему это важно

Новые пользователи с UID 1000+, нестандартным shell или отсутствием логинов — один из первых сигналов, который стоит проверять при аудите сервера.

BashTex 📱 #scripts #du
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Работа с дескрипторами файлов через exec: FD 3, 4, логирование и контроль потоков

В Bash обычно работают только с stdin (0), stdout (1) и stderr (2). Но файловые дескрипторы на этом не заканчиваются - можно использовать FD 3, 4 и выше для более гибкого управления потоками.

▪️Базовая идея

Каждый процесс имеет таблицу файловых дескрипторов:

0 → stdin
1 → stdout
2 → stderr


Но можно открыть дополнительные:

exec 3>debug.log


Теперь FD 3 пишет в файл debug.log.

▪️Разделение логов

Классический приём - разделить обычный вывод и отладку:

echo "normal output"
echo "debug info" >&3


Результат:
stdout остаётся чистым
debug уходит в отдельный файл

▪️Перенаправление команд через FD

Можно связать вывод команды с кастомным дескриптором:

exec 4< input.txt


Теперь FD 4 читает файл как поток.
Чтение:

read -u 4 line
echo "$line"


▪️Логирование через единый канал

Удобный паттерн - централизованный лог:
exec 3>>/var/log/myapp.log

log() {
echo "$(date '+%F %T') $*" >&3
}


Теперь все логи идут через FD 3, без захламления stdout.

▪️Почему это лучше обычного >> везде
единая точка управления логированием
проще отключать/перенаправлять вывод
можно динамически менять файл логов через exec

▪️Закрытие дескрипторов

exec 3>&-


FD освобождается, файл больше не удерживается процессом.

▪️Где это реально используется
сложные Bash-скрипты с несколькими потоками данных
системы логирования без внешних библиотек
обработка нескольких входных источников одновременно
изоляция debug/production вывода
FD выше 2 - это недооценённый инструмент, который превращает Bash из набора команд в полноценную систему управления потоками.

BashTex 📱 #scripts #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁6
Bash strict mode: что реально даёт set -euo pipefail и где он ломает логику

В bash часто добавляют так называемый "strict mode": set -euo pipefail

Идея простая - сделать скрипты более предсказуемыми и ловить ошибки раньше.

▪️Что означает каждая опция

-e - остановить скрипт при любой ошибке команды
-u - ошибка при использовании неинициализированной переменной
-o pipefail - пайп считается упавшим, если упала любая команда в цепочке

▪️Что это реально улучшает

Без strict mode многие ошибки проглатываются:


rm file_not_exist
echo "continue"


Или:


echo "$UNDEFINED_VAR"


будет явная ошибка, а не пустая строка.

▪️ pipefail: скрытая проблема пайп

Без него:


cat file | grep ERROR | sort


Возвращает код последней команды, даже если grep упал.

▪️ Где начинается проблема. Strict mode ломает сценарии, где ошибка - это нормальное состояние.

Пример:


grep pattern file.txt
echo "done"


Если совпадений нет, grep возвращает 1 и скрипт завершается, хотя это не ошибка логики.

▪️ Типичный workaround


grep pattern file.txt || true


Или:


set +e
grep pattern file.txt
set -e


Но это уже ручное управление поведением.

▪️ ещё один частый кейс - test / if


set -e

if grep pattern file.txt; then
echo "found"
fi


Здесь grep может упасть, но в контексте if это нормальный контроль потока - и это не считается фатальной ошибкой.

▪️ Итоговый баланс

Strict mode хорошо работает в:

• CI/CD
• одноразовых скриптах
• автоматизации без ветвлений

Но начинает мешать в:

• парсинге данных
• поиске (grep как логика)
• скриптах с ожидаемыми "ошибками как состоянием"

Это не универсальная защита, а переключатель модели поведения Bash-скрипта: от гибкого к строго детерминированному.

BashTex 📱 #scripts #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
coproc на практике: двусторонний обмен данными с процессом

В bash обычно все сводится к pipe: команда - команда. Но классический пайп односторонний. Если нужен диалог с процессом в обе стороны - используется coproc.

▪️ Что такое coproc. Он запускает процесс и даёт два канала:

stdin - в процесс
stdout - из процесса

И все это без временных файлов и костылей с FIFO.

▪️ Базовый пример


coproc BC { bc -l; }


Теперь у нас есть процесс калькулятора, с которым можно общаться.

Отправляем данные:


echo "2+2" >&"${BC[1]}"
read result <&"${BC[0]}"
echo "$result"


▪️ Как это устроено. После запуска bash создает массив:


${COPROC[0]} # stdout процесса
${COPROC[1]} # stdin процесса


Можно читать и писать независимо.

▪️ Реальный кейс: фоновый parser


coproc JSON { jq -c '.name'; }


Отправляем поток данных:


echo '{"name":"test"}' >&"${JSON[1]}"
read out <&"${JSON[0]}"
echo "$out"


▪️ Почему это лучше pipe Pipe работает так:


cmd1 | cmd2


Но:

• нет обратного канала
• процесс заканчивается сразу
• нельзя поддерживать состояние

coproc позволяет держать живой процесс и общаться с ним как с сервисом.

▪️ Важный момент. Процесс внутри coproc не перезапускается автоматически. Если он завершился - каналы перестают работать, и это нужно проверять вручную.

▪️ Где это реально полезно

• интерактивные CLI-инструменты (bc, python, sqlite3)
• долгоживущие парсеры (jq, awk, кастомные демоны)
• проксирование данных между процессами
• построение "мини-сервисов" прямо в Bash

coproc превращает bash из набора команд в примитивную систему IPC, где процессы начинают вести диалог, а не просто передавать поток данных в одну сторону.

BashTex 📱 #bash #scripts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
nameref (declare -n): ссылки на переменные и передача массивов в функции

В Bash функции по умолчанию работают с копиями значений или с глобальными переменными. Но есть механизм, который позволяет имитировать “ссылки” - nameref.

▪️Что такое nameref

declare -n создаёт ссылку на другую переменную:

arr=(1 2 3)

declare -n ref=arr
ref[0]=999

echo "${arr[0]}"


Результат:

999


ref
не хранит данные - он указывает на arr.

▪️Передача массива в функцию без копирования
Классическая проблема:

func() {
local arr=("$@")
}


Это создаёт копию массива.

С nameref:

func() {
local -n arr=$1
echo "${arr[0]}"
}


Вызов:

data=(10 20 30)
func data


Функция работает с оригинальным массивом.

▪️Модификация массива внутри функции

func() {
local -n arr=$1
arr[1]=999
}

data=(10 20 30)
func data

echo "${data[@]}"
Результат:
10 999 30


▪️Где это особенно полезно
функции обработки конфигураций
парсинг JSON → массивы ключей/значений
работа с таблицами данных
построение библиотек на Bash без глобальных переменных

▪️Важный момент
nameref работает только с именами переменных:

local -n ref=$1


Нельзя передавать:
• значения
• выражения
• результаты команд

Только имя переменной.

▪️Ограничения
нельзя безопасно переиспользовать ссылку на разные переменные в одном scope без переопределения
сложнее отлаживать (меняется оригинальный объект)
требует Bash 4.3+

▪️Почему это важно

Без nameref Bash-функции либо копируют данные, либо используют глобальное состояние. declare -n даёт третий вариант — передачу по ссылке, что делает сложные скрипты заметно чище и ближе к языкам общего назначения.

BashTex 📱 #scripts #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Автоматическая реакция на OOM через systemd и cgroups: перезапуск и контроль памяти

OOM (Out Of Memory) - это не просто “закончилась память”. В Linux это механизм, при котором ядро начинает принудительно завершать процессы, чтобы система не упала целиком.

Проблема в том, что без контроля первым под нож часто попадает не тот процесс, который должен.

▪️Как systemd влияет на OOM

systemd работает поверх cgroups и может задавать приоритеты “жертвенности” процессов:

systemd-cgtop

Показывает, какие группы потребляют память.

▪️Контроль памяти на уровне unit

Можно ограничить сервис:

[Service]
MemoryMax=500M

Теперь процесс физически не сможет превысить лимит.

Дополнительно:

MemoryHigh=400M


Это мягкий порог - systemd начинает давить на процесс раньше, чем наступит OOM.

▪️Влияние на OOM Killer
Можно управлять приоритетом уничтожения:

OOMScoreAdjust=-500
или наоборот:
OOMScoreAdjust=500


Чем выше значение - тем выше шанс, что процесс будет убит первым.

▪️Автоматический перезапуск после OOM
systemd может перезапускать сервис даже после убийства ядром:

[Service]
Restart=on-failure
RestartSec=2


Это работает и для OOM-kill, потому что процесс считается завершённым с ошибкой.

▪️Практический сценарий
Типичная ситуация:

• сервис разогнал память
• ядро убивает его через OOM
• systemd фиксирует падение
• запускает новый экземпляр
• cgroups не дают повторно выйти за лимит

▪️Где начинается реальный контроль

Ключевой момент - сочетание:

• MemoryMax (жёсткий лимит)
• MemoryHigh (раннее давление)
• OOMScoreAdjust (приоритет убийства)
• Restart=on-failure (самовосстановление)

▪️Почему это важно

Без cgroups OOM - это хаос: ядро выбирает жертву само.

С systemd это превращается в управляемую систему: процесс либо не доходит до OOM, либо корректно переживает его через перезапуск и ограничение ресурсов.

BashTex 📱 #scripts #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Please open Telegram to view this post
VIEW IN TELEGRAM
😁6
Проверка файловых систем, смонтированных с опасными опциями

При аудите Linux обычно проверяют права доступа и SUID-биты. Но не менее важно посмотреть, как смонтированы файловые системы.

Если временный каталог или пользовательский раздел смонтирован с exec, suid или dev, это может значительно расширить поверхность атаки.

▪️Посмотреть все точки монтирования

Самый удобный способ:

findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS


Или классический вариант:

mount


▪️На что обратить внимание
Опции монтирования:
exec - разрешает запуск исполняемых файлов.
suid - позволяет работать SUID/SGID-битам.
dev - разрешает использование файлов устройств.

Для каталогов вроде /tmp, /var/tmp или /dev/shm обычно безопаснее использовать противоположные опции:
noexec,nosuid,nodev

▪️Пример проверки

findmnt -no TARGET,OPTIONS /tmp


Если вывод содержит:

rw,relatime


значит ограничения отсутствуют.

Более безопасный вариант:

rw,nosuid,nodev,noexec


▪️Проверка через fstab

Чтобы убедиться, что настройки сохранятся после перезагрузки:

grep -vE '^\s*#|^$' /etc/fstab


Ищите разделы, где для временных или пользовательских файловых систем не заданы защитные опции.

▪️Почему это важно

Представьте, что злоумышленник смог записать файл в /tmp. Если раздел смонтирован с exec, его можно сразу запустить. Если ещё и разрешён suid или dev, последствия могут быть значительно серьёзнее.
Несколько минут на проверку параметров монтирования могут устранить целый класс потенциальных проблем ещё до того, как они будут использованы.

BashTex 📱 #scripts #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Скрипт поиска процессов с аномальным потреблением памяти

Когда на сервере заканчивается память, первое желание - открыть top. Но он показывает только текущее состояние. Для автоматизации удобнее получить список самых “тяжёлых” процессов и использовать его в скриптах.

▪️Быстрый рейтинг по RSS

Размер физической памяти, занимаемой процессом (RSS), можно посмотреть так:

ps -eo pid,user,comm,rss --sort=-rss | head -10


Поле rss выводится в килобайтах, поэтому сразу видно, кто потребляет больше всего ОЗУ.

▪️Автоматическая проверка

Например, вывести процессы, использующие больше 1 ГБ памяти:

ps -eo pid,comm,rss \
| awk '$3 > 1048576 {
printf "%-8s %-20s %.1f MB\n", $1, $2, $3/1024
}'


Такой вывод уже удобно отправлять в отчёт или систему мониторинга.

▪️Если нужен максимум информации

Часть данных о процессе хранится в /proc:

grep -E 'VmRSS|VmSize' /proc/1234/status


VmRSS
- реально занятая физическая память.
VmSize - всё адресное пространство процесса, включая ещё не загруженные страницы.

Эти значения могут сильно отличаться.

▪️Не путайте RSS и VSZ

Большой VSZ ещё не означает проблему. Многие приложения резервируют память заранее, но фактически используют лишь небольшую её часть.
При поиске “пожирателей” памяти обычно ориентируются именно на RSS.

▪️Почему это важно

Периодическая сортировка процессов по RSS помогает заметить утечки памяти ещё до того, как сработает OOM Killer. Особенно полезно для Java, Python, Node.js и других долгоживущих сервисов.

BashTex 📱 #bash #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Анализ активных UNIX-сокетов: поиск неожиданных IPC-соединений

При аудите обычно смотрят TCP- и UDP-порты, но многие сервисы вообще не используют сеть. Вместо этого они обмениваются данными через UNIX-сокеты.
Именно поэтому их тоже стоит периодически проверять.

▪️Посмотреть все UNIX-сокеты

Самый удобный способ:

ss -xl


Ключ -x показывает UNIX-сокеты, а -l - только те, которые находятся в режиме ожидания соединений.

▪️Получить больше информации

Если нужны процессы-владельцы:

ss -xlp


Например:

u_str LISTEN 0 128 /run/docker.sock
users:(("dockerd",pid=812,fd=7))


Сразу видно, какой процесс создал сокет.

▪️На что обратить внимание

Особый интерес представляют сокеты в нестандартных местах:

/tmp/
/dev/shm/
/home/user/


Большинство системных сервисов используют /run или /var/run. Если сокет появился в /tmp, стоит проверить, кто его создал и зачем.

▪️Найти сокеты через файловую систему

find / -type s 2>/dev/null


Это покажет все файлы типа socket, даже если они сейчас не используются.

▪️Когда это полезно

UNIX-сокеты используют Docker, Podman, PostgreSQL, Redis, Nginx, PHP-FPM, systemd и десятки других сервисов.
Неожиданный сокет может указывать на недавно установленное ПО, самописный сервис или процесс, который не должен работать на сервере.

▪️Почему это важно

Во многих инцидентах внимание уделяют только открытым сетевым портам. Но локальный IPC тоже может стать точкой входа или способом взаимодействия между процессами. Проверка UNIX-сокетов помогает увидеть часть инфраструктуры, которая остаётся незаметной при обычном аудите сети.

BashTex 📱 #bash #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1
xargs против while read: где быстрее и безопаснее

Обе конструкции позволяют обработать список файлов или строк, но работают они по-разному. Из-за этого одна может быть заметно быстрее, а другая - безопаснее.

▪️Когда выигрывает xargs

Допустим, нужно удалить все .log-файлы:

find . -name "*.log" | xargs rm


xargs
собирает несколько аргументов и передаёт их одной команде, поэтому вместо сотен запусков rm будет всего несколько.
Для большого количества файлов разница в производительности может быть существенной.

▪️Но есть проблема

По умолчанию xargs разделяет вход по пробелам и переводам строки.

Если встретится файл:

my file.log


или

backup
2025.log


команда отработает некорректно.

Безопасный вариант:

find . -name "*.log" -print0 | xargs -0 rm


Здесь разделителем становится символ NULL, поэтому пробелы и спецсимволы больше не проблема.

▪️Когда лучше while read

Если над каждой строкой нужно выполнить несколько действий:

find . -name "*.log" -print0 |
while IFS= read -r -d '' file; do
echo "Deleting: $file"
rm "$file"
done


Такой код легче расширять: добавить проверки, логирование, условия или обработку ошибок.

▪️Что быстрее?

Для простого запуска одной команды обычно выигрывает xargs.
Для сложной логики, где каждая строка проходит несколько этапов обработки, удобнее использовать while read.

▪️Почему это важно

Многие используют xargs и while read как взаимозаменяемые инструменты. На практике выбор зависит не только от скорости, но и от формата входных данных. Если есть вероятность встретить пробелы, переносы строк или необычные символы в именах файлов, безопасные варианты - xargs -0 или while read -d ''.

BashTex 📱 #bash #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
shopt: малоизвестные настройки Bash, которые меняют поведение shell

Большинство пользователей знают про set -e или set -u, но в Bash есть ещё один мощный инструмент настройки - shopt.
С его помощью можно включать и отключать десятки дополнительных возможностей оболочки.

▪️Посмотреть доступные опции

shopt


Или только включённые:

shopt -s


▪️globstar - рекурсивный поиск без find

По умолчанию:

ls **/*.log


не сработает.

Включаем:

shopt -s globstar


Теперь:

ls **/*.log


найдёт все .log-файлы во вложенных каталогах.

▪️nullglob - если файлов нет

Без этой опции:

for file in *.log; do
echo "$file"
done


выведет:

*.log


Вместо пустого списка.

Исправляем:

shopt -s nullglob


Теперь цикл просто не выполнится.

▪️dotglob - учитывать скрытые файлы

По умолчанию * не включает файлы, начинающиеся с точки.
После:

shopt -s dotglob


они тоже попадут в результат.

▪️failglob - защита от опечаток

Если шаблон не совпал ни с одним файлом:

rm *.bak


с failglob Bash сразу сообщит об ошибке вместо передачи шаблона команде.

shopt -s failglob


Это помогает избежать неожиданных сценариев в автоматизации.

▪️Почему это важно

Несколько опций shopt способны заметно изменить поведение Bash без переписывания скриптов. Особенно полезны globstar, nullglob и failglob - они делают работу с шаблонами более удобной и предсказуемой.

BashTex 📱 #bash #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1
Аудит переменной $PATH: поиск небезопасных директорий и дубликатов

Переменная $PATH определяет, где shell ищет исполняемые файлы. Один лишний каталог - и вместо системной утилиты может запуститься совсем другая программа.

Именно поэтому $PATH стоит периодически проверять.

▪️Посмотреть порядок поиска

echo "$PATH" | tr ':' '\n'


Shell просматривает каталоги сверху вниз. Если команда встречается в нескольких местах, будет использована первая найденная.

▪️Поиск дубликатов

Повторяющиеся каталоги не ломают систему, но замедляют поиск команд и усложняют отладку:

echo "$PATH" | tr ':' '\n' | sort | uniq -d


Если вывод не пустой - есть дубликаты.

▪️Опасные записи

Особое внимание стоит обратить на:

.
./bin
/tmp
/var/tmp
/home/user/bin


Каталог . означает “текущая директория”.

Если он находится в $PATH, достаточно оказаться в папке с вредоносным файлом ls или ssh, чтобы по ошибке запустить его вместо системной утилиты.

▪️Проверка прав доступа

Даже “нормальный” каталог может быть проблемой, если в него могут писать другие пользователи:

find $(echo "$PATH" | tr ':' ' ') \
-maxdepth 0 -perm -0002 -ls 2>/dev/null


World-writable директории в $PATH - серьёзный повод для проверки.

▪️Какая команда будет запущена?

Не всегда очевидно, какой бинарник использует shell:

type -a python


или

which -a python


Это покажет все найденные версии в порядке поиска.

▪️Почему это важно

Ошибки в $PATH могут приводить не только к странному поведению скриптов, но и к компрометации системы. Несколько минут аудита помогут обнаружить небезопасные каталоги, лишние записи и потенциальную подмену исполняемых файлов ещё до того, как это станет проблемой.

BashTex 📱 #bash #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
wait и wait -n: управление несколькими фоновыми задачами

Запустить процесс в фоне через & умеют почти все. Проблемы начинаются, когда таких процессов становится несколько и нужно понять, кто завершился и с каким кодом ошибки.

▪️Базовый wait

sleep 2 &
sleep 5 &

wait
echo "Все процессы завершились"


Без аргументов wait ждёт завершения всех фоновых задач текущего shell.

▪️Ожидание конкретного процесса

sleep 10 &
pid=$!

wait "$pid"
echo "Процесс завершён"


$!
- PID последнего фонового процесса.

▪️Зачем нужен wait -n

Появился в Bash 4.3+ и решает важную задачу: ждать не всех, а первого завершившегося процесса.

sleep 5 &
sleep 2 &
sleep 8 &

wait -n
echo "Кто-то уже завершился"


Скрипт продолжит работу через 2 секунды, а не через 8.

▪️Практический сценарий

Параллельная обработка файлов:

for file in *.log; do
gzip "$file" &
done

while wait -n; do
echo "Одна задача завершилась"
done


Так можно реагировать на завершение задач по мере их выполнения, а не ждать самый медленный процесс.

▪️Почему это важно

Без wait Bash может завершить скрипт раньше фоновых процессов. А wait -n позволяет строить простые очереди задач и параллельную обработку без GNU Parallel, Python и других внешних инструментов. Для многих серверных скриптов этого уже достаточно.

BashTex 📱 #bash #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
tee не только для логов: запись сразу в несколько потоков

Большинство используют tee только для сохранения вывода команды в файл:

command | tee output.log


Но возможности tee этим не ограничиваются. Он позволяет разветвлять поток данных и отправлять его сразу в несколько мест.

▪️Запись в несколько файлов

Например, сохранить один и тот же вывод сразу в два файла:

dmesg | tee kernel.log backup.log >/dev/null


Не нужно запускать команду дважды - tee сам продублирует поток.

▪️Логирование без потери вывода

Если скрипт должен писать лог, но при этом вывод оставаться в терминале:

./backup.sh | tee backup.log


Пользователь видит процесс выполнения, а лог сохраняется автоматически.

▪️Добавление вместо перезаписи

По умолчанию tee перезаписывает файл.
Чтобы дописывать:

echo "Started" | tee -a app.log


Ключ -a работает так же, как >>.

▪️Передача сразу в несколько команд

Вместе с process substitution можно построить разветвление потока:

journalctl -f \
| tee >(grep ERROR > errors.log) \
>(wc -l > count.txt) \
> /dev/null


Теперь один поток одновременно:
фильтруется по ошибкам;
подсчитывается;
может использоваться в других обработчиках.
Команда journalctl при этом запускается только один раз.

▪️Почему это важно

tee - это не просто инструмент для записи логов. Он позволяет строить конвейеры, где один источник данных обслуживает сразу несколько получателей. Это особенно полезно при анализе логов, мониторинге и автоматизации, когда дорого или невозможно повторно запускать исходную команду.

BashTex 📱 #bash #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍2
Анализ активных UNIX-сокетов: ss -xl и неожиданные IPC-соединения

Когда ищут открытые сервисы на сервере, обычно проверяют TCP и UDP:

ss -tulpn


Но часть процессов вообще не использует сеть. Они общаются через UNIX-сокеты - локальный механизм IPC между процессами.

▪️Посмотреть активные UNIX-сокеты

ss -x


Ключ -x включает UNIX-сокеты.

Чтобы увидеть только ожидающие подключения:

ss -xl


Пример:

u_str LISTEN 0 128 /run/docker.sock


Это означает, что какой-то процесс принимает локальные подключения через этот сокет.

▪️Найти владельца сокета

Добавляем информацию о процессе:

ss -xlp


Пример:

users:(("dockerd",pid=842,fd=7))


Теперь понятно, какой процесс создал точку обмена.

▪️Проверка прав доступа

UNIX-сокет - это файл, поэтому у него есть обычные права:

ls -l /run/docker.sock


Например:

srw-rw---- root docker docker.sock


Группа с правом записи может управлять Docker через этот сокет.

▪️Найти все сокеты на диске

find / -type s 2>/dev/null


Особое внимание:

/tmp
/dev/shm
/home/*


Системные сервисы чаще используют:

/run
/var/run


▪️Посмотреть, кто держит конкретный сокет

Через lsof:

lsof /run/docker.sock


или:

fuser /run/docker.sock


▪️Почему это важно

Открытый TCP-порт виден сразу при сетевом сканировании. UNIX-сокеты остаются внутри системы и часто забываются при аудите.
При проверке сервера стоит смотреть не только наружные соединения, но и локальные каналы связи между процессами: именно там могут находиться Docker API, базы данных, агенты мониторинга и другие сервисы с важными правами доступа.

BashTex 📱 #bash #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Поиск файлов с расширенными ACL: getfacl и find для выявления нестандартных прав

В Linux права доступа обычно проверяют через:

ls -l


Но этого недостаточно. Если у файла есть ACL (Access Control List), дополнительный пользователь или группа могут иметь доступ, которого не видно в стандартном выводе.

▪️Проверяем ACL у файла

getfacl /etc/passwd


Обычный вывод:

user::rw-
group::r--
other::r--


Если есть дополнительные правила:

user::rw-
user:backup:r--
group::r--
mask::r--
other::---


Здесь пользователь backup получил отдельное разрешение.

▪️Как найти файлы с ACL

Команда find умеет искать расширенные ACL:

find / -type f -acl 2>/dev/null


Но на многих системах удобнее использовать проверку через getfacl:

find /etc -type f -exec getfacl -p {} \; 2>/dev/null | grep "^user:"


▪️Проверка конкретного каталога

Например, ищем нестандартные права в /srv:

getfacl -R /srv


Обращаем внимание на строки:

user:name:
group:name:


Они показывают дополнительные разрешения.

▪️Удаление лишних ACL

Если доступ больше не нужен:

setfacl -b file.txt


Ключ -b удаляет все дополнительные ACL, оставляя только обычные Unix-права.

▪️Почему ACL часто забывают

Администратор может изменить права:

chmod 600 secret.txt


и считать файл закрытым.

Но если раньше был добавлен ACL:

user:john:r--


пользователь John всё ещё может читать файл.

▪️Почему это важно

ACL полезны для сложных систем с большим количеством пользователей, но они усложняют аудит. При расследовании проблем с доступом всегда нужно проверять не только chmod, но и расширенные правила через getfacl.

BashTex 📱 #bash #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Поиск процессов с удалённым исполняемым файлом

В Linux процесс продолжает работать, даже если его исполняемый файл уже удалён с диска. Пока процесс не завершится, ядро держит файл открытым через файловый дескриптор.

Такие процессы стоит периодически искать - особенно после обновлений ПО, удаления пакетов или при аудите безопасности.

▪️Быстрая проверка
Исполняемый файл каждого процесса доступен через /proc/<PID>/exe:

ls -l /proc/*/exe 2>/dev/null | grep '(deleted)'


Например:

/proc/2841/exe -> /usr/bin/python3.12 (deleted)


Это означает, что процесс продолжает использовать уже удалённый бинарник.

▪️Более удобный вариант

С помощью lsof:

lsof | grep '(deleted)'


Команда покажет не только исполняемые файлы, но и удалённые библиотеки, логи и другие объекты, которые всё ещё удерживаются процессами.

▪️Почему это происходит
Типичный сценарий:

apt upgrade


Во время обновления старый бинарник удаляется и заменяется новым. Но уже запущенный процесс продолжает выполнять старую версию из памяти.
Пока сервис не будет перезапущен, он работает с удалённым файлом.

▪️Когда это становится проблемой

Если удерживается исполняемый файл или библиотека - система использует устаревший код.

Если удерживается большой удалённый лог:

/var/log/app.log (deleted)


место на диске не освободится, пока процесс не закроет файл или не завершится.

▪️Какие процессы требуют внимания

Не все записи (deleted) опасны. В первую очередь стоит проверить:
системные сервисы после обновлений;
процессы с удалёнными библиотеками (.so);
файлы в /tmp или /dev/shm, которые продолжают использоваться после удаления.

▪️Почему это важно

Поиск процессов с (deleted) помогает обнаружить сервисы, которые давно требуют перезапуска, понять, почему не освобождается место на диске, и выявить подозрительные процессы, работающие с уже отсутствующими файлами.

BashTex 📱 #bash #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Поиск бинарников с Linux Capabilities: getcap -r /

В Linux привилегии процесса не всегда завязаны только на root. Существуют capabilities - отдельные разрешения ядра, которые можно выдавать конкретным бинарникам.

Например, программе можно дать возможность менять сетевые настройки без полного root-доступа.

▪️Посмотреть capabilities у файла

getcap /usr/bin/ping


Пример вывода:

/usr/bin/ping cap_net_raw=ep


Это означает, что ping имеет право создавать raw-сокеты.

▪️Поиск всех бинарников с capabilities

getcap -r / 2>/dev/null


Команда рекурсивно проверяет файловую систему и показывает файлы с назначенными capabilities.

Пример:

/usr/bin/python3 cap_net_bind_service=ep
/usr/local/bin/app cap_sys_admin=ep


▪️Что означают флаги

Capability может иметь разные состояния:
cap_net_raw=ep
e (effective) — разрешение активно при запуске;
p (permitted) — процесс может его использовать.
Чаще всего встречается комбинация ep.

▪️Некоторые capabilities фактически дают очень широкие возможности:

cap_sys_admin
cap_dac_override
cap_setuid
cap_sys_ptrace


Например:

cap_dac_override позволяет обходить обычные проверки прав файлов;
cap_setuid позволяет менять UID процесса;
cap_sys_ptrace даёт возможность взаимодействовать с другими процессами.

▪️Проверка конкретного процесса

У работающего процесса capabilities находятся здесь:

cat /proc/1234/status | grep Cap


Ядро хранит их в виде битовых масок.

▪️Удаление capability

Если разрешение больше не требуется:

setcap -r /path/to/binary


После этого файл вернётся к обычной модели прав.

▪️Почему это важно

При аудите Linux недостаточно искать только SUID-биты:

find / -perm -4000


Современные системы активно используют capabilities, и иногда один бинарник с лишним разрешением может иметь больше привилегий, чем ожидается.

BashTex 📱 #bash #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Проверка изменения списка загруженных модулей ядра: lsmod + сравнение снимков

Ядро Linux работает с модулями, которые можно загружать и выгружать без перезагрузки системы.

Это удобно для драйверов и расширений, но неожиданные изменения списка модулей могут быть важным сигналом при аудите.

▪️Получить текущий список модулей

lsmod


Пример:

Module        Size      Used by
nf_conntrack 176128 1
veth 32768 2


Но для автоматического сравнения лучше сохранить только имена:

lsmod | awk 'NR>1 {print $1}' | sort > modules.current


▪️Создание базового снимка

После установки и настройки сервера можно сохранить эталон:

lsmod | awk 'NR>1 {print $1}' | sort > /var/lib/modules.snapshot


Позже сравнить:

diff /var/lib/modules.snapshot modules.current


▪️Поиск новых модулей

Например:

comm -13 /var/lib/modules.snapshot modules.current


Покажет только то, что появилось после создания снимка.

▪️Проверка загрузки модулей в логах

Ядро пишет события загрузки:

journalctl -k | grep -i module


Или:

dmesg | grep -i module


▪️Кто загрузил модуль?

Информацию о самом модуле можно получить через:

modinfo veth


Покажет:

файл модуля;
автора;
версию;
зависимости.

▪️Почему это важно

Большинство администраторов контролируют процессы и сетевые порты, но забывают про уровень ядра.

Неожиданный модуль может появиться после установки нового ПО, драйвера или изменения конфигурации. Сравнение снимков lsmod помогает быстро увидеть изменения в состоянии ядра и понять, что именно изменилось на сервере.

BashTex 📱 #bash #linux
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1