TGViewer
Bash Days | Linux | DevOps Bash Days | Linux | DevOps @bashdays · 23.6K subscribers
Post #1368 8.78K
Фарш обратно не провернёшь

Порой в Bash поделках требуется создать какой-нибудь секрет, для дальнейшей его передачи в CI/CD или куда-то еще. Ежу понятно, это можно сделать «в лоб», но мыж с тобой не волки позорные, поэтому давай сделаем это по всем правилам DevSecOps Best Practice. (* лучшие практики безопасной разработки).

Задача: Создать безопасно секрет, чтобы его не спиздили (например из свапа при форензике).

Форензика — это направление информационной безопасности, связанное с анализом и восстановлением данных для расследования инцидентов


Кто-то извращается со shred и т.п. утилитами, но это избыточно, да и на SSD, Btrfs, ZFS и journal FS оно будет работать хуева и не гарантирует физическое уничтожение данных. Лучше на диск вообще ничего не писать.

Наш вариант это — pipe через printf. Можно конечно усложнить и сделать через анонимный файловый дескриптор, но получаются те же грабли только сбоку, смысла усложнять нет.

#!/usr/bin/env bash

set -euo pipefail

SECRET="$(openssl rand -base64 32)"

printf '%s' "$SECRET" | \
openssl enc -aes-256-cbc -salt -pbkdf2 -iter 200000 \
-in input.txt \
-out output.enc \
-pass stdin

unset SECRET


Что тут происходит?

Ничего необычного, генерим 32 случайных байта, кодируем в base64, получаем пароль высокой энтропии, затем через printf передаем пароль (без \n) через pipe в stdin.

Ну и в конце скармливаем какой-нибудь утилите или в CI/CD, куда нужно передать секрет, в моем случае я передал его в openssl.

По итогу секрет, не попадает в history, не лежит на диске и временно находится в памяти. Но важно понимать, что после unset SECRET переменная удаляется только из таблицы переменных, в памяти эта переменная может по-прежнему храниться и быть уязвима к форензике. Поэтому носи это в голове и по возможности перезатирай память например тем же stress.

А еще оно может попасть в swap и это еще хуже, swap это прям как неочищенная «корзина» с удаленными файлами.

На bash этот момент описать наверное не получится, поэтому покажу как сделать на Сиськах. Будем использовать mlock().

#include <sys/mman.h>
#include <string.h>
#include <stdio.h>

int main() {
char secret[32] = "super_secret_password";

if (mlock(secret, sizeof(secret)) != 0) {
perror("mlock failed");
return 1;
}

printf("Secret in locked memory\n");

// Используем секрет...

memset(secret, 0, sizeof(secret)); // затираем
munlock(secret, sizeof(secret));

return 0;
}


Когда этот код будет вызывать mlock(), указанный диапазон памяти закрепляется в RAM и ядро не имеет права выгружать его в swap.

Получается что сначала mlock() блокирует участок памяти, затирает memset() её перед освобождением и с помощью munlock() снимает блокировку.

Кстати mlock() используют GnuPG, OpenSSH, HashiVault, KeePassXX. Так что вариант надежный, можешь не сомневаться. А еще иногда используется mlockall():

mlockall(MCL_CURRENT | MCL_FUTURE);


Блокируется вся текущая и будущая память процесса, активно применяется демонами в HashiVault.

Такие дела.

Накидай еще своих вариантов в комменты, будет интересно ознакомиться.

🛠 #dev #security #bash

💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
More from @bashdays
  1. Sep 23, 2026Здрасти приехали, решил я в кой-то веке воспользоваться услугами Codex, создал аккаунт, по…
  2. Sep 23, 2026📣 GuardConf 2026 для тех, кто принимает решения о программных продуктах Как быстрее выпус…
  3. Sep 22, 2026Всем привет, с вами TagdTagd. Сегодня опять поднимем тему архивов, но немного с другой сто…
  4. Sep 21, 2026Объектное хранилище в эпоху быстрых данных Объём данных, с которыми нужно работать, растёт…
  5. Sep 15, 2026Всем привет, с вами TagdTagd. И это вторая часть. Практическая. С первой частью можешь озн…
  6. Sep 11, 2026🤖 DevOps в эпоху AI трансформации: что работает уже сейчас! 17 сентября Сбер собирает Dev…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →