Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/CyberStrikeus/CyberStrike --skill wstg-idnt-05명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
macOS post-exploitation for credential harvesting, DTrace monitoring, TCC bypass, and stealth operations via native tools
Windows userland post-exploitation for credential harvesting, monitoring, AMSI/ETW bypass, and stealth operations
Kubernetes post-exploitation for container escape, secret extraction, RBAC abuse, and cluster persistence
SKILL.md 표시 중
SOC 직업 분류 기준
| name | wstg-idnt-05 |
| description | Test Username Policy |
| category | identity-management |
| owasp_id | WSTG-IDNT-05 |
| version | 1.0.0 |
| author | cyberstrike-official |
| tags | ["identity","user-enum","roles","wstg","idnt"] |
| tech_stack | [] |
| cwe_ids | [] |
| chains_with | [] |
| prerequisites | [] |
| severity_boost | {} |
WSTG-IDNT-05
Testing for Weak or Unenforced Username Policy
Username policy testing evaluates the rules and restrictions applied to username creation and management. Weak username policies can lead to account enumeration, impersonation attacks, and user confusion. This test examines whether the application enforces appropriate restrictions on username format, length, allowed characters, and uniqueness while preventing predictable or malicious usernames.
| Aspect | Risk |
|---|---|
| Predictable usernames | Account enumeration |
| Similar usernames | User confusion/impersonation |
| No reserved words | Admin impersonation |
| Case insensitive | Duplicate accounts |
| Special chars allowed | XSS/Injection |
# Test minimum length
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "a",
"email": "short1@test.com",
"password": "TestPass123!"
}'
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "ab",
"email": "short2@test.com",
"password": "TestPass123!"
}'
# Test maximum length
curl -s -X POST \
-H \
-d $(python3 -c )),
: ,
:
}{
:
#!/bin/bash
# Test reserved usernames
RESERVED_NAMES=(
"admin" "administrator" "root" "system"
"support" "help" "info" "security"
"moderator" "mod" "staff" "official"
"webmaster" "postmaster" "hostmaster"
"null" "undefined" "anonymous" "guest"
"api" "www" "mail" "ftp" "smtp"
)
for name in "${RESERVED_NAMES[@]}"; do
response=$(curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d "{
\"username\": \"$name\",
\"email\": \"${name}@test.com\",
\"password\": \"TestPass123!\"
}")
echo "$name: $response"
done
# First, create a user
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "testuser",
"email": "case1@test.com",
"password": "TestPass123!"
}'
# Try variations
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "TestUser",
"email": "case2@test.com",
"password": "TestPass123!"
}'
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "TESTUSER",
"email": "case3@test.com",
"password": "TestPass123!"
}'
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "tEsTuSeR",
"email": "case4@test.com",
"password": "TestPass123!"
}'
#!/bin/bash
# Test special character handling
SPECIAL_CHARS=(
"test<script>"
"test'user"
"test\"user"
"test;user"
"test--user"
"test/*user"
"test../user"
"test%00user"
"test\nuser"
"test\tuser"
"test user"
"test@user"
"test#user"
"test&user"
"test=user"
"test+user"
)
for username in "${SPECIAL_CHARS[@]}"; do
response=$(curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d "{
\"username\": \"$username\",
\"email\": \"special$(date +%s)@test.com\",
\"password\": \"TestPass123!\"
}" 2>/dev/null)
echo "Testing: $username"
echo "Response: $response"
echo "---"
done
# Test Unicode lookalikes
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "аdmin",
"email": "unicode1@test.com",
"password": "TestPass123!"
}' # Cyrillic 'а' instead of Latin 'a'
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "ɑdmin",
"email": "unicode2@test.com",
"password": "TestPass123!"
}' # Latin alpha
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "admin\u200b",
"email": "unicode3@test.com",
"password": "TestPass123!"
}' # Zero-width space
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "admin\u00a0",
"email": "unicode4@test.com",
"password": "TestPass123!"
}' # Non-breaking space
# Test confusing similar usernames
# If "company_admin" exists, try:
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "company-admin",
"email": "similar1@test.com",
"password": "TestPass123!"
}'
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "company.admin",
"email": "similar2@test.com",
"password": "TestPass123!"
}'
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "companyadmin",
"email": "similar3@test.com",
"password": "TestPass123!"
}'
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d '{
"username": "company__admin",
"email": "similar4@test.com",
"password": "TestPass123!"
}'
# Test purely numeric usernames
for num in 1 12 123 1234 12345; do
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d "{
\"username\": \"$num\",
\"email\": \"num$num@test.com\",
\"password\": \"TestPass123!\"
}"
done
# Test sequential patterns
for user in user1 user2 user3 test1 test2 test3; do
curl -s -X POST "https://target.com/api/register" \
-H "Content-Type: application/json" \
-d "{
\"username\": \"$user\",
\"email\": \"$user@test.com\",
\"password\": \"TestPass123!\"
}"
done
| Tool | Description | Usage |
|---|---|---|
| Burp Suite | Request manipulation | Test various username formats |
| curl | Command-line HTTP | Scripted testing |
| Unicode tools | Character lookup | Homograph testing |
| Tool | Description |
|---|---|
| Burp Intruder | Fuzzing usernames |
| Custom scripts | Comprehensive testing |
| Regex testers | Validate patterns |
# Length tests
a
ab
abc
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa (very long)
# Reserved names
admin
administrator
root
system
support
null
undefined
# Case variations
Admin
ADMIN
aDmIn
# Special characters
user<script>
user'test
user"test
user;test
user--test
user/../admin
user%00admin
# Unicode/Homograph
аdmin (Cyrillic a)
ɑdmin (Latin alpha)
admin (zero-width space)
admin (with invisible chars)
# Similar patterns
company_admin
company-admin
company.admin
companyadmin
# Numeric
123456
user123
1user
#!/usr/bin/env python3
import requests
import json
import unicodedata
class UsernamePolicyTester:
def __init__(self, register_url):
self.url = register_url
self.results = []
def test_username(self, username, description):
"""Test a single username"""
try:
response = requests.post(
self.url,
json={
"username": username,
"email": f"test_{hash(username)}@test.com",
"password": "TestPass123!"
},
timeout=10
)
result = {
"username": username,
"description": description,
"status": response.status_code,
"accepted": response.status_code in [200, 201],
"response": response.text[:200]
}
except Exception as e:
result = {
"username": username,
"description": description,
"error": str(e)
}
self.results.append(result)
return result
def run_all_tests(self):
"""Run comprehensive policy tests"""
# Length tests
self.test_username("a", "1 character")
self.test_username("ab", "2 characters")
self.test_username("abc", "3 characters")
self.test_username("a" * 50, "50 characters")
self.test_username("a" * 100, "100 characters")
self.test_username("a" * 500, "500 characters")
# Reserved names
reserved = ["admin", "administrator", "root", "system",
"support", "null", "undefined", "api", "www"]
for name in reserved:
self.test_username(name, f"Reserved: {name}")
# Case sensitivity
self.test_username("TestCase", "Mixed case")
self.test_username("testcase", "Lower case")
self.test_username("TESTCASE", "Upper case")
# Special characters
specials = [
("test<tag>", "HTML tag"),
("test'quote", "Single quote"),
("test\"quote", "Double quote"),
("test;semi", "Semicolon"),
("test--sql", "SQL comment"),
("test../path", "Path traversal"),
("test user", "Space"),
("test\tuser", "Tab"),
]
for username, desc in specials:
self.test_username(username, desc)
# Unicode/Homograph
self.test_username("аdmin", "Cyrillic 'a'") # Cyrillic
self.test_username("admin\u200b", "Zero-width space")
self.test_username("admin\u00a0", "Non-breaking space")
# Numeric
self.test_username("123456", "Pure numeric")
self.test_username("user123", "Alphanumeric")
return self.results
def print_report(self):
"""Print test results"""
print("\n=== USERNAME POLICY TEST RESULTS ===\n")
accepted = [r for r in self.results if r.get("accepted")]
rejected = [r for r in self.results if not r.get("accepted") and "error" not in r]
errors = [r for r in self.results if "error" in r]
print(f"Accepted: {len(accepted)}")
print(f"Rejected: {len(rejected)}")
print(f"Errors: {len(errors)}")
print("\n--- ACCEPTED (Potential Issues) ---")
for r in accepted:
print(f" {r['description']}: {r['username'][:30]}")
print("\n--- REJECTED (Expected) ---")
for r in rejected:
print(f" {r['description']}: {r['username'][:30]}")
# Usage
tester = UsernamePolicyTester("https://target.com/api/register")
tester.run_all_tests()
tester.print_report()
import re
import unicodedata
def validate_username(username):
"""Validate username against security policy"""
errors = []
# Length check
if len(username) < 3:
errors.append("Username must be at least 3 characters")
if len(username) > 30:
errors.append("Username must be 30 characters or less")
# Allowed characters (alphanumeric + underscore only)
if not re.match(r'^[a-zA-Z0-9_]+$', username):
errors.append("Username can only contain letters, numbers, and underscores")
# Must start with letter
if not re.match(r'^[a-zA-Z]', username):
errors.append("Username must start with a letter")
# No consecutive underscores
if '__' in username:
errors.append("Username cannot contain consecutive underscores")
# Reserved names check
reserved = ['admin', 'administrator', 'root', 'system', 'support',
'null', 'undefined', 'api', 'www', 'mail', 'ftp']
if username.lower() in reserved:
errors.append("This username is reserved")
# Check for Unicode tricks
normalized = unicodedata.normalize('NFKC', username)
if normalized != username:
errors.append("Username contains invalid characters")
# Check for confusable characters
if contains_confusables(username):
errors.append("Username contains potentially confusing characters")
return errors
def contains_confusables(username):
"""Check for homograph/confusable characters"""
# Simple check - only allow ASCII
try:
username.encode('ascii')
return False
except UnicodeEncodeError:
return True
from sqlalchemy import func
def is_username_available(username):
"""Check username availability (case-insensitive)"""
normalized = username.lower()
existing = User.query.filter(
func.lower(User.username) == normalized
).first()
return existing is None
def create_user(username, email, password):
if not is_username_available(username):
raise ValueError("Username already taken")
# Store normalized (lowercase) version
user = User(
username=username,
username_normalized=username.lower(),
email=email
)
# ...
def is_similar_to_existing(username):
"""Check if username is too similar to existing ones"""
normalized = normalize_for_comparison(username)
similar_users = User.query.filter(
User.username_normalized.like(f"%{normalized}%")
).all()
for user in similar_users:
if calculate_similarity(normalized, user.username_normalized) > 0.8:
return True
return False
def normalize_for_comparison(username):
"""Normalize username for similarity comparison"""
# Remove separators
normalized = re.sub(r'[-_.]', '', username.lower())
# Remove numbers
normalized = re.sub(r'[0-9]', '', normalized)
return normalized
# Allow more flexibility in display names
# Keep strict rules for usernames (used in URLs, mentions)
class User:
username = Column(String(30)) # Strict validation
display_name = Column(String(50)) # More relaxed
@validates('username')
def validate_username(self, key, username):
errors = validate_username(username)
if errors:
raise ValueError('; '.join(errors))
return username
| Finding | CVSS | Severity |
|---|---|---|
| Reserved names allowed (admin) | 7.5 | High |
| Unicode homograph allowed | 6.5 | Medium |
| Case sensitivity issues | 5.3 | Medium |
| XSS via username | 6.1 | Medium |
| Weak length requirements | 3.7 | Low |
| CWE ID | Title | Description |
|---|---|---|
| CWE-20 | Improper Input Validation | Weak username validation |
| CWE-79 | Cross-site Scripting | XSS via username |
| CWE-178 | Improper Handling of Case | Case sensitivity issues |
[ ] Minimum length requirement tested
[ ] Maximum length limit tested
[ ] Reserved username protection tested
[ ] Case sensitivity verified
[ ] Special character handling tested
[ ] Unicode/homograph attacks tested
[ ] SQL injection in username tested
[ ] XSS in username tested
[ ] Similar username prevention tested
[ ] Numeric-only usernames tested
[ ] Sequential pattern prevention tested
[ ] Whitespace handling tested
[ ] Findings documented
[ ] Remediation recommendations provided