{"id":50376909,"url":"https://github.com/vnegrea/ldaplookup","last_synced_at":"2026-05-30T10:01:33.424Z","repository":{"id":336111069,"uuid":"1148141233","full_name":"vnegrea/ldaplookup","owner":"vnegrea","description":"Hardened LDAP lookup tool with embedded credentials, runtime locks, and anti-tampering protection","archived":false,"fork":false,"pushed_at":"2026-02-02T21:34:12.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-03T10:44:38.349Z","etag":null,"topics":["authentication","binary-obfuscation","garble","go","golang","hardened","ldap","ldap-client","obfuscation","security"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vnegrea.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-02T16:16:24.000Z","updated_at":"2026-02-02T20:54:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/vnegrea/ldaplookup","commit_stats":null,"previous_names":["vnegrea/ldaplookup"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/vnegrea/ldaplookup","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vnegrea%2Fldaplookup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vnegrea%2Fldaplookup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vnegrea%2Fldaplookup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vnegrea%2Fldaplookup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vnegrea","download_url":"https://codeload.github.com/vnegrea/ldaplookup/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vnegrea%2Fldaplookup/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33687722,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","binary-obfuscation","garble","go","golang","hardened","ldap","ldap-client","obfuscation","security"],"created_at":"2026-05-30T10:01:32.690Z","updated_at":"2026-05-30T10:01:33.418Z","avatar_url":"https://github.com/vnegrea.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ldaplookup\n\nA hardened, self-contained LDAP lookup tool. Produces a statically linked binary with no runtime dependencies. Credentials are either sealed on the target machine (recommended) or embedded at build time — operators choose the mode per build.\n\n## Features\n\n- **Zero dependencies**: Single static binary with no runtime libraries required (no libldap, no ldapsearch)\n- **Portable**: Runs on any Linux system without installation\n- **Secure credential handling**: Credentials are obfuscated and embedded at build time, never exposed in process tables or environment variables\n- **Deployment locks**: Restrict execution to specific hostnames and paths, rendering the binary useless if copied elsewhere ([see details](#runtime-locks))\n- **Tamper protection**: Built-in resistance to debugging and analysis ([see details](#tamper-protection))\n- **Dual mode**: Use `ldaplookup` for users, `ldaplookupg` for groups\n- **Smart lookups**: Numeric input automatically searches by uidNumber/gidNumber\n\n## ⚠️ When to Use This Tool\n\nThis tool embeds LDAP credentials directly in the binary. Before using it, consider these alternatives:\n\n**Preferred alternatives:**\n- **Kerberos/GSSAPI**: Uses ticket-based authentication with no stored secrets. If your environment supports Kerberos, this is the recommended approach.\n- **Secrets management platforms**: Enterprise solutions offer better audit trails, credential rotation, and access controls.\n\n**When this tool may be appropriate:**\n- Parallel automation across many systems where secrets management platforms may hit rate limits or cause latency\n- LDAP services that do not support GSSAPI authentication\n- Environments without centralized secrets infrastructure\n- Situations where a self-contained, dependency-free binary is required\n\n**This tool is not:**\n- A replacement for proper secrets management\n- Immune to reverse engineering (obfuscation ≠ encryption)\n- Suitable for public or untrusted systems\n\n**Recommendation:** Always enable hostname and path locks to maximize protection.\n\n## 🔒 Hardening\n\n### Build-time Obfuscation\n\nGo produces native machine-code binaries. This can raise the effort to reverse engineer compared to shipping source or readily decompilable artifacts, but it does not prevent reverse engineering. This tool adds another layer using [garble](https://github.com/burrowers/garble), a build wrapper that obfuscates Go binaries by randomizing symbol names, obscuring string literals, and stripping/altering metadata.\n\nThe build uses flags from garble, Go's build system, the Go linker, and environment variables:\n\n| Flag | Source | Purpose |\n|------|--------|---------|\n| `-literals` | garble | Obfuscate string literals, preventing simple string extraction |\n| `-tiny` | garble | Strip debug info and runtime panic/trace output, hindering analysis |\n| `-seed` | garble | Use deterministic randomization for reproducible builds |\n| `-trimpath` | go build | Remove local filesystem paths from binary |\n| `-buildid=` | go linker | Remove Go build ID to hinder version fingerprinting |\n| `GOGARBLE='*'` | env var | Obfuscate all packages including dependencies |\n\n### Sealed Credentials (Recommended)\n\nSealed credentials protect against binary analysis by keeping the password **out of the binary entirely**.\n\n**How it works:**\n\n```\n┌─────────────┐        ┌─────────────┐        ┌─────────────┐\n│   BUILD     │        │   DEPLOY    │        │    SEAL     │\n│ No password │  ───►  │ Copy binary │  ───►  │  --seal     │\n│  embedded   │        │  to target  │        │ encrypts pw │\n└─────────────┘        └─────────────┘        └──────┬──────┘\n                                                     │\n                                                     ▼\n                                              ┌─────────────┐\n                                              │ .seal file  │\n                                              │ AES-256-GCM │\n                                              │machine-bound│\n                                              └─────────────┘\n```\n\nThe password is encrypted using a key derived from:\n- The target machine's unique ID (`/etc/machine-id`)\n- A random salt generated at build time\n- The deployment directory path\n- The running user's UID\n- A SHA-256 hash of the binary itself\n\n**This means:**\n- The binary contains no extractable password\n- The `.seal` file is useless on any other machine, under any other user, or at any other path\n- Moving, copying, or upgrading the binary breaks decryption — re-run `--seal` after replacing the binary\n- Each user gets their own seal file (`\u003cbinary\u003e.seal.\u003cuid\u003e`)\n\n**Credential rotation:**\n```bash\n./ldaplookup --seal    # Prompts to overwrite if .seal exists\n```\n\n**Choosing a mode (selected when you run `build.sh`):**\n\n| | Mode 1 — Sealed (recommended) | Mode 2 — Embedded (legacy) |\n|---|---|---|\n| Password location | Encrypted `.seal` on the target; never in the binary | XOR-obfuscated inside the binary |\n| Static-analysis resistance | High — key is bound to machine, user, path, and binary | Low — recoverable from the binary |\n| Deployment | Requires running `--seal` once on the target | Single artifact, no post-deploy step |\n\nBoth modes are built from the same source; you choose one per build.\n\n### Runtime Locks\n\n**Hostname lock:** Restricts execution to specific servers using DNS verification.\n1. At build time, specify a trusted DNS server IP and allowed hostnames\n2. At runtime, the binary queries the trusted DNS server to resolve its own hostname and verifies it matches the allowed list\n\nUsing a DNS server you control is critical. It prevents attackers from spoofing hostname resolution on a compromised system. If verification fails, [tamper protection](#tamper-protection) is triggered.\n\n**Important:** Hostname matching is exact. Use the **FQDN** (e.g., `myserver.umich.edu`) not just the short name.\n\nTo check what your system will return, run: `hostname -f`\n\nYou can provide multiple FQDNs (comma-separated) for systems with multiple hostnames: `server1.umich.edu,server2.umich.edu`\n\n**Known limitation:** The DNS step confirms that the *allowed FQDN resolves* via your trusted DNS server; it does not cryptographically prove that the local host's identity is that FQDN. Use it together with the path lock and OS-level access controls for defense in depth.\n\n**Path lock:** Restricts execution to a specific deployment directory.\n1. At build time, specify the allowed deployment path (e.g., `/opt/ldaplookup`)\n2. At runtime, the binary verifies its executable path matches the allowed location\n\nThis prevents the binary from being copied elsewhere and executed. If verification fails, [tamper protection](#tamper-protection) is triggered.\n\n### Tamper Protection\n\nBuilt-in tamper resistance protects against analysis and unauthorized use.\n\n**Self-Destruct Behavior**\n\n| Trigger | Action | Reason |\n|---------|--------|--------|\n| Hostname mismatch | Binary deletes itself | Unauthorized host |\n| Path mismatch | Binary deletes itself | Moved/copied illegally |\n| Debugger detected | Binary deletes itself | Analysis attempt |\n\n**Note:** Self-destruct is best-effort. Deletion can fail on read-only filesystems, immutable (`chattr +i`) files, hardlinked binaries, or where the running user lacks write access to the binary's directory. Treat the locks as a strong deterrent, not a hard guarantee.\n\n### Best Practices\n- Use `chmod 110` and open up as needed\n- Use a dedicated LDAP service account with read-only permissions\n- Deploy only to trusted, access-controlled systems\n- Rotate credentials if a binary is compromised\n\n## 📦 Installing Go Locally (Linux)\n\n**Note:** If you already have Go installed and configured (`go version` works), skip this section. The build scripts will install garble automatically.\n\nIf Go is not available system-wide and you prefer not to install it globally, use the included helper script:\n\n```bash\n./install-go-local.sh      # Downloads and installs Go + garble\nsource ~/myGo/env.sh       # Activate in current terminal\n./test_build.sh            # Verify build works\n./build.sh                 # Build with real credentials\n```\n\nThe script installs to `~/myGo/` and creates an environment file. To make permanent, add `source ~/myGo/env.sh` to your `~/.bashrc`.\n\n## Build\n\n```bash\n./build.sh\n```\n\nYou'll be prompted for:\n- Security disclaimer acknowledgment (type 'yes' to continue)\n- LDAP server URL (e.g., `ldaps://ldap.umich.edu`)\n- User search base (e.g., `ou=People,dc=umich,dc=edu`)\n- Group search base (e.g., `ou=User Groups,ou=Groups,dc=umich,dc=edu`)\n- Bind DN (full Distinguished Name, e.g., `cn=App01,ou=Applications,o=services` — not just `cn=App01`)\n- Bind password\n- Hostname lock (enabled by default)\n- Path lock (enabled by default)\n- Whether to generate a new obfuscation seed\n\n### Testing the Build\n\nTo verify the build process works without real credentials:\n\n```bash\n./test_build.sh\n```\n\nThis script builds with dummy test data, verifies the binary is created and executes, then cleans up.\n\n### Deployment\n\nThe build produces `ldaplookup` and a symlink `ldaplookupg`. To deploy:\n\n```bash\n# Copy the binary to target\ncp ldaplookup /path/to/destination/\n\n# Create the symlink for group lookups\nln -s ldaplookup /path/to/destination/ldaplookupg\n\n# If using sealed credentials (default), seal on the target machine\n/path/to/destination/ldaplookup --seal\n# Enter the LDAP password when prompted\n```\n\nThe binary detects its invocation name. When called as `ldaplookupg`, it queries groups instead of users.\n\n**Note:** If you used legacy embedded credentials during build, the `--seal` step is not required.\n\n### Obfuscation Seed\n\nThe build script prompts whether to generate a new obfuscation seed. The seed controls how garble randomizes the obfuscation. The same seed produces the same obfuscated output.\n\n**When to keep the existing seed (answer N):**\n- Rebuilding with the same credentials\n- You want the binary hash to remain consistent\n- Avoiding detection as a \"new\" binary by endpoint security tools\n\n**When to generate a new seed (answer Y):**\n- Credentials have changed\n- You want protection against differential analysis (comparing two binaries to identify patterns)\n- Deploying to a new environment where a fresh fingerprint is acceptable\n\n**Trade-off:** A new seed produces a completely different binary, which provides better protection against reverse engineering through comparison. However, endpoint detection and response (EDR) tools may flag it as an unknown binary until it's re-baselined in your environment.\n\nThe seed is stored in `.garble_seed` (gitignored) and reused on subsequent builds unless you choose to regenerate it.\n\n## Usage\n\n```bash\n# User lookup by uid\n./ldaplookup \u003cuid\u003e\n\n# User lookup by uidNumber (auto-detected)\n./ldaplookup 12345\n\n# Group lookup by name\n./ldaplookupg \u003cgroupname\u003e\n\n# Group lookup by gidNumber (auto-detected)\n./ldaplookupg 1001\n\n# Specific attributes\n./ldaplookup \u003cuid\u003e uid displayName uidNumber\n./ldaplookupg \u003cgroupname\u003e cn gidNumber memberUid\n```\n\n### Examples\n\n```bash\n# Get all attributes for user\n./ldaplookup jsmith\n\n# Get specific user attributes\n./ldaplookup jsmith uid uidNumber mail\n\n# Get group by name\n./ldaplookupg staff\n\n# Get group by gidNumber\n./ldaplookupg 1001\n```\n\n## Requirements\n\n- Go 1.25.10+ (patch level matters — earlier 1.25.x have known crypto/tls and crypto/x509 advisories)\n- [garble](https://github.com/burrowers/garble): `go install mvdan.cc/garble@latest`\n- openssl (for seed generation)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvnegrea%2Fldaplookup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvnegrea%2Fldaplookup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvnegrea%2Fldaplookup/lists"}