130 lines
5.2 KiB
PowerShell
130 lines
5.2 KiB
PowerShell
# Recover local MySQL root from logs / admin-login-recovery; never print secrets.
|
|
$ErrorActionPreference = "Continue"
|
|
$mysql = "C:\yutongda\tools\mysql-8.0.39-winx64\bin\mysql.exe"
|
|
|
|
function Test-Root([string]$pass, [string[]]$hostArgs) {
|
|
if ([string]::IsNullOrWhiteSpace($pass)) { return $false }
|
|
$argList = @() + $hostArgs + @("-uroot","-p$pass","--connect-timeout=8","--batch","-N","-e","SELECT 1")
|
|
$out = & $mysql @argList 2>&1
|
|
$text = ($out | ForEach-Object { "$_" }) -join "`n"
|
|
if ($text -match "ERROR\s+\d+") { return $false }
|
|
$lines = $out | ForEach-Object { "$_".Trim() } | Where-Object { $_ -ne "" -and $_ -notmatch "Warning" }
|
|
return ($lines -contains "1")
|
|
}
|
|
|
|
Write-Output "=== admin-login-recovery files ==="
|
|
Get-ChildItem "C:\yutongda\secure\admin-login-recovery" -Recurse -EA SilentlyContinue |
|
|
ForEach-Object { $_.FullName }
|
|
|
|
Write-Output "=== e2e env keys ==="
|
|
$e2e = "C:\yutongda\secure\e2e-business-20260826-205407.env"
|
|
if (Test-Path $e2e) {
|
|
Get-Content $e2e | ForEach-Object { if ($_ -match '^([^=]+)=') { $matches[1] } }
|
|
}
|
|
|
|
Write-Output "=== collect candidate passwords from recovery (names only) ==="
|
|
$cands = New-Object System.Collections.Generic.List[object]
|
|
function Add-Cand([string]$src, [string]$pass) {
|
|
if ([string]::IsNullOrWhiteSpace($pass)) { return }
|
|
$pass = $pass.Trim().Trim("'").Trim('"')
|
|
if ($pass.Length -lt 4) { return }
|
|
$cands.Add([pscustomobject]@{ src = $src; pass = $pass; len = $pass.Length })
|
|
}
|
|
|
|
Get-ChildItem "C:\yutongda\secure\admin-login-recovery" -Recurse -File -EA SilentlyContinue | ForEach-Object {
|
|
$f = $_
|
|
Write-Output ("file=" + $f.Name + " size=" + $f.Length)
|
|
$raw = Get-Content $f.FullName -Raw -EA SilentlyContinue
|
|
if (-not $raw) { return }
|
|
if ($f.Extension -eq ".json") {
|
|
try {
|
|
$j = $raw | ConvertFrom-Json
|
|
foreach ($p in $j.PSObject.Properties) {
|
|
Write-Output (" key=" + $p.Name)
|
|
if ($p.Name -match '(?i)pass|secret|pwd|root' -and $p.Value -is [string]) {
|
|
Add-Cand ("recovery." + $f.Name + "." + $p.Name) ([string]$p.Value)
|
|
}
|
|
}
|
|
} catch {}
|
|
} else {
|
|
foreach ($line in ($raw -split "`r?`n")) {
|
|
if ($line -match '(?i)^(MYSQL_ROOT_PASSWORD|MYSQL_ROOT|ROOT_PASSWORD|password)\s*=\s*(.+)$') {
|
|
Add-Cand ("recovery." + $f.Name + "." + $Matches[1]) $Matches[2]
|
|
}
|
|
if ($line -match '(?i)temporary password is[^:]*:\s*(\S+)') {
|
|
Add-Cand ("recovery." + $f.Name + ".temp") $Matches[1]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# error log temporary passwords
|
|
Get-ChildItem "C:\yutongda\data\mysql" -Recurse -Include *.err,*.log,*.txt -EA SilentlyContinue |
|
|
ForEach-Object {
|
|
Write-Output ("logscan=" + $_.Name)
|
|
Select-String -Path $_.FullName -Pattern "temporary password|A temporary password for" -EA SilentlyContinue |
|
|
ForEach-Object {
|
|
if ($_.Line -match '(?i)temporary password[^\r\n]*?:\s*(\S+)') {
|
|
Add-Cand ("errlog." + $_.Filename) $Matches[1]
|
|
}
|
|
}
|
|
}
|
|
|
|
# also common install docs under ops
|
|
Get-ChildItem "C:\yutongda\ops" -Recurse -Include *.md,*.txt,*.env,*.ps1 -EA SilentlyContinue -Depth 4 |
|
|
Select-String -Pattern "MYSQL_ROOT|mysqld.*password|root@localhost" -EA SilentlyContinue |
|
|
Select-Object -First 30 |
|
|
ForEach-Object {
|
|
Write-Output ("ops_hit=" + $_.Filename + ":" + $_.LineNumber)
|
|
if ($_.Line -match '(?i)(MYSQL_ROOT_PASSWORD|password)\s*=\s*(\S+)') {
|
|
Add-Cand ("ops." + $_.Filename) $Matches[2]
|
|
}
|
|
if ($_.Line -match '(?i)temporary password[^\r\n]*?:\s*(\S+)') {
|
|
Add-Cand ("ops." + $_.Filename + ".temp") $Matches[1]
|
|
}
|
|
}
|
|
|
|
Write-Output ("candidates=" + $cands.Count)
|
|
$hostModes = @(
|
|
@{ n = "socket"; a = @() },
|
|
@{ n = "127"; a = @("-h127.0.0.1","-P3306") }
|
|
)
|
|
$hit = $null
|
|
foreach ($c in $cands) {
|
|
foreach ($h in $hostModes) {
|
|
if (Test-Root $c.pass $h.a) {
|
|
Write-Output ("HIT src=" + $c.src + " len=" + $c.len + " mode=" + $h.n)
|
|
$hit = $c
|
|
Set-Content "E:\wwwroot\ops\.mysql_root_stash.tmp" -Value $c.pass -Encoding ascii -NoNewline
|
|
Set-Content "E:\wwwroot\ops\.mysql_root_mode.txt" -Value $h.n -Encoding ascii
|
|
break
|
|
}
|
|
}
|
|
if ($hit) { break }
|
|
}
|
|
if (-not $hit) { Write-Output "NO_ROOT_HIT" }
|
|
|
|
Write-Output "=== two mysqld processes detail ==="
|
|
Get-CimInstance Win32_Process -Filter "Name='mysqld.exe'" | ForEach-Object {
|
|
# redact possible password in cmdline
|
|
$cmd = $_.CommandLine -replace '(?i)password[=\s]+\S+','password=***'
|
|
"pid=$($_.ProcessId) $cmd"
|
|
}
|
|
|
|
Write-Output "=== remote ytd_jeecg: can create? ==="
|
|
$dbCred = Get-Content "C:\yutongda\secure\application-database-credentials.json" -Raw | ConvertFrom-Json
|
|
$u = [string]$dbCred.mysql_username
|
|
$p = [string]$dbCred.mysql_password
|
|
$h = [string]$dbCred.mysql_host
|
|
$grants = & $mysql "-h$h" -P3306 "-u$u" "-p$p" --batch -e "SHOW GRANTS FOR CURRENT_USER()" 2>&1 | Out-String
|
|
($grants -split "`r?`n" | Where-Object { $_ -match "GRANT" }) | ForEach-Object { $_ }
|
|
$createTry = & $mysql "-h$h" -P3306 "-u$u" "-p$p" --batch -e "CREATE DATABASE IF NOT EXISTS inquiry_robot_probe_x" 2>&1 | Out-String
|
|
if ($createTry -match "ERROR") {
|
|
($createTry -split "`r?`n" | Where-Object { $_ -match "ERROR" } | Select-Object -First 1)
|
|
} else {
|
|
Write-Output "UNEXPECTED_CREATE_OK"
|
|
& $mysql "-h$h" -P3306 "-u$u" "-p$p" -e "DROP DATABASE IF EXISTS inquiry_robot_probe_x" 2>&1 | Out-Null
|
|
}
|
|
|
|
Write-Output "DONE"
|