KuangPlus: A general computer
vulnerability checker
A thesis submitted as part ofthe requirements for the
Master of Information Science
course undertaken at the
Australian Defence Force Academy.
November, 1999.
Declaration
This workis intended to fulfil part of the requirements of the Master of InformationSciences course undertaken at the University College, Australian DefenceForce Academy, UNSW.
The workis submitted by Jeff Howard
............................................
Acknowledgements
I'd like to acknowledge the insight of DrWarren Toomey in coming up with the initial idea for this work. I'd alsolike to thank Deb and Jesse for their support and smiles whilst I worked onthis project. Finally, I'd like to thank my employer the AustralianGeological Survey Organisation for covering the fees incurred whilst Iundertook this project.
Abstract
The complexity of the computing environment in generaluse today is increasing. At the same time the number and availability ofinformation about new security vulnerabilities is also increasing. Thesevulnerabilities are generally found in poor configuration choicesand badly written software. In this environment, there is a need to have anautomatic tool which will apply up to date information about knownvulnerabilities to audit a system, and report on what was found.
There are a number of well written and usefultools which provide a system administrator with the ability to "audit"their system. These packages share some common flaws which reduces theirusefulness as "general" solutions for finding vulnerabilities. TheKuangPlus prototype was developed to address these shortcomings by creatinga new tool which was platform independent and trustworthy. Key elements ofthe KuangPlus prototype are the use of "Perl" as the implementationlanguage; the separation of the vulnerability discovery process fromthe specific vulnerability information; the ability to load thevulnerability information at runtime using separate files called maxims;and the use of an inference engine to identify and inform the administratorof specific vulnerabilities found. .
There is some work remaining to be done to bringKuangPlus to the stage of being a finished product: Authentication andintegrity checks on the vulnerability information needs to be included;reporting of vulnerabilities could encompass other options such ashtml and email. The final step would be to generate interest in theprototype from security groups in order to leverage their experience toassess the prototype and to develop the maxims.
The development of the prototype has shown that it ispossible to create a tool which addresses the shortcomings of existingtools. With the extra work completed, the tool would be very useful tosystems administrators wanting to quantify the computer securitythreat in their environment.
Table of Contents
Declaration 1
Acknowledgments 2
Abstract 3
Table of Contents 4
List of Figures 5
Chapter1: Introduction 6
Chapter 2: Key terms andconcepts 8
Chapter 3: The problem of root compromise in detail 13
Chapter4: Existing tools and their shortcomings 16
Chapter 5: Design goals for a newtool 20
Chapter 6: Prototype tool - KuangPlus 26
Chapter 7: Effectiveness and applicability of KuangPlus 36
Chapter8: Future development of the prototype 38
Chapter 9: Conclusion 40
Bibliography 42
Appendix A: Theprototype code 44
Appendix B: Logic flow diagrams for theprototype 63
Appendix C: KuangPlus data dictionary 67
AppendixD: KuangPlus user manual 75
Appendix E: KuangPlus maintenance 78
Appendix F: Online Resources 80
Appendix G: Opcode.3online manual 81
Appendix H: Safe.3 online manual 90
Appendix I: A complicated maxim 97
Appendix J: Using thehelp option 101
List of Figures
Figure 1: KuangPlus Design Concept 22
Figure 2: KuangPlus Prototype 29
Chapter 1:Introduction
The amount of work required to secure your system is directlyproportionate to the value you place on your server [Anon99a].
"Maintaining strongsecurity is a process, not an event. Independent audits performed at afrequent interval are a desired best practice, but constant logfile andsystem health monitoring is a must. [...] future developments [...] willautomate security assessment and reduce risk, [however] continuousvigilance is the [...] administrator's best security tool" [Anon99a].
Reliance on computer systems for business isa trend which has been in evidence for some time now. One of the drivinginfluences of this is the need to allow information to be made availableand exchanged within and between key elements of an organisation.Hand in hand with this need to share information, is the trend towardgaining a presence on the Internet and using it as a key element inproviding access to information for remote staff and clients. The problemwith this is that the Internet is a jungle - if you connect amachine to it, you can be sure that it will be probed for securityweaknesses by the malicious and the curious. In a recent AusCERT report[Lor99] the trend for reported vulnerabilities was shown to be increasingat a non-linear rate: In 1993 there were less then 200 incidentsreported, in 1996 the number had grown to nearly 400 and in 1998 the figurewas close to 1300. This increasing trend in security vulnerabilityreporting should worry anyone that is attached to the Internet andwants to have some confidence that the computing environment theysupport will not be compromised by an external entity. The problem ofguaranteeing access to the organisations computer resources is alsocompounded by the fact that the threat to the computer resourcesalso comes from within.
In thissituation there is a need for the systems administrator to have as manytools as required to audit the computers under their care, on a level ofregularity that suits them, to give them the confidence that the computerswill not be vulnerable when attacked.
Many tools already exist in the public and commercialdomain which allow a system administrator to check for knownvulnerabilities. However, they have a couple of fundamental weaknesses -they are system specific, maintained in a haphazard fashion and lackthe flexibility to search for vulnerabilities which didnt exist whenthey were created. In this atmosphere the project, KuangPlus, which isdescribed in this work has had its birth. The concept behind the project isto create a tool which will have a generalised and stable "core"which will not contain any specific knowledge about securityvulnerabilities and hence will not need constant updating. The core will beable to load, "on the fly", the specific information about securityvulnerabilities relevant to the system on which it is running anduse an inference engine to compute any "plans" which could be acted on toachieve a root compromise of the computer under examination.
In the next chapter some of the key "termsand concepts" will be defined in the context of this work. The thirdchapter will look at the problem of root compromise in more detail anddemonstrate why it is a problem which requires attention. In the fourthchapter the weaknesses already mentioned above will be elaboratedupon and some of the tools currently available will be briefly reviewed.Next, a conceptual schema for a tool to address these shortcomings ispresented followed by the details of the implementation of aprototype. The prototype is then discussed in the light of the originalproposal and with the benefit of the experience gained in creating it. Thenext chapter will discuss the future of this project in terms of whatremains to be done. In the concluding chapter, the problem ofauditing your computer systems is restated. The major points made in thiswork are noted and the validity of the approach taken in this work isdiscussed. In closing, some suggestions for future research are given.
Chapter 2: Key Terms and Concepts
This chapter shouldaid the reader in understanding the way some common terms are used in thespecific context of this work as well as understanding some terms andconcepts which may not be familiar.
A computer system
A "computer system" or just a "system" are the termswhich will be used interchangeably to refer to both a single physicalcomputer unit and a set of computer units linked, by common ownership, insome sort of networked arrangement. Where it is not obvious form thecontext, it should be taken to refer to both a single unit and a network ofunits. It should be noted that unless specifically noted in the text, acomputer system could be any of those in common use. For example, it mightrefer to a Unix (and its variants such as Linux, and FreeBSD), NT,MacOS or VMS system.
TheInternet
The Internet is the term in common usage to describe theloosely coupled network of computers which spans the globe and allowsinformation to be shared between globally distributed computer systems. TheInternet is relevant to this work because when computer systems aremade available on the Internet the organisation is unable to control whomight access them.
Superuser
The "superuser" is the most powerful account on acomputer system. It is equivalent to the "root" account on a Unix systemand the "administrator" account on an NT system. It is also sometimes evenreferred to as "god" with reference to the all seeing and allpowerful nature of the account, although not within this work.
Vulnerability
As pointed out by "The MITREorganisation" [MITR99b] the term vulnerability is applied in common use intwo senses: The wider application of the term is to refer to any fact abouta computer system which is a legitimate security concern in the context ofa reasonable site security policy; the narrower application of theterm is in only considering as a vulnerability those facts which are asecurity concern in all contexts. The example given in the "MITRE"[MITR99b] discussion is the use of the "finger" service whichreveals information about an individual user on the local system toexternal entities. In a very security conscious environment like a DefenceSecurity Organisation, this would be considered a "vulnerability" and theservice would be disallowed. In another organisation where sharinginformation is considered more important then denying access to it, such asa University, the mere disclosure of user information through the fingerservice may not be regarded as a vulnerability, although other aspects of the implementation of that service may raise concerns.
Within this work, theterm vulnerability will be used in the narrower sense of the word to referto any fact which might allow an external entity to access the privilegesof the "superuser" when they are not entitled to them. In this regard, theapplication of the term vulnerability should always be considered asecurity concern. The threat does not have to be realised: The term is alsoapplicable where the necessary conditions exist that would allow anexternal entity to compromise the system.
Exploits
Based on the definitions available from thework done by the "The MITRE Corporation" [MITR99a] the term "exploit" willbe used within this work to refer to any deficiency in either software orthe configuration of the system which will allow an entity to violate a reasonable site security policy. An "exploit" is a widerdefinition then "vulnerability". It encompasses all vulnerabilities aswell as other "security" problems which may not be so serious and maydepend on the context in which the "site" operates.
Secure system
Based on the work of Farmer andSpafford [Farm94] we can view a secure system as one which providesprotection of information from inappropriate disclosure and alteration;protects against the denial of access to the system, services and datawhich it contains to legitimate users; protects against degradedperformance; protects against unauthorised changes to system configuration;and denies unauthorised access to it.
Compromise
This term is used in the specific context of a computersystem where a "vulnerability" has been discovered and acted upon. Acomputer system is described as being "compromised" or as a "compromised[computer] system".
Hacker
Externalentity
The phrase external entity will be used to refer to a personor program which is accessing an organisations computers, but is notwithin the organisation. The term hacker is a specific instance of anexternal entity that is accessing the computer resources in a waywhich would not meet the requirements of the sites security policy.
User
The term user is used to refer to allpeople authorised to access a given computer system.This includesemployers, clients and systems staff.
Site security policy
As indicated in Garfinkel et. al. [Garf96]the first step to securing a computer system is to define the managementsview of what is and isn't acceptable practice in the use of the computerequipment provided by the organisation. This definition is referredto in the context of this work as the "site security policy". It shouldencompasses what is considered reasonable in terms of accessprovided to users of the organisations computer resources.
Object
A simple entitywithin the computer system under scrutiny as defined for use by theKuangPlus prototype. An "object" is one of "user id", "group id","pathname", or "version instance". It is associated with an "operation" andthe two are linked as a "controlling operation". A specific instanceof an object will vary in its representation: An instance of a "user id"and "group id" is an integer value; a "pathname" instance is a set ofalphanumeric characters with the additional characters '/', '-' and '.';and a version instance is a set of alphanumeric together with thecharacters '-' and '.'.
Operation
A simple action which is applicable to an object as used in thecontext of the KuangPlus prototype. An operation is one of "write","replace", "user", "group" or "version". It is associated with an "object"and the two are presented as a "controlling operation". Theoperations are typically shown in terms of their mnemonic values "w", "r","u", "g" and "v" rather than the full term.
Controlling Operation
The instance of an association of an "object"and an "operation". Not all objects are applicable to all operations: Anoperation of type "read" or "replace" is only applicable to a "pathname";an operation of type "user" is only applicable to a "user id"; anoperation of type "group" is only applicable to a "group id"; and anoperation of type "version" is only applicable to an object of type"version instance". The controlling operation is the basic building blockfor each "rule".
Maxim
One of the definitions of maxim found in a readily accessibledictionary [Turn87] is a general truth drawn from science orexperience. This is an appropriate term to use in this work to refer tothe encapsulation of the information about how to identify thepresence of a vulnerability. A maxim will be generated by a vendor,security organisation, or security interest group. In the specific contextof the KuangPlus prototype, the maxim is encapsulated within asmall piece of Perl code.
Rule
Arule has a specific meaning in the context of the KuangPlusprototype in that it is the internal representation of the result ofevaluating a maxim. A rule any a combination of two linkedcontrolling operations which may or may not be useful in formulatinga plan.
Plan
A plan is a singleinstance of a chain of rules which will allow progression from a "known"state to a "goal" state. The plan is generated by the inference engine. Itis usually represented in this work backwards with the goal as thefirst rule on the left hand side, a series of intervening rules, andthen the rule describing the pertinent known state on the righthand side. This reflects the underlying property of the inference engineused to discover the existence of plans.
Search Space
The set of all applicable rules generated bythe evaluation of the maxims, together with the rules associated with theknown and goal states, for the system under scrutiny. Ifno rules are generated by the maxims, and there is nothing known about thesystem, the search space will contain just one goal.
Known state
The simple facts about the systemunder scrutiny. An example of a known state is the version and type of theoperating system, expressed as an object.
Goal state
The final state which we are interested inachieving. In the context of this work the "goal state is always "rootcompromise". In rule terms, this is represented as u 0.
Inference Engine
An automated process whichattempts to match a series of isolated pieces of information, described byrules, into a plan which enable progression from a "known"state to a "goal" state.
Publiclyavailable
The term "publicly available" will be used to refer to situationswhere information about a vulnerability is available on the Internet. Thesort of publication varies widely. It could be in the form of a bulletinfrom a security organisation describing a particular problem; itcould instructions on how to take advantage of a particular vulnerability;or it could be a notice from a vendor acknowledging the existence of avulnerability in their product and giving instructions for rectifyingit.
Kuang
The name "Kuang" derives from ascience fiction work by William Gibson [Gibs84], wherein there was aprogram called "Kuang Grade Mark II Ice Breaker" used to break theprotection of information. In a curious twist, this name is linked with aset of tools which has, as its core aim, the property of allowing asystem administrator to protect information.
Chapter 3: The problem of root compromise indetail
Theproblem under discussion is the existence of "vulnerabilities" in acomputer system which may allow an entity, be it manifested as a human orin software form, to access the privileges of the "superuser" when they arenot entitled to them.
There aretwo questions related to this work which will be discussed in this section.The first is: Does the existence of vulnerabilities sufficiently warrantattention? The second is: What are the consequences which flow from theexistence of these vulnerabilities? In the following sections,theses two questions will be used as the framework to demonstrate the depthand consequences of the problem.
3.1 Does the existence of "vulnerabilities" sufficientlywarrant attention?
Thephrase "sufficiently warrant attention" is taken, in the context of thiswork, to imply two questions: Do vulnerabilities exist? Is the informationdescribing them generally available to the extent that a reasonablesite security policy would consider them to be anunacceptable risk? The answer to these questions is an unequivocal yes.
The first question can be resolved withreference to some of the organisations which assemble "databases" ofinformation describing vulnerabilities. For example, the "Security Alertfor Enterprise Resources (SAFER)" [Siam99] for September 1999 describes23 new "vulnerabilities". Similarly, the the "X-Force Vulnerabilityand Threat Database" [XFor99] published in the same period describes 22vulnerabilities. For the year to date, the "Australian Computer EmergencyResponse Team" has redistributed 99 security advisories andbulletins from "other computer security response teams, vendors, and othergroups concerned about security" [AusC99]. For a historical perspective, anAusCERT presentation [Lor99] showed that the annual incident load hasincreased in a non-linear fashion over the past 6 years. In 1993 and1994, the number of reported incidents noted by AusCERT was less then 200;in 1995 the number of reports was just over 200; in 1996 it was just below400; in 1997 it was over 600; and in 1998 it was around 1300. In theview of the author, this number of exploits indicates that the presence ofvulnerabilities is sufficiently evident and knowledge of them easy toobtain to say that "yes" they do warrant attention.
The second question can be resolved by observing thatthere is a growing trend toward using the "Internet" and "WWW" to conductday-to-day business as both an extension of the current enterprise or as anew endeavour. In this scenario, the accessibility of corporatecomputer systems to "outside" entities is available on an unprecedentedscale. Taken with the information in the preceding paragraph, the authorbelieves that the conditions well and truly exist for computer systems tobe compromised. Goodin [Good99a] supports this view with a quotefrom the "Computer Security Institute" based in San Francisco: "With therise of the Internet and the transaction of e-commerce, corporations andgovernment agencies are far more open to attack then ever before".Further support for this point of view can be found in the work ofBaldwin [Bald??] in discussing the reasoning behind the creation of the"SU-Kuang" system audit tool. In this work he describes the basic problemas being the conflicting aims of making computer systems more usefulby "increasing [the] number of mechanisms which allow users to executecommands and share information" and keeping the protection system simpleand obvious as it "grows larger and progressively harder to understand".
3.2 What are the consequences whichflow from the existence of these vulnerabilities?
There are new business opportunities. In an articledistributed on the "CNET" electronic news site [Good99a] it is noted thatin response to the "dramatic growth in computer-perpetrated crime" twoaccounting firms "Deloitte and Touche" and "Price WaterhouseCoopers" have formed "cyber-fraud squads". Their role will be toinvestigate after the event and also to evaluate security in the context ofthe presence of computer crime.
In the same article by Goodin [Good99a] he quotes the editorialdirector of the "Computer Security Institute" as saying that in a survey of521 security practitioners across a broad range of organisations (e.g.banks, universities, government) reported security breaches costmore than $US123 million dollars last year. The director goes on toestimate that the cost worldwide to businesses is in the order of tens ofbillions of dollars. It would appear from the article that a lot of theproblems which gave rise to this cost are not directly related tosecurity exploits on the computer system. However, a component of the workdone by the "Deloitte and Touche" team as described, relates to "copyright"infringement and "misappropriation of company trade secrets" whichare facilitated by the presence of vulnerabilities on the company computersystems.
Another article byGoodin [Good99b] describes a "hacker" attack on a site in America which isused by "Foreign citizens and diplomats all over the world [...] to getinformation about U.S. affairs, including official speeches and transcriptsof hearings". The site was compromised on January 13 and was stillunavailable on January 21 when Goodin wrote the article in which thecompromise was described. It is also noted that the same hacker is believeto be responsible for a previous attack which caused the loss of alldata on the site. Whilst it isn't stated, it is implied that the firstattack exploited weaknesses in the "ftp" and "telnet" services and thesecond exploited a weakness in the "DNS" service. The author believes thatboth these types of exploits could conceivably have been detectedand neutralised by an automated process.
A quick scan of other news items on the CNET site[CNET99] reveals numerous other stories relating to the economic cost of"hacker" attacks on computer systems. These items are cited here todemonstrate that there is a very real social and economic cost associated with the presence of vulnerabilities on computer systems. Whilstthe fact that these organisations are connected to the Internet means thatvulnerabilities are exposed to a wide audience, Goodin [Good99a] cites areport by the "Computer Security Institute" that of the 32% oforganisations which reported serious security incidents, 55% of thesereports referred to company insiders. This information leads to theobservation that even those systems not directly attached to the Internetare also exposed to vulnerabilities.
3.3 Conclusion - the need for an automatedtool.
A Unix administratorreflecting on his own experience with a little time on his hands describedthe practical problem of finding flaws as follows [Mitr98]: Most systemadministrators are very busy people who don't have the time, or will, toengage in the detailed study of their computer systems security.So only those administrators responsible for sensitive information will.However, when an unexpected security incident occurs, the interruption towork and the time taken to evaluate, fix and restore the systemmakes security a very important consideration. Farmer et al. [Farm94]described the security problems particular to Unix as displaying twocharacteristics: they are usually simple to correct if found, and they arefairly easy to detect. These two characteristics make finding thesesort of security problems an ideal candidate for an automatic process. Thisshould also help address Mitra's concerns [Mitr98] in that it would allow asystem administrator, with little or no time on his hands, to do basicsecurity auditing "off line" and deal with the problems highlightedin the report. so generated
Chapter 4: Existing tools and their shortcomings
There are several "security audit" packagesavailable, both for free or as commercial products. This review hasconcentrated on the non-commercial packages due to their readyaccessibility and ample reference material surrounding them. It is alsogenerally true to say that the commercial products are sometimesderived from, directly or indirectly, the same source as the public domainproducts. For example the publicly available "ISS" package is a cut-downversion of the commercial product by the same name [Aust99, p. 40].
The aim in this chapter is not to present acomprehensive list of what is available, but to demonstrate through theexamination of a set of well used and worthy security packages, that theyshare a set of common weaknesses with respect to solving the generalproblem of providing a security auditing tool that is not platformspecific. In the following text, the weaknesses will be described and thenthe set of security tools will be looked at individually with comments onhow the weaknesses described earlier relate to it.
4.1 Common weaknesses
There are 5 basic areas in which weaknesses can be shownto exist in the security tools reviewed: generality, maintenance,relevance, trust and timeliness. These 5 areas are described as:
generality - The concept of agiven tool being written in a general enough way that it is independent ofboth the hardware platform and operating system on which it is run.
maintenance - A lot of thesepackages, whilst being well written and able to still perform a usefultask, are not actively maintained. This is sometimes because they wereoriginally written as academic projects.
relevance - Where a tool has been createdwith an internal database of vulnerabilities which need to be checked, itis out of date from the moment it is released. In a preceding chapter itwas pointed out that the number of exploits currently being discovered andpublicised is in the order of 20 a month. Any tool is not able todetect these new problems declines in relevance as time goes by. Onereference [Anon99b] cited a symposium where the common belief amongst agathering of security representatives was that the "biggest faultfound with existing products were the weak capabilities for detectingpreviously unknown attacks". The work of "The MITRE Corporation" [MITR99a]suggests that by separating the "tool" from the "database" ofvulnerabilities, the same tool that is currently being used will beable to leverage new developments in vulnerability databases because thetool will use information loaded at run-time rather then informationavailable at creation time.
trust - Typically, any audit tool willrequire access to the entire computer system in order to completely assessthe existence for vulnerabilities. This means running the audit tool withsuperuser permissions. In this scenario, the system administratormust be able to trust the tool in terms of its operation,interaction with the system on which it runs and the results it produces.In short, the system administrator must be able to trust that the use ofthe tool wont expose the site to precisely the sort of compromise that the tool was meant to reveal.
timeliness - In order to protectagainst the latest vulnerabilities, the tool should be able to accesscurrent information in a timely fashion. If it cannot by its design orbecause of practical impediments, then it doesn't exhibit the desirablequality of timeliness. Not all tools exhibit all 5weaknesses, but all tools appear to suffer from some of them.
4.2 Some public domain securityauditing tools
The following publicdomain tools are presented in brief and the related to the 5 weaknessesoutlined above where appropriate.
COPS - Computer Oracle and Password System
COPS was developed asa Purdue University student project by Dan Farmer, under the guidance ofEugene H. Spafford. It was first described in the summer 1990 USENIXConference in Anaheim, [California, USA]. in a paper titled "The COPSSecurity Checker System". The COPS program is still referenced bymany first rate texts on computer security. As of early 1996, COPS hasn'tbeen updated in more than four years and fails to install cleanly on manymajor versions of UNIX. Dan Farmer moved onto other projects (suchas the SATAN tool presented below) [Garf96, p. 893]. COPS first used theKuang term to refer to a component of the package which applied aninference engine to find complex configuration problems on the system.
The COPSpackage suffers from all 5 weaknesses. It was written for a Unix system andthus lacks generality. It has not been maintained for some time. It uses aninternal database of vulnerabilities and as such lacks somerelevance. It runs as superuser, but does not enforce any model totrust to ease the concerns of the system administrator. It lacks timelinessin that there is no facility for it access current information. However, itis noted in Garfinkel et al. [Garf96, p. 893] ... that there isstill some value in applying COPS - some of the flaws that it findsare still present in systems shipped by some vendors ...".
ISS - Internet Security Scanner
ISS was a tool created to monitorand track outsiders attempting to gain access to a computer system [Aust99,p. 40]. It was written by Christopher William Klaus in approximately 1994when he was 19. There are two versions of ISS: One is a commercialproduct, the other is a "freeware" product which is a cut-downversion of the commercial product both in terms of support andcapabilities.
In Garfinkel et al [Garf97, p. 902] ISS is described as atool which "probes your system for software bugs and configurations errorscommonly exploited by crackers". The text goes on to say that "informalconversation with personnel at various response teams indicates thatthey find ISS involved in a significant number of intrusions - far morethan they find assoc. with SATAN."
It is to be expected that, since ISS is acurrent commercial tool that it should not exhibit many of the weaknessesunder examination. It certainly is available on Unix and NT systems so itcan be said to address the generality weakness to some degree. Ituses a signature database of known attacks so it will suffer fromthe weaknesses of relevance, timeliness and maintenance.
RSCAN
Nathaniel Sammons[Samm99] is currently developing the RSCAN package. It reports on local"scans" of a system and reports in HTML or plain ASCII. RSCAN uses a"modlist" to define what scans should be done on a particular host. Scansare classified in terms of general problems, problems specific to anoperating system or problems specific to a version of the operating system.The selected scans cause modules to be loaded at runtime. The modulesencompass the "SATAN" checks as well as specific module for the SGI"IRIX" operating system. RSCAN is implemented in "Perl".
The RSCAN packagedoes not appear to enforce any model of trust. It is implemented inPerl which should mean it is available as a general package although theinformation available indicates that it is specific to the SGI systems atpresent.. There is no facility apparent for accessing newinformation, so timeliness is a weakness. RSCAN uses modules which areloaded at runtime so relevance may not be a problem for this package.
SATAN - SecurityAdministrator Tool for Analysing Networks
This package also goes by the name "SANTA"where the acronym is repackaged as "Security Administrator Network Tool forAnalysis".
SATAN is described in Garfinkel et al. [Garf96, p. 903] was writtenby Wietse Venema and Dan Farmer. A major feature of this package is itsanalysis of a system from the "network" perspective rather than frominside. It is able to recognise and reports on several commonsecurity problems related to network access, without actually exploitingthem. For any given exploit, a tutorial is available to the systemadministrator. SATAN was released to the public domain in approximately1994.
SATAN is not timely in that there is no facility to access noinformation. It appears to enforce a model of trust in that it does notexploit any vulnerabilities found. The exploits that SATAN looks for aredescribed in internal information and as such the package suffersfrom a decrease in relevance as new vulnerabilities are discovered.
TIGER
Written by Doug Schales of Texas A&MUniversity, TIGER is described in Garfinkel et al. [Garf96, p. 905] as aset of scripts that scans a UNIX system looking for security problems, in amanner similar to COPS. It was used at the A&M University to inspect a computer before it was made available to the Internet.
TIGER is Unixspecific and thus lacks generality. It does not appear to allow for newinformation to be included and thus is not timely.
Chapter 5: Design goals for a newtool
In the previouschapter we described the shortcomings of some of the widely used tools fordetecting vulnerabilities in a system. In this chapter we will use thoseshortcomings to lay out the design goals for a new tool, to be calledKuangPlus.
5.1 Design Goals
The newtool should address the 5 shortcomings discussed in the previous chapter byexhibiting the following properties:
relevance Property 1:Separate the tool from the database of vulnerabilities. In this waythe tool will be flexible and will be able to detect new vulnerabilities assoon as they are added to the database.
generality Property 2: Implement the tool in such a way that it is independentof the platform and operating system it is running on.
maintenance Property 3: The tool should comprise acentral core of static (unchanging) code with dynamic maxims representingthe "database" of vulnerabilities loaded at runtime. This will mean thatthe central core will not require ongoing maintenance as newvulnerabilities are discovered.
trust Property 4: Should be simple and obvious in its design and securein its operation.
Property 5: The source for the tool and therules must be in an easy to read format that gives the system administratorthe confidence to use them.
Property 6: The tool should neverbe allowed to alter the configuration of the system on which it runs. Norshould any of the maxims be able to effect the operation of the tool, thesystem on which it is running or the evaluation of other maxims.
There are furthergoals which relate to the operation of the prototype. These properties aredesirable because they further help satisfy the properties alreadyoutlined.
Property 7: It must find all plans, not just the first one itdiscovers. This could be described as a property of completeness.
Property 8: Use an inference engine to reveal complex plans as wellas the simple ones. This is a direct development from the "SU-Kuang"[Bald??] and "NetKuang" [Zerk??] approaches where a backward chaining,goal based, breadth first search, inference engine was used.
Property 9: Have an automatic process by which a systemadministrator can download new maxims from trusted sources and verify thesource and integrity of the maxim.
Property 10: Have a well describedlanguage for rules and have clear instructions for creatingmaximswhich will generate valid rules.
Property 11: The toolshould generate useful information suitable to a wide range of systemadministrators, from the novice to the experienced.
5.2 The prototype - design choices
5.2.1 Choice of language
Perl was chosen for the language to implementthe tool. This choice was made because it fitted well with some of thedesirable properties as outlined below:
It is commonly available on a broad range ofsystems either supplied by the vendor as part of the operating system oravailable as a third party add on.
It has a rich standard library which shouldavoid the need to "recode" the interface between the tool and each specificplatform.
The source code is only compiled at "run-time". As such theadministrator can satisfy themselves, in any appropriate way, that theoperation of the tool will be reflected by the code they have just lookedat.
The tool is going to run in an environment where trust is veryimportant. Utilisation of Perl's "taint" mode will give some confidence inthe operation of the tool. The taint mode is intended to provide afacility to stop accidental changes to something outside theoperation of the tool by the use of data which was derived from anuntrusted source. In addition, Perl provides the compile time instruction"use strict" which can be utilised in the prototype to enforce clearprogramming practices. Finally, the compile time flag "-w" can alsobe used to warn about anything that looks like bad programmingpractice.
In version 5.004 the "Safe" module was further refined. This hasbecome a key element in the construction of the prototype. Its usage willprevent the maxims from interfering with either the system or theenvironment in which the tool is running. The "Safe" module will bediscussed in more detail below.
5.2.2 Structure
The basic tool will be composed of three main modules (see Figure 1).The first module will provide the "front end" to the tool. It will providethe user interface, handle loading maxims and build a search space ofrules. The second module will contain the "inference engine" whichwill be invoked with a reference to the search space and will return anysuccessful exploits found. The third module is the SafeOps moduleand will contain any sub-routines which should be available to the maximsas they are evaluated within the "Safe" compartment.
5.2.3 The "Safe" module
The existence of the "Safe" module was aminor revelation during the development of the prototype. It was stumbledacross when the author was perusing the security related items discussed inthe "Programming Perl" book [Wall96].
There are three implicit requirements relating to the property oftrust which the process of loading and evaluating maxims shouldexhibit:
i) Theintegrity of the KuangPlus main logic should be guaranteed to bequarantined from any interference with respect to the evaluation of themaxims.
ii) When each maxim is evaluated there should be no residual effecton that evaluation environment caused by a previously evaluated maxim.Stating this same property from the other point of view, having beenevaluated, a maxim shouldn't be able to leave any residual effectthat might effect subsequent maxim evaluation.
iii) In the process of evaluatinga maxim, there should be no unplanned interaction between the computersystem and the maxim.
The use of the "Safe" module with a set of routines which allow andcontrol interaction with the system satisfies the above three requirements.The Safe module is part of the standard Perl library in version 5.004 ofPerl. The Safe module enables a maxim to be evaluated in arestricted environment where the only variables and routines which it can"see" are explicitly "shared" into it's environment. This should satisfyrequirements (i) and (iii) presented above. By loading each maxim into anew "Safe compartment, the possibility of rules interfering witheach other should be eliminated and that will satisfy requirement (ii)above. Wall et al. [Wall96, p. 489]. give a good description of the Safemodule and what methods exist for creating the desired environment.Meeting these three requirements is a necessary aim in satisfying theproperty of trust.
What theSafe module doesn't protect against
Whilst the use of the "Safe" module should give the users of the toolconfidence that the operation of KuangPlus is reliable, there are somethings which it cant protect against which are worth noting. They arediscussed in the online documentation on the Safe module [Perl98a] (and contained in Appendix H. The safety aspects are discussed on page H-6).The potential for code to consume the CPU or memory of the host system isidentified as a means by which clumsy or malicious rules could prevent thecalling script from ever finishing. There are also complex issuessurrounding the possibility of disclosure of environment variables and sideeffects that might occur if the compartment is able to access variableswithin the namespace of routines "shared" into it. Whilst theconsumption of memory and CPU is beyond our control at this stage, theother information should guide the design of the prototype to attempt toavoid these situations.
Whatmight happen if we don't use the "Safe" module.
If "Safe" were not used, the system on which it runswould be vulnerable to interference from the evaluated code. If theuntrusted code were simply evaluated, it would have full access to thefunctionality of Perl. This would open the possibility of loss anddisclosure of information, and changes to the state of the computer systemas a result of running the tool. This means that the tool would have a lotof trouble satisfying the property of trust.
Chapter 6: Prototype tool - KuangPlus
In this section the more specific information concerningthe implementation of the prototype will be presented.
6.1 Perl modules
There are four logical units to KuangPlus: the"frontend"; the "inference engine"; the "safe" operations and the "maxims"themselves. The first three components are instantiated in the files"kuangplus.pl", "engine.pl" and "safeops.pl" respectively. The "maxims" are the fourth component and are created as a series of independentfiles of Perl code.
0 In Appendix B thelogic flow diagrams for the modules described below are shown.These are the frontend, the inference engine and theloading of maxims. Figure 2 shows a conceptual schematic of theKuangPlus prototype.
6.2 Using the "Safe" compartment
The general properties of the "Safe" module have been discussedalready. In that discussion it was mentioned that the operations availableto code being evaluated in a "Safe" compartment are very restricted. Theamount of restriction is actually in the hands of the Perlprogrammer. For the purpose of this prototype, the default set has beenused. This decision was based on a need to develop a working prototype andin the full knowledge that the methods available in the "Safe" module andthe associated "Opcode" module will allow this decision to be easilyreviewed and further restrictions added as necessary. The "Opcode" module[Perl98b] defines a series of "tags" which define a set of operators or aset of other "tags" which themselves contain a list of operators.The number of operators which are available in the ":default" set is toolarge to list here, but the "Opcode" and "Safe" online documentation isincluded in Appendix G and H.
An example of the error message which is generated at runtime by amaxim trying to access an operation to which it has not been given accessis shown below (where the second line has been broken for this example). Inthis example, the stat operation was not available to themaxim:
Use ofuninitialized value at ./safe.pl line 31.
$KuangPlus::rtn = "" (stattrapped by operation mask at
/home/Kuangplus/unsafe.pl line 16.)
If a given maxim attempts to access anoperation which is not available to it, the attempt will be detected atruntime, an error similar to that shown above will be written to the screenand the maxim in question will not be evaluated.
6.4 Interface between the modules ofKuangPlus
This sectiondescribes the interface between the components of KuangPlus. There are 4components to be considered:
1. The user.
2. What will be referred to in the following as theKuangPlus "frontend". This is the Perl program which the user will invoke.It will, in turn, invoke and load the other components described below.
3. Theinference engine.
4. The maxims.
After discussing the separate components in a little more detail, theremaining text in this section will describe the relationship between the"frontend" and the "user", the "frontend" and the "maxims" and finally the"frontend" and the "inference" engine.
The user
The useris the invoker of the KuangPlus program. Practically, the KuangPlus programmay be invoked automatically at a set time (e.g. at 2 am each morning)without any manual involvement. However, in the following text, the "user"is the generic reference to the invoker of the program irrespectiveof whether it is a person or an automatic process.
The frontend
The "frontend" is the program which the user will invoke. It willhandle resolving the command line options; set up the run-time environmentas required including initialising variables and loading additionalmodules; evaluate or reject each of the maxims; invoke the inferenceengine; and handle the results in some meaningful way.
The frontend is instantiated within the "kuangplus.pl"file.
The maxims
The rules considered by the inference engineare generated as a result of the separate evaluation of a number of maximscontained within small "Perl" scripts. For the purposes of developing theprototype, these scripts were developed by the author.
Each maxim will use available information to createappropriate rules for the computer system on which KuangPlus isrunning.
The maxims are allloaded from the "maxims" directory, which by default will be asub-directory found in the same directory where the rest of the modules arelocated. The maxims directory can also be specified as a command lineargument.
By encoding thevulnerability information as separate, runtime loaded, files the desirableproperties in the design goals of timeliness and generalityshould be satisfied.
Theinference engine
The inference engineis of the "backwards chaining, goal based, breadth first" type. Appendix Bcontains a logic flow diagram for the inference engine. In simpleterms, based on a nominated "goal", the logic will look through the searchspace of rules to see which rules can be combined ("chained") toachieve the goal given some initial condition. The logic is such that itstarts with the goal (hence the descriptive terms "backwards andgoal based"), and attempts to find a non-empty set of rules whichwill achieve the "goal". Having found a non-empty set of matchingrules, these rules will then act as a temporary goals, for which thesearch space will be re-examined to see which rules will allow these newgoals to be achieved (hence the application of the term breadthfirst). The process repeats until a rule is found which represents aninitial known condition or there are no matching rules. At thispoint the work of the inference engine is complete.
The inference engine is implemented in the "engine.pl"Perl module and the logic is shown diagrammatically in Appendix B.
6.4.1 The interface between the frontend and the user
The "user" has several command line optionswhen invoking KuangPlus. The options include the ability to print outdebugging information as the program runs, and to print anysuccessful exploits discovered in a verbose mode. When theinference engine has completed its work, a report is printed on thescreen. If no vulnerabilities were found then that is stated. If some werefound, they are presented either as a simple plan or a verbose version ofthe same information, depending on whether or not the verbose optionwas used when KuangPlus was invoked.
6.4.2 The interface between the frontend and the maxims
Rules are generated by evaluating the maximsfound in each file in the "maxims" directory. Each file is evaluated inits own "compartment" (created using the Perl "Safe" module) which disablesunintended interaction between: the maxim and the operating systemon which it runs; the maxim and other maxims run before or after; and themaxim and the operation of the KuangPlus prototype.
The intentional interaction between the maxims and theenvironment in which it is evaluated is restricted to two types: Thecreation of rules in a specific associative array which is sharedinto the compartment and used for passing the results back to thefrontend; and the use of a set of sub-routines also sharedinto the compartment.
At thetime of writing, the defined sub-routines available to the maxims arelocal, caching, emulations of Perl system calls. They are:
stat(), uname(), getpwent(),getpwname() and getpwuid()
Thesesub-routines give a maxim the ability to derive account and system specificinformation from the computer system on which KuangPlus was invoked. As theneed arises, other routines can be added by defining local versionsin the safeops.pl script file in the SafeOpsnamespace.
Because thesub-routines have the same name as the operating system equivalents, themaxims can be tested outside of the Safe environment.Further, whilst efficiency is not a big consideration in the operation ofthe prototype, by caching each look up, information such asuserids will only need to be obtained once and will then be servedout from the cache when the same information is requested subsequently. Thebiggest advantage though is that the interaction of the maxim with theoperating system must use these routines and so there is a tightcontrol over what information is available to the maxims and how they canget at it..
The associativearray, "%new_plans", is defined within the KuangPlus namespace andshared into the Safe compartment. The maxim is able to use it topass any generated rules back to the "frontend". Before each maxim isevaluated, the "%new_plans" associative array is initialised. Theexpected structure of the array is that each "key" in the associative arrayis a rule of the form "op ob op ob" (such as "r /etc/afile u 1234"). The"value" part of the associative array is a free formatted stringwhich provides a short description of the rule. It is up to thecreator of the maxim how this string is used. In the previous example, thestring might be something like
/etc/afile can be replaced by uid 1234
In the frontend, the values in the"%new_plans" associative array are checked for any unexpected content bythe "rule_qc()" routine. The valid rules returned by each maxim areaccumulated in a different internal variable which will later be madeavailable to the inference engine. Invalid rules discovered byrule_qc() will be ignored and an error message will be printedstating that this action has been taken.
6.4.3 The interface between the inferenceengine and the frontend
Theinference engine is passed a reference to an associative array whichcontains the accumulated "rules" from the evaluation of the various maxims.The inference engine returns to the frontend an array of "successfulexploits", if any were found, in the form of plans. If thereturn value is null (i.e. no exploits were discovered), then a message isprinted by the frontend stating as much. If the return value is non-empty,then a sub-routine within the front-end is invoked which will cause eachexploit to be printed, with the actual message depending on whetheror not the verbose flag was used when KuangPlus was invoked.
6.5 What is a rule?
A rule is created by the evaluation of amaxim. The syntax of a rule is described as follows: A rule is constructedfrom the association of two controlling operations (CO). Each CO is made upof an operator object pair where the set of object typeswhich can be associated with a given operator type is restricted.Each rule has associated with it a free text string which is intended tosupply additional information about the rule. It is up to the maxim tosupply any text for the string, and it is not an error if none issupplied. If a syntactically invalid rule is supplied by a maxim, theKuangPlus::rule_qc() sub-routine will discover it and reject it atruntime. Two or more rules can be combined to form a plan where theCO on the left hand side of one rule is the same as the CO on theright hand side of another. The plan describes how it is possible to movefrom one piece of information to another. In KuangPlus the only plans ofinterest are those exposed by the inference engine, which allowprogression from the goal state back to a knownstate.
An operator is one ofcan obtain user id, can obtain group id, canoverwrite, can replace and is version. These operatorsare represented internally in KuangPlus as u, g, w,r or v respectively. An object is one of a numeric userid or group id, a pathname or a versioninstance. A user or group object should only be associated with theappropriate can obtain .. operator. A pathname object can beassociated with either a can overwrite or can replaceoperator. It follows that an is version operator should onlybe associated with a version instance.
The descriptive definition for a rule given above canalso be stated in notation as:
<plan> := <rule> <rule> [<rule> ...]
<rule> := <co> <co>
<goal>|<known> := <co>
<co> := <op> <ob>
<op> := u | g | w | r|v
<ob> :=[-0-9a-bA-B/.*]+
where (--> represents the term can only be associated with)
<op> u | g --><ob> of type numeric or .*
<op> w | r --> <ob> of typealphanumeric plus /.-
<op> v --> <ob> alphanumeric plus.-
6.5.2 Example rules
Therepresentation of a rule, and hence its interpretation, is from right toleft in terms of COs. Some simple example rules, with theirexplanation follow:
u 0 w /etc/passwd
This rule represents the knowledge that ifthe file /etc/passwd is writeable, then user id 0 is achievablei.e. superuser.
w /etc/group u .*
This rule indicates that any userid can write to the /etc/group file.
u .* v Linux-2.0.34
This ruleindicates that if version 2.0.34 of Linux is the operating system, then anyuser can get access to the system.
6.6 What is a maxim?
The maxims form a "flat database of vulnerabilityinformation contained in a series of files in a specific directory. Thedirectory in which they are located has a default location, which is thesame place as the tool itself, in the sub-directory "maxims".However, a command line option will enable the user to nominate a differentdirectory full of maxims. A given maxim may contain Perl code to generateseveral different rules if appropriate, or it may just create one rule. Thescope of what Perl code is in a maxim is limited in terms of theoperations available within the Safe compartment in which the maximis evaluated.
6.6.1Simple maxim example
Thefollowing example is of a relatively simple maxim. It interacts with thesystem through the Safe uname operation and loads a rule if theoperating system matches the one nominated in the maxim.
package Linux;
main::pdebug "Loading Linux rule now ...", 6.1;
# CIAC_J035 -
# ESB-1999.039 -- CIAC Bulletin J-035
# Linux Blind TCPSpoofing
# 22March 1999
subCIAC_J035 {
my($description) = "CIAC_J035";
# The uname array has something like this in it:
# Linux (none) 2.0.34 #1Fri May 8 16:05:57 EDT 1998
# i486 unknown
my($version) = (main::uname())[2];
@frag = split('.', $version);
if (($frag[0] <= 2 ) && ($frag[1] <= 0) &&
($frag[2] <= 36)) {
# This rule is triggered if theversion of the
# Linux kernel
# running on this machine is less than a known level.
#Note
# that we record the string "Linux-$version" using
# the
# kernelversion of this system so that the "known_
# facts"
# will match itwhen the "rule_engine" chews over all
# the plans.
$main::new_plans{"u -1 vLinux-$version"} = $description;
}
}
my(@uname) = main::uname();
if ( "$uname[0]" =~ /Linux/ ) {
main::pdebug "Invoking Linux rule set", 6.3;
CIAC_J035();
} else {
main::pdebug"Skipping run_Linux rules", 6.3;
}
A morecomplicated maxim is shown in Appendix I. It interacts with the system toget user account information and file permissions. All this interaction isthrough the Safe operations provided in the safeops.plmodule.
6.7 Sample output fromrunning the prototype
Thefollowing example reflects a run of the KuangPlus prototype on a Linuxsystem where the system had been previously seeded with a writeable/etc/group file.
Success: "u 0 w/etc/passwd g 0 w /etc/group u .* v Linux-2.0.34"
To explain this output, refer to the earlier discussion of a planwhere it was noted that the plan is presented with the goal on the lefthand side and the known condition on the right hand side. Hence, theexploit shown above describes a situation where, due to a problem inthe implementation of version 2.0.34 of Linux, anyone could gain access tothe system. Having gained access, the /etc/group file is found tobe writeable, and thus the group id 0 can be achieved. With accessto group id 0, it is possible to write to the/etc/passwd file which in turn will enable access to the superuseraccount, user id 0.
TheKuangPlus prototype can also provide a more mechanical explanation of theabove exploit by using the verbose mode option when KuangPlus isinvoked. The verbose mode will also display any strings which wereassociated with the rule when it was created by the evaluation of amaxim. Below, the known information is the version of the operatingsystem, which is shown to be derived from the POSIX::uname() systemcall. The verbose output also shows that the vulnerability which gives riseto this exploit, namely the version of the Linux system, isdescribed in the security bulletin CIAC J035.
Success: "u 0 w /etc/passwd g 0 w /etc/group u .* vLinux-2.0.34"
Theverbose breakdown follows:
The goal is "u 0"
Plan: "u 0 w /etc/passwd"
(root access via. writeable/etc/passwd)
(verbose) you can get access to userid 0 if
(verbose) you can overwrite file/etc/passwd if
Plan: "w /etc/passwd g 0"
(/etc/passwd is writeable by gid 0)
(verbose) you can overwrite file/etc/passwd if
(verbose) you can get access to the gid 0 if
Regex Plan: g .* w /etc/group == g 0w /etc/group
(/etc/group can be overwritten)
Plan: "w /etc/group u .*"
(/etc/group is world writeable)
(verbose) youcan overwrite file /etc/group if
(verbose) you can get access to userid .* if
Regex Plan:u -1 v Linux-2.0.34 == u .* v Linux-2.0.34
(CIAC_J035)
Known: "v Linux-2.0.34"
(From POSIX::uname()call.)
Property 7, as listedin the design goals (Chapter 5) was that all exploits should be found bythe tool, not just the first one encountered. The following example showsthe same Linux system as used in the previous examples, with theseeded vulnerability that the /etc directory isworld writeable. Whereas in the previous examples, there was only oneexploit listed, this example shows that KuangPlus will do an exhaustivesearch to find all exploits possible (some of the exploits listed are widerthen the page width so the lines have been wrapped to the next linefor readability).
Success:"u 0 r /etc/rc.config u .* v Linux-2.0.34"
Success: "u 0 r /etc/passwd u .* v Linux-2.0.34"
Success: "u 0 r /etc/hosts.eqiv u .* vLinux-2.0.34"
Success: "u 0 r/etc/rc.single u .* v Linux-2.0.34"
Success: "u 0 r /etc/aliases u .* v Linux-2.0.34"
Success: "u 0 r /etc/rc.local u .* v Linux-2.0.34"
Success: "u 0 r /etc/rc u .* vLinux-2.0.34"
Success: "u 0 r/etc/rc.boot u .* v Linux-2.0.34"
Success: "u 0 r /etc/rc.config g 0 r /etc/group u .* v
Linux-2.0.34"
Success: "u 0 r /etc/passwd g 0 r /etc/groupu .* v Linux-2.0.34"
Success:"u 0 r /etc/hosts.eqiv g 0 r /etc/group u .* v
Linux-2.0.34"
Success: "u 0 w /etc/passwd g 0 r /etc/group u .* vLinux-2.0.34"
Success: "u 0 r/etc/rc.single g 0 r /etc/group u .* v
Linux-2.0.34"
Success: "u 0 r /etc/aliases g 0 r /etc/group u .* v
Linux-2.0.34"
Success: "u 0 r/etc/rc.local g 0 r /etc/group u .* v
Linux-2.0.34"
Success: "u 0 r /etc/rc g 0 r /etc/group u .* vLinux-2.0.34"
Success: "u 0 r/etc/rc.boot g 0 r /etc/group u .* v
Linux-2.0.34"
6.8 Lines of code in the prototype
The kuangplus.pl module, which implements thefront end is implemented 348 lines of code (without counting commentlines).
Thesafeops.pl module, which implements the sub-routines for theSafe compartment is 88 lines of code.
The engine.pl module, which contains the code forthe inference engine is 187 lines of code.
Chapter 7: Effectiveness and applicability of KuangPlus
In theprevious chapters a number of perceived weaknesses were identified withrespect to a selection of public domain tools available. From that basisthe new tool, KuangPlus, was designed and developed. In this chapter, theeffectiveness of the KuangPlus prototype in meeting the originaldesign criteria will be discussed.
The five original weaknesses were identified as being a lack ofgenerality, a need for active maintenance, a loss of relevance, the lack ofa trust model and the lack of timeliness. These five weaknesses were thenrestated in the form of 11 properties which either directly relatedto the weaknesses or indirectly supported the aim of addressing theweaknesses. It is appropriate then to assess the KuangPlus prototypeagainst each of the 11 properties to see how well it supplies them.
The first property required the separation ofthe vulnerability database from the tool in order to address therelevance weakness. The KuangPlus prototype has a core whichcontains no knowledge of any security vulnerabilities. All the securityknowledge is encoded as maxims and loaded at runtime. In this wayproperty 1 is supplied.
Thesecond property required that the tool be implemented in a way that wasindependent of the hardware and operating system on which it ran. Theprototype was written in Perl to attempt to address this by implementingthe tool using a language which is commonly available on a diverserange of platforms. Further, by using the Perl library routines to makesystem calls, a level of abstraction will be obtained from the underlyingoperating system. The prototype was developed on a series of Unixlike systems - FreeBSD, Solaris and Linux - so undoubtedly it is notappropriate at this stage for a different system like NT or MacOS. However,the prototype has proven the concept and further development could be madeto make it more generalised by removing any operating systemdependencies found. This would lead to the observation that the secondproperty has been at least party met in the prototype.
The third property has been satisfied by the separationof the core functionality of KuangPlus from the database ofvulnerabilities. The core functionality is supplied by thefrontend, inference engine and safe operationscomponents. The database is implemented in a series ofmaxims loaded at runtime.
The fourth, fifth and sixth properties concerned thenotion oftrust and how much was enforced by the tool. The tool is simple indesign with the clear separation of the functionality into separate Perlmodules. Further, by using Perl, the system administrator is able toread any aspect of the core or the maxims in order to satisfythemselves that the tool will work as documented and expected. The sixthproperty related specifically to the evaluation of the maxims and the factthat the evaluation of any maxim should not effect the system or theevaluation of other maxims. The Perl Safe module allows theKuangPlus prototype to meet this requirement. Firstly, Safe allows theevaluation to be done in a compartment which isolates it from both the tooland the system on which it runs. By permitting only certainoperations and sharing sub-routines into the compartment which controlaccess to the system the evaluation can be trusted not to interfere withthe system or tool. By creating a new Safe compartment for theevaluation of each maxim, we are further guaranteed that the maxims will beisolated from each other because they will not have any sharednamespace.
Property 7 addressedthe concern that the tool should find all possible vulnerabilities ratherthan just prove that it is possible by finding one. The construction of theinference engine is such that it does an exhaustive search of all the ruleslooking for any that allow a plan of compromise to be created. Theseare all reported and as such property 7 is supplied by the KuangPlusprototype. Further, because an inference engine is used property 8 is alsosupplied.
Disappointingly,property 9 has not been met at all. It was not possible in the timeavailable to implement this facility. It remains to be seen whether futurework will address this shortcoming, although it is conceivable that itwould not be too hard to do.
The rule language is well described in these pages andshould, with the examples given of rules and maxims, allow further maximsto be successfully developed. This should suffice to show that theKuangPlus prototype shows property 10 as well.
The final property, that of being applicable to a widerange of system administration skills, is met by providing theverbose flag when the KuangPlus prototype is invoked. When inverbose mode, KuangPlus explains in great detail what a plan means. Theimplementation of automatic maxim downloading as per property 9would have further enhanced KuangPluss ability to exhibit property11.
To review the previous paragraphs. All butone of the properties, property 9, described in the design goals have beenmet completely or in part. The one property that was not included is notprevented by any restriction in the concept of design and as suchthere is no impediment for it to be added by future developments of theprototype.
It must be obviousfrom this text that testing of the prototype has been done using contrivedexamples. Whilst the author is satisfied that this has not invalidated theapproach taken, further development of the maxims available and exposure tothe wider security community should dispel any lingering doubt as tothe applicability of the prototype. In operation, KuangPlus proved capablein exposing the seeded weaknesses in the system when single andmultiple vulnerabilities existed. This indicates that the concept ofKuangPlus is applicable as a tool in assessing security vulnerability in acomputer system.
Chapter 8: Futuredirection
Theprototype has been created and discussed in some length in the previoussection. The time constraints of this work are such that not everythingthat was considered desirable for the tool has been included. In thissection the possible direction for future work is presented.
8.1 Authentication and integrity ofrules
It was considered inthe initial proposal that a system administrator should be given theability to authenticate the writer of the rule and also to verify that theintegrity of the rule was in tact i.e. nobody had altered the contents ofthe rule. The "Pretty Good Privacy" package developed by PhilZimmerman (in [Garf96, p. 179]) was considered a likely candidate for thisrole. Whilst developing the package the author has also become aware of the"Penguin" module [Wall96, p. 362] which seems tailor made for thisrole. Its author, quoted in Garfinkel et al. [Wall96, p. 363], describesPenguin as having "vastly simplified, superior, and innate methods ofensuring safety and security". As of 1996 when the book to which thepreceding references apply was published, Penguin was not a part ofthe standard Perl distribution, but Garfinkel et al. considered it a verylikely candidate for inclusion.
8.2 Generation of "net" interest
For a tool such as the one described here to be of muchvalue to anyone beyond myself as an academic exercise, a comprehensive setof rules needs to be created. The original conception of this tool includedvendors and other security related organisations publishingvulnerabilities in a form which could automatically be interpreted byKuangPlus without any need for system administrators to be involved in theprocess.
Another tangiblebenefit in generating "net" interest in the prototype as it stands is sothat the concept and design of the prototype can be examined and criticisedby the security community at large.
8.3 Making use of vulnerability databases
Another possibility which might deserveinvestigation is that of reshaping the "language" of KuangPlus to leveragethe work of the groups which currently assemble databases ofvulnerabilities. For example the work of "The MITRE Corporation" [MITR99a]in attempting to define a "Common Vulnerability Enumeration" looksinteresting. Some of the other databases that exist are the ISS X-ForceDatabase [XFor99], the "SAFER" bulletin [Siam99], and the AusCERT effort[AusC99].
8.4Reporting formats
It shouldbe a reasonably straightforward task to take the current exploit reportingroutines and recreate them so that they will also output in other usefulforms - the immediate one that springs to mind is HTML. Other possibilitiesmight be email or even XML.
8.5 Testing on other platforms
One of the original design goals was to create asufficiently general tool which could be put touse on any platform. Theprototype has been developed and tested on FreeBSD, Linux and Solaris. Itsgenerality remains to be proven on other platforms such as NT andMacOS.
Chapter 9: Conclusion
There is a wholeclass of problems associated with a computer system with regard torestricting those with access to it, from going beyond the boundaries whichare set by a reasonable site security policy. The scope of this work wasthen described as being with the particular subset of problemsassociated with vulnerabilities in a computer system, either through poorconfiguration choices or faulty software or a combination of the two. Withthe aid of examples, it was shown that the problem is evident in awide variety of systems and has a demonstrable economic cost to thecommunity right now. In a small sample of organisations, the cost was putat some $US123 million [Good99a]. Further, it was suggested that in theforeseeable future there is evidence to suggest that the number andvariety of vulnerabilities will increase [AusC99, Lor99] and the costassociated with the exploitation of these vulnerabilities will increase[Good99a]. There is also an indication that most of the vulnerabilities aresimple to fix when they have been identified and they are reasonablyeasy to identify [Farm94]. This leads to the application of automatedtechniques in the form of security "tools" to discover and report on thepresence of vulnerabilities.
Havingestablished the problem is worth paying attention to, and that it is anappropriate problem for an automated solution, some of the tools currentlyavailable to system administrators were examined. This examination wasrestricted to public domain tools as they are the most available tosystem administrators and there is a readily accessible body ofdocumentation on using them and what they are good for. It was observed inthis work that the set of tools currently available have some or all of thefollowing short comings: They were not constantly updated with newinformation as it became available; they were generally unable to pick upvulnerabilities which were not envisaged when they were created; they werespecific to a particular operating system in the exploits that theyfound; they were generally restricted to a small set of platforms that theycould be run on; and they included within their construction the "database"of vulnerabilities along with what ever logic is required to try anddiscern whether or not he system under examination wasvulnerable.
A new tool was thendescribed, called "KuangPlus", which would have as its design goalovercoming the shortcomings previously enumerated. The design would use "onthe fly" loading to access a database of vulnerabilities called maximswhich would be interpreted to produce "rules". The rules could thenbe assessed by a backward chaining, goal based, breadth first inferenceengine to search for vulnerabilities. Any vulnerabilities detected would bereported. The implementation choices which need to be made werediscussed and a prototype based on these choices was presented. Theprototype was shown to be a good match with the original design goals.Future development of the prototype was suggested which involved developingautomatic methods for "authenticating" the maxims, generatinginterest in the tool on the "net"to open the prototype to scrutiny andgenerate interest in writing maxims.
The further development of KuangPlus along the lines presented abovehas the capacity to create a tool which is general enough to run on justabout any computing platform whilst a rich and timely set of maxims wouldenable any publicly identified vulnerability, in either theconfiguration or the software running on the system, to be exposedpro-actively by the system administrator. This will prove to be much morethen an academic pursuit as the economic cost to the community has beenassessed as being in the order of millions in a sample oforganisations and, extrapolating from that, in the order of billionsworldwide [Good99a].
Bibliography
[Anon99a] Anonymous. "Closing theOpen (Source) Doors: Common Linux Security Vulnerabilities and Solutions".May 24, 1999. Published electronically at:http://www.securityportal.com.
[Anon99b] Anonymous. "The Futureof Information Security: Trust No "1" (Reflections on the SecurityResearch Alliance Crystal Ball Symposium)". April 26, 1999. Publishedelectronically at: http://www.securityportal.com.
[Aust99]Computer Section. Published in "The Australian" newspaper. Tuesday, May18.
[AusC99] Australian Computer Emergency Response Team(AusCERT). "External Security Bulletins Released in 1999". Viewed October31, 1999. Published electronically at: http://www.auscert.org.com/.
[Bald??] Baldwin, Robert W. "Kuang: Rule-Based Security Checking". Itis unclear when this paper was produced. Lab for Computer ScienceProgramming Systems Research Group, MIT.
[Bora99] Boran, Sean."Hardening Solaris: Securely installing a firewall bastion host". October,1999. Published electronically at: http://www.securityportal.com/
[Chri98] Christiansen, Tom and Nathan Torkington. "Perl Cookbook:Solutions and examples for Perl programmers". 1998. O'Reilly andAssociates, California.
[CNET99] Cnet news service.Viewed October 31, 1999. Published electronically at:http://news.cnet.com.
[Farm94] Farmer, Daniel and Eugene H.Spafford. "The COPS Security Checker System". July 28, 1994. PurdueUniversity Technical Report CSD-TR-993. The paper originally appeared inthe proceedings of the Summer Usenix Conference, 1990, Anaheim,California.
[Garf96] Garfinkel and Spafford. "Practical Unix andInternet Security". 2nd Edition. 1996. O'Reilly and Associates,California.
[Gibs84] Gibson, William. "Neuromancer". 1984. Referencedin [Bald??]
[Good99a] Goodin, Dan. "Accounting firms fightcybercrime". June 7, 1999. Available electronically at:http://news.cnet.com.
[Good99b] Goodin, Dan. "USIA site hackedagain by crafty cracker". January 21, 1999. Published electronically at:http://news.cnet.com/category/0-1005-200-337641.html
[Lor99]Lor, Sam. "The Effect and Handling of Resent Security Incidents". AusCERTreport in conference proceedings of "AUUG Tenth Annual Canberra Conferenceand Workshops" held at the Australian National University, February 12,1999. AUUG, Canberra.
[Mitr98] Mitra, Rajib K. "UNIX Security".1998. Published electronically at:http://www.spy.net/~jeeb/unix_security.html.
[MITR99a] Mann, DavidE., Steven M. Christey. "Towards a Common Enumeration of Vulnerabilities".January 8, 1999. Published electronically at: "http://cve.mitre.org/".
[MITR99b] "Terminology: Vulnerability and Exposures". Publishedelectronically at: "http://cve.mitre.org/exposures.html".
[Perl98a]Online documentation distributed with version 5.004 of Perl. It can beaccessed using the "man" command or the "Perldoc" command as in manSafe or "Perldoc Safe". On the Linux system that this code was largelydeveloped on, the actual file is at"/usr/lib/Perl5/man/man3/Safe.3".
[Perl98b] Online documentationdistributed with version 5.004 of Perl. It can be accessed using the "man"command or the "Perldoc" command as in man Opcode or "PerldocOpcode". On the Linux system that this code was largely developed on, theactual file is at "/usr/lib/Perl5/man/man3/Opcode.3".
[Samm99]Sammons, Nathaniel. "RSCAN User's Guide: Version 1.4.0". October 31, 1999.Published electronically at: http://www.vis.colostate.edu/rscan.
[Siam99] Siam Relay Ltd. "Security Alert for Enterprise Resources(SAFER)". September 1999. Volume 2, Issue 9. Monthly publication availableelectronically by subscription at http://safer.siamrelay.com.
[Sriv97]Sriram Srinivasan. "Advanced Perl Programming". 1997. O'Reilly andAssociates, California.
[Turn87] Turner, George W. (Ed.).The Australian Concise Oxford Dictionary. 1987. Oxford UniversityPress, Melbourne.
[Wall96] Wall, Larry, Tom Christiansen &Randal L. Schwartz. "Programming Perl". 2nd Edition. 1996. O'Reilly &Associates, California.
[XFor99] "ISS Security AlertSummary". September 15, 1999. Volume 4, Number 7. Internet SecuritySystems. Published electronically at: http://xforce.iss.net/
[Zerk??]Zerkle, Dan and Karl Levitt. "NetKuang - A Multi-Host ConfigurationVulnerability Checker". It is unclear when this document was created.Department of Computer Science, University of California at Davis.
Appendix A: Perl code from KuangPlusprototype
kuangplus.pl
#!/usr/bin/perl -Tw
# -T - Force "taint" checks to be turned on.
# -w - Warn about anything which looks likebad code.
require 5.004;
package KuangPlus;
###Begin user configurable options section
# directory in which to find the othermodules which are part of kuangplus,
# namely engine.pl and safeops.pl. Also used as thedirectory in which the
# "maxims" are expected if the "-m" option isn't used on the commandline.
$KuangPlus::kuang_home = "/home/jhoward/Kuangplus/new-work/wip";
### End user configurable options section
###
### N.B. the order of declaration is "use" first,followed in order by
### global variables, local "require" statements, command lineargument
###processing, subroutines declaration and then "MAIN" logic.
use Getopt::Long; # for GetOptions functionused for command line args parsing.
use strict;
use Safe; # for compartmentalising maxims.
$ENV{PATH} = "/bin"; # Because we'rerunning in taint if for no other reason.
push(@INC,$KuangPlus::kuang_home); # so we can find things undertaint and if we
# aren't being run from the directory containing
# thesupporting utilities.
### load other modules
# the psuedo safe operations for maxims to call.
require"$KuangPlus::kuang_home/safeops.pl";
# the "engine.pl" file defines the "Engine"namespace.
require"$KuangPlus::kuang_home/engine.pl";
### end of module loading
### usage message
$KuangPlus::usage = "
usage: $0 [-d[=<level>]] [-v] [-h] [-m=<pathname>]
$0 finds security concerns in theconfiguration of the system it is run on.
-h, --h, -help, --help
- Prints this message and exits.
-v, --v, -verbose, --verbose
- verbose output. Onfinding a successful exploit, any
information relevant to the exploit isprinted.
-m=<dir>,--m=<dir>, -maximdir=<dir>, --maximdir=<dir>
- nominate the directory in which the"maxims" can be found. By
default this is the directory "maxims" in the samedirectory as
the "kuangplus.pl" script was invoked from.
-d[=level], --d[=level], -debug[=level],--debug[=level]
-Various debugging information is available. The "=level"
argument indicates whatinformation is of interest. With no level
specified, "all" debugginginformation is printed. The following,
"-d=1", "-d=.1" and "-d=1.1", are all validlevels. The following
are the attributes attached to the different levels:
1 - main.1 - file access
2 - humanize() .2 - @plan arrayaccess
3- addto() .3 - miscellaneous messages
4 -init_kuang() .5 - @known array access
5 - evaluate_plans().6 - rejected rules
6 - maxim files
7 - command line argumenthandling
8- print_success()
9 - find_match()
10 - safeops - stat()
11 - safeops - uname()
12 - safeops -getpwent()
13 - safeops - getpwname()
14 - safeops - getpwuid()
15 - safeops - general
16 - rule_qc()
";
### end of usage message
### initialise and set options,
$KuangPlus::debug = ""; $KuangPlus::verbose =""; $KuangPlus::help = "";
# Where to find maxims by default
$KuangPlus::maxim_dir ="$KuangPlus::kuang_home/maxims";
@KuangPlus::original_ARGV = @ARGV;
# process command line arguments. @ARGV iscleaned out of all
# arguments unless the "--" is given to terminate command line
# argumentprocessing. If no argument is given to an option
# which can have an argument, such as '-d',then
# thecorresponding variable, i.e. $KuangPlus::debug, is set to 0.
$KuangPlus::go_return =Getopt::Long::GetOptions(
"debug|d:f", $KuangPlus::debug,
"verbose|v",$KuangPlus::verbose,
"help|h", $KuangPlus::help,
"maximdir|m=s",$KuangPlus::maxim_dir
);
$KuangPlus::debug = "all" if ( $KuangPlus::debug eq "0" );
pdebug("Level $KuangPlus::debugdebugging turned on.", $KuangPlus::debug);
pdebug("Before processing, ARGV was"@KuangPlus::original_ARGV"", 7.3);
pdebug("debug = "$KuangPlus::debug", help ="$KuangPlus::help", verbose = "$KuangPlus::verbose",", 7.3);
pdebug("GetOptionsreturn is "$KuangPlus::go_return", and ARGV is "@ARGV"", 7.3);
if ( "@ARGV" ne "" || "$KuangPlus::help" eq"1" ) {
print $KuangPlus::usage;
exit 0;
}
### endof option handling
###define sub-routines
# humanize()
# Re-presents a controlling operation in a human readable formi.e. an
#operation like "w /etc/passwd" is re-presented as "overwrite file
#/etc/passwd".
#
# Calls:KuangPlus::pdebug()
# Called by: KuangPlus::print_success()
# Expects: a controlling operation i.e. anoperator object pair
# Returns: none.
# Side effects: causes message to be printed to STDOUT.
# Global variables: none
# Private variables:$co_s, $string, $leader, @co_a, $op, $ob,
sub humanize {
my($co_s) = $_[0];
my($string);
my($leader) = "(verbose)";
pdebug("humanize($co_s)",2.3);
my(@co_a) = split(' ',$co_s);
while ( @co_a ) {
my($op) = shift(@co_a); # changeorder & use "pop" to get it printed in
my($ob) = shift(@co_a); # event order rather thanbackward chain.
pdebug("humanize(), working with op: "$op" and ob: "$ob"",2.3);
if ( $op eq"u" ) {
if ( $ob eq "-1" ) {
$string .= "$leader you can get access to the systemif";
} else {
$string .= "$leader you can get access to userid $ob if";
}
} elsif ($op eq "g" ) {
$string .= "$leader you can get access to the gid $ob if";
} elsif ( $op eq "r" ){
$string.= "$leader you can replace file $ob if";
} elsif ( $op eq "w" ) {
$string.= "$leader you can overwrite file $ob if";
} elsif ( $op eq "v" ) {
$string.= "$leader operating system is version $ob if";
} else {
$string .= "$leader $op $ob (notranslation)";
}
}
print "$string";
} # end of humanize()
# print_success()
# Prints out the successful "plan",breaking it up into rules and prior
# knowledge.
# Calls: KuangPlus::pdebug(), KuangPlus::humanize()
# Called by: main
# Expects: a stringcomprising a series of controlling operation pairs.
# Returns: nothing
# Side Effects: prints to STDOUT
# External references:$KuangPlus::verbose, %KuangPlus::plans,
# %KuangPlus::known_facts
# Private variables: @elements, $offset,$index, $leader, @co_a
sub print_success {
my(@elements) = split('',$_[0]);
my($leader) = "";
pdebug("print_success(@elements)",8.2);
print ":"@elements"";
if ( $KuangPlus::verbose ) {
print "The verbose breakdown follows:";
# The firstco is the goal, by definition
print "$leader The goal is"@elements[0..1]"";
# The last co must be known or we couldn't have got here. Sotake a copy
#of it for later use
my($known) = $elements[$#elements - 1] . " " .$elements[$#elements];
# The rest we know were loaded in the plans array
my($offset,$index);
my($co_s) .=shift(@elements)." ".shift(@elements);
while ( @elements ) {
$co_s .= " ".shift(@elements)."".shift(@elements);
pdebug("print_success: Checking out how came"$co_s"",8.2);
if ( defined($KuangPlus::plans{$co_s} ) ) {
print "$leader Plan:"$co_s"$leader(".
$KuangPlus::plans{$co_s} .")";
humanize($co_s);
} elsif ( my($match) = find_regexp_plan($co_s) ) {
print "$leader Regex Plan:$match == $co_s$leader(" .
3 $KuangPlus::plans{$match} .")";
} else {
print"Can't find "$co_s" in %plans ... this shouldn't happen.";
}
$co_s =~ s/.*(+[/.]+)/$1/;
}
print "$leader Known:"$known"$leader(".$KuangPlus::known_facts{$known} .")";
}
} # end of print_success()
# find_regexp_plan()
# Given a controlling operation pair,look for a regular expression
# match in the %KuangPlus::plans assoc. array.
# called by:print_success.
#expects: a co pair
# returns: the plan match if found, 0 otherwise
# side effects: none
# globals used: %KuangPlus::plans
sub find_regexp_plan {
my($co_s) =$_[0];
foreach (keys(%KuangPlus::plans) ) {
pdebug("find_regexp_plan: comparing "$co_s" and"$_"",9.3);
if ( ( "$_" =~ "$co_s" ) || ( "$co_s" =~ "$_" ) ) {
return $_;
}
}
return 0;
}
#pdebug()
# printdebugging statemement if necessary. Takes a string and a level as
# arguments. Thelevel should be a real number. The whole part should
# reflect the procedure the debuggingstatement came from, the fractional
# part should reflect what the debugging statement refersto. If the
#debugging option is in place, and the level matches the debugging level
# specified then thissub-routine will cause the string to be printed. If
# the debugging option is only specified witha "-d" and no level, then
# all debugging statements will be printed.
#
# Calls: print()
# Called by: numerous procedures throughout code.
# External variablesused: $KuangPlus::debug
# Expects: A string.
# Returns: None.
# Side effects: causes a string to be printed to STDOUT ifappropriate.
#
sub pdebug {
my($string) =$_[0];
my($level) = $_[1];
my($whole_level,$frac_level);
3 # whole_level reflects where the call came from i.e. procedurelevel
($whole_level = $level ) =~ s/(+).+/$1/;
# frac_level reflects what the call isdoing. e.g. manipulating the plan
( $frac_level = $level ) =~ s/+(.+)/$1/;
if ( $KuangPlus::debug eq "") {
# check tosee if debug is set first, since this is the most
# likely case. Do nothing if itisn't.
}elsif ( $KuangPlus::debug eq $level ||
$KuangPlus::debug eq $whole_level ||
$KuangPlus::debug eq $frac_level ||
$KuangPlus::debug eq "all" ) {
print "debug($level):$string";
}else {
#If the level of interest (in $KuangPlus::debug) doesn't
# match the level of thismessage (in $level or its derivatives),
# do nothing.
}
# If the level is '*' then always print it, no matterwhat the
#debugging flag is set to.
if ( "$level" eq '*' ) {
print "debug($level): $string";
}
} # end of pdebug()
# KuangPlus::rule_qc()
# Calls:
# Called by:
# External variables used:
# Expects: first arg is a string representinga plan. Second arg is the
# file from which it was loaded.
# Returns:
# Side effects:
# Debug hooks used: major - 16.
sub KuangPlus::rule_qc {
my($new_plans_r)= $_[0];
my($f_r) = $_[1];
my($plan,$rule,@els,$el0,$el1);
foreach $rule ( keys(%$new_plans_r) ) {
my($qc_failed) = 1;
pdebug "rule_qc():testing $rule ($$f_r) now ...", 16.3;
(@els) = split('',$rule);
if ( @els != 4 ) {
KuangPlus::pdebug
"rule_qc(): ignoring incomplete rule:"$rule" ($$f_r)",
16.6;
} else {
while ( @els &&$qc_failed ) {
$el0 = shift(@els);
$el1 = shift(@els);
KuangPlus::pdebug
"el0 is"$el0" and el1 is "$el1" ..",
16.3;
if ( $el0 =~ /^[wr]$/ && $el1=~ /^[/-.]+$/ ) {
# its a good w|r CO
if ( SafeOps::stat($el1)) {
$KuangPlus::plans{$rule} = $$new_plans_r{$rule} ;
KuangPlus::pdebug "rule_qc(): Loading "$rule".", 16.2;
} else{
KuangPlus::pdebug
"rule_qc(): "$el1" doesn't exist($$f_r)",
16.1;
}
} elsif ( $el0 =~ /^[ug]$/ && $el1 =~/^(([-]+)|(.))$/ ) {
# its a good u|g C0
$KuangPlus::plans{$rule} = $$new_plans_r{$rule} ;
KuangPlus::pdebug"rule_qc(): Loading "$rule".", 16.2;
} elsif ( $el0 =~ /^v$/ && $el1 =~/^[-.]+/ ) {
# its a good v C0
$KuangPlus::plans{$rule} =$$new_plans_r{$rule} ;
KuangPlus::pdebug "rule_qc(): Loading"$rule".", 16.2;
} else {
KuangPlus::pdebug
"rule_qc(): invalid rule:"$rule" ($$f_r)",
16.6;
$qc_failed =0;
} #if
} #while
} # if
} #foreach
} # endof KuangPlus::rule_qc()
### endof sub-routine definitions.
####
## MAIN logic follows
####
# Define what we know:
# Generally known things -
$KuangPlus::known_facts{"u -1"}= "Anybody has access.";
# Things about the platform we are running on derived from uname()call
@KuangPlus::uname =KuangPlus::uname();
$KuangPlus::known_facts{"v$KuangPlus::uname[0]-$KuangPlus::uname[2]"} =
"From POSIX::uname() call.";
if ( $KuangPlus::debug =~ /.5/ ) {
pdebug"Generating "known" file for reference ...", 1.5;
open(K,">known") or die "Can't open fileto dump known facts in";
print K "# file generated at ".`date`."#";
print K "## These are the facts areprior knowledge.#";
print K "# uname:# @KuangPlus::uname#";
my($fact);
foreach $fact(keys(%KuangPlus::known_facts)) {
pdebug("I know this:$fact($KuangPlus::known_facts{$fact} )", 1.5);
print K "$fact($KuangPlus::known_facts{$fact} )";
}
close(K);
}
pdebug "Ready to loadrules, maxim_dir is "$KuangPlus::maxim_dir"", 6.1;
opendir(Rules,"$KuangPlus::maxim_dir") or die "Can't openmaxims subdirectory";
my(@rule_files) = readdir(Rules);
closedir(Rules);
foreach (@rule_files) {
next if ( /(.|..)/ ); # skip current and parentdirectories
# The followingline "untaints" the string we want to require later. We
# use the result of the search pattern as$1 in setting $rule_file.
# "" matches with a "Word character" ([a-zA-Z_0_9]).
if ( /^(+)$/ ){
my($rule_file) = "$KuangPlus::maxim_dir/$1";
if ( -f $rule_file ) {
# variables shar'd tosafe compartments
%KuangPlus::new_plans = ();
pdebug "loading "$rule_file" togenerate plans ...",1.1;
$KuangPlus::cmpt = new Safe;
$KuangPlus::cmpt->share_from('KuangPlus',
['&pdebug','%new_plans']);
# Thislittle bit of code automatically loads every sub-routine
# loaded in the"SafeOps::" namespace.
my($routine,$fullname);
foreach $routine(keys(%SafeOps::)) {
$fullname = "SafeOps::$routine";
if ( defined(&$fullname) ){
pdebug "It appears I should load "&$fullname"", 15.3;
$KuangPlus::cmpt->share_from('SafeOps',['&'."$routine"]);
}
}
# This is how I firsttried to use load routines from SafeOps::
#$KuangPlus::cmpt->share_from('SafeOps',
# ['&uname', '&stat','&getpwent', '&getpwnam', '&getpwuid']);
$KuangPlus::cmpt->rdo($rule_file);
if ( "$@"ne "" ) {
KuangPlus::pdebug "Problem with rule "$rule_file": $@", '*';
} else{
KuangPlus::rule_qc(%KuangPlus::new_plans,$rule_file);
}
KuangPlus::pdebug "finishedloading "$rule_file".",1.1;
undef $KuangPlus::cmpt;
} else {
print STDERR "Skipping irregularrule file "$rule_file"";
}
} else {
print STDERR "Bodgy file name "$_" skipped";
}
}
pdebug "Prior to invoking rule-engine, plans are:".keys(%KuangPlus::plans),1.2;
if ( $KuangPlus::debug =~ /.2/ ) {
pdebug "Generating "plans" file forreference ...", 1.2;
open(P,">plans") || die "Can't open plan file for debugging dumpof plans";
printP "# file generated at ".`/bin/date`."#";
print P "# Raw plans which will be chewedover by the rule engine#";
print P "# uname:# @KuangPlus::uname#";
my($i) = 0;
my($p);
foreach $p (keys(%KuangPlus::plans) ) {
print P "$p";
$i++;
}
print P "## Summary: $i plans in total.#";
close(P);
}
# Allthats left is to invoke Engine::evaluate_plans to chew over the
# "%plans"associative array.
@KuangPlus::successful_exploits =Engine::evaluate_plans(%KuangPlus::plans);
if ( $#KuangPlus::successful_exploits == -1 ) {
print "were no exploits detected.";
} else {
KuangPlus::pdebug "Successful_exploits are ".
""@KuangPlus::successful_exploits"", 3.0;
my($exploit);
foreach $exploit (@KuangPlus::successful_exploits ) {
print_success($exploit);
print "";
}
}
exit0;
engine.pl
package Engine;
use strict;
# initialise this one for later filling out by thisroutine. If we don't
# initialise it, then the mainline will be using an unitialised valuewhere
# nosuccessful exploits were found.
@Engine::successful_exploits = ();
# find_match()
# Find a match if one exists. There will be two sortsof matches. The
# firsttype, and easiest to find, is an exact match where the given
# string matches another stringexactly. The second type is where the
# given string comprises a wildcard, which will matchwith another string.
#
#Returns: 1 if a match is found, 0 otherwise.
# Expects: a CO string and the name of anasociative array to lookup.
# Called By: addto()
# Side Effects: none.
# External References: The associative array passed as the secondargument.
# Errors:None looked for.
subfind_match {
my($co) = $_[0];
my($name) = $_[1];
my($assoc_r) = $_[2];
my($key);
KuangPlus::pdebug "find_match(): Matching for "$co" in "$name"",9.3;
if ( defined$$assoc_r{$co} ) {
KuangPlus::pdebug "find_match(): simple, it was defined.",9.3;
return 1;
}
foreach $key(keys(%$assoc_r)) {
KuangPlus::pdebug "find_match(): test: "$co" =~"$key"?",9.3;
if ( "$co" =~ /^$key$/ ) {
KuangPlus::pdebug "find_match(): regex match found.",9.3;
return1;
}
}
return 0;
} # end of find_match()
# addto()
# selectively adds and evaluates plans with a view to gettingaccess to the
#superuser account. Popluates @Engine::successful_exploits as they
# are found.
#
# Calls: KuangPlus::debug()
# Called by:
# Expects: a list of at least 2 elements.
# Returns:
# Side effects:
# Externalreferences:
# Errors:looks out for plans which are the same as the objective.
sub addto {
my($op) = $_[0];
my($ob) = $_[1];
my($plan) = $_[2];
@Addto::plan = $plan ? split(' ',$plan) : ();
my($co) = "$op$ob";
my($i);
KuangPlus::pdebug
"addto(op:"$op", ob: "$ob" plan[".@Addto::plan."]: ".
""@Addto::plan")",
3.3;
# check to see if $op and $ob is "u 0". If the planis empty, then
# itsok to pursue this (i.e. its the initial goal). However, if
# the plan is not-empty, thenit is silly to pursue it because we can
# do what ever we like if we have rootaccess.
if ($op eq "u" && $ob eq "0" && $#Addto::plan >= 0 ) {
KuangPlus::pdebug "addto: silly topursue: "$co"", 3.3;
return;
}
# The%KuangPlus::known_facts associative array is populated with what
# access we haveat the moment and other "known" facts such as from
# the "uname" call. If the $co is amongstthe things we "know" then
# we have a chain of controlling operation pairs (a plan) which
# will take usbackward from the goal to a known fact i.e. SUCCESS
KuangPlus::pdebug "addto(): Checkingknown_facts for "$co"", 3.3;
if (Engine::find_match($co,"known_facts",%KuangPlus::known_facts) ) {
push(@Engine::successful_exploits,"@Addto::plan $co");
KuangPlus::pdebug
"addto(): added"@Addto::plan $co" to successful_exploits", 3.3;
}
# loop checker - make sure that the "$co" we're looking atdoesn't
#already appear in the plan we're looking at.
for ( $i = 0; $i <= $#Addto::plan; $i +=2 ) {
my($entry) = "@Addto::plan[$i .. $i+1]";
KuangPlus::pdebug
"addto(): loopchecker: comparing "$co" to "$entry"", 3.3;
if ($entry eq $co ) {
KuangPlus::pdebug
"addto(): loop found "$entry" eq "$co". ", 3.3;
KuangPlus::pdebug
"addto(): loop:"$co" is in "@Addto::plan" already.", 3.3;
return;
}
}
# add this $co to the existing @plan because it is not "known"and is not
# aloop. It will be later loaded as a new goal if we haven't already
# looked at this@plan
push(@Addto::plan, "$co");
#check to see if the plan has been done
if ( defined($Engine::beendone{"@Addto::plan"} ) ){
KuangPlus::pdebug
"addto(): This plan, "@Addto::plan", has been done.",3.3;
return;
}
# This plan hasn't been done already, sostore it in the "beendone"
# array ...
$Engine::beendone{"@Addto::plan"} = 1;
# and load it to "new" as it is worthpursuing further.
push(@Engine::new, "@Addto::plan");
KuangPlus::pdebug
"addto(): Adding "@Addto::plan" to@Engine::new plan array.", 3.3;
} # end of addto()
# ------------------
# init_kuang()
# Creates other data structures as required.
#
# Calls:
# Called by: evaluate_plans()
# Expects: Nothing.
# Returns:
# Global references: sets $KuangPlus::goal
# Errors: prints to STDERR if plan doesn'thave the correct ingredients.
#
sub init_kuang {
my($plans_r) = $_[0];
KuangPlus::pdebug "init_kuang: plans are ".keys(%$plans_r),4.2;
$KuangPlus::goal= "u 0";
#load pre-generated plans to search space. The pregenerated plans
# come from thescripts in the "rules/" subdirectory. By loading the
# plans into a new "search_space" array,we get the opportunity to
# discard anything that doesn't appear to be sensible. In thiscontext,
# arule which contains the goal on the RHS is silly to pursue i.e. we
# are looking forexploits to achieve the goal so it makes no sense to
# pursue a rule which requires the goalas a pre-existing condition.
foreach (keys(%$plans_r)) {
# The "next" line is only useful if we arereading from a file.
# next if ( /^#/ || /^$/ ); # ignore blank lines andcomments
if ( $_ =~ /^[ugrw] [^ ]+ $KuangPlus::goal$/ ) {
KuangPlus::pdebug
"Goal is on RHSof plan. Skipping "$_"", 4.6;
} else {
KuangPlus::pdebug
"init_kuang: loading "$_"to search space", 4.2;
push(@Engine::search_space,$_);
}
}
KuangPlus::pdebug
"init_kuang: search_space is"@Engine::search_space"", 4.3;
}
#------------------
# evaluate_plans()
# Main component of Engine
#
# Calls: init_kuang(), KuangPlus::pdebug()
# Called by: KuangPlus::
# Expects:
# Returns: nothing
# Side effects: prints out successful attacksif encountered.
#External references: uses $KuangPlus::goal.
# Errors:
#
sub evaluate_plans {
my($plans_r) = $_[0];
my($s_plan,$o_plan);
my(@old);
tx5040
init_kuang($plans_r);
KuangPlus::pdebug "goal: "$KuangPlus::goal"", 5.3;
if ( $KuangPlus::goal =~/^([ugrw]) ([^ ]+)$/ ) {
# initial setup for a new goal
@old = ();
@Engine::new = ();
%Engine::beendone =();
# As a sideeffect of the next "addto()" call, the "@Engine::new"
# variable is set to the goal. Notethat $1 and $2 are from the
# regular expression match in the "if" above.
addto($1, $2);
# Thefollowing "while" loop will continue trying to match the RHS
# of the goal(s) with theLHS of plans in the search space.
while ( $#Engine::new >= 0 ) {
KuangPlus::pdebug
"Starting search.".@Engine::new." goals: "@Engine::new"", 5.3;
@old =@Engine::new;
@Engine::new = ();
foreach $o_plan (@old) {
my(@o_plan) = split('',$o_plan);
my($o_op) = $o_plan[$#o_plan-1];
my($o_ob) = $o_plan[$#o_plan];
KuangPlus::pdebug "* matching for goal "$o_plan" ...", 5.3;
foreach $s_plan (@Engine::search_space ) {
my(@s_plan) = split(' ',$s_plan);
my($s_op) =$s_plan[0];
my($s_ob) = $s_plan[1];
KuangPlus::pdebug "** searchspace:"$s_plan"", 5.3;
KuangPlus::pdebug "** goal:"$o_plan"", 5.3;
#in order to make the regexp work, the regexp has to
# be on the RHS of thetest. However, there is a chance
# it will appear on either side so wehave to do two
# tests, where the second has the LHS and RHS
# transposed in relationto the first. Note the use of
# start '^' and end '$' characters onRHS to stop
# sub-string matches.
if (( "$o_op $o_ob" =~ /^$s_op$s_ob$/ ) ||
( "$s_op $s_ob" =~ /^$o_op $o_ob$/ )) {
KuangPlus::pdebug
"*** found a match, calling addto()", 5.3;
my($s_lop) =$s_plan[$#s_plan-1];
my($s_lob) = $s_plan[$#s_plan];
addto($s_lop,$s_lob,"@o_plan");
}
}
}
}
return@Engine::successful_exploits;
} else {
print STDERR "bad goal "$KuangPlus::goal"";
}
}
1;
safeops.pl
# safeops.pl
# Should beoperations here which will cache returns from system calls.
# The effect we are seeking istwo fold: 1) we cache returned values so
# that there is a chance to speed up theperformance and 2) we provide a
# restricted set of calls which are available to "rules"and hence control
# access to the system as we desire.
#
# It should be noted that this routine has access to the"real" namespace
# inwhich "kuangplus" operates. This is in contrast to the "rule" which
# has access only tothose things (variables and routines) "shared" to it
# by the main kuangplus calling routine.
# SafeOps::stat()
# Routine which emulates the behaviour ofthe real "stat()" sub routine.
# This one however, will cache lookups and so improveperformance of
#routines which call it.
sub SafeOps::stat {
my($name) = $_[0];
KuangPlus::pdebug "safe stat($name) called", 10.3;
if ( $name =~ /^([/.]+)$/ ) {
if ( !defined($KuangPlus::stat_cache{$1} ) ) {
KuangPlus::pdebug "caching entryfor "$name" called", 10.3;
$KuangPlus::stat_cache{$1} = [ stat($1) ];
}
return@{$KuangPlus::stat_cache{$1} } ;
} else {
return ();
}
} # end of SafeOps::stat()
# SafeOps::uname
# Front end for the POSIX::uname call to make it available for"rules"
# whichwon't have access to the POSIX library of routines.
#
# Expects: no arguments
# Returns: a 5 element array as describedbelow.
# SideEffects: caches the value of the uname so that subsequent calls will
# get the cachedvalue and not need to call the library routine again.
#
# POSIX::uname returns the following list:
# ($sysname, $nodename,$release, $version, $machine)
#
# discussion: Without the "{local $^W ... } " fiddle around this,we get a
# >Subroutine KuangPlus::uname redefined at
# >/home/jhoward/Kuangplus/new-work/wip/safeops.pl line 41.
# This particular fiddle issuggested on p.589 of "Programming Perl, 1996".
sub SafeOps::uname {
pdebug "safeops - uname(): invoked ...", 11.3;
if ( !defined(@KuangPlus::uname) ) {
pdebug "safeops - uname(): caching value ...",11.3;
use POSIX;
@KuangPlus::uname = POSIX::uname();
}
pdebug "safeops - uname(): returning "@KuangPlus::uname".",11.3;
return @KuangPlus::uname;
} # end of SafeOps::uname()
sub SafeOps::getpwent {
my(@pwent_a);
pdebug "SafeOps::getpwent(): invoked ...", 12.3;
#getpwent returns a list:
# ($name, $pwd, $uid, $gid,$quot, $comment, $gcos, $dir, $shell)
if ( ! defined(%KuangPlus::pwd_cache) ) {
pdebug"SafeOps::getpwent(): initialising data ...", 12.3;
$KuangPlus::pwd_max = -1;
while ( @pwent_a =getpwent() ) {
$KuangPlus::pwd_max++;
pdebug "SafeOps::getpwent(): $KuangPlus::pwd_max:@pwent_a",
'12.3';
$KuangPlus::pwd_cache{$KuangPlus::pwd_max} = [ @pwent_a ];
$KuangPlus::pwd_by_name{$pwent_a[0]} =
$KuangPlus::pwd_cache{$KuangPlus::pwd_max} ;
$KuangPlus::pwd_by_uid{$pwent_a[2]} =
$KuangPlus::pwd_cache{$KuangPlus::pwd_max} ;
}
pdebug "SafeOps::getpwent():$KuangPlus::pwd_max values", 12.3;
$KuangPlus::counter = 0;
}
pdebug "pwd counter is $KuangPlus::counter, max is$KuangPlus::pwd_max",
12.3;
if ( $KuangPlus::counter <= $KuangPlus::pwd_max ) {
pdebug "Should return@{$KuangPlus::pwd_cache{$KuangPlus::counter} } ",
12.3;
return@{$KuangPlus::pwd_cache{$KuangPlus::counter++} } ;
} else {
$KuangPlus::counter = 0;
return;
}
} # end of SafeOps::getpwent()
sub SafeOps::getpwnam {
my($v) = $_[0];
pdebug "SafeOps::getpwnam($v): invoked ...",13.3;
#getpwnam(NAME) returns a list:
# ($name, $pwd, $uid, $gid, $quota, $comment,$gcos, $dir, $shell)
SafeOps::getpwent if ( ! defined(%KuangPlus::pwd_by_name) );
return@{$KuangPlus::pwd_by_name{$v} } ;
} # end of SafeOps::getpwnam()
sub SafeOps::getpwuid {
my($v) = $_[0];
pdebug "SafeOps::getpwuid($v): invoked ...",14.3;
#getpwnam(UID) returns a list:
# ($name, $pwd, $uid, $gid, $quota, $comment,$gcos, $dir, $shell)
SafeOps::getpwent if ( ! defined(%KuangPlus::pwd_by_uid) );
return @{$KuangPlus::pwd_by_uid{$v} };
} # end ofSafeOps::getpwuid()
1;
Appendix B:KuangPlus logic flow diagrams
Appendix C: KuangPlusdata dictionary
Thisdocument represents the data dictionary of the kuangplus package. It listsand describe each namespace, library, sub-routine, global variable andlocal variable used. The grouping is done on the basis of the file inwhich the subject is defined. In the following, where the term"kuangplus" is used, it refers to the entire package. When "kuangplus.pl"is used, it is a reference to the actual file by the same name. Localvariables are indicated by the preface my which reflects the use ofmy in the code for the same purpose. Where an entity isdefined within a specific namespace, that namespace is prepended in thesame way as it would be used in the Perl code.
1. Files used by the "kuangplus" package.
1.1 kuangplus.pl
This file contains the basic "frontend" for kuangplus. Itinitialises as required, evaluates the maxims in a "safe" environment,invokes the inference engine and prints the results.
1.2 engine.pl
Contains the inference engine.
1.3 safeops.pl
Containsthe definition of sub-routines which are shared into the maxims when theyare evaluated. These routines call the actual routines by the same name,cache the result, and then return the result to the maxim.
1.4 maxims/*
The directory contains any maxims available.
2. Data dictionary and Sub-routine description byfile.
2.1 File"kuangplus.pl"
2.1.1 Library modulesincluded with the Perl "use" command:
Getopt::Long
Contains the definition for the"GetOptions()" sub-routine used to process command line arguments.
strict
Imposes lexical scoping on variables, symbolic references andbarewords([Wall96], p.110).
Safe
Used later for evaluating rules in a restricted namespace.
2.1.2 Global variables used or set
$ENV{PATH}
Environment variable which is explicitly set to "/bin" for securityreason to restrict the path.
@INC
Global array which contains the places tolook when a "require" statements seeks to load a new package. See"KaungPlus::kuang_home" below.
@ARGV
Contains command linearguments.
2.1.3 Namespacesdefined
KuangPlus::
The variables and sub-routines defined inthis file are in the "KuangPlus" namespace which is declared near the topof the file.
2.1.4 Standard Perlroutines used
open()
opendir()
2.1.5 Other KuangPlus modules included
safeops.pl
Module inwhich "safe" routines for maxims to use are defined. Described below.
engine.pl
Module which implements the inference engine. Described below.
2.1.6 External subroutines called
Engine::evaluate_plans()
Defined in engine.pl. Described later.
2.1.6 Variables
$KuangPlus::kuang_home
String variable which contains the name of the directoryin which the "kuangplus" package is installed. To satisfy taintchecks, it is loaded into the "@INC" array for subsequent "require"statements. Also used to define path when iterating through the "maxims" directory.
$KuangPlus::usage
Stringwhich contains a brief description of the "KuangPlus" package and helpinformation for running it. It is displayed when the command line "help"option, or an error in command line arguments, are found.
$KuangPlus::debug
Used to indicate whether or not debugging is turned on.Initialised to the empty string. Can take a integer, decimal or stringvalue. The only valid string value is the word "all". If set to the emptystring, no debugging information is printed (default).
$KuangPlus::verbose
Numeric variable used to indicate state of "verbose"mode. Initialised to "". If null, verbose mode is turned off.
$KuangPlus::help
Variable used to indicate whether the "help" option hasbeen requested.
@KuangPlus::original_ARGV
Used tostore a copy of the command line arguments before processing.
$KuangPlus::go_return
Used to contain the return value from the"Getopt::Long::GetOptions()" library call.
%KuangPlus::known_facts
Associative array to contain "prior Knowledge". The "key" is acontrolling operation pair. The "value" is a brief description of thekey.
@KuangPlus::uname
Contains the return value from "POSIX::uname()".
rd
<K>
Used to contain the filehandle of the file in which known things aredumped if the "KuangPlus::debug" value indicates that this should bedone.
my $fact
Used in a "foreach" loop to hold each valueof the "known_facts" array, only defined if "K" is opened.
<Rules>
Used to contain filehandle for "opendir" on "rules" directory.
my @rule_files
Contains the return value from "readdir(Rules)".
my $rule_file
String referring to a file within the "Rules"directory.
$KuangPlus::cmpt
Used to hold the return value of "new Safe"which is invoked each time a new rule file is identified.
<P>
Filehandle used to dump the plans into, if "KuangPlus::debug"indicates this should be done.
my $i
Counter used for thenumber of plans in "%KuangPlus::plans".
my $p
Used in foreach loopto iterate through "%KuangPlus::plans".
@KuangPlus::successful_exploits
Holds return value from "Engine::evaluate_plans()" calls.
my $exploit
Used in foreach loop to iterate through successfulexploits as contained in the "@KuangPlus::successful_exploits"variable.
2.1.7 Sub-routinesdefined
2.1.7.1KuangPlus::humanize(string)
Re-presents a controlling operation in a human readable form i.e. anoperation like "w /etc/passwd" will be written to the screen as "overwritefile /etc/passwd". Only invoked in "verbose" mode, from"KuangPlus::print_success()".
Called from: KuangPlus::print_success()
Calls: KuangPlus::pdebug()
Returns:
Side effects
Global variables:
Namespaces: Defined in the "KuangPlus"namespace.
StandardPerl routines: split, shift
Debug flags:
Variables:
my $co_s - used tostore the string variable passed to "humanize" as "@_".
my $string - used to prepare a printable string.
my $leader - the string to print at the startof each line.
my @co_a - array usedto hold elements of "$co_s", separated by " ".
my $op - string which is used to hold "operation" part ofcontrolling operation.
my $ob -string which is used to hold "object" part of controlling operation.
2.1.7.2 KuangPlus::print_success(string)
Organises for the successful "plan" to beprinted, breaking it up into rules and prior knowledge. If the verbose flagwas used when kuangplus was invoked, then this routine calls theKuangPlus::humanize sub-routine. Otherwise, the printing is donefrom within this routine.
Called from: main.
Calls: KuangPlus::pdebug(), KuangPlus::humanize(),KuangPlus::find_regexp_plan().
Returns:
Side effects:
External variables: %KuangPlus::plans, $KuangPlus::verbose
Namespaces: Definedin the KuangPlus namespace.
Standard Perl routines: print, defined, shift
Debug flags:
Variables:
my @elements - breaks the argument string, "@_", intoelements, separated by "" (spaces).
my $leader - string used at the start of any line printed.
my $known - extracted from "@elements"array.
my $offset
my $index - numeric place markers used toselect ranges of elements from the "@elements" array.
my $co_s - a controlling operation from elements of"@elements".
my $match - used tohold return value from "find_regexp_plan".
2.1.7.3 KuangPlus::find_regexp_plan(string)
Given a controlling operation pair, look fora regular expression match in the %KuangPlus::plans assoc. array.
Called from: KuangPlus::humanize()
Calls:KaungPlus::pdebug()
Returns: plan string if found, 0 otherwise.
Side effects:
External variables: %KuangPlus::plans
Namespace: Defined inthe KuangPlus namespace
Standard Perl routines: return(), keys().
Debug flags:
Variables:
my $co_s - internal string variables used to hold thestring as passed as argument in "@_".
2.1.7.4 KuangPlus::pdebug(string, string)
The first argument is a string containing a debuggingmessage, the second argument is a numeric or the character *,which indicates at what level of debugging that this string is relevant.Only relevant strings are printed. The presence of the * indicates that this string is always relevant i.e. it is always printed.
Called from: generally throughout theKuangplus package.
Calls:
Returns:
Sideeffects:
Externalvariables: KuangPlus::debug( )
Namespace:
Standard Perl routines: print
Debug flags:
Variables:
my$string - used to contain first passed value.
my $level - used to contain second passed value.
my $whole_level
my $frac_level - used to contain the whole number andfractional parts of the "$level" respectively.
2.1.7.5 KuangPlus::rule_qc(hash reference, stringreference)
The first argument isa reference to an associative array (hash) which contains the uncheckedrules as generated by a maxim file. The second argument contains areference to a string which contains the name of the file from which therules were loaded. This routine will do "quality control" checks onthe generated rules.
Calledfrom:
Calls:KuangPlus::pdebug, SafeOps::stat
Returns:
Side effects: Loads "good" rules into %KuangPlus::plans.
External variables:%KuangPlus::plans
Namespace: Defined in the KuangPlus namespace.
Standard Perl routines: keys
Debug flags: 15
Variables:
my $new_plans_r - contains first passed argument, theplans associative array.
my $f_r -contains second passed argument, a reference to a string.
my $plan
my $qc_failed
my $op1,$ob1, $op2, $ob2 - used to contain regular expression matches, whichcorrespond to two controlling operations.
2.2 engine.pl
Creates namespace "Engine::".
Global variables: none
uses "strict" package.
@Engine::successful_exploits - initialised to an emptyarray. This array is used to contain any successful exploitsdiscovered.
Engine::find_match()- expects three arguments which represent a controlling operation, adescriptive string and a reference to an associative array. Thesub-routine will do a lookup, through the associative array reference, tosee if the given controlling operation is described in it. Returns 1if found and 0 otherwise.
Calledby: "Engine::addto()"
Calls: "KuangPlus::pdebug"
Global variables:
tx5040
$co, $name, $assoc_r - local storage for passed arguments.
$key - used in foreach loop to iteratethrough the elements of the associative array passed by reference in the"$assoc_r" variable.
Engine::addto() - expects an operator, an object and a plan array as thethree arguments. Invoked by "Engine::evaluate_plans()".
Called by:
Calls: "KaungPlus::pdebug( )", "Engine::find_match( )"
External variables:@Engine::successful_exploits
$op, $ob,@plan - local storage for arguments.
$co - text string which is set to "$op $ob".
$i - used in a "for" loop to index through plans lookingfor repetition.
$entry - holds valuefrom the plan array.
@plan -loaded with "$co" as necessary.
%Engine::beendone - stores the list controlling operations which havealready been examined during the current pass.
@Engine::accessible - list of Uid's which areaccessible.
Engine::init_kuang()- initialise data structures necessary for the backward changing effort.Expects a reference to the "%plans" array. Invoked from"Engine::evaluate_plans".
Calledby: "Engine::evaluate_plans()"
Calls: "KuangPlus::pdebug()", "print()".
Globals Used: none.
$plans_r - local storage for "%plans"associative array.
$KuangPlus::goal - a controlling operation pair which represents the goalwhich is pursued.
Engine::evaluate_plans() - main component of the backwards chainingengine.
Called by: main.
Calls: "Engine::init_kuang()","KuangPlus::goal()", "KuangPlus::pdebug()", "Engine::addto()".
Externalvariables: @Engine::new(), %Engine::beendone(), @Engine::accessible(),@Engine::search_space.
Returns: "@Engine::successful_exploits".
$plan_r - local storage for array passed byreference.
$s_plan, $o_plan,@old - data structures used for managing plans as we loop through lookingfor backward chains.
@Engine::new(), %Engine::beendone, @Engine::accessible - set to emptyarray.
@o_plan - an arrayset to the elements, space delimited, of "$o_plan".
$o_op - operator part of the last element of the"@o_plan" array.
$o_ob - object partof the last element of the "@o_plan" array.
@s_plan - elements, space delimited, of the plans in the"@Engine::search_space".
$s_op -operator part of the first plan in "@s_plan".
$s_ob - object part of the first plan in "@s_plan".
$s_lop - operator part of the last plan in"@s_plan".
$s_lob - object partof the last plan in "@s_plan".
2.3 safeops.pl
POSIX -POSIX::uname()" sub-routine used to get a characterisation of thecurrent system.
Appendix D: KuangPlus usermanual
KuangPlus - November 1999.
NAME
KuangPlus- a security audit tool written in Perl (for version 5.004 and probablyabove).
SYNOPSIS
kuangplus.pl [-d=[[n][.n]]] [-v][-h] [-m=<pathname>]
DESCRIPTION
KuangPlusis a security audit tool which has as its central design goals platformindependence, a stable core and a dynamic collection of maxims whichencapsulate all the knowledge about security flaws and configurationproblems germane to the system on which the tool is run. Further,the KuangPlus package will not change anything on the system on which itruns.
The script "kuangplus.pl" is the front end for the KuangPlus package.When the script completes, it will print out a message indicating it didn'tfind any exploits or, if some were found, it will print a message statingwhat the exploit was.
The "kuangplus.pl" script and the associated "engine.pl"and "safeops.pl" script are the stable part of the kuangplus package andare the instantiations of the "frontend", the "inference engine", and the"safe operations" respectively.
The maxims are small files containing Perlcode. Each file may describe one or a related set of vulnerabilities. Whenevaluated, the maxim should load appropriate rules into the searchspace to enable there later consideration by an inference engine to see what sort of complex plans might be enacted to achieve rootcompromise of the system.
OPTIONS
-d[=level]
--d[=level]
-debug[=level]
--debug[=level]
If the "-d" option is usedwithout a "level" specification, then all debugging information is printed.By specifying a "level" as a single integer, a real number or a fractionalpart the reported debugging information can be restricted. There is onlyone level of debugging used i.e. if multiple "-d" options arespecified, only the last option will be used.
-h
--h
-help
--help
This command lineoption will cause a usage message to appear, followed by all the debugginglevels available. The script will then exit without doing any furtherwork.
-v
--v
-verbose
--verbose
This option causes any exploits discovered tobe explained rather than just printing the "plan" which describes theexploit.
-m=<pathname>
--m=<pathname>
-maximdir=<pathname>
--maximdir=<pathname>
By default the directory from which maxims are loaded atrun-time is the directory "maxims" in the same directory as the "kuangplus"script itself. If the location of the "maxims" directory differs (forexample the "kuangplus" script might be on read-only media) thenthis option can be used to nominate a new directory location.
RUN TIME SETTINGS
There is a variable within the script,"$kuang_home" which should be a path to where the "engine.pl" and"safeops.pl" modules can be found. At run-time, the "$kuang_home" variableis pushed into the "@INC" array and thus used indirectly when the"engine.pl" and "safeops.pl" are "required" within the script.
Perl ENVIRONMENT
Requires 5.004. This is because it was withinthis version that enhancements were made to the "Safe" module which areused within the script.
When invoked, the Perl script should use the "-T" and"-w" flags to set the "taint" mode and "warn" about anything that lookslike bad code. These flags should help the invoker have some confidence inthe code.
Uses the "Getopt::Long", "strict" and "Safe" standard modules.
The"kuangplus.pl" script defines the "KuangPlus" namespace. The "engine.pl"script defines the "Engine" namespace and the "safeops.pl" script definesthe "SafeOps" namespace.
SHELLENVIRONMENT
Noenvironment variables are used. For "taint" requirements the PATHenvironment variable is set to "/bin" at runtime.
SEE ALSO
At the time of writing, the best source of information about the"Safe" module was in "Programming Perl, Wall, Christiansen and Schwartz.2nd Edition. 1996. O'Reilly and Associates, California, USA.".
Online manual pagesthat are distributed with Perl have a great deal of information in them. Ofparticular interest in the context of the kuangplus package will be: The"Perlsec" information about the Perl security model and about "Safe" and"taint"; "Perlrun" for runtime arguments to Perl and in particularthe "-T" and "-w" flags.
BUGS
None known.
AUTHOR
Jeff Howard, supervised by Dr Warren Toomey, as part ofthe requirements for the "Master of Information Sciences" course undertakenat the Australian Defence Force Academy, 1999.
Appendix E: KuangPlusmaintenance
Thissection should provide a guide for anyone that is going to be involved inmaintaining the KuangPlus distribution. It covers how to add newsub-routines to be used within the Safe compartment. It alsodescribes in some detail the use of the debugging flags wheninvoking KuangPlus.
Loading new "safe" routines.
The sub routines defined in the "SafeOps::"namespace are automatically loaded into the Safe compartment. This is donethrough the knowledge that a namespace is just an associative array ofvalues. The frontend searches through the namespace and shares anyfound into the Safe compartment.
For future development, if there is a need to make moresub-routines available, then it is best to define them in thesafeops.pl file and in the SafeOps:: namespace.
Debugging
"KuangPlus" has been written with a comprehensivedebugging environment included those interested in the workings of thepackage to easily obtain information. If the level of detail available isnot sufficient to satisfy the enquirer, they can always invoke thescript with the "-d" flag of Perl and step through the script line by line(e.g. Perl -d kuangplus.pl).
The debugging flag to kuangplus is dual level. The firstlevel provides information about the functional elements of the KuangPluspackage. It is specified as the right hand side of the decimal point. Thesecond level provides information about the logical elements ofKuangPlus. The second level is specified on the right hand side of thedecimal point. These two areas of interest can be selected together orseparately by specifying an argument with the "-d" flag to "kuangplus" (notto be confused with the "-d" flag to Perl itself, to which thisbares no relation). Examples of valid debugging levels and there meaningare:
kuangplus -d1.2
Here the both the lexical information "1" andthe logical information "2" are selected (see the table below for the keyto the numerical values).
kuangplus -d1
Specifiesonly the lexical information
kuangplus -d.2
Specifiesonly the logical information.
kuangplus -d
generates all debugging information.
The current list of debugging flags is available usingthe -h flag when invoking kuangplus.
The debugging information is written to the screen by theroutine "KuangPlus::pdebug()" which is defined in the "kuangplus.pl" file.The pdebug() routine takes two arguments, the string to be printed followedby a symbol which indicates at what level this message should beprinted. The level may be numeric such as those presented above, or itcould be the quoted symbol '*' which means always print this message.
The following text is an example of KuangPlusinvoked with the -d1.1 option to display file accesscontained in the main logic (the frontend). The successful exploitis the same one as shown in Chapter 6 where the Linux system had beenseeded with a world writeable /etc/group file.
debug(1.1): Level 1.1 debugging turnedon.
debug(1.1): loading"/home/jhoward/Kuangplus/new-work/wip/rules/Kuang" to generate plans...
debug(1.1): finishedloading "/home/jhoward/Kuangplus/new-work/wip/rules/Kuang".
debug(1.1): loading"/home/jhoward/Kuangplus/new-work/wip/rules/Linux" to generate plans...
debug(1.1): finishedloading "/home/jhoward/Kuangplus/new-work/wip/rules/Linux".
Success: "u 0 w /etc/passwd g 0 w /etc/groupu .* v Linux-2.0.34"
Appendix F: Online Resources
The resourcesidentified below will probably be of interest to somebody following up onthis project or just interested in this field. Not all of these sites wereused directly in this work, but the content of these sites was part of the"background" which went into this work and is listed here forcompleteness. The are listed in alphabetical order of the "keyword" andwhere appropriate a note about why the reference was included is given.
COAST
CVE
http://cve.mitre.org/
The "Common Vulnerability Database" isdiscussed. The MITRE organisation uses several intrusion detection systemsand saw a need for a centralised database of exploits to exist which couldbe shared by all systems to support enterprise security operations.
SecurityPortal
http://SecurityPortal.com
TIGER
ftp://coast.cs.purdue.edu/pub/tools/unix/tiger
ftp://net.tamu.edu/pub/security/TAMU
Appendix G: Opcode.3 onlinemanual
This is the online manual page distributed with Perl5.004 and displayed with the "Perldoc Opcode" command.
Opcode(3) User Contributed Perl Documentation Opcode(3)
9/May/98 Perl 5.004, patch 041
NAME
Opcode - Disable namedopcodes when compiling Perl code
SYNOPSIS
use Opcode;
DESCRIPTION
Perl code isalways compiled into an internal format
before execution.
Evaluating Perl code (e.g. via "eval" or "do'file'")
causes the code to be compiled into an internal format and
then, provided there wasno error in the compilation,
executed. The internal format is based on many distinct
_______.
By default no opmask is in effect andany code can be
compiled.
The Opcodemodule allow you to define an ________ ____ to
be in effect when Perl ____ compilesany code. Attempting
to compile code which contains a masked opcode will cause
thecompilation to fail with an error. The code will not
be executed.
NOTE
The Opcode module is not usually used directly. See the
ops pragma andSafe modules for more typical uses.
WARNING
The authors make no warranty, implied or otherwise, about
the suitability of thissoftware for safety or security
purposes.
The authors shall not in any case be liable for special,
incidental,consequential, indirect or other similar
damages arising from the use of thissoftware.
Your mileagewill vary. If in any doubt do not use it.
Operator Names and Operator Lists
The canonical list of operator namesis the contents of
the array op_name defined and initialised in file ________
of the Perlsource distribution (and installed into the
Perl library).
Each operator has both a terse name (its opname)and a
more verbose or recognisable descriptive name. The opdesc
function can be used toreturn a list of descriptions for
a list of operators.
Many of the functions and methods listed belowtake a list
ofoperators as parameters. Most operator lists can be
made up of several types of element.Each element can be
one of
anoperator name (opname)
Operator names are typically small lowercase words
likeenterloop, leaveloop, last, next, redo etc.
Sometimes they are rathercryptic like gv2cv,
i_ncmp and ftsvtx.
an operator tag name (optag)
Operator tags can be used torefer to groups (or
sets) of operators. Tag names always being with a
colon.The Opcode module defines several optags
and the user can define othersusing the
define_optag function.
anegated opname or optag
An opname or optag can be prefixed with an
exclamation mark,e.g., !mkdir. Negating an
opname or optag means remove the corresponding ops
fromthe accumulated set of ops at that point.
an operator set (opset)
An _____ as a binary string ofapproximately 43
bytes which holds a set or zero or more operators.
The opset and opset_to_ops functions canbe used
to convert from a list of operators to an opset
and ____ _____.
Wherever a list of operatorscan be given you can
use one or more opsets. See also Manipulating
Opsetsbelow.
Opcode Functions
The Opcodepackage contains functions for manipulating
operator names tags and sets. All areavailable for export
by the package.
opcodes In a scalar context opcodes returns the number of
opcodes in thisversion of Perl (around 340 for
Perl5.002).
In a list context it returns a list of allthe
operator names. (Not yet implemented, use @names
=____________(full_opset).)
opset (OP, ...)
Returns an opset containing the listed operators.
opset_to_ops (OPSET)
Returns a list of operatornames corresponding to
those operators in the set.
opset_to_hex (OPSET)
Returns a stringrepresentation of an opset. Can
be handy for debugging.
full_opset
Returns an opset whichincludes all operators.
empty_opset
Returns an opset which contains no operators.
invert_opset (OPSET)
Returns an opset which is theinverse set of the
one supplied.
verify_opset (OPSET, ...)
Returns true if the supplied opset lookslike a
valid opset (is the right length etc) otherwise it
returns false. If an optionalsecond parameter is
true then verify_opset will croak on an invalid
opsetinstead of returning false.
Most of the other Opcode functions call
verify_opset automatically andwill croak if given
an invalid opset.
define_optag (OPTAG, OPSET)
Define OPTAG as a symbolicname for OPSET. Optag
names always start with a colon :.
The optag name used must not be definedalready
(define_optag will croak if it is already
defined). Optag names areglobal to the Perl
process and optag definitions cannot be altered or
deleted once defined.
It is strongly recommended that applications using
Opcode should use a leadingcapital letter on
their tag names since lowercase names are reserved
foruse by the Opcode module. If using Opcode
within a module you shouldprefix your tags names
with the name of your module to ensure uniqueness
andthus avoid clashes with other modules.
opmask_add (OPSET)
Adds the supplied opset to the currentopmask.
Note that there is currently __ mechanism for
unmasking ops once they havebeen masked. This is
intentional.
opmask Returns an opset corresponding to the current
opmask.
opdesc (OP,...)
Thistakes a list of operator names and returns
the corresponding list ofoperator descriptions.
opdump (PAT)
Dumps to STDOUT a two column list of op names and
op descriptions. If anoptional pattern is given
then only lines which match the (case insensitive)
pattern will be output.
It's designed to be used as a handy command line
utility:
Perl -MOpcode=opdump -e opdump
Perl -MOpcode=opdump -e 'opdump Eval'
Manipulating Opsets
Opsets may be manipulated using the Perl bit vector
operators &(and), | (or), ^ (xor) and ~ (negate/invert).
However you should never rely on the numericalposition of
any opcode within the opset. In other words both sides of
a bit vector operatorshould be opsets returned from
Opcode functions.
Also, since the number of opcodes in your currentversion
ofPerl might not be an exact multiple of eight, there may
be unused bits in the last byte of anupset. This should
not cause any problems (Opcode functions ignore those
extra bits)but it does mean that using the ~ operator
will typically not produce the same'physical' opset
'string' as the invert_opset function.
TO DO (maybe)
$bool = opset_eq($opset1, $opset2) true if opsets arelogically eqiv
$yes =opset_can($opset, @ops) true if $opset has all @ops set
@diff = opset_diff($opset1,$opset2) => ('foo', '!bar', ...)
Predefined Opcode Tags
:base_core
null stub scalar pushmark wantarray const defined undef
rv2sv sassign
rv2av aassign aelem aelemfastaslice av2arylen
rv2hvhelem hslice each values keys exists delete
preinc i_preinc predec i_predec postinci_postinc postdec i_postdec
int hex oct abs pow multiply i_multiply dividei_divide
modulo i_modulo add i_add subtract i_subtract
left_shift right_shiftbit_and bit_xor bit_or negate i_negate
not complement
lt i_lt gt i_gt le i_le ge i_ge eq i_eqne i_ne ncmp i_ncmp
slt sgt sle sge seq sne scmp
substr vec stringify study pos lengthindex rindex ord chr
ucfirst lcfirst uc lc quotemeta trans chop schop chomp schomp
match split
list lslice splice push popshift unshift reverse
cond_expr flip flop andassign orassign and or xor
warn die lineseq nextstate unstack scopeenter leave
rv2cvanoncode prototype
entersub leavesub return method -- XXX loops via recursion?
leaveeval -- needed for Safeto operate, is safe without entereval
:base_mem
These memory related ops are not included in
:base_core because they caneasily be used to
implement a resource attack (e.g., consume all
availablememory).
concat repeat join range
anonlist anonhash
Note that despite the existance of this optag a
memory resource attack may stillbe possible using
only :base_core ops.
Disabling these ops is a ____ heavy handed way to
attemptto prevent a memory resource attack. It's
probable that a specific memorylimit mechanism will
be added to Perl in the near future.
:base_loop
These loop ops are not included in :base_corebecause
they can easily be used to implement a resource
attack (e.g., consume allavailable CPU time).
grepstart grepwhile
mapstart mapwhile
enteriter iter
enterloop leaveloop
lastnext redo
goto
:base_io
These opsenable __________ (rather than filename)
based input and output. These aresafe on the
tx2160 assumption that only pre-existing filehandles are
available for use. To create newfilehandles other
ops such as open would need to be enabled.
readline rcatline getcread
formline enterwriteleavewrite
printsysread syswrite send recv
eof tell seek sysseek
readdir telldir seekdir rewinddir
:base_orig
These are a hotchpotch of opcodes still waiting to be
considered
gvsv gv gelem
padsv padav padhv padany
rv2gv refgen srefgen ref
bless -- could be used tochange ownership of objects (reblessing)
pushre regcmaybe regcomp substsubstcont
sprintf prtf -- can core dump
crypt
tie untie
dbmopen dbmclose
sselect select
pipe_op sockpair
getppid getpgrp setpgrp getpriority setpriority localtime gmtime
entertry leavetry -- can beused to 'hide' fatal errors
:base_math
These opsare not included in :base_core because of
the risk of them being used togenerate floating
point exceptions (which would have to be caught using
a$SIG{FPE} handler).
atan2 sin cos exp log sqrt
These ops are not included in :base_core because they
have aneffect beyond the scope of the compartment.
rand srand
:default
A handy tag name for a __________ default set of ops.
(Thecurrent ops allowed are unstable while
development continues. It will change.)
:base_core :base_mem:base_loop :base_io :base_orig
If safety matters to you (and why else would you be
using theOpcode module?) then you should not rely
on the definition of this, orindeed any other,
optag!
:filesys_read
statlstat readlink
ftatime ftblk ftchr ftctime ftdir fteexec fteowned fteread
ftewrite ftfileftis ftlink ftmtime ftpipe ftrexec ftrowned
ftrread ftsgid ftsize ftsockftsuid fttty ftzero ftrwrite ftsvtx
fttext ftbinary
fileno
:sys_db
ghbyname ghbyaddr ghostentshostent ehostent -- hosts
gnbyname gnbyaddr gnetent snetent enetent-- networks
gpbyname gpbynumber gprotoent sprotoent eprotoent --protocols
gsbyname gsbyport gservent sservent eservent -- services
gpwnam gpwuid gpwent spwentepwent getlogin -- users
ggrnam ggrgid ggrent sgrent egrent-- groups
:browse
A handytag name for a __________ default set of ops
beyond the :default optag. Like:default (and indeed
all the other optags) its current definition is
unstablewhile development continues. It will change.
The :browse tag represents the next stepbeyond
:default. It it a superset of the :default ops and
adds :filesys_read the :sys_db.The intent being
that scripts can access more (possibly sensitive)
information about your system butnot be able to
change it.
80 :default:filesys_read :sys_db
:filesys_open
sysopen open close
umask binmode
open_dir closedir -- other dir ops are in:base_io
:filesys_write
link unlink rename symlink truncate
mkdir rmdir
utime chmod chown
fcntl -- not strictly filesysrelated, but possibly as dangerous?
:subprocess
backtick system
fork
wait waitpid
glob -- access to Cshell via<`rm *`>
:ownprocess
exec exit kill
time tms -- could be used for timingattacks (paranoid?)
:others
This tagholds groups of assorted specialist opcodes
that don't warrant having optagsdefined for them.
SystemV Interprocess Communications:
msgctl msgget msgrcv msgsnd
semctl semget semop
shmctl shmget shmread shmwrite
:still_to_be_decided
chdir
flock ioctl
socket getpeername ssockopt
bind connectlisten accept shutdown gsockopt getsockname
sleep alarm -- changes global timer stateand signal handling
sort -- assorted problems including core dumps
tied-- can be used to access object implementing a tie
pack unpack -- can be used tocreate/use memory pointers
entereval -- can be used to hide code from initial compile
require dofile
caller -- get info about calling environment and args
reset
dbstate -- Perl -d version of nextstate(ment)opcode
:dangerous
This tag is simply a bucket foropcodes that are
unlikely to be used via a tag name but need to be
tagged for completness anddocumentation.
syscall dump chroot
SEE ALSO
___(3) -- Perl pragmainterface to Opcode module.
____(3) -- Opcode and namespace limited execution
compartments
AUTHORS
Originally designed and implemented by Malcolm Beattie,
mbeattie@sable.ox.ac.uk as part of Safe version 1.
Split out from Safe module version 1, named opcodetags
and otherchanges added by Tim Bunce <__________________>.
Appendix H: Safe.3 online manual
This is the Safe.3 manual page distributedwith Perl 5.004 and retrieved in this instance with the command "PerldocSafe".
Safe(3) User Contributed PerlDocumentation Safe(3)
9/May/98Perl 5.004, patch 04 1
NAME
Safe - Compile and execute code in restricted compartments
SYNOPSIS
use Safe;
$compartment = new Safe;
$compartment->permit(qw(time sort :browse));
$result =$compartment->reval($unsafe_code);
DESCRIPTION
The Safe extension module allows the creation of
compartments in which Perl code can beevaluated. Each
compartment has
a newnamespace
The "root" of the namespace (i.e. "main::") is
changed to a different packageand code evaluated
in the compartment cannot refer to variables
outside this namespace, even with run-time glob
lookups and other tricks.
Code which is compiled outsidethe compartment can
choose to place variables into (or _____ variables
with)the compartment's namespace and only that
data will be visible to codeevaluated in the
compartment.
By default, the only variables shared with
compartments are the"underscore" variables $_ and
@_ (and, technically, the less frequentlyused %_,
the _ filehandle and so on). This is because
otherwise Perl operators whichdefault to $_ will
not work and neither will the assignment of
arguments to @_ on subroutine entry.
an operator mask
Each compartment has an associated"operator
mask". Recall that Perl code is compiled into an
internal format beforeexecution. Evaluating Perl
code (e.g. via "eval" or "do 'file'") causes the
codeto be compiled into an internal format and
then, provided there was noerror in the
compilation, executed. Code evaulated in a
compartment compiles subjectto the compartment's
operator mask. Attempting to evaulate code in a
compartment which contains a masked operator will
cause the compilation to failwith an error. The
code will not be executed.
The default operator mask for a newlycreated
compartment is the ':default' optag.
It is important that you read the______(3) module
documentation for more information, especially for
detailed definitions ofopnames, optags and
opsets.
Since it is only at the compilation stage that the
operator mask applies,controlled access to
potentially unsafe operations can be achieved by
havinga handle to a wrapper subroutine (written
outside the compartment)placed into the
compartment. For example,
$cpt = new Safe;
sub wrapper {
# vetarguments and perform potentially unsafe operations
}
$cpt->share('&wrapper');
WARNING
The authors make nowarranty, implied or otherwise, about
the suitability of this software for safety orsecurity
purposes.
The authorsshall not in any case be liable for special,
incidental, consequential, indirect orother similar
damages arising from the use of this software.
Your mileage will vary. If in any doubt do not useit.
RECENT CHANGES
The interface to the Safe module has changedquite
dramatically since version 1 (as supplied with Perl5.002).
Study these pagescarefully if you have code written to
use Safe version 1 because you will need to makeschanges.
Methods inclass Safe
To create anew compartment, use
$cpt = new Safe;
Optional argument is (NAMESPACE), where NAMESPACE is the
root namespace to use forthe compartment (defaults to
"Safe::Root0", incremented for each new compartment).
Note that version 1.00 of the Safemodule supported a
second optional parameter, MASK. That functionality has
been withdrawnpending deeper consideration. Use the
permit and deny methods described below.
The following methods can then be usedon the compartment
object returned by the above constructor. The object
argument isimplicit in each case.
permit (OP, ...)
Permit the listed operators to be used when
compiling code in thecompartment (in ________ to
any operators already permitted).
permit_only (OP, ...)
Permit ____ the listedoperators to be used when
compiling code in the compartment (__ other
operators are permitted).
deny (OP, ...)
Deny the listed operators from being used when
compiling code in thecompartment (other operators
may still be permitted).
deny_only (OP, ...)
Deny ____ the listed operatorsfrom being used
when compiling code in the compartment (___ other
operators will bepermitted).
trap (OP,...)
untrap (OP, ...)
The trap and untrap methodsare synonyms for deny
and permit respectfully.
share (NAME, ...)
This shares the ________(s) inthe argument list
with the compartment. This is almost identical to
exporting variables using the the ___________
manpage module.
Each NAME must be the name ofa variable,
typically with the leading type identifier
included. A bareword istreated as a function
name.
Examples of legal names are '$foo' for a scalar,
'@foo' for an array, '%foo'for a hash, '&foo' or
'foo' for a subroutine and '*foo' for a glob (i.e.
allsymbol table entries associated with "foo",
including scalar, array, hash,sub and
filehandle).
Each NAME is assumed to be in the calling package.
See share_from for analternative method (which
share uses).
share_from (PACKAGE, ARRAYREF)
This method is similar to_______ but allows you
to explicitly name the package that symbols should
beshared from. The symbol names (including type
characters) are supplied as anarray reference.
$safe->share_from('main', [ '$foo', '%bar', 'func' ]);
varglob (VARNAME)
This returns a glob reference for thesymbol table
entry of VARNAME in the package of the
compartment. VARNAME must bethe name of a
variable without any leading type marker. For
example,
$cpt = new Safe 'Root';
$Root::foo ="Hello world";
# Equivalent version which doesn't need to know $cpt's packagename:
${$cpt->varglob('foo')} = "Hello world";
reval (STRING)
This evaluates STRING as Perl code inside the
compartment.
Thecode can only see the compartment's namespace
(as returned by the rootmethod). The
compartment's root package appears to be the
main:: package to the codeinside the compartment.
Any attempt by the code in STRING to use an
operator which is notpermitted by the compartment
will cause an error (at run-time of the main
program but at compile-time for the code in
STRING). The error is of theform "%s trapped by
operation mask operation...".
If an operation is trapped in this way,then the
code in STRING will not be executed. If such a
trapped operation occurs orany other compile-time
or return error, then $@ is set to the error
message, just as with an ______.
If there is no error, then the method returns the
valueof the last expression evaluated, or a
return statement may be used, just aswith
subroutines and eval(). The context (list or
scalar) is determined by thecaller as usual.
Thisbehaviour differs from the beta distribution
of the Safe extension whereearlier versions of
Perl made it hard to mimic the return behaviour of
the______ command and the context was always
scalar.
0 Some points to note:
If the entereval op is permitted then thecode can
use eval "..." to 'hide' code which might use
denied ops. This is not amajor problem since when
the code tries to execute the eval it will fail
because the opmask is still in effect. However
this technique would allowclever, and possibly
harmful, code to 'probe' the boundaries of what is
possible.
Anystring eval which is executed by code
executing in a compartment, or by codecalled from
code executing in a compartment, will be eval'd in
the namespace of thecompartment. This is
potentially a serious problem.
Consider a function _____ in package pkgcompiled
outside a compartment but shared with it. Assume
the compartment has a rootpackage called 'Root'.
If _____ contains an eval statement like eval
'$foo= 1' then, normally, $pkg::foo will be set
to 1. If _____ is called fromthe compartment (by
whatever means) then instead of setting $pkg::foo,
theeval will actually set $Root::pkg::foo.
This can easily be demonstrated by using a module,
suchas the Socket module, which uses eval "..."
as part of an AUTOLOADfunction. You can 'use' the
module outside the compartment and share an
(autoloaded) function with the compartment. If an
autoload is triggered by codein the compartment,
or by any code anywhere that is called by any
meansfrom the compartment, then the eval in the
Socket module's AUTOLOADfunction happens in the
namespace of the compartment. Any variables
created or used by the eval'd code are now under
the control of the code in thecompartment.
Asimilar effect applies to ___ runtime symbol
lookups in code called from acompartment but not
compiled within it.
rdo (FILENAME)
This evaluates the contents of fileFILENAME
inside the compartment. See above documentation
on the reval method forfurther details.
root(NAMESPACE)
This method returns the name of the package that
is the root of thecompartment's namespace.
Note that this behaviour differs from version 1.00
of the Safe module where theroot module could be
used to change the namespace. That functionality
hasbeen withdrawn pending deeper consideration.
mask (MASK)
This is a get-or-set method for thecompartment's
operator mask.
With no MASK argument present, it returns the
current operator mask of thecompartment.
Withthe MASK argument present, it sets the
operator mask for the compartment(equivalent to
calling the deny_only method).
Some Safety Issues
This section is currently just an outline of some of the
things code ina compartment might do (intentionally or
unintentionally) which can have aneffect outside the
compartment.
Memory Consuming all (or nearly all) available memory.
CPU Causing infinite loops etc.
Snooping
Copying private informationout of your system.
Even something as simple as your user name is of
valueto others. Much useful information could be
gleaned from your environmentvariables for
example.
SignalsCausing signals (especially SIGFPE and SIGALARM)
to affect your process.
Setting up a signal handlerwill need to be
carefully considered and controlled. What mask is
in effect when a signalhandler gets called? If a
user can get an imported function to get an
exception and call the user's signal handler, does
that user's restricted maskget re-instated before
the handler is called? Does an imported handler
getcalled with its original mask or the user's
one?
State Changes
Ops such as chdir obviously effect theprocess as
a whole and not just the code in the compartment.
Ops such as rand and srandhave a similar but more
subtle effect.
AUTHOR
Originally designed and implemented by Malcolm Beattie,
mbeattie@sable.ox.ac.uk.
Reworked to use the Opcode module andother changes added
by Tim Bunce <__________________>.
tql
Appendix I: A complicated maxim
package KUANG;
main::pdebug "Loading Kuang rule now ...",6.1;
# writers()
# Get the writers of the named file ordirectory - return as (UID, GID, OTHER)
# triplet. Owner can always write, since he can chmodthe file if he
# wants.
#
# Calls: main::stat()
# Called From: KUANG::eval_access().
# Expects: A filenameas the only argument.
# Returns: A string containing the owner, group and other permissions
# associatedwith the filename given on invocation.
# Side effects: none.
# Errors: If the file doesn't exist (as tested with the"-e" test) the
#string returned is empty.
#
# (fixme)are there any problems in this sort of builtin rule? should
# we make this knowledge moreexplicit?
#
sub writers {
my($target) =@_;
my(@srtn,$gid,$other,$uid);
@srtn= main::stat($target);
if ( $#srtn != -1 ) {
main::pdebug
"stat("$target"), mode: $srtn[2], uid/gid:$srtn[4]/$srtn[5]",
'6.3';
$uid = $srtn[4];
$gid = $srtn[5];
if (($srtn[2] & 020) != 020) {
$gid ="";
}
if ( ($srtn[2] & 02 ) == 02 ) {
$other = 1;
} else {
$other = 0;
}
} else {
($uid,$gid,$other) = ("","","");
}
return($uid, $gid, $other);
}
# eval_access()
# Given a filename, add appropriate plans reflecting theaccess to the file
# itself and the directory which contains it.
#
# Called from KUANG::control_file_attacks().
# Calls KUANG:writers()
# Expects: a filenameand a reference to a "new_plans" associative array.
# Returns: none.
# Side effects: Creates new entries in the"new_plans" assoc. array.
# Error checking: none.
#
sub eval_access {
my($ob,$new_plans_r) = @_;
# See if we can overwrite the file
my($owner, $group,$other) = &writers($ob);
# owner can w file always with chmod.
$$new_plans_r{"w $ob u $owner"} ="$ob is writeable by uid $owner"
if ($owner ne "");
$$new_plans_r{"w $ob g $group"} ="$ob is writeable by gid $group"
if ($group ne "");
$$new_plans_r{"w $ob u .*"} = "$obis world writeable" if ($other);
# We can replace the file if we can write to
# the directorycontaining the file.
my($dirname);
( $dirname = $ob ) =~ s/(.+)/[^/]+/$1/;
($owner, $group, $other) =&writers($dirname);
$$new_plans_r{"r $ob u $owner"} =
"directory of $ob is writeable byuid $owner" if ($owner ne "");
$$new_plans_r{"r $ob g $group"} =
"directory of $ob iswriteable by gid $group" if ($group ne "");
$$new_plans_r{"r $ob u .*"} =
"directoryof $ob is world writeable" if ($other);
} # end of eval_access()
# control_file_attacks()
# This routine establishes some rulesindicating that access to a given
# set of files will allow access to the root account.It then goes
#through the list of files to create rules about who does have access
# to thesefiles.
#
# Expects: Areference to a "new_plans" associative array.
# Calls: KUANG::eval_access()
# Called by:KUANG::run_KUANG()
# Returns: nothing.
# Side-effects: Creates new entries in "new_plans" assoc. array.
# Errors: none.
subcontrol_file_attacks {
my($new_plans_r) = pop(@_);
#
#Controlling files for root and users. If any of these files can
# be replaced or written bynon-root user, then the system is
# vulnerable.
my(@sys_files) = ("/etc/passwd","/usr/lib/aliases",
"/etc/aliases", "/etc/rc", "/etc/rc.boot", "/etc/rc.single",
"/etc/rc.config","/etc/rc.local", "/usr/lib/crontab",
"/usr/spool/cron/crontabs","/etc/hosts.eqiv");
foreach (@sys_files) {
# first we create therules pertaining to the control-files ...
$$new_plans_r{"u 0 r $_"} =
"rootaccess via replaceable $_";
$$new_plans_r{"u 0 w $_"} =
"root access via. writeable$_";
# then wecreate rules describing the access to these files.
eval_access($_,$new_plans_r);
}
## Check uid specific "home" directoryand "control files". If any
## are writeable by other than root or the uidthemselves, thenthat
##uid can be accessed.
my(@pwent);
while ( @pwent = main::getpwent ) {
my($home_s) = $pwent[7];
my($uid_s) =$pwent[2];
if ( $home_s ne "" && main::stat($home_s) ) {
eval_access($home_s,$new_plans_r);
$home_s = "" if ($home_s eq "/");
foreach(".rhosts",".login",".logout",".cshrc",".profile") {
my($target) ="$home_s/$_";
if ( main::stat($target) ) {
$$new_plans_r{"u $uid_s r $target"}=
"Access user if I can replace $_ control file";
$$new_plans_r{"u $uid_sw $target"} =
"Access user if I can write $_ control file";
eval_access("$target", $new_plans_r);
}
}
}
}
} # end of control_file_attacks()
# gid_attacks ()
#
# Called by: anonymous return for this file.
sub gid_attacks {
my($new_plans_r) = pop(@_);
#
# Plans for attacking GIDs...
# N.B. At this stage all this routinedoes is load the plans. It
# should evaluate the state of the files first, to see if theplan
# is worthloading.
#
# If we canwrite or replace /etc/group we can become any group
#
$$new_plans_r{"g .* r /etc/group"} = "/etc/group can be replaced";
$$new_plans_r{"g .* w /etc/group"} = "/etc/group can beoverwritten";
eval_access("/etc/group", $new_plans_r);
} # end of gid_attacks()
# main for KUANG
# the "well defined" name of the KuangPlusroutine which will, in turn, invoke
# the subroutines created above.
#
# Expects: nothing
# Calls: KUANG::control_file_attacks()
# Called by:KuangPlus::kuangplus()
# Returns: a new associative array of plans.
tql# Side effects: none.
# Errors: none.
my(@uname) = main::uname();
if ( $uname[0] =~ /(Linux|FreeBSD)/ ) {
main::pdebug"Invoking KUANG rule set", 6.3;
KUANG::control_file_attacks(%main::new_plans);
KUANG::gid_attacks(%main::new_plans);
} else {
main::pdebug "Not appropriate platform for KUANGrules", 6.3;
}
Appendix J: Usingthe help option
Theoutput shown below is generated when the -help option is used withthe KuangPlus prototype. The output has been reformatted slightly for thepurposes of this document, however, the content has not been changed.
usage: ./kuangplus.pl [-d[=<level>]] [-v][-h] [-m=<pathname>]
./kuangplus.pl finds security concerns in the configuration of
the system it is run on.
-h, --h, -help, --help
- Prints this message and exits.
-v, --v,-verbose, --verbose
- verbose output. On finding a successful exploit, any informationrelevant to the exploit is printed.
-m=<dir>, --m=<dir>, -maximdir=<dir>,--maximdir=<dir>
- nominate the directory in which the "maxims" can be found. Bydefault this is the directory "maxims" in the same directory as the"kuangplus.pl" script was invoked from.
-d[=level], --d[=level],-debug[=level], --debug[=level]
- Various debugging information is available.The "=level" argument indicates what information is of interest. With nolevel specified, "all" debugging information is printed. The following,"-d=1", "-d=.1" and "-d=1.1", are all valid levels. The followingare the attributes attached to the different levels:
1 - main .1 - file access
2 -humanize() .2 - @plan array access
3 - addto() .3 -miscellaneous messages
4 - init_kuang() .5 - @known array access
5 -evaluate_plans() .6 - rejected rules
6 - maxim files
7 - command line argumenthandling
8- print_success()
9 - find_match()
10 - safeops - stat()
11 - safeops - uname()
12 - safeops -getpwent()
13 - safeops - getpwname()
14 - safeops - getpwuid()
15 - safeops - general
16 - rule_qc()