mirror of
https://github.com/emanuele-f/PCAPdroid.git
synced 2026-06-16 21:10:57 +08:00
2nd-level domain rules now match all subdomains
A rule like "example.com" is now interpreted as "*.example.com", so it will match all its sub-domains (e.g. "yet.another.example.com"). This is importantant, in particular, to match malware subdomains.
This commit is contained in:
parent
667a9b6e39
commit
bc5589d2e1
@ -797,7 +797,7 @@ public class Utils {
|
||||
}
|
||||
|
||||
// a.example.org -> example.org
|
||||
public static String getRootDomain(String domain) {
|
||||
public static String getSecondLevelDomain(String domain) {
|
||||
int tldPos = domain.lastIndexOf(".");
|
||||
|
||||
if(tldPos <= 0)
|
||||
|
||||
@ -351,11 +351,17 @@ public class ConnectionsFragment extends Fragment implements ConnectionsListener
|
||||
item.setVisible(true);
|
||||
|
||||
String dm_clean = Utils.cleanDomain(conn.info);
|
||||
String rootDomain = Utils.getRootDomain(dm_clean);
|
||||
String rootDomain = Utils.getSecondLevelDomain(dm_clean);
|
||||
|
||||
if(!rootDomain.equals(dm_clean)) {
|
||||
item = menu.findItem(R.id.hide_root_domain);
|
||||
item.setTitle(Utils.shorten(MatchList.getRuleLabel(ctx, RuleType.ROOT_DOMAIN, rootDomain), max_length));
|
||||
label = Utils.shorten(MatchList.getRuleLabel(ctx, RuleType.HOST, rootDomain), max_length);
|
||||
|
||||
item = menu.findItem(R.id.hide_domain);
|
||||
item.setTitle(label);
|
||||
item.setVisible(true);
|
||||
|
||||
item = menu.findItem(R.id.block_domain);
|
||||
item.setTitle(label);
|
||||
item.setVisible(true);
|
||||
}
|
||||
|
||||
@ -426,8 +432,8 @@ public class ConnectionsFragment extends Fragment implements ConnectionsListener
|
||||
} else if(id == R.id.hide_proto) {
|
||||
mAdapter.mMask.addProto(conn.l7proto);
|
||||
mask_changed = true;
|
||||
} else if(id == R.id.hide_root_domain) {
|
||||
mAdapter.mMask.addRootDomain(Utils.getRootDomain(conn.info));
|
||||
} else if(id == R.id.hide_domain) {
|
||||
mAdapter.mMask.addHost(Utils.getSecondLevelDomain(conn.info));
|
||||
mask_changed = true;
|
||||
} else if(id == R.id.hide_country) {
|
||||
mAdapter.mMask.addCountry(conn.country);
|
||||
@ -459,6 +465,9 @@ public class ConnectionsFragment extends Fragment implements ConnectionsListener
|
||||
} else if(id == R.id.block_host) {
|
||||
blocklist.addHost(conn.info);
|
||||
blocklist_changed = true;
|
||||
} else if(id == R.id.block_domain) {
|
||||
blocklist.addHost(Utils.getSecondLevelDomain(conn.info));
|
||||
blocklist_changed = true;
|
||||
} else if(id == R.id.open_app_details) {
|
||||
Intent intent = new Intent(requireContext(), AppDetailsActivity.class);
|
||||
intent.putExtra(AppDetailsActivity.APP_UID_EXTRA, conn.uid);
|
||||
|
||||
@ -66,7 +66,6 @@ public class MatchList {
|
||||
APP,
|
||||
IP,
|
||||
HOST,
|
||||
ROOT_DOMAIN,
|
||||
PROTOCOL,
|
||||
COUNTRY
|
||||
}
|
||||
@ -146,7 +145,6 @@ public class MatchList {
|
||||
switch(tp) {
|
||||
case APP: resid = R.string.app_val; break;
|
||||
case IP: resid = R.string.ip_address_val; break;
|
||||
case ROOT_DOMAIN: value = "*" + value; // fallthrough
|
||||
case HOST: resid = R.string.host_val; break;
|
||||
case PROTOCOL: resid = R.string.protocol_val; break;
|
||||
case COUNTRY: resid = R.string.country_val; break;
|
||||
@ -196,18 +194,24 @@ public class MatchList {
|
||||
|
||||
for(JsonElement el: ruleArray) {
|
||||
JsonObject ruleObj = el.getAsJsonObject();
|
||||
String typeStr = ruleObj.get("type").getAsString();
|
||||
String val = ruleObj.get("value").getAsString();
|
||||
RuleType type;
|
||||
|
||||
try {
|
||||
type = RuleType.valueOf(ruleObj.get("type").getAsString());
|
||||
type = RuleType.valueOf(typeStr);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// can happen if format is changed, ignore
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
// can happen if format is changed
|
||||
if(typeStr.equals("ROOT_DOMAIN")) {
|
||||
Log.i(TAG, String.format("ROOT_DOMAIN %s migrated", val));
|
||||
type = RuleType.HOST;
|
||||
mFormatMigration = true;
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
String val = ruleObj.get("value").getAsString();
|
||||
|
||||
// Handle migration from old uid-based format
|
||||
if(type == RuleType.APP) {
|
||||
try {
|
||||
@ -241,7 +245,6 @@ public class MatchList {
|
||||
public void addIp(String ip) { addRule(new Rule(RuleType.IP, ip)); }
|
||||
public void addHost(String info) { addRule(new Rule(RuleType.HOST, Utils.cleanDomain(info))); }
|
||||
public void addProto(String proto) { addRule(new Rule(RuleType.PROTOCOL, proto)); }
|
||||
public void addRootDomain(String domain) { addRule(new Rule(RuleType.ROOT_DOMAIN, domain)); }
|
||||
public void addCountry(String country_code) { addRule(new Rule(RuleType.COUNTRY, country_code)); }
|
||||
|
||||
public void addApp(int uid) {
|
||||
@ -325,11 +328,16 @@ public class MatchList {
|
||||
}
|
||||
|
||||
public boolean matchesHost(String host) {
|
||||
return mMatches.containsKey(matchKey(RuleType.HOST, Utils.cleanDomain(host)));
|
||||
}
|
||||
// Keep in sync with the native blacklist_match_domain
|
||||
host = Utils.cleanDomain(host);
|
||||
|
||||
public boolean matchesRootDomain(String root_domain) {
|
||||
return mMatches.containsKey(matchKey(RuleType.ROOT_DOMAIN, root_domain));
|
||||
// exact domain match
|
||||
if(mMatches.containsKey(matchKey(RuleType.HOST, host)))
|
||||
return true;
|
||||
|
||||
// 2nd-level domain match
|
||||
String domain = Utils.getSecondLevelDomain(host);
|
||||
return !domain.equals(host) && mMatches.containsKey(matchKey(RuleType.HOST, domain));
|
||||
}
|
||||
|
||||
public boolean matchesCountry(String country_code) {
|
||||
@ -345,8 +353,7 @@ public class MatchList {
|
||||
matchesIP(conn.dst_ip) ||
|
||||
matchesProto(conn.l7proto) ||
|
||||
matchesCountry(conn.country) ||
|
||||
(hasInfo && matchesHost(conn.info))) ||
|
||||
(hasInfo && matchesRootDomain(Utils.getRootDomain(conn.info)));
|
||||
(hasInfo && matchesHost(conn.info)));
|
||||
}
|
||||
|
||||
public Iterator<Rule> iterRules() {
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
* Copyright 2020-21 - Emanuele Faranda
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <string.h>
|
||||
#include "pcapdroid.h"
|
||||
#include "common/utils.h"
|
||||
|
||||
@ -265,14 +267,41 @@ bool blacklist_match_ipstr(blacklist_t *bl, const char *ip_str) {
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
static char* get_second_level_domain(const char *domain) {
|
||||
char *dot = (char*) memrchr(domain, '.', strlen(domain));
|
||||
if(!dot || (dot == domain))
|
||||
return (char*)domain;
|
||||
|
||||
dot = (char*) memrchr(domain, '.', dot - domain);
|
||||
if(!dot)
|
||||
return (char*)domain;
|
||||
|
||||
return dot + 1;
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
bool blacklist_match_domain(blacklist_t *bl, const char *domain) {
|
||||
// Keep in sync with MatchList.matchesHost
|
||||
string_entry_t *entry = NULL;
|
||||
|
||||
if(strncmp(domain, "www.", 4) == 0)
|
||||
domain += 4;
|
||||
|
||||
// exact domain match
|
||||
HASH_FIND_STR(bl->domains, domain, entry);
|
||||
return(entry != NULL);
|
||||
if(entry != NULL)
|
||||
return true;
|
||||
|
||||
// 2nd-level domain match
|
||||
char *domain2 = get_second_level_domain(domain);
|
||||
if(domain2 != domain) {
|
||||
HASH_FIND_STR(bl->domains, domain2, entry);
|
||||
if(entry != NULL)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
@ -34,7 +34,8 @@ static void test_match() {
|
||||
|
||||
// Use blacklist
|
||||
assert1(blacklist_match_domain(bl, "www.example.org"));
|
||||
//assert1(blacklist_match_domain(bl, "some.example.org")); // TODO support subdomains matching
|
||||
assert1(blacklist_match_domain(bl, "some.example.org"));
|
||||
assert1(blacklist_match_domain(bl, "evil.some.example.org"));
|
||||
|
||||
assert0(blacklist_match_ipstr(bl, "1.2.3.0"));
|
||||
assert1(blacklist_match_ipstr(bl, "1.2.3.4"));
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
android:visible="false" />
|
||||
|
||||
<item
|
||||
android:id="@+id/hide_root_domain"
|
||||
android:id="@+id/hide_domain"
|
||||
android:title=""
|
||||
tools:title="@string/host_val"
|
||||
android:visible="false" />
|
||||
@ -59,6 +59,12 @@
|
||||
android:id="@+id/block_host"
|
||||
android:title=""
|
||||
tools:title="@string/host_val" />
|
||||
|
||||
<item
|
||||
android:id="@+id/block_domain"
|
||||
android:title=""
|
||||
tools:title="@string/host_val"
|
||||
android:visible="false" />
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user