How To Permanently Wipe A Solid-State Drive (SSD) / Hard Disk Drive (HDD)
- Biohazard

- Jul 17
- 6 min read

Erasing Data Permanently From A SSD / HDD
Here's the complete methodology for permanent HDD/SSD sanitization. This is a(n) article / guide on how to permanently wipe a SSD / HDD.
Standards (Quick Reference)
Standard | Passes | Method | Use Case |
NIST 800-88 (Clear) | 1 | Single overwrite with fixed value | Modern HDDs — sufficient |
NIST 800-88 (Purge) | N/A | ATA Secure Erase / crypto erase | SSDs, SEDs |
DoD 5220.22-M | 3 | 0x00 → 0xFF → random | Legacy compliance (older drives) |
Gutmann | 35 | Complex patterns | Obsolete — never use |
ATA Secure Erase | Internal | Drive firmware command | Best for SSDs |
NVMe Format | Internal | NVMe sanitize command | Best for NVMe |
Physical Destruction | 1 | Shredder, drill, incinerator | Highest assurance |
Identify The Target Drive First
bash
# List all block devices
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,MODEL,SERIAL
fdisk -l
ls -la /dev/disk/by-id/
# CRITICAL: Verify you have the RIGHT drive
# Every command below is irreversibleATA Secure Erase (Recommended - HDD & SSD)
The firmware-level command that tells the drive to wipe itself. Fast, complete, and handles bad sectors that software overwrite misses.
Find the Drive
bash
# List drives
lsblk
# Check if Secure Erase is supported
hdparm -I /dev/sda | grep -i "security"
# Look for:
# Security:
# Master password revision code = 65534
# supported
# enabled ← means frozen/locked
# not locked
# not frozen
# not expired: security count
Unfreeze the Drive
Most modern systems freeze the drive at boot for safety. You need to unfreeze it:
bash
# Option 1: Suspend/resume cycle (works on most laptops/desktops)
echo -n mem > /sys/power/state
# System sleeps — press power button to wake
# Drive is now unfrozen
hdparm -I /dev/sda | grep frozen
# Should say: "not frozen"
# Option 2: If suspend doesn't work, hotplug the drive
# Disconnect SATA power cable, reconnect, retry
# Option 3: Boot from USB, set kernel parameter
# Add to kernel boot line: libata.allow_tpm=1
Execute Secure Erase
bash
# Set a temporary password
hdparm --user-master u --security-set-pass Eins /dev/sda
# Password: "Eins" (can be anything — it's temporary)
# Verify password was set
hdparm -I /dev/sda | grep "enabled"
# Should show: enabled
# Execute Secure Erase
time hdparm --user-master u --security-erase Eins /dev/sda
# This can take seconds to minutes depending on drive size
# Enhanced Secure Erase (writes manufacturer-specific patterns)
time hdparm --user-master u --security-erase-enhanced Eins /dev/sda
# Verify drive is blank
hdparm -I /dev/sda | grep "enabled"
# Should show: not enabled (password cleared automatically after erase)
hexdump -C /dev/sda | head -50
# Should show all zeros or repeating byteNVMe Secure Erase (NVMe Drives)
NVMe drives use a different command set:
bash
# Install nvme-cli
sudo apt install nvme-cli -y
# List NVMe drives
nvme list
# Check sanitize support
nvme id-ctrl /dev/nvme0 | grep -i sanitize
# Format NVM (equivalent to Secure Erase)
nvme format /dev/nvme0 -s 1 -n 0xffffffff
# -s 1 = user data erase
# -s 2 = cryptographic erase (for SEDs — near-instant)
# -n 0xffffffff = format all namespaces
# Cryptographic Erase (fastest — for self-encrypting drives)
nvme format /dev/nvme0 -s 2
# Full Sanitize (most thorough, takes longest)
nvme sanitize /dev/nvme0 -a 2
# -a 1 = overwrite
# -a 2 = block erase
# -a 3 = cryptographic eraseSoftware Overwrite (Shred / dd / Wipe)
Use when firmware commands aren't available or you want visible proof of overwrite.
Single Pass (NIST 800-88 Clear — Modern Drives)
bash
# dd — single pass zero
dd if=/dev/zero of=/dev/sda bs=4M status=progress
# Modern HDDs: single pass is adequate for all practical purposes
# Guttman 35-pass is obsolete and unnecessary on modern drives
# Confirm
dd if=/dev/sda bs=4M count=10 | hexdump -C
Three Pass (DoD 5220.22-M Equivalent)
bash
# Pass 1: Zeros
dd if=/dev/zero of=/dev/sda bs=4M status=progress
# Pass 2: Ones (0xFF)
dd if=/dev/urandom of=/dev/sda bs=4M count=1
# Actually: tr '\0' '\377' < /dev/zero | dd of=/dev/sda bs=4M status=progress
# Simpler:
dd if=<(yes $'\377' | tr -d '\n') of=/dev/sda bs=4M status=progress
# Pass 3: Random
dd if=/dev/urandom of=/dev/sda bs=4M status=progress
shred (Single Command, Multi-Pass)
bash
# 3 passes + final zero overwrite
shred -vfz -n 3 /dev/sda
# -v = verbose (show progress)
# -f = force (change permissions if needed)
# -z = final zero pass (hides that shred was used)
# -n 3 = 3 random passes before the zero pass
# Warning: shred is NOT effective on SSDs due to wear leveling
# Use ATA Secure Erase or NVMe Format for SSDs
wipe (Advanced)
bash
sudo apt install wipe -y
# Single pass random
wipe -q /dev/sda
# Quick random + verify
wipe -q -Q 1 /dev/sda
# Paranoid (4x random, slower)
wipe -q -x 4 /dev/sdaVerification
Always verify the wipe was successful:
bash
# Method 1: Sample random sectors (fast)
for i in $(seq 1 20); do
OFFSET=$((RANDOM % $(blockdev --getsz /dev/sda) * 512))
dd if=/dev/sda bs=1 count=512 skip=$OFFSET 2>/dev/null | hexdump -C | head -3
done
# Method 2: Check first and last sectors
dd if=/dev/sda bs=512 count=1 2>/dev/null | hexdump -C # MBR area
dd if=/dev/sda bs=512 skip=$(($(blockdev --getsz /dev/sda)-1)) count=1 2>/dev/null | hexdump -C
# Method 3: Statistical sample
badblocks -sv /dev/sda
# If fully zeroed, should show "0 bad blocks" AND scan clean
# Method 4: Forensic check
# Look for any non-zero bytes
dd if=/dev/sda bs=4M 2>/dev/null | tr -d '\0' | head -c 1024
# If output is empty → drive is fully zeroedSSDs - Critical Warning
NEVER use multi-pass overwrite (shred/dd multiple passes) on SSDs. It:
Doesn't work reliably — wear leveling and over-provisioning mean you can't reach all flash cells
Reduces drive life — burns through write endurance for no benefit
Gives false confidence — data may survive in over-provisioned blocks
Always use ATA Secure Erase or NVMe Format for SSDs:
bash
# For SATA SSD:
hdparm --security-erase Eins /dev/sda
# For NVMe SSD:
nvme format /dev/nvme0 -s 1
# For self-encrypting SSDs (fastest, most secure):
nvme format /dev/nvme0 -s 2 # Crypto erase — instantPhysical Destruction
When the drive must be physically destroyed:
bash
# Method 1: Industrial shredder (best)
# Requires access to an e-waste shredder
# Method 2: Drill press
# Drill 3+ holes through the platters (HDD)
# Drill through NAND chips (SSD)
# Method 3: Hydraulic press / hammer
# Destroys platters and controller board
# Method 4: Incinerator
# 800+ °C destroys all magnetic media
# Method 5: Degausser
# Only effective on magnetic HDDs
# Does NOT work on SSDs (flash storage is immune)Reporting & Chain Of Custody
markdown
## Asset Disposal Verification Report
### Device Information
- Serial Number: 5XZ8K123
- Model: Seagate ST2000DM008 (2TB HDD)
- Hostname: FIN-DEPT-07
- Asset Tag: CORP-004721
### Sanitization Method
- Standard: NIST SP 800-88 Rev 1 (Purge)
- Method: ATA Enhanced Secure Erase (firmware command)
- Command: hdparm --user-master u --security-erase-enhanced Eins /dev/sda
- Duration: 4 minutes 12 seconds
### Verification
- Method: Statistical sampling (100 random sectors)
- Result: All sectors zero-filled
- Verified by: [Name], [Date/Time]
### Disposition
- [ ] Return to inventory
- [ ] Physical destruction
- [ ] Donation/recycling
- [ ] Other: _______________
### Sign-Off
Performed by: ________________ Date: __________
Witnessed by: ________________ Date: __________Full Automation Script
bash
#!/bin/bash
# secure_wipe.sh — automated disk sanitization for pentest
DRIVE="$1"
METHOD="${2:-ata-secure}"
if [ -z "$DRIVE" ]; then
echo "Usage: $0 /dev/sdX [ata-secure|nvme|crypto|dod|nist|verify]"
echo ""
echo "Methods:"
echo " ata-secure ATA Secure Erase (HDD/SSD)"
echo " nvme NVMe Format"
echo " crypto Cryptographic erase (instant, SED only)"
echo " dod 3-pass DoD 5220.22-M"
echo " nist 1-pass NIST 800-88 Clear"
echo " verify Verify drive is blank (no wipe)"
exit 1
fi
echo "=== DISK SANITIZATION ==="
echo "Drive: $DRIVE"
echo "Method: $METHOD"
echo ""
# Capture drive info before wipe
echo "[*] Capturing drive information..."
lsblk -o NAME,SIZE,MODEL,SERIAL "$DRIVE" | grep -v NAME
hdparm -I "$DRIVE" 2>/dev/null | grep -E "Model|Serial|Firmware" > "/tmp/wipe_${DRIVE##*/}_info.txt"
cat "/tmp/wipe_${DRIVE##*/}_info.txt"
echo ""
echo "WARNING: This will IRREVERSIBLY destroy all data on $DRIVE"
read -p "Type the drive name (e.g., sda) to confirm: " CONFIRM
if [ "$CONFIRM" != "${DRIVE##*/}" ]; then
echo "Confirmation failed. Exiting."
exit 1
fi
case "$METHOD" in
ata-secure)
echo "[*] Unfreezing drive..."
echo -n mem > /sys/power/state 2>/dev/null || true
echo "[*] Setting temporary password..."
hdparm --user-master u --security-set-pass Eins "$DRIVE"
echo "[*] Executing Enhanced Secure Erase..."
time hdparm --user-master u --security-erase-enhanced Eins "$DRIVE"
echo "[*] Verifying..."
hdparm -I "$DRIVE" | grep "not.*enabled" && echo "[+] Password cleared"
;;
nvme)
echo "[*] Executing NVMe Format (user data erase)..."
time nvme format "${DRIVE}" -s 1
;;
crypto)
echo "[*] Executing cryptographic erase..."
nvme format "${DRIVE}" -s 2 2>/dev/null || \
hdparm --user-master u --security-erase-enhanced Eins "$DRIVE"
;;
dod)
echo "[*] DoD 5220.22-M 3-pass wipe..."
echo " Pass 1/3: Zeros"
dd if=/dev/zero of="$DRIVE" bs=4M status=progress 2>/dev/null
echo " Pass 2/3: 0xFF"
tr '\0' '\377' < /dev/zero | dd of="$DRIVE" bs=4M status=progress 2>/dev/null
echo " Pass 3/3: Random"
dd if=/dev/urandom of="$DRIVE" bs=4M status=progress 2>/dev/null
;;
nist)
echo "[*] NIST 800-88 Clear (single pass zeros)..."
dd if=/dev/zero of="$DRIVE" bs=4M status=progress
;;
verify)
echo "[*] Verification only..."
;;
esac
# Verify
echo ""
echo "[*] Verifying sanitization..."
SAMPLE_SIZE=50
for i in $(seq 1 $SAMPLE_SIZE); do
OFFSET=$((RANDOM % $(blockdev --getsz "$DRIVE" 2>/dev/null || echo 1) * 512))
DATA=$(dd if="$DRIVE" bs=1 count=512 skip=$OFFSET 2>/dev/null | tr -d '\0')
if [ -n "$DATA" ]; then
echo "[!] Non-zero data found at offset $OFFSET"
dd if="$DRIVE" bs=1 count=64 skip=$OFFSET 2>/dev/null | hexdump -C | head -3
fi
done
echo ""
echo "=== SANITIZATION COMPLETE ==="
echo "Drive: $DRIVE"
echo "Method: $METHOD"
echo "Date: $(date)"
echo "Samples checked: $SAMPLE_SIZE"
echo "Info saved: /tmp/wipe_${DRIVE##*/}_info.txt"





Comments