mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-08-09 23:12:23 -04:00
CLI: add 'analyze' subcommand for offline HIBP breach checks
This new subcommand checks all passwords in the given database against a given list of SHA-1 password hashes. Such lists are available from the "Have I Been Pwned" project at https://haveibeenpwned.com/Passwords. Note that this support offline checking only. The HIBP project also provides a web API for checking specific hash ranges; this is not currently supported.
This commit is contained in:
parent
bb2d7bca5a
commit
0e0cba653f
19 changed files with 517 additions and 3 deletions
81
src/cli/Analyze.cpp
Normal file
81
src/cli/Analyze.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Analyze.h"
|
||||
#include "cli/Utils.h"
|
||||
#include "core/HibpOffline.h"
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QFile>
|
||||
#include <QString>
|
||||
|
||||
#include "cli/TextStream.h"
|
||||
#include "core/Group.h"
|
||||
#include "core/Tools.h"
|
||||
|
||||
const QCommandLineOption Analyze::HIBPDatabaseOption = QCommandLineOption(
|
||||
{"H", "hibp"},
|
||||
QObject::tr("Check if any passwords have been publicly leaked. FILENAME must be the path of a file listing "
|
||||
"SHA-1 hashes of leaked passwords in HIBP format, as available from "
|
||||
"https://haveibeenpwned.com/Passwords."),
|
||||
QObject::tr("FILENAME"));
|
||||
|
||||
Analyze::Analyze()
|
||||
{
|
||||
name = QString("analyze");
|
||||
description = QObject::tr("Analyze passwords for weaknesses and problems.");
|
||||
options.append(Analyze::HIBPDatabaseOption);
|
||||
}
|
||||
|
||||
int Analyze::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<QCommandLineParser> parser)
|
||||
{
|
||||
TextStream inputTextStream(Utils::STDIN, QIODevice::ReadOnly);
|
||||
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
|
||||
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
|
||||
|
||||
QString hibpDatabase = parser->value(Analyze::HIBPDatabaseOption);
|
||||
QFile hibpFile(hibpDatabase);
|
||||
if (!hibpFile.open(QFile::ReadOnly)) {
|
||||
errorTextStream << QObject::tr("Failed to open HIBP file %1: %2").arg(hibpDatabase).arg(hibpFile.errorString()) << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
outputTextStream << QObject::tr("Evaluating database entries against HIBP file, this will take a while...");
|
||||
|
||||
QList<QPair<const Entry*, int>> findings;
|
||||
QString error;
|
||||
if (!HibpOffline::report(database, hibpFile, findings, &error)) {
|
||||
errorTextStream << error << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
for (auto& finding : findings) {
|
||||
printHibpFinding(finding.first, finding.second, outputTextStream);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void Analyze::printHibpFinding(const Entry* entry, int count, QTextStream& out)
|
||||
{
|
||||
QString path = entry->title();
|
||||
for (auto g = entry->group(); g && g != g->database()->rootGroup(); g = g->parentGroup()) {
|
||||
path.prepend("/").prepend(g->name());
|
||||
}
|
||||
|
||||
out << QObject::tr("Password for '%1' has been leaked %2 times!").arg(path).arg(count) << endl;
|
||||
}
|
35
src/cli/Analyze.h
Normal file
35
src/cli/Analyze.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef KEEPASSXC_ANALYZE_H
|
||||
#define KEEPASSXC_ANALYZE_H
|
||||
|
||||
#include "DatabaseCommand.h"
|
||||
|
||||
class Analyze : public DatabaseCommand
|
||||
{
|
||||
public:
|
||||
Analyze();
|
||||
int executeWithDatabase(QSharedPointer<Database> db, QSharedPointer<QCommandLineParser> parser) override;
|
||||
|
||||
static const QCommandLineOption HIBPDatabaseOption;
|
||||
|
||||
private:
|
||||
void printHibpFinding(const Entry* entry, int count, QTextStream& out);
|
||||
};
|
||||
|
||||
#endif // KEEPASSXC_HIBP_H
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
set(cli_SOURCES
|
||||
Add.cpp
|
||||
Analyze.cpp
|
||||
Clip.cpp
|
||||
Create.cpp
|
||||
Command.cpp
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "Command.h"
|
||||
|
||||
#include "Add.h"
|
||||
#include "Analyze.h"
|
||||
#include "Clip.h"
|
||||
#include "Create.h"
|
||||
#include "Diceware.h"
|
||||
|
@ -107,6 +108,7 @@ void populateCommands()
|
|||
{
|
||||
if (commands.isEmpty()) {
|
||||
commands.insert(QString("add"), new Add());
|
||||
commands.insert(QString("analyze"), new Analyze());
|
||||
commands.insert(QString("clip"), new Clip());
|
||||
commands.insert(QString("create"), new Create());
|
||||
commands.insert(QString("diceware"), new Diceware());
|
||||
|
|
|
@ -16,6 +16,9 @@ keepassxc-cli \- command line interface for the \fBKeePassXC\fP password manager
|
|||
.IP "add [options] <database> <entry>"
|
||||
Adds a new entry to a database. A password can be generated (\fI-g\fP option), or a prompt can be displayed to input the password (\fI-p\fP option).
|
||||
|
||||
.IP "analyze [options] <database>"
|
||||
Analyze passwords in a database for weaknesses.
|
||||
|
||||
.IP "clip [options] <database> <entry> [timeout]"
|
||||
Copies the password or the current TOTP (\fI-t\fP option) of a database entry to the clipboard. If multiple entries with the same name exist in different groups, only the password for the first one is going to be copied. For copying the password of an entry in a specific group, the group path to the entry should be specified as well, instead of just the name. Optionally, a timeout in seconds can be specified to automatically clear the clipboard.
|
||||
|
||||
|
@ -120,6 +123,16 @@ Specify the title of the entry.
|
|||
Perform advanced analysis on the password.
|
||||
|
||||
|
||||
.SS "Analyze options"
|
||||
|
||||
.IP "-H, --hibp <filename>"
|
||||
Check if any passwords have been publicly leaked, by comparing against the given
|
||||
list of password SHA-1 hashes, which must be in "Have I Been Pwned" format. Such
|
||||
files are available from https://haveibeenpwned.com/Passwords; note that they
|
||||
are large, and so this operation typically takes some time (minutes up to an
|
||||
hour or so).
|
||||
|
||||
|
||||
.SS "Clip options"
|
||||
|
||||
.IP "-t, --totp"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue