Redacting passwords. #40
Replies: 3 comments
-
I've been pondering this problem for sometime now and I've tried different approaches. I've not had enormous success finding an efficient way to detect passwords. That's where this package originally comes from, at my previous job I had developers accidentally logging pretty sensitive stuff including passwords through a CMS/CRM internal system. Long story short, detecting passwords without any context is difficult. My leading theory is to grab all the different regexs that are used to verify password rules are followed that most applications use when someone is creating a password. Doing this and having some sort of probability calculation based on how many of the password regex rules are passed. All this would require another strategy class to process it all within the actual regex checker when providing content to be analyzed. |
Beta Was this translation helpful? Give feedback.
-
imho in general - password can be anything - cannot be redacted as long as it's not wrapped withing some predictable structure, |
Beta Was this translation helpful? Give feedback.
-
I'm playing with a strategy since the discussion was opened up to use multiple regex patterns to detect potential passwords where each pattern is assigned a weight. By running a piece of content through each strategy detection handler and seeing what patterns hit, using the weighted value from each hit pattern and divide it out by the total available weight. I can come up with a rough probability that there MAY (very very vague all be it) possibly that the piece of content contains a password. Using a configurable threshold I can set the threshold up to around 70-80% before it alerts on a detection. With some refining around the different handler patterns & weights, this may be fruitful and worth implementing into the package. I got a working prototype working last night & got a basic functionality test passing. /**
/**
* @dataProvider passwordDataProvider
*/
public function test_it_can_detect_passwords_with_different_thresholds($password, $expectedResult, $threshold)
{
$this->strategy->overrideProbabilityThreshold($threshold);
$passwordDetection = $this->strategy->detect($password);
$this->assertEquals($expectedResult, $passwordDetection->isThresholdExceeded());
$this->assertIsFloat($passwordDetection->getProbability());
$this->assertIsFloat($passwordDetection->getThreshold());
}
public function passwordDataProvider()
{
return [
// content, expected detection, threshold to set
// Basic/Weak Passwords
['password', false, 0.50],
['123456', false, 0.50],
['qwerty', false, 0.50],
['12345678', false, 0.50],
['abc123', true, 0.50],
['letmein', false, 0.50],
['admin', false, 0.50],
['111111', false, 0.50],
['1234567890', false, 0.50],
['password123', true, 0.50],
// Medium/Moderate Passwords
['P@ssw0rd', true, 0.75],
['Summer2022', true, 0.75],
['iloveyou123', true, 0.75],
['football', false, 0.75],
['welcome1', true, 0.75],
['123abc', true, 0.75],
['mypassword', false, 0.75],
['sunshine', false, 0.75],
['987654321', false, 0.75],
['admin123', true, 0.75],
// Advanced/Strong Passwords
['xY9@#4rBc$^qZ2!', true, 0.70],
['Tr1ckyP@$$w0rd', true, 0.70],
['securePass789!', true, 0.70],
['2fA!w$5XnYz', true, 0.70],
['P@55w0rdStr0ng!', true, 0.80],
['C0mpl3x_Pa$$w0rd', true, 0.80],
['9S@!mR#7nPtZ3', true, 0.80],
['StrongP@ssw0rd', true, 0.80],
['D1ff1cultP@$$', true, 0.80],
['Secure123$Pwd!', true, 0.80],
// Super Complex Advanced Passwords
['r23pPd#7mS9&!k1z', true, 0.80],
['5@nTrF!dC8#jP3*x', true, 0.80]
];
} With all that being said, here are some issues I found. The detection still works when the password is nested into an array or LogReport, however, since it's using multiple patterns to detect and the patterns are not all the same, it makes it very difficult to be used to redact just the specific piece of content instead of the entire array or LogReport. Need to find a way to concat and coherently generate a mega pattern that can be used to redact just the specific piece of content instead of the entire array or LogReport. The only way I see without generating a mega pattern is to just redact the entire piece of content. Which is what I end up doing with Here is summary of patterns I used to experiment with:
The meat and potato's of the detection strategy public function detect(string $content): PasswordDetection
{
$probability = 0;
$handlers = new Collection();
$this->getHandlers()->each(function(PasswordDetectionHandlerContract $handler) use($content, &$probability, &$handlers){
if($this->checkPattern($handler->getPattern(), $content) > 0) {
$handlers->push($handler);
$probability += $handler->getWeight();
}
});
$distributedProbability = $this->distributeProbabilityByHandlers($probability);
return new PasswordDetection(
$distributedProbability,
$this->probabilityThreshold,
$this->prepareRedactionPattern($content),
$handlers,
$this->isProbabilityExceeded($distributedProbability),
);
}
private function distributeProbabilityByHandlers(float $probability): float
{
$handlerCount = $this->getHandlers()->count();
if ($handlerCount > 0) {
return $probability / $this->getProbabilityMaxWeight();
}
return 0.00;
}
private function prepareRedactionPattern(string $content): string
{
return addcslashes($content, '!@#$%^&*()-=_+');
}
private function checkPattern(string $pattern, string $content): int
{
return $this->regexRepository::check($pattern, $content);
}
private function isProbabilityExceeded(float $probability): bool
{
return $this->probabilityThreshold < $probability;
} Would like to get some thoughts on this approach before I do anything more with it. |
Beta Was this translation helpful? Give feedback.
-
More like a brainstorming about the possibility to redact passwords.
This is the regex I tried using
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\s]).{8,}$
.The problem I encountered is that almost everything could be a password. For example: [email protected]. Therefore I ended up with pretty useless logs.
The ugly workaround I did was this. Basically looking is what I'm trying to log has the "password" key. But yes... I couldn't come out with anything better just yet.
Beta Was this translation helpful? Give feedback.
All reactions