0Pricing
Linux Command Line & Bash Scripting Mastery · درس

التعامل الآمن مع الأسرار ونظافة البيئة

أبقِ بيانات الاعتماد خارج قوائم العمليات والسجلات باستخدام الإدخال القياسي والملفات والبيئات المنقّحة

التعامل الآمن مع الأسرار ونظافة البيئة درس مجاني في Linux Command Line & Bash Scripting Mastery على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Linux Command Line & Bash Scripting Mastery، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Linux Command Line & Bash Scripting Mastery 4 دروس في المجموع.

لماذا تُعدّ النظافة الأمنية للأسرار مهمة

الأسرار — مثل مفاتيح API وكلمات المرور والرموز المميزة — هي أكثر البيانات حساسية في أي نظام. ويُعدّ سوء التعامل معها في برامج Bash النصية من أكثر الأخطاء الأمنية شيوعًا وأشدها ضررًا.

  • قوائم العمليات: تظهر الوسائط الممررة إلى الأوامر في ps aux و/proc/<pid>/cmdline وسجلات تدقيق النظام، ويمكن لجميع المستخدمين على المضيف رؤيتها.
  • سجل الصدفة: تُسجّل الأوامر المكتوبة تفاعليًا (وأحيانًا البرامج النصية) في ~/.bash_history.
  • ملفات السجل: يمكن لتتبعات set -x وسجلات التطبيقات ومخرجات CI/CD التقاط قيم المتغيرات.
  • تسرّب البيئة: ترث العمليات الابنة البيئة الكاملة للعملية الأم، بما في ذلك أي أسرار مُصدّرة.

يتعامل البرنامج النصي المحصّن مع الأسرار كما لو كانت مواد مشعة — يقلل مدة التعرض، ويحد من مساحة الانتشار، وينقّي كل شيء عند إخراجه.

سطح الهجوم في قوائم العمليات

عندما تمرر سرًا باعتباره وسيطًا لسطر الأوامر، يستطيع كل مستخدم على النظام قراءته فورًا عبر ps. وهذا ليس أمرًا نظريًا؛ إذ يُستغل بانتظام في بيئات الاستضافة المشتركة والحاويات.

يوضح المقتطف أدناه المشكلة والإصلاح جنبًا إلى جنب.

#!/usr/bin/env bash
# DANGEROUS: password visible in 'ps aux' output
# curl -u "admin:SuperSecret123" https://api.example.com/data

# SAFE: pass credentials via stdin or a flag that reads from a file
# Many tools support reading secrets from stdin with '-' or dedicated flags:

# Option 1 — pipe the secret so it never appears in argv
echo 'SuperSecret123' | curl -u 'admin' --password-stdin \
  https://api.example.com/data 2>/dev/null || true

# Option 2 — write a temporary netrc and point curl at it
# (covered in a later scene)
echo 'Secret never touches the command line this way'

قراءة الأسرار من stdin

إن النمط التفاعلي الأكثر أمانًا هو قراءة السر أثناء التشغيل باستخدام read -rs. إذ يمنع الخيار -s عرض المحارف، بينما يمنع الخيار -r تفسير الشرطات المائلة العكسية.

نقاط أساسية:

  • لا يُصدَّر المتغير أبدًا، لذلك لا تستطيع العمليات الابنة رؤيته عبر /proc/<pid>/environ.
  • بعد استخدامه، ألغِ تعيين المتغير فورًا باستخدام unset لتقليص فترة التعرض.
  • تجنب echo "$SECRET" — واستخدم printf '%s' لمنع سطر جديد لاحق من إفساد القيمة، ولتبقى القيمة غير ظاهرة في التتبعات.
#!/usr/bin/env bash
set -euo pipefail

# Prompt on stderr so stdout stays clean for piping
read -rsp 'Enter API token: ' API_TOKEN <&2
printf '\n' >&2

# Use the secret — printf keeps it out of argv
response=$(printf '%s' "$API_TOKEN" | curl -sS -X POST \
  -H 'Content-Type: application/json' \
  --data-binary @- \
  https://httpbin.org/post 2>/dev/null) || true

echo "Request sent."

# Scrub immediately — unset removes it from shell memory
unset API_TOKEN

الأسرار في الملفات: الأذونات والملكية

عندما يجب أن يبقى سرّ ما محفوظًا على القرص (مثل مفتاح حساب خدمة)، فإن أذونات الملف هي وسيلة دفاعكم الأساسية.

  • الوضع 0600 — يمكن للمالك وحده القراءة والكتابة. ولا يوجد وصول للمجموعة أو لأي مستخدم آخر.
  • الوضع 0400 — للمالك حق القراءة فقط. ويُفضَّل استخدامه للمفاتيح التي يجب ألا تستبدلوها عن طريق الخطأ مطلقًا.
  • خزّنوا ملفات الأسرار ضمن دليل مخصّص مثل ~/.secrets/ أو /run/secrets/ (والأخير هو نظام ملفات tmpfs مدعوم بذاكرة RAM في كثير من أنظمة Linux، ولا يبقى إلا حتى إعادة التشغيل).
  • لا تضعوا ملفات الأسرار داخل دليل يتتبعه git مطلقًا من دون ملف .gitignore محكم وموثوق تمامًا.
#!/usr/bin/env bash
set -euo pipefail

SECRETS_DIR="${HOME}/.secrets"
mkdir -p "$SECRETS_DIR"
chmod 700 "$SECRETS_DIR"   # directory: only owner can list contents

KEY_FILE="${SECRETS_DIR}/api_token"

# Write secret — atomically restrict permissions before writing content
install -m 0600 /dev/null "$KEY_FILE"
printf '%s' 'my-super-secret-token' > "$KEY_FILE"

echo "Permissions:"
ls -la "$KEY_FILE"

# Read back safely — no subshell, no echo
API_TOKEN=$(< "$KEY_FILE")
echo "Token length: ${#API_TOKEN} chars (value not printed)"
unset API_TOKEN

استخدام ملف .netrc مع curl

يدعم curl ملف ~/.netrc (أو مسارًا عشوائيًا عبر --netrc-file) يربط أسماء المضيفين ببيانات الاعتماد. ويؤدي ذلك إلى إبقاء بيانات المصادقة بعيدة تمامًا عن سطر الأوامر ونصّ البرنامج النصي.

تنسيق الملف بسيط:

machine api.example.com
  login admin
  password s3cr3t

أفضل الممارسات:

  • اضبطوا دائمًا chmod 0600 ~/.netrc — إذ يرفض curl الملف إذا كان مقروءًا من جميع المستخدمين على بعض الأنظمة.
  • استخدموا --netrc-file /run/secrets/netrc للإشارة إلى سرّ مدعوم بـ tmpfs أو مُحقن داخل الحاوية.
  • نظّفوا ملفات netrc المؤقتة باستخدام trap عند EXIT.
#!/usr/bin/env bash
set -euo pipefail

TMP_NETRC=$(mktemp)
chmod 0600 "$TMP_NETRC"

# Trap ensures cleanup even on error or signal
trap 'rm -f "$TMP_NETRC"' EXIT

# Write credentials to the temp netrc
cat > "$TMP_NETRC" <<'EOF'
machine httpbin.org
  login myuser
  password mypassword
EOF

curl -fsS --netrc-file "$TMP_NETRC" \
  https://httpbin.org/basic-auth/myuser/mypassword \
  -o /dev/null -w 'HTTP %{http_code}\n' || true

# trap fires here: $TMP_NETRC is deleted
echo 'Temp netrc cleaned up by trap.'

سلامة متغيرات البيئة

تُعدّ متغيرات البيئة طريقة شائعة لحقن الأسرار في البرامج النصية (في تطبيقات 12-factor وخطوط CI/CD). لكنها تتسرّب إلى كل عملية فرعية وتظهر في /proc/<pid>/environ طوال مدة العملية.

أساليب دفاعية:

  • استوردوا السر فورًا إلى متغير محلي ثم ألغوا ضبط متغير البيئة حتى لا تتمكن العمليات الفرعية من وراثته.
  • مرّروا الأسرار إلى أوامر محددة باستخدام env -i أو باستخدام إسناد inline بدلًا من تمرير البيئة الموروثة كاملة.
  • لا تستخدموا export لمتغير سرّي مطلقًا — استخدموا الإسناد فقط (من دون export) متى أمكن.
#!/usr/bin/env bash
set -euo pipefail

# Simulate a secret arriving via environment (e.g., from CI system)
export DB_PASSWORD='hunter2'   # set by CI — we did not choose this

# Capture locally, then strip from environment immediately
db_password="$DB_PASSWORD"
unset DB_PASSWORD

# Verify the env var is gone before spawning any child process
if printenv DB_PASSWORD 2>/dev/null; then
  echo 'ERROR: DB_PASSWORD still in environment!' >&2
  exit 1
fi

echo 'Secret captured and env var scrubbed.'
echo "Password length: ${#db_password}"
unset db_password

منع ظهور الأسرار في تتبعات set -x

يُعدّ set -x (xtrace) أداة لا غنى عنها لتصحيح الأخطاء، لكنه يطبع قيمة كل متغير يوسّعه — بما في ذلك الأسرار — إلى stderr. وغالبًا ما تنتهي هذه التتبعات في سجلات CI أو syslog.

استراتيجيات حماية الأسرار مع الإبقاء على فائدة التتبع:

  • عطّلوا التتبع مؤقتًا حول العمليات الحساسة باستخدام { set +x; } 2>/dev/null.
  • أعيدوا تفعيله بعد ذلك باستخدام set -x.
  • وجّهوا مخرجات xtrace إلى واصف ملف منفصل يرسلها إلى ملف سجل محمي، لا إلى مجرى السجل العام.
#!/usr/bin/env bash
set -euo pipefail
set -x   # tracing ON — safe for non-sensitive sections

echo 'Building application...'
SRC_DIR='/tmp/build'
mkdir -p "$SRC_DIR"

# Disable xtrace around secret handling (suppress the set +x line itself)
{ set +x; } 2>/dev/null

read -rsp 'Token (hidden from trace): ' SECRET_TOKEN <&2
printf '\n' >&2
token_len=${#SECRET_TOKEN}
unset SECRET_TOKEN

set -x  # tracing back ON

echo "Token captured (length=$token_len). Continuing build..."
ls "$SRC_DIR"

تنقية الأسرار من ملفات السجل

حتى عند توخي الحذر، قد تجد الأسرار طريقها أحيانًا إلى مخرجات السجل — ولا سيما في البرامج النصية المطوّلة أو القديمة. وتضيف دالة تغليف للتسجيل، تحجب الأنماط المعروفة، طبقة أمان إضافية.

يستخدم هذا النمط استبدالًا قائمًا على regex لجميع مخرجات السجل. وهو طبقة الملاذ الأخير، وليس بديلًا عن ممارسات السلامة الأخرى التي تناولناها.

#!/usr/bin/env bash
set -euo pipefail

# A logging function that scrubs common secret patterns before writing
log() {
  local line
  # Replace anything that looks like key=VALUE or password=VALUE
  line=$(printf '%s\n' "$*" \
    | sed -E 's/(password|token|secret|key)=[^[:space:]]*/\1=***REDACTED***/gi')
  printf '[%s] %s\n' "$(date -u '+%T')" "$line"
}

# Usage:
log 'Connecting to database with password=hunter2'
log 'Loaded API token=sk-abc123xyz secret'
log 'Build step completed successfully'   # unchanged

بيئات معزولة باستخدام env -i

يبدأ env -i أمرًا باستخدام بيئة فارغة تمامًا، ما يمنع وصول أي متغيرات موروثة — بما فيها الأسرار غير المقصودة — إلى العملية الفرعية. ثم تمرّرون صراحةً ما تحتاجون إليه فقط.

يفيد ذلك خصوصًا عند تشغيل برامج نصية غير موثوقة أو أدوات بناء أو أدوات من جهات خارجية قد تستخرج بيانات البيئة.

#!/usr/bin/env bash
set -euo pipefail

# Polluted parent environment (simulating a CI runner)
export AWS_SECRET_ACCESS_KEY='AKIAIOSFODNN7EXAMPLE'
export GITHUB_TOKEN='ghp_faketoken123'
export HOME="$HOME"
export PATH="$PATH"

echo '--- Child sees full environment:'
env | grep -E 'AWS|GITHUB' | head -5

echo '--- Sanitised child (env -i) sees nothing secret:'
env -i HOME="$HOME" PATH="$PATH" TERM="${TERM:-dumb}" \
  bash -c 'env | grep -E "AWS|GITHUB" || echo "No secrets visible"'

unset AWS_SECRET_ACCESS_KEY GITHUB_TOKEN

ملفات الأسرار المؤقتة على tmpfs

‏tmpfs هو نظام ملفات مدعوم بذاكرة RAM. ولا تُفرَّغ الملفات المكتوبة فيه إلى القرص مطلقًا، ما يلغي خطر بقاء الأسرار في مساحة التبديل أو ذاكرة التخزين المؤقت للقرص أو اللقطات.

  • في Linux، يكون كل من /dev/shm و/run/user/<uid> عادةً نقطتي تحميل tmpfs.
  • احرصوا دائمًا على إقران استخدام tmpfs بـ trap EXIT لحذف الملفات عند انتهاء البرنامج النصي.
  • في الحاويات (Docker وKubernetes)، يمكن تحميل الأسرار مباشرةً كوحدات tmpfs داخل /run/secrets.
#!/usr/bin/env bash
set -euo pipefail

# Prefer /run/user/$UID (user-owned tmpfs) or /dev/shm (world-readable dir!)
if [[ -d "/run/user/$UID" ]]; then
  TMPFS_DIR="/run/user/$UID"
elif [[ -d '/dev/shm' ]]; then
  TMPFS_DIR='/dev/shm'
else
  # Fallback: warn that disk will be used
  echo 'WARNING: No tmpfs available; using /tmp (disk-backed)' >&2
  TMPFS_DIR='/tmp'
fi

SECRET_FILE=$(mktemp "${TMPFS_DIR}/secret.XXXXXX")
chmod 0600 "$SECRET_FILE"
trap 'shred -u "$SECRET_FILE" 2>/dev/null || rm -f "$SECRET_FILE"' EXIT

printf '%s' 'my-runtime-token' > "$SECRET_FILE"
echo "Secret stored in: $SECRET_FILE"
df -T "$SECRET_FILE" | awk 'NR==2 {print "Filesystem type:", $2}'

# Use the secret...
token=$(< "$SECRET_FILE")
echo "Token length: ${#token}"
unset token
# trap fires on exit: file shredded

جمع كل العناصر: برنامج نصي للنشر محصَّن

يجمع البرنامج النصي التالي كل التقنيات الواردة في هذا الدرس ضمن مساعد نشر واقعي. لاحظوا كيف تعزّز كل طبقة من طبقات الدفاع الطبقات الأخرى:

  • القراءة من stdin باستخدام -s — من دون إظهار الإدخال في الطرفية
  • ملف سرّ على tmpfs مع تنظيف باستخدام trap
  • تنقية البيئة — إلغاء ضبط السر قبل أي عملية فرعية
  • حارس xtrace — إيقاف التتبع حول التعليمات البرمجية الحساسة
  • حجب السجلات — استخدام regex كشبكة أمان قبل الكتابة إلى السجل
#!/usr/bin/env bash
set -euo pipefail

### 1. Redacting logger
log() {
  local msg
  msg=$(printf '%s' "$*" \
    | sed -E 's/(password|token|secret|key)=[^[:space:]]*/\1=***/gi')
  printf '[%s] %s\n' "$(date -u +%T)" "$msg"
}

### 2. tmpfs secret store
TMPFS_DIR="${XDG_RUNTIME_DIR:-/tmp}"
SECRET_FILE=$(mktemp "${TMPFS_DIR}/deploy_token.XXXXXX")
chmod 0600 "$SECRET_FILE"
trap 'rm -f "$SECRET_FILE"; log "Secret file cleaned up."' EXIT

### 3. Read secret without trace
{ set +x; } 2>/dev/null
read -rsp 'Deploy token: ' _tok <&2; printf '\n' >&2
printf '%s' "$_tok" > "$SECRET_FILE"
unset _tok
set -x

### 4. Scrub inherited env vars before subprocess
unset DEPLOY_TOKEN 2>/dev/null || true

log 'Starting deployment...'
# Simulate deploy using secret from file (token never in argv)
# curl -H "Authorization: Bearer $(< $SECRET_FILE)" https://api.example.com/deploy
log 'Deployment complete. token=hidden_by_redactor'

echo 'Done.'

اختبار المعرفة: انكشاف الأسرار عبر قائمة العمليات

اختبروا فهمكم لكيفية تسرّب الأسرار عبر قوائم العمليات وكيفية منع ذلك.

مراجعة الدرس: التعامل الآمن مع الأسرار

لقد أكملتم درس التعامل الآمن مع الأسرار وسلامة البيئة. إليكم مرجعًا موجزًا لكل ما تناولناه:

  • قوائم العمليات: لا تمرّروا الأسرار أبدًا كوسائط لسطر الأوامر — إذ تظهر في ps aux و/proc/<pid>/cmdline. استخدموا تمريرها عبر stdin أو --netrc-file بدلًا من ذلك.
  • القراءة من stdin: استخدموا read -rs لجمع الأسرار تفاعليًا من دون إظهارها في الطرفية أو كشفها في سجل الصدفة.
  • أذونات الملفات: يجب أن تكون ملفات الأسرار بإذن chmod 0600 (أو 0400). استخدموا install -m 0600 للإنشاء الذري.
  • ملفات netrc: فوّضوا بيانات الاعتماد إلى ملف مؤقت يُحدَّد عبر --netrc-file، ونظّفوه باستخدام trap EXIT.
  • سلامة البيئة: ألغوا فورًا ضبط متغيرات البيئة السرية باستخدام unset بعد حفظها محليًا؛ ولا تستخدموا export لها بلا حاجة؛ واستخدموا env -i لعزل العمليات الفرعية.
  • حارس xtrace: غلّفوا التعليمات البرمجية الحساسة ضمن { set +x; } 2>/dev/null ... set -x لمنع تتبعات التصحيح من كشف القيم.
  • حجب السجلات: استخدموا مسجّلًا قائمًا على sed كشبكة أمان أخيرة.
  • tmpfs: خزّنوا أسرار وقت التشغيل في /run/user/$UID أو /dev/shm حتى لا تلامس القرص مطلقًا؛ ثم أتلفوها عند الخروج.

الفكرة الأساسية هي الدفاع متعدد الطبقات: لا يكفي أي إجراء منفرد، لكن جمعها معًا يجعل تسرّب الأسرار بالغ الصعوبة.

الأسئلة الشائعة

هل درس «التعامل الآمن مع الأسرار ونظافة البيئة» مجاني؟

نعم — نص درس «التعامل الآمن مع الأسرار ونظافة البيئة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Linux Command Line & Bash Scripting Mastery، انتقل إلى CoddyKit PRO. تتضمن دورة Linux Command Line & Bash Scripting Mastery 4 دروس في المجموع.

ماذا ستتعلم في «التعامل الآمن مع الأسرار ونظافة البيئة»؟

أبقِ بيانات الاعتماد خارج قوائم العمليات والسجلات باستخدام الإدخال القياسي والملفات والبيئات المنقّحة تتمرن على Linux Command Line & Bash Scripting Mastery مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Linux Command Line & Bash Scripting Mastery؟

لا تُشترط خبرة سابقة. Linux Command Line & Bash Scripting Mastery على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «التعامل الآمن مع الأسرار ونظافة البيئة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Linux Command Line & Bash Scripting Mastery هذا؟

نعم. كل درس في Linux Command Line & Bash Scripting Mastery يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. منع حقن الأوامر والوسائط
  2. التعامل الآمن مع الأسرار ونظافة البيئة
  3. التنفيذ بأقل الصلاحيات والانضباط في استخدام sudo
  4. التحليل الساكن والتدقيق باستخدام ShellCheck
← العودة إلى Linux Command Line & Bash Scripting Mastery