Web3 Wallet Security Fundamentals (Linux Command Line)


Honors Dojo.

Web3 Wallet Security Fundamentals: A Linux Command Line Approach

A practical, hands-on module focused on Web3/Crypto wallet security, using only the Linux command-line utilities you have learned in class(CSE365).

  • Objective: Learn fundamental and advanced wallet security concepts by using core Linux commands to simulate real-world security failures and forensic analysis.
  • Commands Used: cat, grep, diff, touch, tr, chmod, Pipelining, Shell Scripting with Conditionals (if/then/else), and Environment Variable usage.

Challenge Progression

1. Securing the Seed Phrase

  • Core Concept: Cold Storage Simulation, File Permissions, Simple Obfuscation
  • Key Commands Used: touch, cat, tr (Translating chars), chmod (Changing Permissions)

2. The Hot Wallet Exposure

  • Core Concept: Environment Variable Attacks, Private Key Leakage
  • Key Commands Used: grep (on Exported Variables)

3. Phishing Content Analysis

  • Core Concept: Content Forensics, Identifying Subtle Fraud
  • Key Commands Used: diff (comparing files), grep

4. API Key Log Forensics

  • Core Concept: Multi-Stage Log Filtering, Data Pipelining
  • Key Commands Used: grep (Pipelining/Grepping live output), Text Extraction

5. Basic Signature Validation

  • Core Concept: Integrity Check Simulation, Scripting Logic
  • Key Commands Used: Scripting with Conditionals (if/then/else), cat

It is recommended to have a solid understanding of the commands listed above to successfully complete this module.

This module was created by Jacob Blemaster.



Challenges

Securing the Seed Phrase

Introduction to Seed Phrases

In the world of cryptocurrency and Web3, a seed phrase (also called a recovery phrase) is a series of 12-24 words that gives you access to your crypto wallet. It's essentially the master key to all your funds.

Critical Security Concept: If someone gets your seed phrase, they own your wallet. Forever.

This is why seed phrases should NEVER be:

  • Stored in plain text on your computer
  • Saved in cloud storage
  • Shared with anyone
  • Left with default file permissions that anyone can read

Cold Storage Best Practice

One approach to securing seed phrases is cold storage - keeping them completely offline and protected. In this challenge, you'll simulate cold storage security using Linux commands:

  1. Obfuscation with tr: Transform the text so it's not immediately readable
  2. File Permissions with chmod: Restrict access to owner-only

The Challenge

In this challenge, you need to:

  1. Create a file containing a dummy seed phrase
  2. Obfuscate it using the tr command (ROT13 cipher)
  3. Set proper file permissions so only YOU (the owner) can read/write it

Commands You'll Use

tr (translate characters):

hacker@dojo:~$ echo "hello" | tr 'a-z' 'n-za-m'
uryyb

The tr command translates characters. The format A-Za-z to N-ZA-Mn-za-m performs ROT13 encryption.

chmod (change mode/permissions):

hacker@dojo:~$ chmod 600 myfile.txt

This sets permissions to rw------- (read/write for owner only).

File permission format:

  • 6 = read(4) + write(2) for owner
  • 0 = no permissions for group
  • 0 = no permissions for others

Your Task

Run the seedPhrase command to validate your solution. This script will check:

  1. Whether you created the obfuscated seed phrase file correctly
  2. Whether file permissions are set to 600 (owner read/write only)

If successful, you'll receive the flag!

Hint

The tr command can read from a file and output to another file using:

cat input.txt | tr 'A-Za-z' 'N-ZA-Mn-za-m' > output.txt

Good luck, and remember: In the real world, proper seed phrase security can mean the difference between keeping your crypto safe and losing everything!

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

The Hot Wallet Exposure

What is a Hot Wallet?

A hot wallet is a cryptocurrency wallet that's connected to the internet and actively used for transactions. Unlike cold storage (offline wallets), hot wallets prioritize convenience over security, making them vulnerable to various attacks.

The Risk: Hot wallets are especially vulnerable when private keys are exposed through:

  • Environment variables
  • Log files
  • Process memory dumps
  • Temporary files
  • Error messages

Environment Variables: A Hidden Threat

In Linux, environment variables are dynamic values that affect running processes. Developers sometimes make a critical mistake: storing sensitive information (API keys, passwords, private keys) in environment variables.

Why is this dangerous?

  1. Environment variables are inherited by child processes - any program you run can see them
  2. They can be accidentally logged by applications or system tools
  3. They're visible to anyone who can run commands on the system
  4. Many debugging tools and error messages dump environment variables
  5. They persist in shell history and process listings

Real-World Example

A developer might do this thinking it's "secure":

export WALLET_PRIVATE_KEY="0x1234567890abcdef..."

But now ANY process can access it:

# Other users or processes can see it
ps aux -e  # Shows environment variables of all processes
/proc/PID/environ  # Kernel exposes env vars in filesystem

Viewing Environment Variables

The env Command

The env command displays all environment variables in your current shell:

hacker@dojo:~$ env
USER=hacker
HOME=/home/hacker
PATH=/usr/local/bin:/usr/bin:/bin
SHELL=/bin/bash
WALLET_PRIVATE_KEY=0xABCD1234...
...

The grep Command for Searching

Since env outputs many variables, we use grep to filter:

hacker@dojo:~$ env | grep WALLET
WALLET_PRIVATE_KEY=0xABCD1234567890...

How this works:

  • env lists all environment variables
  • | (pipe) sends the output to the next command
  • grep WALLET searches for lines containing "WALLET"

Other Useful Commands

printenv - Another way to display environment variables:

hacker@dojo:~$ printenv WALLET_PRIVATE_KEY
0xABCD1234567890...

Direct variable access:

hacker@dojo:~$ echo $WALLET_PRIVATE_KEY
0xABCD1234567890...

The Scenario

You're a security analyst investigating a cryptocurrency theft. A careless developer exported their wallet's private key as an environment variable named WALLET_PRIVATE_KEY during development.

The private key is still exposed in the environment, and you need to find it before an attacker does.

Your Task

Run bin/walletExposure to set up the challenge environment. This will export the WALLET_PRIVATE_KEY variable to your shell configuration.

Use grep to search through the environment variables and locate the exposed WALLET_PRIVATE_KEY.

Optional: Run the walletExposure command to see challenge instructions and hints.

The flag is embedded in the private key value.

Hints

  1. Use the env command to list all environment variables
  2. Pipe the output to grep to search for patterns: env | grep PATTERN
  3. Look for a variable named WALLET_PRIVATE_KEY
  4. The private key contains your flag

Commands You'll Need

# List all environment variables
env

# Search for a specific pattern
env | grep WALLET

# Alternative approach
printenv | grep WALLET

Security Best Practices

DO:

  • Use hardware wallets (Ledger, Trezor) for storing private keys
  • Use secret management tools (HashiCorp Vault, AWS Secrets Manager, 1Password)
  • Use encrypted configuration files with restricted permissions
  • Keep private keys in cold storage for long-term holdings
  • Use environment-specific secrets that are never committed to version control

DON'T:

  • Store private keys in environment variables
  • Log environment variables in application logs
  • Share environment variables across services
  • Commit .env files to Git repositories
  • Use the same keys in development and production

Remember: In production Web3 applications, use proper key management systems and hardware security modules (HSMs). Never expose private keys in environment variables, even "temporarily" during development!

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

Phishing Content Analysis

The Phishing Threat in Web3

Phishing is one of the most dangerous and common attack vectors in the cryptocurrency ecosystem. Attackers create fake websites that look nearly identical to legitimate services (MetaMask, Coinbase, Uniswap, OpenSea) to steal users' credentials, private keys, or trick them into sending funds to attacker-controlled wallets.

The Statistics:

  • Over $100 million stolen through phishing attacks in 2023 alone
  • 80% of crypto theft starts with phishing
  • Average time to detect a phishing site: 12-24 hours
  • Victims rarely recover stolen funds

Common Phishing Techniques

1. Domain Spoofing

Using similar-looking domains that are easy to miss:

  • Legitimate: metamask.io
  • Phishing: metarnask.io (rn looks like m)
  • Phishing: metamask.io (Cyrillic 'а' instead of Latin 'a')

2. Visual Cloning

Creating pixel-perfect copies of legitimate sites:

  • Identical logos, colors, fonts
  • Same page layout and structure
  • Copied error messages and help text

3. Subtle Content Changes

The most dangerous type - everything looks legitimate except:

  • Wallet addresses where funds are sent
  • Smart contract addresses for token swaps
  • Transaction confirmations
  • One character different in a 42-character address

4. URL Manipulation

Using Unicode homoglyphs and look-alike characters:

  • һ (Cyrillic) vs h (Latin)
  • а (Cyrillic) vs a (Latin)
  • О (Cyrillic) vs O (Latin)

The diff Command: Finding Differences

The diff command compares two files line by line and shows what's different.

Basic syntax:

hacker@dojo:~$ diff file1.txt file2.txt

Example:

hacker@dojo:~$ diff legitimate.txt phishing.txt
3c3
< Send funds to: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
---
> Send funds to: 0xDEADBEEF1234567890ABCDEF...

Understanding the output:

  • 3c3 means "line 3 changed" (c = change)
  • < shows content from the first file (legitimate.txt)
  • --- is a separator
  • > shows content from the second file (phishing.txt)

Other diff notations:

  • 5a6 - line added after line 5
  • 7d6 - line 7 deleted
  • 2,4c2,5 - lines 2-4 changed to lines 2-5

Using grep with diff

You can filter diff output to find specific changes:

hacker@dojo:~$ diff file1.txt file2.txt | grep ">"
> Send funds to: 0xDEADBEEF...

This shows only lines from the second file that are different.

hacker@dojo:~$ diff file1.txt file2.txt | grep "0x"
< Send funds to: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
> Send funds to: 0xDEADBEEF1234567890ABCDEF...

This shows both lines containing wallet addresses.

The Scenario

You're a security analyst at a cryptocurrency exchange. Multiple users have reported losing funds after "confirming" MetaMask transactions.

Upon investigation, you've obtained two HTML files:

  1. legitimate_metamask.html - The real MetaMask transaction confirmation page
  2. phishing_metamask.html - A suspected phishing page from a malicious site

The files look visually identical, but somewhere in the code there's a subtle change: the destination wallet address has been swapped to the attacker's address.

Your mission: Find the malicious wallet address that's stealing user funds.

Your Task

Run the phishingDetector command to set up the challenge files. Then use diff to compare the legitimate and phishing HTML files to identify the exact line that was changed.

The flag is embedded in the phishing wallet address.

Hints

  1. The phishingDetector command will create two files for you to compare
  2. Use diff to compare both HTML files
  3. Look for lines showing destination wallet addresses
  4. The > symbol in diff output shows content from the phishing file
  5. Try combining with grep to filter for specific patterns
  6. The malicious address contains the flag

Commands You'll Need

# Compare two files
diff legitimate_metamask.html phishing_metamask.html

# Show only lines from the phishing file (second file)
diff legitimate_metamask.html phishing_metamask.html | grep ">"

# Filter for wallet addresses (0x pattern)
diff legitimate_metamask.html phishing_metamask.html | grep "0x"

# Show just the changed lines with context
diff -u legitimate_metamask.html phishing_metamask.html

Real-World Phishing Detection

In production environments, security teams use:

Automated Tools:

  • PhishTank - Community-driven phishing site database
  • Google Safe Browsing - Real-time phishing detection API
  • MetaMask's phishing detector - Checks domains against known phishing lists
  • OpenPhish - Machine learning phishing detection

Manual Analysis:

  • Visual inspection of page source
  • SSL certificate verification
  • WHOIS domain registration checks
  • File hash comparison
  • Network traffic analysis

Browser Extensions:

  • MetaMask - Built-in phishing detection
  • Pocket Universe - Transaction simulation before signing
  • Fire - Warns about malicious smart contracts
  • Wallet Guard - Blocks known phishing sites

Security Best Practices

DO:

  • Always verify URLs character by character before entering credentials
  • Bookmark legitimate sites and only use bookmarks
  • Check SSL certificates (look for the padlock icon)
  • Verify contract addresses on multiple block explorers
  • Use hardware wallets with address verification on-device
  • Double-check wallet addresses before confirming transactions
  • Enable transaction simulation (Pocket Universe, Fire)

DON'T:

  • Click links in emails, Discord, Telegram, or Twitter DMs
  • Trust sites from Google search results (attackers buy ads)
  • Ignore browser security warnings
  • Rush through transaction confirmations
  • Share your screen during transactions
  • Enter seed phrases anywhere except your hardware wallet

Critical Rule: If a site asks for your seed phrase, it's 100% a scam. Legitimate services never ask for seed phrases.

Real-World Examples

1. Fake Uniswap (2023): $8M stolen via fake swap interface 2. MetaMask Phishing (2022): Thousands of users lost funds to fake "verify wallet" pages 3. OpenSea Clone (2022): Users tricked into listing NFTs on fake marketplace 4. Ledger Phishing (2021): Fake firmware update emails led to seed phrase theft

Remember: In crypto, you are your own bank. There's no customer support to reverse fraudulent transactions. Once your private keys are compromised or you send funds to an attacker, they're gone forever.

Stay vigilant, verify everything, and when in doubt, don't click!

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

API Key Log Forensics

The Logging Vulnerability

Server logs are essential for debugging, monitoring, and security analysis. However, they can also become a massive security liability when sensitive information is accidentally logged.

Common Secrets Leaked in Logs:

  • API keys and access tokens
  • Private keys and wallet seeds
  • User passwords and session tokens
  • Database credentials
  • OAuth tokens and JWT secrets
  • Credit card numbers (PCI compliance violation)

The Problem: A single exposed API key buried in millions of log lines can lead to:

  • Complete system compromise
  • Data breaches affecting millions of users
  • Cryptocurrency wallet drains
  • Unauthorized access to cloud resources
  • Regulatory fines (GDPR, PCI-DSS violations)

Real-World Log Security Incidents

Uber (2016): Engineers stored AWS keys in private GitHub repo, which were then logged. Cost: $148M settlement.

Capital One (2019): Misconfigured logging exposed 100M customer records. Cost: $80M fine.

DeFi Protocol Exploit (2022): API key logged in error messages. Result: $3.6M stolen.

Docker Hub (2021): Authentication tokens exposed in container logs. Result: 190,000 accounts compromised.

The Scenario

You're a security analyst at a Web3 infrastructure company. Yesterday morning, attackers drained $500,000 from the company's hot wallet using an unauthorized API key.

Your job: Find the compromised API key that was accidentally logged during a security incident.

The challenge: The log file contains over 50,000 lines of mixed operational logs, errors, warnings, and debug messages from various services.

The grep Command: Searching Through Noise

grep is a powerful command-line tool for searching text using patterns.

Basic syntax:

hacker@dojo:~$ grep "pattern" filename.txt

Example:

hacker@dojo:~$ grep "ERROR" server.log
[2024-01-15 10:23:45] [ERROR] NetworkService: Connection timeout
[2024-01-15 10:24:12] [ERROR] APIGateway: Rate limit exceeded
[2024-01-15 10:25:33] [ERROR] WalletService: Transaction failed

Pipelining: Multi-Stage Filtering

The real power of grep comes from pipelining - chaining multiple grep commands together to progressively narrow down results.

Pipe symbol |: Sends output from one command as input to the next command.

Example - Three-stage filter:

hacker@dojo:~$ cat server.log | grep "ERROR" | grep "API" | grep "KEY"

How it works:

  1. cat server.log - Reads the entire file (50,000+ lines)
  2. | grep "ERROR" - Filters to only ERROR level logs (~500 lines)
  3. | grep "API" - Further filters to API-related errors (~50 lines)
  4. | grep "KEY" - Final filter for lines containing "KEY" (~1 line)

More efficient syntax (skip cat):

hacker@dojo:~$ grep "ERROR" server.log | grep "UNAUTHORIZED" | grep "API_KEY"

Log Levels Explained

DEBUG: Verbose developer information (usually too detailed)

  • Example: "Cache hit for key: wallet_balance_abc123"

INFO: General informational messages

  • Example: "Transaction added to pool: 0x1234..."

WARN: Warning messages that aren't errors yet

  • Example: "Rate limit approaching for IP: 192.168.1.1"

ERROR: Error events that need attention

  • Example: "Connection timeout to peer node"

CRITICAL: Severe errors requiring immediate action

  • Example: "Database connection pool exhausted"

Your Task

Run the logForensics command to generate the breach log file.

Then, use multi-stage grep pipelining to:

  1. Filter the 50,000+ line log to only ERROR entries
  2. Further filter to UNAUTHORIZED access attempts
  3. Finally, extract the line containing the compromised API_KEY

The flag is embedded in the API key value.

Hints

  1. The logForensics command will create a large log file for you
  2. Start by filtering for ERROR level logs
  3. The breach involved "UNAUTHORIZED" access
  4. Look for a line containing "API_KEY="
  5. Use pipes (|) to chain grep commands together
  6. Each stage should significantly reduce the number of lines

Commands You'll Need

# Count total lines in the log
wc -l ~/web3_server.log

# Filter for ERROR logs and count them
grep "ERROR" ~/web3_server.log | wc -l

# Three-stage pipeline to find the API key
grep "ERROR" ~/web3_server.log | grep "UNAUTHORIZED" | grep "API_KEY"

# Alternative: Use regex for more precise matching
grep -E "ERROR.*UNAUTHORIZED.*API_KEY" ~/web3_server.log

# Show line numbers with matches
grep -n "UNAUTHORIZED" ~/web3_server.log

# Case-insensitive search
grep -i "api_key" ~/web3_server.log

Advanced grep Options

grep -n: Show line numbers

hacker@dojo:~$ grep -n "ERROR" server.log
523:[2024-01-15 10:23:45] [ERROR] Connection timeout
1247:[2024-01-15 11:15:22] [ERROR] Invalid token

grep -i: Case-insensitive search

hacker@dojo:~$ grep -i "api" server.log
# Matches API, api, Api, etc.

grep -c: Count matching lines

hacker@dojo:~$ grep -c "ERROR" server.log
523

grep -v: Invert match (show lines that DON'T match)

hacker@dojo:~$ grep -v "DEBUG" server.log
# Show all logs except DEBUG level

grep -A 3: Show 3 lines AFTER match grep -B 3: Show 3 lines BEFORE match grep -C 3: Show 3 lines of context (before and after)

Production Log Security Best Practices

DO:

Log Sanitization:

  • Strip sensitive data before logging
  • Use placeholder values: API_KEY=***REDACTED***
  • Implement structured logging (JSON) with field filtering

Secure Storage:

  • Encrypt logs at rest
  • Restrict access with IAM policies
  • Use log aggregation services (ELK, Splunk, Datadog)
  • Implement log rotation and retention policies

Monitoring:

  • Set up alerts for suspicious patterns
  • Monitor for leaked credentials in logs
  • Scan logs for accidental PII exposure
  • Use automated secret scanning tools

DON'T:

  • Log full API keys, passwords, or private keys
  • Store logs in world-readable locations
  • Keep logs indefinitely without review
  • Log request/response bodies without sanitization
  • Include user PII in debug logs
  • Disable logging in production (you need it for security!)

Log Forensics Tools

For Local Analysis:

  • grep - Pattern matching (what we're using!)
  • awk - Text processing and filtering
  • sed - Stream editing and substitution
  • jq - JSON log parsing
  • cut, sort, uniq - Data manipulation

For Production:

  • ELK Stack (Elasticsearch, Logstash, Kibana) - Log aggregation and search
  • Splunk - Enterprise log management and SIEM
  • Datadog - Cloud monitoring and log analytics
  • AWS CloudWatch - AWS-native log management
  • Google Cloud Logging - GCP log aggregation
  • Grafana Loki - Open-source log aggregation

The Investigation Process

  1. Understand the incident: API key was used to drain hot wallet
  2. Identify the timeframe: Breach occurred yesterday morning
  3. Locate relevant logs: server.log contains all service logs
  4. Filter progressively: ERROR → UNAUTHORIZED → API_KEY
  5. Extract evidence: Find the exact API key used
  6. Report findings: Document the compromised credential

Security Lessons

Why was the API key logged?

  • Developer left debug logging enabled in production
  • Error handler printed full request context
  • Exception stack trace included environment variables
  • Middleware logged all API request headers

How to prevent this:

  • Use secret management services (Vault, AWS Secrets Manager)
  • Implement log sanitization middleware
  • Review all logging statements before deployment
  • Set up automated secret scanning (GitGuardian, TruffleHog)
  • Regular security audits of logging practices
  • Train developers on secure logging

Remember: Logs are permanent. Once a secret is logged, assume it's compromised. Rotate keys immediately, review access logs, and implement monitoring.

In production systems, security teams often scan logs retroactively for accidentally exposed secrets. This challenge simulates that real-world forensics workflow!

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

Basic Signature Validation

Digital Signatures in Web3

In cryptocurrency and blockchain systems, digital signatures are the fundamental mechanism that proves ownership and authorization. Every transaction you make with your crypto wallet is digitally signed with your private key.

What a digital signature proves:

  1. Authentication: The message was signed by the owner of the private key
  2. Integrity: The message wasn't altered after being signed
  3. Non-repudiation: The signer cannot deny having signed it

Without signatures, crypto wouldn't work - anyone could spend anyone else's funds!

How Digital Signatures Work

The Process

  1. Transaction Creation: You want to send 1 ETH to someone
  2. Hashing: The transaction data is hashed into a fixed-size digest
  3. Signing: Your private key encrypts the hash, creating a signature
  4. Broadcasting: Transaction + signature sent to the network
  5. Verification: Nodes use your public key to verify the signature

The Math (Simplified)

Ethereum uses ECDSA (Elliptic Curve Digital Signature Algorithm) with the secp256k1 curve:

  • Private Key: A random 256-bit number (keep secret!)
  • Public Key: Derived from private key using elliptic curve math
  • Wallet Address: Last 20 bytes of the Keccak-256 hash of the public key
  • Signature: 65 bytes (r, s, v values from ECDSA)

Ethereum Signature Format:

0x + 64 hex characters = 66 total characters
Example: 0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef12345678

Shell Scripting with Conditionals

For this challenge, we'll simulate signature validation using bash conditionals. Real validation uses cryptographic libraries, but the conditional logic pattern is the same.

Basic If/Then/Else Structure

#!/bin/bash

if [ condition ]; then
    # Code if condition is true
    echo "Condition met!"
else
    # Code if condition is false
    echo "Condition not met"
fi

Variable Assignment

# Read file content into a variable
CONTENT=$(cat filename.txt)

# Get character count
LENGTH=$(echo -n "$CONTENT" | wc -c)

# Command line arguments
FIRST_ARG=$1
SECOND_ARG=$2

Comparison Operators

Numeric Comparisons:

  • -eq → equal to
  • -ne → not equal to
  • -lt → less than
  • -le → less than or equal to
  • -gt → greater than
  • -ge → greater than or equal to

String Comparisons:

  • = → equal to
  • != → not equal to
  • -z → string is empty
  • -n → string is not empty

Examples:

if [ $NUMBER -eq 42 ]; then
    echo "The answer!"
fi

if [ "$STRING" = "hello" ]; then
    echo "Greeting found"
fi

if [ $COUNT -gt 100 ]; then
    echo "More than 100"
fi

The Challenge

In this challenge, you'll write a bash script that validates Ethereum signatures by checking their format.

The Scenario

You're building a transaction validator for a Web3 application. Before attempting cryptographic verification (which is expensive), you need to check if signatures have the correct format.

Valid Ethereum signatures must be exactly 66 characters:

  • 0x prefix (2 characters)
  • 64 hexadecimal characters

Your task: Write a validation script that:

  1. Reads a transaction file
  2. Reads a signature file (passed as argument)
  3. Counts the signature's characters
  4. Checks if it's exactly 66 characters
  5. Awards the flag if valid, shows error if invalid

Your Task

Run the signatureValidator command to set up the challenge files.

Then, write a bash script called validate.sh that implements the validation logic using if/then/else conditionals.

The flag will be awarded when your script correctly validates the signature format.

Files Provided

After running signatureValidator, you'll have:

  • transaction.txt - A JSON transaction object
  • valid_signature.txt - A properly formatted signature (66 chars)
  • invalid_signature.txt - An improperly formatted signature (wrong length)

Hints

  1. Use wc -c to count characters in a file
  2. Use echo -n "$VAR" | wc -c to count variable length
  3. Ethereum signatures are exactly 66 characters
  4. Use -eq for numeric equality in bash
  5. The script should accept a filename as its first argument ($1)
  6. Make your script executable with chmod +x validate.sh

Script Template

Here's the structure (you need to fill in the logic):

#!/bin/bash

# Read the transaction (for context)
TRANSACTION=$(cat ~/transaction.txt)

# Get signature filename from first argument
SIGNATURE_FILE=$1

# Read the signature content
SIGNATURE=$(cat "$SIGNATURE_FILE")

# Count signature length
SIG_LENGTH=$(echo -n "$SIGNATURE" | wc -c)

# Validate length
if [ $SIG_LENGTH -eq 66 ]; then
    echo "✓ Valid signature format!"
    echo "✓ Length correct: 66 characters"
    echo "✓ Transaction can proceed"
    # Award flag here
else
    echo "✗ Invalid signature format"
    echo "✗ Expected: 66 characters"
    echo "✗ Got: $SIG_LENGTH characters"
    echo "✗ Transaction rejected"
fi

Real-World Signature Verification

In production systems, signature verification involves cryptographic operations:

JavaScript (ethers.js)

const ethers = require('ethers');

// Message to sign
const message = "Transfer 1 ETH";

// Sign with private key
const wallet = new ethers.Wallet(privateKey);
const signature = await wallet.signMessage(message);

// Verify signature
const recoveredAddress = ethers.utils.verifyMessage(message, signature);
console.log(recoveredAddress === wallet.address); // true

Python (web3.py)

from eth_account import Account
from eth_account.messages import encode_defunct

# Message to sign
message = encode_defunct(text="Transfer 1 ETH")

# Sign with private key
signed_message = Account.sign_message(message, private_key)
signature = signed_message.signature.hex()

# Verify signature
recovered_address = Account.recover_message(message, signature=signature)
print(recovered_address == wallet_address)  # True

Solidity (Smart Contract)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SignatureVerifier {
    function verifySignature(
        bytes32 messageHash,
        bytes memory signature,
        address signer
    ) public pure returns (bool) {
        // Recover signer address from signature
        address recovered = recoverSigner(messageHash, signature);
        return recovered == signer;
    }

    function recoverSigner(
        bytes32 messageHash,
        bytes memory signature
    ) internal pure returns (address) {
        (bytes32 r, bytes32 s, uint8 v) = splitSignature(signature);
        return ecrecover(messageHash, v, r, s);
    }
}

Security Implications

Why signature validation matters:

Without Validation:

  • Malformed signatures could crash your app
  • Attackers could bypass authentication
  • Invalid transactions processed
  • Gas wasted on verification attempts

With Validation:

  • Early rejection of invalid signatures
  • Reduced computational cost
  • Better error messages for users
  • Protection against malformed input attacks

Real attacks prevented by validation:

  • Replay attacks: Reusing signatures on different chains
  • Signature malleability: Modifying signature values
  • Invalid parameter attacks: Crafted inputs to break verification
  • DoS attacks: Flooding with invalid signatures

Advanced Bash Scripting

File Tests

if [ -f filename.txt ]; then
    echo "File exists"
fi

if [ -r filename.txt ]; then
    echo "File is readable"
fi

if [ -x script.sh ]; then
    echo "File is executable"
fi

Logical Operators

# AND
if [ $AGE -gt 18 ] && [ $AGE -lt 65 ]; then
    echo "Working age"
fi

# OR
if [ $DAY = "Saturday" ] || [ $DAY = "Sunday" ]; then
    echo "Weekend!"
fi

# NOT
if [ ! -f temp.txt ]; then
    echo "Temp file doesn't exist"
fi

Case Statements

case $RESPONSE in
    yes|YES|y|Y)
        echo "Proceeding..."
        ;;
    no|NO|n|N)
        echo "Cancelled"
        ;;
    *)
        echo "Invalid response"
        ;;
esac

Testing Your Script

# Create your validation script
nano validate.sh

# Make it executable
chmod +x validate.sh

# Test with valid signature (should succeed)
./validate.sh ~/valid_signature.txt

# Test with invalid signature (should fail with error)
./validate.sh ~/invalid_signature.txt

Expected Outputs

Valid Signature:

✓ Valid signature format!
✓ Length correct: 66 characters
✓ Transaction can proceed
pwn{...your_flag...}

Invalid Signature:

✗ Invalid signature format
✗ Expected: 66 characters
✗ Got: 9 characters
✗ Transaction rejected

Security Best Practices

DO:

  • Always validate input before cryptographic operations
  • Check signature format (length, encoding, structure)
  • Verify signatures match expected addresses
  • Implement replay protection (nonces, chainID)
  • Use hardware wallets for signing high-value transactions
  • Test signature verification with known test vectors

DON'T:

  • Skip format validation ("it's probably fine")
  • Trust user-provided signatures without verification
  • Reuse signatures across different chains
  • Store private keys in code or environment variables
  • Implement your own cryptography (use audited libraries)

Remember: In Web3, signature verification is the only thing protecting your funds. Every transaction must be properly signed and verified. A single bypass could mean complete loss of funds with no recovery possible!

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

30-Day Scoreboard:

This scoreboard reflects solves for challenges in this module after the module launched in this dojo.

Rank Hacker Badges Score