From 970af03c09cb992ae65346fca5de442732a46756 Mon Sep 17 00:00:00 2001 From: Felix Steghofer Date: Thu, 1 Feb 2018 01:40:07 +0100 Subject: [PATCH] rush hour 3 --- Thesis/bibliography.bib | 41 ++++++++--- .../Abuse_of_Domain_Names.tex | 10 +-- Thesis/content/Conclusion/Conclusion.tex | 5 +- .../Development_of_DoresA.tex | 68 ++++++++++-------- .../doresa_example_tree_root.png | Bin 0 -> 20902 bytes .../Evaluation_of_existing_Systems.tex | 4 +- .../Exposure/Exposure.tex | 14 ++-- .../Kopis/Kopis.tex | 29 ++++---- .../Notos/Notos.tex | 28 ++++---- Thesis/content/Introduction/Introduction.tex | 10 +-- .../content/Technical_Background/DNS/DNS.tex | 54 +++++++------- .../Detecting_Malicious_Domain_Names.tex | 2 - .../Technical_Background.tex | 8 +-- Thesis/content/abstract.tex | 3 +- Thesis/glossar.tex | 43 +++-------- Thesis/main.tex | 17 ++--- Thesis/meta.tex | 2 +- Thesis/packages.tex | 22 +++--- 18 files changed, 183 insertions(+), 177 deletions(-) create mode 100644 Thesis/content/Development_of_DoresA/doresa_example_tree_root.png diff --git a/Thesis/bibliography.bib b/Thesis/bibliography.bib index c4d1d5d..d130f16 100644 --- a/Thesis/bibliography.bib +++ b/Thesis/bibliography.bib @@ -147,8 +147,7 @@ month = {May}, organization = {theguardian}, publisher = {theguardian}, - title = {{'Accidental hero' halts ransomware attack and warns: this is not over}}, - url = {https://www.theguardian.com/technology/2017/may/13/accidental-hero-finds-kill-switch-to-stop-spread-of-ransomware-cyber-attack}, + title = {The Guardian - 'Accidental hero' halts ransomware attack and warns: this is not over}, year = 2017 } @@ -167,8 +166,7 @@ month = {September}, organization = {DELL SecureWorks Counter Threat Unit}, publisher = {DELL CTU}, - title = {{2016 Underground Hacker Marketplace Report}}, - url = {https://www.secureworks.com/resources/rp-2016-underground-hacker-marketplace-report}, + title = {{Secureworks - 2016 Underground Hacker Marketplace Report}}, year = 2016 } @@ -262,7 +260,7 @@ } @misc{SBLOnline, - author={The Spamhaus Project, Ltd}, + author={Spamhaus}, title={{The Spamhaus Block List}}, month=dec, year={2017}, @@ -321,7 +319,7 @@ title={{scikit-learn - Decision Trees}}, month=jan, year={2018}, - howpublished={\url{http://scikit-learn.org/stable/modules/tree.html#tree-algorithms-id3-c4-5-c5-0-and-cart}} + howpublished={\url{http://scikit-learn.org/stable/modules/tree.html\#tree-algorithms-id3-c4-5-c5-0-and-cart}} } @misc{DENICOnline, @@ -342,7 +340,7 @@ @misc{WannaCryTwitterOnline, author={Darien Huss}, - title={{WannaCry propagation payload contains previously unregistered domain}}, + title={WannaCry propagation payload contains previously unregistered domain}, month=jan, year={2018}, howpublished={\url{https://twitter.com/darienhuss/status/863083680528576512}} @@ -350,12 +348,35 @@ @misc{WhyDGOWinsOnline, author={LITAL ASHER-DOTAN}, - title={{THE FBI VS. GAMEOVER ZEUS: WHY THE DGA-BASED BOTNET WINS}}, - month=jan, - year={2018}, + title={THE FBI VS. GAMEOVER ZEUS: WHY THE DGA-BASED BOTNET WINS}, + month=dec, + year={2017}, howpublished={\url{https://www.cybereason.com/blog/the-fbi-vs-gameover-zeus-why-the-dga-based-botnet-wins}} } +@misc{IDNOnline, + author={ICANN}, + title={{Internationalized Domain Names}}, + month=feb, + year={2012}, + howpublished={\url{https://www.icann.org/resources/pages/idn-2012-02-25-en}} +} + + +@Article{Salzberg1994, +author="Salzberg, Steven L.", +title="C4.5: Programs for Machine Learning by J. Ross Quinlan. Morgan Kaufmann Publishers, Inc., 1993", +journal="Machine Learning", +year="1994", +month="Sep", +day="01", +volume="16", +number="3", +pages="235--240", +issn="1573-0565", +doi="10.1007/BF00993309", +url="https://doi.org/10.1007/BF00993309" +} @inproceedings{Stone-Gross:2009:YBM:1653662.1653738, author = {Stone-Gross, Brett and Cova, Marco and Cavallaro, Lorenzo and Gilbert, Bob and Szydlowski, Martin and Kemmerer, Richard and Kruegel, Christopher and Vigna, Giovanni}, diff --git a/Thesis/content/Abuse_of_Domain_Names/Abuse_of_Domain_Names.tex b/Thesis/content/Abuse_of_Domain_Names/Abuse_of_Domain_Names.tex index de84b79..319d217 100644 --- a/Thesis/content/Abuse_of_Domain_Names/Abuse_of_Domain_Names.tex +++ b/Thesis/content/Abuse_of_Domain_Names/Abuse_of_Domain_Names.tex @@ -1,21 +1,21 @@ \chapter{Abusive use of Domain Names} \label{cha:abuse_of_domain_names} -The \gls{dns} makes it easy to browse the internet with human readable domain names. It adds an extra layer on top of TCP/IP that allows administrators to reliably maintain services, especially for large applications which are served by many servers in different locations. Using techniques like round robin, where the DNS server has a list of available servers and rotationally returns clients one of those servers, \gls{dns} enables efficient use of multiple machines, decreases access time for different users and enhances availability if single nodes in the machine cluster fail (by removing failing servers from the round robin rotation). Although this leads to the described advantages it can also be used by malicious applications. In this work three major types of domain name misuses are taken into account, malware, Phishing and Botnets. +The Domain Name System (DNS) makes it easy to browse the internet with human readable domain names. It adds an extra layer on top of TCP/IP that allows administrators to reliably maintain services, especially for large applications which are served by many servers in different locations. Using techniques like round robin, where the DNS server has a list of available servers and rotationally returns clients one of those servers, DNS enables efficient use of multiple machines, decreases access time for different users and enhances availability if single nodes in the machine cluster fail (by removing failing servers from the round robin rotation). Although this leads to the described advantages, it can also be used by malicious applications. In this work three major types of domain name misuses are taken into account: general \textit{Malware}, \textit{Phishing} and \textit{Botnets}. \section{Malware} \label{sec:malware} -On May 12th 2017, British security researchers discovered malware which was spreading massively at the time, especially in central Europe. After successful attack the ``WannaCry'' called malware encrypted files and pretended that the only solution to get back the decrypted files was to pay an amount of about \$ 300 in a cryptocurrency. This a popular case of a so called ransomware. Ransomware in general is a type of malicious software that threatens to publish the victim's data or blocks access to it unless a ransom is paid. Researchers quickly discovered a request that was made by the malware to an unregistered domain. The purpose of the very long nonsensical domain name (\texttt{iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com}) was not known at the time one of the researchers (\fsAuthor{WannaCryTwitterOnline}) registered it. Afterwards Huss registered many thousands of requests every second to this domain. After more investigations it was clear that the domain was acting as a kill switch for the ransomware and by registering the domain, further spreading could be slowed down \fsCite{theguardiancom_wannacry}. +On May 12th 2017, British security researchers discovered malware which was spreading massively at the time, especially in central Europe. After successfully attacking a target, the ``WannaCry'' called malware encrypted files and pretended that the only solution to get back the decrypted files was to pay an amount of about \$ 300 in a cryptocurrency. This is one popular case of a so called ransomware. Ransomware in general is a type of malicious software that threatens to publish the victim's data or blocks access to it unless a ransom is paid. Researchers quickly discovered a request to an unregistered domain that was made by ``WannaCry''. The purpose of the very long nonsensical domain name (\texttt{iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com}) was not known at the time one of the researchers (\fsAuthor{WannaCryTwitterOnline}) registered it. Afterwards Huss registered many thousands of requests every second to this domain. After more investigations it was clear that the domain was acting as a kill switch for the ransomware and by registering the domain, further spreading could be slowed down \fsCite{theguardiancom_wannacry}. -This case shows an example of how domains can be used by attackers to control their malware. Usually domains are more often used to connect to command and control servers or to communicate with other infected machines (see Section~\ref{sec:botnets} for an). To infect a machine, attackers often use so called \textit{droppers} or \textit{injectors} that do not ship the malicious code at first but are little programs to download further source code or binaries containing the harmful functionality. It is much easier for malware authors to use domains for this purpose instead of hard coding the IP addresses for many reasons: If machines that serve the down-loadable content are e.g. confiscated by the police or taken down for other reasons, domains can simply be pointed to a different servers' IP address to maintain the malicious service. Reliable endpoints are also used to maintain the malicious software and load additional code. Domains do generally have three advantages for malware authors over IP addresses, they are much more cheaper (few cents a year compared to at least \$ 10), the efforts to point a domain to a new IP address are much lower than assigning a new IP to a machine and finally it is much faster. This follows that attackers can build a pool of many domains and to compensate for take downs of some domain names. This could change when IPv6 is widely adopted (with IPv6 addresses being much cheaper) but according to statistics of Google, only about 20\% of worldwide users accessing google where IPv6 enabled (natively or using IPv6 to IPv4 bridges) \fsCite{googlecom_ipv6adoption}. This prevents the usage of IPv6 as the primary protocol in malware for obvious reasons. +This case shows an example of how domains can be used by attackers to control their malware. Usually domains are more often used to connect to command and control servers or to communicate with other infected machines (see Section~\ref{sec:botnets} for more details on botnets). To infect a machine, attackers often use so called \textit{droppers} or \textit{injectors} that do not ship the malicious code at first but are little programs to download further source code or binaries containing the harmful functionality. It is much easier for malware authors to use domains for this purpose instead of hard coding the IP addresses for many reasons: If machines that serve the downloadable content are taken down e.g. confiscated by the police, domains can simply be pointed to a different servers' IP address to maintain the malicious service. Reliable endpoints are also used to control (C\&C) the malicious software and load additional code. Domains do generally have three advantages for malware authors over IP addresses: they are much more cheaper (few cents a year compared to at least \$ 10), the efforts (e.g. in terms of configuration) to point a domain to a new IP address are much lower than assigning a new IP to a machine and another advantage is that it is much faster to change domain names compared to IP addresses. This follows that attackers can quickly build a pool of many domains to compensate for take downs of some of those domain names. This could change when IPv6 is widely adopted (with IPv6 addresses being much cheaper) but according to statistics of Google, only about 20\% of worldwide users accessing google are IPv6 ready (natively or using IPv6 to IPv4 bridges) \fsCite{googlecom_ipv6adoption}. This prevents the usage of IPv6 as the primary protocol in malware for obvious reasons. \section{Phishing} \label{sec:phishing} -Phishing describes malicious activities where attackers try to steal private information from internet users which are mostly used to gain financial benefit from (\fsCite{6151979}). There are various different types of phishing attacks that have been identified. Starting long before emails and the world wide web had significant popularity, criminals used social engineering on phones to trick users into handing over private personal and financial information. This method is known as vishing (Voice phishing). In the mid 90s, AOL was the number one provider of Internet access and the first big target of phishing activities like it is known today. At the time, people from the warez community used phishing to get passwords for AOL accounts. By impersonating AOL employees in instant messengers as well as email conversations they could obtain free internet access or financially harm people using their credit card information. With the success of the world wide web including the movement of more financial services to the internet, criminals used another approach to trick users. By registering domains that look very much like a benign service and imitating the appearance of the corresponding benign website many internet users unknowingly put their banking credentials into fake sites and suffer financial harm (also known as cybersquatting or domaine squatting). Those credentials may be sold on black markets e.g. in the dark web and can worth up to 5\% of the balance for online banking credentials according to the SecureWorks Counter Threat Unit \fsCite{rp-2016-underground-hacker-marketplace-report}. +Phishing describes malicious activities where attackers try to steal private information from internet users which are mostly used to gain financial benefit from (\fsCite{6151979}). There are various different types of phishing attacks that have been identified. Starting long before emails and the world wide web having significant popularity, criminals used social engineering on phones to trick users into handing over private personal and financial information. This method is known as vishing (Voice phishing). In the mid 90s, AOL was the number one provider of Internet access and the first big target of phishing activities like it is known today. At the time, people from the warez community used phishing to get passwords for AOL accounts. By impersonating AOL employees in instant messengers as well as email conversations they could obtain free internet access or financially harm people using their credit card information. With the success of the world wide web including the movement of more financial services to the internet, criminals used another approach to trick users. By registering domains that look very much like a benign service and imitating the appearance of the corresponding benign website, many internet users unknowingly put their banking credentials into fake sites and suffered financial harm (also known as cybersquatting or domaine squatting). Those credentials may be sold on black markets e.g. in the dark web and can worth up to 5\% of the balance for online banking credentials according to the SecureWorks Counter Threat Unit \fsCite{rp-2016-underground-hacker-marketplace-report}. @@ -29,4 +29,4 @@ To understand how botnets can be detected, mainly considering how botnets make u \subsection{Fast-Flux service networks} \label{subsec:fast-flux_service_networks} -Fast-Flux service network is a technique, for example often used to serve illegal web pages or in botnets (\fsCite{nazario2008net}), to hide the actual location of core components like command and control servers (C\&C servers is used as an example here). Using DNS round robin which helps e.g. legitimate services to reduce downtimes when a single node fails, command and control servers are hidden behind groups of bots which are acting as proxies and are accessible by a domain name. As botnets usually contain a large number of bots, these proxies can quickly be changed and leave no trace back to the actual C\&C server. To be able to quickly change the hiding proxy, the time to live of the domain names to those proxies has to be set to a low value. This is one characteristic that can be used to distinguish legitimate from malicious services. Domain-Flux networks are the successor of Fast-Flux service networks and in addition do use dynamic domains for the proxies. Domain-Flux networks use changing domain names for the proxies that hide the location of core components in the botnet. For this method to work properly, all bots in the botnet do have to know under which domain the C\&C server is reachable. To be able to communicate with the C\&C server, the bot first generates the currently valid domain name (e.g. based on time) and afterwards is able to send data through the proxy to the command and control server. Some examples for malware that uses DGAs are the Srizbi botnet, the Conficker worm and the GameOver Zeus botnet. One major difference of algorithmically generated domains in contrast to legitimate domains is that they usually contain more numbers and fewer/no human readable words. +Fast-Flux service network is a technique often used to serve illegal web pages or used in botnets to hide the actual location of core components like command and control servers (\fsCite{nazario2008net}). Using DNS round robin, which helps e.g. legitimate services to reduce downtimes when a single node fails, command and control servers are hidden behind groups of bots which are acting as proxies and are accessible by a domain name. As botnets usually contain a large number of bots, these proxies can quickly be changed and leave no trace back to the actual C\&C server. To be able to quickly change the hiding proxy, the time to live (TTL, see Section~\ref{sec:DNS}) of the domain names to those proxies has to be set to a low value. This is one characteristic that can be used to distinguish legitimate from malicious services. Domain-Flux networks are the successor of Fast-Flux service networks. Compared to Fast-Flux networks, Domain-Flux networks additionally use changing domain names for the proxies that hide the location of core components in the botnet. For this method to work properly, all bots in the botnet do have to know under which domain the C\&C server is reachable. To be able to communicate with the C\&C server, the bot first has to generates the currently valid domain name (e.g. based on time) and is then able to send data through the proxy to the command and control server. Some examples for malware that uses DGAs are the Srizbi botnet, the Conficker worm and the GameOver Zeus botnet. One major difference of algorithmically generated domains in contrast to legitimate domains is that they usually contain more numbers and fewer/no human readable words. diff --git a/Thesis/content/Conclusion/Conclusion.tex b/Thesis/content/Conclusion/Conclusion.tex index fe561b0..31e46c3 100644 --- a/Thesis/content/Conclusion/Conclusion.tex +++ b/Thesis/content/Conclusion/Conclusion.tex @@ -1,6 +1,7 @@ \chapter{Conclusion} \label{cha:conclusion} -All existing machine learning systems show a promising accuracy in detecting malicious domains with different feature sets. This shows that such system can effectively detect domains that are involved in a variety of malicious activities like, botnets, phishing and spam-campaigns. The three most popular systems that have been published, \textit{Notos}, \textit{Exposure} and \textit{Kopis} are however either hard to deploy and/or require a lot of manual work to get started and can generally be seen more like academic prototypes than mature products. +All evaluated machine learning systems show high detection rates and low false rates in detecting domains that are involved in malicious activities like, botnets, phishing and spam-campaigns with a variety of different features. The three most popular systems that have been proposed, \textit{Notos}, \textit{Exposure} and \textit{Kopis} are however either hard to deploy and/or require a lot of manual work to get started and can generally be seen more like research prototypes than mature products. + +In this work, a dynamic reputation system (\textit{DoresA}) has been implemented by combining different aspects of the previously evaluated systems. Most aspects have been adopted from one system \textit{Exposure}, mostly due to its simplicity while maintaining similar detection rates and because the passive DNS data that has been available for this work showed most similarities to the data that was used in that system. To test \textit{DoresA}, a model with a total of 1 million data samples has been trained using a decision tree learning algorithm. The characteristics of the DNS resource usage, especially how often the TTL value for a domain is changed, has shown be useful to distinguish between malicious and benign domains. In the time of writing this thesis, no evaluation of the implemented algorithm could be finished. Future work can use this implementation and investigate the accuracy of this approach. Furthermore, built on top of this work, a monitoring system can be realized to proactively warn of requests to domains, involved in malicious activities. To the best of my knowledge, no system that can easily be deployed to networks exists, neither commercial or non-commercial. A dynamic domain reputation system could be run in addition to traditional malware detection software and shows advantages, especially in the discovery of unknown malware with a lightweight approach using a passive DNS database. -In the time of writing this thesis, no evaluation of the implemented algorithm could be finished. Future work can use this implementation and investigate the accuracy of this approach. Furthermore, built on top of this work, a monitoring system can be realized to proactively warn of requests to domains, involved in malicious activities. To the best of my knowledge, no system that can easily be deployed to networks exists, neither commercial or non-commercial. diff --git a/Thesis/content/Development_of_DoresA/Development_of_DoresA.tex b/Thesis/content/Development_of_DoresA/Development_of_DoresA.tex index 6f2e75b..8262ae5 100644 --- a/Thesis/content/Development_of_DoresA/Development_of_DoresA.tex +++ b/Thesis/content/Development_of_DoresA/Development_of_DoresA.tex @@ -1,12 +1,12 @@ \chapter{Development of DoresA} \label{cha:development_of_doresa} -The last part of this work the development of a dynamic domain reputation system, \textit{DoresA} (or Domain reputation scoring Algoriothm). A lot of concepts for this system will be adopted from the previously evaluated systems, most concepts will be taken from \textit{Exposure} with some general ideas of \textit{Notos} and \textit{Kopis}. In general, there are some limitations to be taken into account which arise mostly by the specific type of data that is available for this work and where it has been monitored. The passive DNS logs that have been provided for this work have been collected on three recursive DNS servers in a large company in locations in Europe, Asia and the United States. As those logs do contain sensitive data, raw logs used in this work can not be published mostly due to privacy reasons. It also has to be noted, that the DNS requests are not available for this work for the same reason. +The last part of this work describes the development of a dynamic domain reputation system, \textit{DoresA} (or Domain reputation scoring Algorithm). A lot of concepts for this system will be adopted from the previously evaluated systems, most concepts will be taken from \textit{Exposure} with some general ideas of \textit{Notos} and \textit{Kopis}. In general, there are some limitations to be taken into account which arise mostly by the specific type of data that is available for this work and where it has been monitored. The passive DNS logs that have been provided for this work have been collected on three recursive DNS servers in a large company network in locations in Europe, Asia and the United States. As those logs do contain sensitive data, raw logs used in this work can not be published mostly due to privacy reasons. It also has to be noted that the DNS requests are not available for this work for the same reason. \section{Initial Situation and Goals} \label{sec:initial_situation_and_goals} -Ultimately, this work should come up with an algorithm to find domains that are involved in malicious activities. Most of the latest approached work has been working with machine learning techniques to build domain reputation scoring algorithms. As those publications have generally shown promising results (see Section~\ref{cha:evaluation_of_existing_systems}), this work is also focusing on a dynamic approach with machine learning algorithms involved. The network, in which the logs for this work have been collected is different from most ISP or other public networks. There is a lot of effort made to keep the network malware-free. This includes both software solutions (like anti-virus software and firewalls) as well as a team that proactively and reactively monitors and removes malware. Another defensive task is to train the employees to be aware of current and upcoming threats (e.g., to pay attention on hyperlinks in emails, distrust public usb sticks and physical access guidelines). Although this should lead to a mostly malware free network with few requests to malicious domains, 2017 has shown to be the year of ransomware (see Section~\ref{sec:malware}). Private internet users and companies have been infected with malware that was encrypting their data and requiring the target to pay an amount of money to decrypt it. There are of course other ongoing threats that have existed for many years, like spam campaigns (\fsCite{TrendMicroOnline}). The particular task in this work is to discover whether a dynamic reputation system for domains is useful and applicable under this circumstances. The ultimate goal (not part of this work) is an automated warning system that triggers when a malicious domain is requested. +Ultimately, this work should come up with an algorithm to find domains that are involved in malicious activities. Most of the latest approached work has been working with machine learning techniques to build domain reputation scoring algorithms. As those publications have generally shown promising results (see Section~\ref{cha:evaluation_of_existing_systems}), this work is also focusing on a dynamic approach with machine learning algorithms involved. The network, in which logs used for analysis and the development of the new algorithm, have been collected, is different from most ISP or other public networks. There is a lot of effort made to keep the network malware-free. This includes both software solutions (like anti-virus software and firewalls) as well as a team that proactively and reactively monitors and removes malware. Another defensive task is to train the employees to be aware of current and upcoming threats (e.g., to pay attention on hyperlinks in emails, distrust public usb sticks and physical access guidelines). Although this should lead to a mostly malware free environment (in this particular and similarly hardened networks) with few requests to malicious domains, 2017 has shown to be the year of ransomware (see Section~\ref{sec:malware}). Companies as well as private internet users have been infected with malware that was encrypting their data and requiring the target to pay an amount of money to decrypt it. There are of course other ongoing threats that have existed for many years, like spam campaigns (\fsCite{TrendMicroOnline}). The task in this work is to discover whether a dynamic reputation system for domains is useful and applicable under these circumstances. The ultimate goal (not part of this work) is an automated warning system that triggers when a malicious domain is requested. \section{System Architecture} @@ -16,8 +16,8 @@ The overall system will take an similar approach which was first introduced by \ \begin{itemize} \item \textit{Malware Prevention through Domain Blocking} list from malwaredomains.com which is an professionally maintained list with domains involved in malicious activities like the distribution of malware and spyware (\fsCite{malwaredomainsInformationOnline}). \item \textit{Phishtank}: A list that targets domains that are engaged in spam activities (\fsCite{PhishtankInformationOnline}). - \item \textit{ZeuS Tracker}: Blocking list for domains and IP addresses involved in the ZeuS botnet as command and control (C\&C)servers. - \item \textit{Alexa} with a list of the most popular domains in various countries as well as a global overview (total of 2000 domains). + \item \textit{ZeuS Tracker}: Blocking list for domains and IP addresses involved in the ZeuS botnet as command and control (C\&C) servers. + \item \textit{Alexa} with a list of the most popular domains from a global perspective (total of 2000 domains). \end{itemize} \begin{figure}[!htbp] @@ -28,63 +28,71 @@ The overall system will take an similar approach which was first introduced by \ \end{figure} -The malicious domains list from those three services consisted of 28367 individual entries when first collected. This information is later used to label benign and malicious domains in the training process. The \textit{Malicious/Benign Domains Collector} can be rerun at any time to keep up with known malicious and benign domains at a later stage and increase the accuracy of \textit{DoresA}. The second module, \textit{Data Aggregation Module} is collecting all passive DNS logs and persisting those. The \textit{Data Aggregation Module} is also responsible for extracting and persisting all feature values that are needed in the training step and such consumed by the \textit{Training Module}. This \textit{Training Module}'s primary concern is to learn a model that holds information about resource usage of certain DNS responses as well as labeling those data samples. Due to the limitation of available time, the training period has been reduced to three days (starting from the first of september in 2017) and for simplicity has been reduced to 1 million samples (which have been chosen randomly over the three days). The training model thus consisted of a total of 1 million DNS responses and included resolutions for \textit{how many individual domains} individual domains. The accuracy of this model can be also be increased by retraining the model e.v. once a day or week to keep up with new characteristics of malicious usage. This training model can then be used in the last module, the \textit{Classification Module}, to classify resolutions (feature vector) of unlabeled domains. The \textit{Classification Module} could e.g. be used to act as a real-time warning system when deployed in a network. +The malicious domains list from those three services consisted of 28367 individual entries when first collected. This information is later used to label benign and malicious domains in the training process. The \textit{Malicious/Benign Domains Collector} can be rerun at any time to keep up with known malicious and benign domains at a later stage and thus increase the accuracy of \textit{DoresA}. The second module, \textit{Data Aggregation Module} is collecting all passive DNS logs and persisting those. The \textit{Data Aggregation Module} is also responsible for extracting and persisting all feature values that are needed in the training step and such consumed by the \textit{Training Module}. This \textit{Training Module}'s primary concern is to learn a model that holds information about resource usage of certain DNS responses as well as labeling those data samples. Due to the limitation of available time, the training period has been reduced to three days (starting from the first of september in 2017) and for simplicity has been reduced to 1 million samples (which have been chosen randomly over the three days). The accuracy of this model can be also be increased by retraining the model e.g. once a week to keep up with new characteristics of malicious usage. This training model can then be used in the last module, the \textit{Classification Module}, to classify resolutions (feature vector) of unlabeled domains. The \textit{Classification Module} could e.g. be used to act as a real-time warning system when deployed on a resolver. -The logs that are provided have been collected in different locations all over the world and are aggregated on a single machine as csv files. As operating on the raw csv logs in the training step has shown to be very inefficient (with roughly one week of training time for one day), especially when performing multiple analysis cycles, a different solution for accessing the logs had to be found. Experimenting with putting the raw passive DNS logs into a NoSQL database (MongoDB \fsCite{MongoDBOnline}) as well as a relational database (MariaDB \fsCite{MariaDBOnline}) did not show a significant decrease in accessing the data so a slightly different approach has been used. By using an in-memory database (redis \fsCite{RedisOnline}) and only keeping those information, that are needed for the analysis has shown to give much better results, e.g. one day for the training of 1 million samples. It has to be stated though that while retaining most of the needed information, information like the timestamp of individual requests could not be kept. The following attributes are stored inside the redis instance. +The logs that are provided have been collected in different locations all over the world and are aggregated on a single machine as csv files. As operating on the raw csv logs in the training step has shown to be very inefficient (with roughly one week of training time for one day), especially when performing multiple analysis cycles, a different solution for accessing the logs had to be found. Experimenting with putting the raw passive DNS logs into a NoSQL database (MongoDB \fsCite{MongoDBOnline}) as well as a relational database (MariaDB \fsCite{MariaDBOnline}) did not show a significant decrease in accessing the data so a slightly different approach has been used. By using an in-memory database (Redis \fsCite{RedisOnline}) and only keeping information that are needed for the analysis has shown to give much better results: for a training set with 1 million samples, the execution time could be reduced to two day. It has to be stated though that while retaining most of the needed information, aspects like the timestamp of individual requests could not be kept. As the time patterns of single requests could not be used for the classification anyway, due to caching in lower hierarchies, this has not shown to be a problem. The following attributes are stored inside the Redis instance. \begin{itemize} - \item \textbf{Resource record}, i.e. the domain name in this scope - \item The \textbf{type of the resource record}, DoresA does only take A records into account as most features can not be extracted from other types. See Section~\ref{subsubsec:dns_resource_records} for an explanation of the DNS resource record types.. - \item All \textbf{TTL} values that this domain has had in the analysis period. + \item \textbf{Resource record}, i.e. the domain name in this scope. + \item The \textbf{type} of the resource record, DoresA does only take A records into account as most features can not be extracted from other types. See Section~\ref{subsubsec:dns_resource_records} for an explanation of the DNS resource record types. + \item All \textbf{TTL} values that this domain has been assigned to in the analysis period. \item \textbf{Resolution}: The IP addresses, that the record type resolved to. \item \textbf{First/last-seen}: Timestamps of when the domain has been seen for the first and last time. \item Additionally, all \textbf{reverse DNS} results are persisted, e.g. to find all historic domains that resolved to a known IP address. \end{itemize} -Using an in-memory database for this application led to a different challenge. Even though trimmed down to the minimum set of information, the data. For this reason, a machine with an appropriate amount of internal RAM had to be used. In this case, a total of 512 Gigabyte of RAM was available with an Intel Xeon CPU with 32 cores. +Using an in-memory database for this application led to a different challenge. Even though trimmed down to the minimum set of information, the Redis database used 3354 Megabyte of memory for traffic of one week. For this reason, a machine with an appropriate amount of internal RAM had to be used. In this case, a total of 512 Gigabyte of RAM was available with an Intel Xeon CPU with 32 cores to be able to perform analysis in a reasonable time. As training on a single core with those amounts of data was not feasible in the available time, a multi core processing approach has been targeted. \subsection{Decision Tree Classifier} \label{subsec:decision_tree_classifier} -While evaluating previous work, mainly two classification algorithms have shown to provide good results in this area. A decision tree classifier has some advantages over different other classification systems: the training time is comparably low, especially in contrast to neural networks. It delivers quite easily interpretable results when plotting the resulting decision tree, it requires little data preparation (e.g. no normalization of the input is needed like in many other algorithms and can handle both numerical and categorical inputs) and it is possible to validate the results of the training using techniques like cross validation. In this work, the implementation of the python library scikit-learn is used. The current implementation of the scikit-learn algorithm is called \textit{CART} (Classification and Regression Trees) and is based on the C4.5 decision tree implementation that is also used in \textit{Exposure}. For a detailed comparison of classification algorithms see \fsCite{Lim2000}. +While evaluating previous work, two classification algorithms have shown to provide good results in this area. While using a random forest implementation was giving good results in the case of \textit{Kopis}, decision tree classifiers has one major advantage over a random forest implementation. Performance has shown to be a major challenge in this work and as random forest is basically an implementation consisting of multiple (arbitrary sized) decision trees, the runtime of the training time increases by the factor of trees the random forest is generating. As \textit{Exposure} and \textit{Notos} have proved to achieve good results with a decision tree, this classification algorithm will also be used in this work. Decision tree classification further features: easily interpretable results when plotting the resulting tree, it requires little data preparation (e.g. no normalization of the input is needed like in many other algorithms and can handle both numerical and categorical inputs) and it is possible to validate the results of the training using techniques like cross validation. In this work, the implementation of the python library scikit-learn is used. The current implementation of the scikit-learn algorithm is called \textit{CART} (Classification and Regression Trees) and is based on the C4.5 decision tree implementation that is also used in \textit{Exposure}. For a detailed comparison of classification algorithms see \fsCite{Lim2000}. \section{Feature Selection} \label{sec:feature_selection} -The feature selection is primarily motivated by the results of the evaluation of previously proposed systems. As \textit{Exposure} has shown to be the system that shares most similarities compared to the network and traffic that is available, also most features are adopted from \textit{Exposure} in the first place. Due to the restricted analysis time, the \textit{Time-Based Features} can unfortunately not be used in this work. To recapture, at least one week of traffic has to be trained to benefit from those features. Besides from that, nearly all features of \textit{Exposure} could be used for the training. See Table~\ref{tab:doresa_features} for all features that are used to model the resource usage characteristics of domains, used in legitimate and malicious activities. For a detailed explanation of why these features have been included, see Section~\ref{subsec:exposure_features}. +The feature selection is primarily motivated by the results of the evaluation of previously proposed systems. As \textit{Exposure} has shown to be the system that shares most similarities, mostly regarding the traffic that is available, most features are also adopted from \textit{Exposure} in the first place. Due to the restricted analysis time, the \textit{Time-Based Features} can unfortunately not be used in this work. To recapture, at least one week of traffic has to be trained to benefit from those features. Besides from that, nearly all features of \textit{Exposure} could be used for the training. See Table~\ref{tab:doresa_features} for all features that are used to model the resource usage characteristics of domains, used in legitimate and malicious activities. For a detailed explanation of why these features have been included, see Section~\ref{subsec:exposure_features}. This sums up to a total of nine different features with some features having multiple feature values in the feature vector: The \textit{Reverse DNS query results} contain the ratio of IPs that can not be resolved (NX domains), the number of all resolved IPs for a domain, the ratio of ip addresses that are known to be used as digital subscriber lines (DSL), the ratio of IPs that are used for web hosting, the ratio of IPs that are used by internet service providers (ISPs) and the ratio of IPs that can be matched with a valid domain name. Please not that a software that would have been used to generate these features could not be shipped in time and the NX domains have not yet been available in the database so these features are ignored in the sample training. The percentage usage of specific TTL ranges includes the following individual features (in seconds): [0, 1], [1, 10], [10, 100], [100, 300], [300, 900], [900, inf]. \begin{table}[!htbp] \centering \caption{Doresa: Features} \label{tab:doresa_features} - \begin{tabularx}{\textwidth}{|l|X|} + \begin{tabularx}{\textwidth}{|l|X|l|} \hline - \textbf{Feature Set} & \textbf{Feature Name} \\ \hline - \multirow{4}{*}{\textit{DNS Answer-Based Features}} & Number of distinct IP addresses \\ \cline{2-2} - & Number of distinct countries \\ \cline{2-2} - & Number of domains share the IP with \\ \cline{2-2} - & Reverse DNS query results \\ \hline - \multirow{5}{*}{\textit{TTL Value-Based Features}} & Average TTL \\ \cline{2-2} - & Standard Deviation of TTL \\ \cline{2-2} - & Number of distinct TTL values \\ \cline{2-2} - & Number of TTL change \\ \cline{2-2} - & Percentage usage of specific TTL ranges \\ \hline - \multirow{2}{*}{\textit{Domain Name-Based Features}} & \% of numerical characters \\ \cline{2-2} - & \% of the length of the LMS \\ \hline -\end{tabularx} -\end{table} + \textbf{Feature Set} & \textbf{Feature Name} & \textbf{\# in Vector} \\ \hline + \multirow{4}{*}{\textit{DNS Answer-Based Features}} & Number of distinct IP addresses & \#1 \\ \cline{2-3} + & Number of distinct countries & \#2 \\ \cline{2-3} + & Number of domains share the IP with & \#3 \\ \cline{2-3} + & Reverse DNS query results & \#4 - \#8 \\ \hline + \multirow{5}{*}{\textit{TTL Value-Based Features}} & Average TTL & \#9 \\ \cline{2-3} + & Standard Deviation of TTL & \#10 \\ \cline{2-3} + & Number of distinct TTL values & \#11 \\ \cline{2-3} + & Number of TTL change & \#12 \\ \cline{2-3} + & Percentage usage of specific TTL ranges & \#13 - \#17 \\ \hline + \multirow{2}{*}{Domain Name-Based Features} & \% of numerical characters & \#18 \\ \cline{2-3} + & \% of the length of the LMS & \#19 \\ \hline + \end{tabularx} + \end{table} \section{Implementation} \label{sec:implementation} -The implementation of \textit{DoresA} does include several different pieces of software. The main part is implemented in python and consists of the \textit{Training Module} and the \textit{Classification Module}. Apart from the main application, the \textit{Malicious/Benign Domains Collector} is a collection of bash scripts to fetch the filter lists and combine them into lists that can easily be consumed by the main application. The \textit{Data Aggregation Module} is written in C (\fsCite{kernighan2006c}), mostly for performance reasons as these logs are aggregated in real time and fed into the redis database. Most of the \textit{Data Aggregation Module} implementation has been available for this work but had to be extended to also persist all TTL changes for a domain. +The implementation of \textit{DoresA} does include several different pieces of software. The main part is implemented in python and consists of the \textit{Training Module} and the \textit{Classification Module}. Apart from the main application, the \textit{Malicious/Benign Domains Collector} is a collection of bash scripts to fetch the filter lists and combine them into lists that can easily be consumed by the main application. The \textit{Data Aggregation Module} is written in C (\fsCite{kernighan2006c}), mostly for performance reasons as these logs are aggregated in real time and fed into the Redis database. For the \textit{Data Aggregation Module}, a previously available implementation could be extended to also persist all TTL changes for a domain. To further decrease training time, the Redis database actually consists of nine different instances which can be accessed in parallel. To actually benefit from multiple instances, the domain (acting as a key) has been hashed and the modulo operation has been used to evenly fill the instances. -The main application is mainly working in two modes. In the training mode, all entries are first loaded from the raw csv logs for the given period. The next step extracts and calculates the values that are needed for each feature and uses the filter lists, gathered by the \textit{Malicious/Benign Domains Collector} to label the dataset. After this, the feature values along with the label is persisted as serialized python objects. This persistence step is on the one side needed to do the final step of training but can also be useful if for some reason, the training is crashing or stopped, it can be continued and picked up where the previous training left off. The last step is using the preprocessed features and the corresponding labels to build the decision model, i.e. generate the decision tree. The training can mostly (apart from the last step) be done in parallel to get a reasonable training time – the implementation in this work has efficiently been executed on 32 cores and took roughly two days for training a dataset with 1 million samples. In the second mode, the \textit{Classification Module} classifies a dataset as either being benign or malicious. While the evaluated systems do have a variable reputation score from zero to one, this system does a binary classification for the dataset in the first place. This could be changed to a variable reputation score, e.g. using the probability for each class that can also be retrieved by the scikit-learn decision tree implementation. +The main application is working in two modes. In the training mode, all entries are first loaded from the raw csv logs for the given period. The next step extracts and calculates the values that are needed for each feature and uses the filter lists, gathered by the \textit{Malicious/Benign Domains Collector} to label the dataset. After this, the feature values along with the label are persisted. The last step is using the preprocessed features and the corresponding labels to build the decision model, i.e. generate the decision tree. The training can mostly (apart from the last step) be done in parallel to get a reasonable training time – the implementation in this work has efficiently been executed on 32 cores and took roughly two days for training a dataset with 1 million samples. In the second mode, the \textit{Classification Module} classifies a dataset as either being benign or malicious. While the evaluated systems do have a variable reputation score from zero to one, this system does a binary classification for the dataset in the first place. This could be changed to a variable reputation score, e.g. using the probability for each class that can also be retrieved by the scikit-learn decision tree implementation. A variable score has one major advantage over a binary classification. Operators can set a threshold to make sure that no false positives occur, for example in an automated blocking system. -Figure~\ref{fig:doresa_selection_decision_tree} shows an excerpt of the resulting decision tree from the test training with 1 million data samples. \todo{describe what is seen on the decision tree excerpt} +Figure~\ref{fig:doresa_selection_decision_tree} shows an excerpt of the resulting decision tree from the test training with 1 million data samples. Looking at the root node (see Figure~\ref{fig:doresa_selection_decision_tree_root}) we can see that the overall model consists of 1 million samples and the first row shows that feature twelve (the number of TTL changes) \(X[11]\) has the most information gain to split the initial dataset. The second column shows the equality distribution, where zero represents an equal distribution and one an completely unequal distribution (all samples in one class). Considering any leaf in Figure~\ref{fig:doresa_selection_decision_tree} we can see the amount of samples that belongs to a class and the resulting class/label (zero represents a benign, one a malicious domain). + + +\begin{figure}[!htbp] + \centering + \includegraphics[width=.8\textwidth, clip=true]{content/Development_of_DoresA/doresa_example_tree_root.png} + \caption{DoresA: root node of resulting decision tree} + \label{fig:doresa_selection_decision_tree_root} +\end{figure} \begin{figure}[!htbp] \centering diff --git a/Thesis/content/Development_of_DoresA/doresa_example_tree_root.png b/Thesis/content/Development_of_DoresA/doresa_example_tree_root.png new file mode 100644 index 0000000000000000000000000000000000000000..b42665bb4300e97d4c3f229c5b21b16a9875a77e GIT binary patch literal 20902 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�pT0ztJSM>w^5pj`J)A$|GAPQhdSJ&+JXPbeS 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 Xi+!R(u^l{U5v3$|SGGXL