Open cbiere opened 5 days ago
I've looked at database/src/main/java/com/kunzisoft/keepass/database/search/SearchHelper.kt and this check is really bad:
stringToCheck.endsWith("/$word", !searchParameters.caseSensitive)
If I have the following URL in my KeePass database: https://www.example.com/login.sh
It will match on https://login.sh/. This isn't only wrong but if the path can be registered as a domain, it can be used for phishing. In a LAN this might even work with just a hostname (e.g. http://login/ or http://signin).
I agree, it's not ideal at all. The problem, as I said, is to use an algorithm that doesn't take time to search. I'd already tried accent searching and it caused ANRs. I'm afraid it'll do the same thing with URL objects. I'll give it a try anyway.
I'll add unit tests to handle all cases. If anyone sees anything missing, don't hesitate to tell me.
Unit tests :
fun testBuildURL() {
val expected = "domain.org"
assertTrue(expected.inTheSameDomainAs("domain.org", sameSubDomain = false))
assertTrue(expected.inTheSameDomainAs("http://domain.org", sameSubDomain = false))
assertTrue(expected.inTheSameDomainAs("https://domain.org", sameSubDomain = false))
assertTrue(expected.inTheSameDomainAs("domain.org/login", sameSubDomain = false))
assertTrue(expected.inTheSameDomainAs("http://domain.org/login", sameSubDomain = false))
assertTrue(expected.inTheSameDomainAs("https://domain.org/login", sameSubDomain = false))
assertTrue(expected.inTheSameDomainAs("https://www.domain.org", sameSubDomain = false))
assertTrue(expected.inTheSameDomainAs("www.domain.org", sameSubDomain = false))
assertTrue(expected.inTheSameDomainAs("ww.domain.org", sameSubDomain = false))
assertTrue(expected.inTheSameDomainAs("domain.org", sameSubDomain = true))
assertTrue(expected.inTheSameDomainAs("http://domain.org", sameSubDomain = true))
assertTrue(expected.inTheSameDomainAs("https://domain.org", sameSubDomain = true))
assertTrue(expected.inTheSameDomainAs("domain.org/login", sameSubDomain = true))
assertTrue(expected.inTheSameDomainAs("http://domain.org/login", sameSubDomain = true))
assertTrue(expected.inTheSameDomainAs("https://domain.org/login", sameSubDomain = true))
assertFalse(expected.inTheSameDomainAs("https://www.domain.org", sameSubDomain = true))
assertFalse(expected.inTheSameDomainAs("www.domain.org", sameSubDomain = true))
assertFalse(expected.inTheSameDomainAs("ww.domain.org", sameSubDomain = true))
assertFalse(expected.inTheSameDomainAs("domain.com", sameSubDomain = false))
assertFalse(expected.inTheSameDomainAs("omain.org", sameSubDomain = false))
assertFalse(expected.inTheSameDomainAs("odomain.org", sameSubDomain = false))
assertFalse(expected.inTheSameDomainAs("tcp://domain.org", sameSubDomain = false))
assertFalse(expected.inTheSameDomainAs("domain.com", sameSubDomain = true))
assertFalse(expected.inTheSameDomainAs("omain.org", sameSubDomain = true))
assertFalse(expected.inTheSameDomainAs("odomain.org", sameSubDomain = true))
assertFalse(expected.inTheSameDomainAs("tcp://domain.org", sameSubDomain = true))
}
I don't know how to write code in Kotlin, but maybe I can provide some pseudocode:
// stringtomatch contains the URL from each entry the database // word is the hostname to search in the database
// extract the hostname from the URL hostname = stringtomatch.replace("^([a-z]+://)([^/]+)(/.*)?$", $2) // compare the extracted hostname, case-insensitive if (hostname.equals(word, true)) return true
// if enabled, check if hostname is a subdomain of word domain = "." + word if (searchsubdomain && hostname.endswith(domain) return true
If a regular expression is too expensive, the hostname can simply be extracted by removing everything up to the first "://" sequence and then everything after the first slash of the remaining sequence.
As for unit tests I would recommend adding the following checks:
assertFalse(expected.inTheSameDomainAs("https://example.com/domain.org", sameSubDomain = true)) assertFalse(expected.inTheSameDomainAs("https://example.com/www.domain.org", sameSubDomain = false))
Describe the bug
Autofill sugggestions are not matched to existing entries anymore, if the URL in the database includes any path after the hostname. This used to work fine until 4.0.8.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Step 3 should not be necessary, if you have the login URL in your KeePass database entry.
KeePass Database
content://
URI): content://com.android.externalstorage.documents/document/primaryKeePassDX:
Android:
Additional context
If you change the URL to https://github.com without any path in your KeePass database or add another URL item to it (URL_1), the problem can be worked around.
This issue results from the changes to fix #1820.