top of page

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

How To Permanently Wipe A Solid-State Drive (SSD) / Hard Disk Drive (HDD) | Black Hat HQ

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 irreversible

ATA 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 byte

NVMe 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 erase

Software 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/sda

Verification


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 zeroed

SSDs - Critical Warning


NEVER use multi-pass overwrite (shred/dd multiple passes) on SSDs. It:


  1. Doesn't work reliably — wear leveling and over-provisioning mean you can't reach all flash cells

  2. Reduces drive life — burns through write endurance for no benefit

  3. 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 — instant

Physical 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"

Enroll In Online Cybersecurity & Hacking Classes/Courses | Black Hat HQ

Comments


bottom of page