पाठ 7 / 25

Parse किया हुआ Allowlist

Commands को arguments में parse करें, shell metacharacters अस्वीकार करें और सटीक command prefixes मिलाएँ।

पहले parse, फिर मिलाएँ

ज़्यादा मज़बूत तरीक़ा है: पहले shell metacharacters (; & | $ < > ` और newlines) वाली किसी भी पंक्ति को **अस्वीकार** करें, फिर बाक़ी को उचित parser (Python में shlex) से argument सूची में बाँटें, और जाँचें कि सूची किसी मंज़ूर command से शुरू होती है। अज्ञात या जटिल पंक्तियाँ चलने की जगह "ask" में जाती हैं। यह जानबूझकर रूढ़िवादी है: हानिरहित command के बारे में इंसान से पूछना, हानिकारक को allow करने से बेहतर है।

Parse की गई जाँच, चलाकर

मैंने यह चलाया। Chain किए और substitute किए commands अस्वीकार होते हैं, सुरक्षित पास होते हैं, और npm install evil सूची में नहीं है।

import shlex, re
SAFE = {("git", "status"), ("git", "diff"), ("git", "log"), ("npm", "test"), ("ls",)}
META = re.compile(r"[;&|`$<>\n\\]")

def allowed(cmd):
    if META.search(cmd): return False
    try: argv = shlex.split(cmd)
    except ValueError: return False
    return any(tuple(argv[:len(p)]) == p for p in SAFE)

for c in ("git status", "git diff --stat", "git status; rm -rf /tmp/x",
          "echo $(whoami)", "npm test", "npm install evil", "ls -la"):
    print(allowed(c), repr(c))

Output:

True 'git status'
True 'git diff --stat'
False 'git status; rm -rf /tmp/x'
False 'echo $(whoami)'
True 'npm test'
False 'npm install evil'
True 'ls -la'

जोखिम वाले tools के arguments मिलाएँ

कुछ commands flags के अनुसार सुरक्षित या ख़तरनाक होते हैं। git push ठीक हो सकता है जबकि git push --force नहीं। ऐसे tools के लिए सिर्फ़ program नाम नहीं, argument स्तर पर नियम लिखें।

त्वरित जाँच: Parse किए allowlist में `$(...)` वाली पंक्ति का क्या होता है?

  • Metacharacter के कारण अस्वीकार होती है
  • अतिरिक्त logging के साथ चलती है
  • Shell उसे दोबारा लिखता है
  • वह हमेशा allow होती है
Answer

Metacharacter के कारण अस्वीकार होती है — Metacharacters पहले ही अस्वीकार हो जाते हैं, इसलिए command substitution दूसरा command नहीं छिपा सकता।