Linux LINUX ENTERPRISE DESKTOP 10 SP1 - Manual Download Page 1

SUSE Linux Enterprise

www.novell.com

10 SP1

May 08, 2008

The Linux Audit Framework

Summary of Contents for LINUX ENTERPRISE DESKTOP 10 SP1 -

Page 1: ...SUSE Linux Enterprise www novell com 10 SP1 May 08 2008 The Linux Audit Framework ...

Page 2: ...hat this manual specifically for the printed format is reproduced and or distributed for noncommercial use only The express authorization of Novell Inc must be obtained prior to any other use of any manual or part thereof For Novell trademarks see the Novell Trademark and Service Mark list http www novell com company legal trademarks tmlist html Linux is a registered trademark of Linus Torvalds Al...

Page 3: ...Audit Data 32 2 Setting Up the Linux Audit Framework 35 2 1 Determining the Components to Audit 36 2 2 Configuring the Audit Daemon 37 2 3 Enabling Audit for System Calls 38 2 4 Setting Up Audit Rules 39 2 5 Adjusting the PAM Configuration 40 2 6 Configuring Audit Reports 41 2 7 Configuring Log Visualization 44 3 Introducing an Audit Rule Set 47 3 1 Adding Basic Audit Configuration Parameters 48 3...

Page 4: ...Filtering System Call Arguments 54 3 7 Managing Audit Event Records Using Keys 57 4 Useful Resources 59 A Creating Flow Graphs from the Audit Statistics 61 B Creating Bar Charts from the Audit Statistics 65 ...

Page 5: ...PP Assurance requirements are summarized under the Evalu ation Assurance Level EAL EAL describes any activities that must take place for the evaluators to be confident that security attributes are present effective and implemented Examples for activities of this kind include documenting the developers search for se curity vulnerabilities the patch process and testing This guide provides a basic un...

Page 6: ...line documentation and enter your comments there 2 Documentation Updates For the latest version of this documentation see the SLES 10 SP1 doc Web site http www novell com documentation sles10 3 Documentation Conventions The following typographical conventions are used in this manual etc passwd filenames and directory names placeholder replace placeholder with the actual value PATH the environment ...

Page 7: ...ning and the end of the text block ipseries s390 zseries This paragraph is only relevant for the specified architec tures The arrows mark the beginning and the end of the text block Dancing Penguins Chapter Penguins Another Manual This is a reference to a chapter in another manual About This Guide vii ...

Page 8: ......

Page 9: ... the relevant events The auditd daemon writes the audit reports to disk Various command line utilities take care of displaying querying and archiving the audit trail Audit enables you to do the following Associate Users with Processes Audit maps processes to the user ID that started them This makes it possible for the administrator or security officer to exactly trace which user owns which process...

Page 10: ... of interest and also to tune audit to record only selected events You can create your own set of rules and have the audit daemon record only those of interest to you Guarantee the Availability of the Report Data Audit reports are owned by root and therefore only removable by root Unau thorized users cannot remove the audit logs Prevent Audit Data Loss If the kernel runs out of memory the audit da...

Page 11: ...omponents of audit interact with each other Figure 1 1 Introducing the Components of Linux Audit kernel audit auditd auditd conf auditctl audit rules audit log audispd autrace aureport ausearch application Straight arrows represent the data flow between components while dashed arrows rep resent lines of control between components auditd The audit daemon is responsible for writing the audit message...

Page 12: ... aureport utility allows you to create custom reports from the audit event log This report generation can easily be scripted and the output used by various other applications for example to plot these results For more information about aureport refer to Section 1 5 Understanding the Audit Logs and Generating Reports page 15 ausearch The ausearch utility can search the audit log file for certain ev...

Page 13: ...auditing by default Set to no for full audit functionality includ ing file and directory watches and system call auditing The etc auditd conf configuration file determines how the audit system functions once the daemon has been started For most use cases the default settings shipped with SUSE Linux Enterprise should suffice For CAPP environments most of these param eters need tweaking The followin...

Page 14: ...nt have the audit log reside on its own partition By doing so you can be sure that the space detection of the audit daemon is accurate and that you do not have other processes consuming this space priority_boost Determine how much of a priority boost the audit daemon should get Possible values are 0 to 3 with 3 assigning the highest priority The values given here translate to negative nice values ...

Page 15: ...tion specified in dispatcher This appli cation must be a highly trusted one because it needs to run as root disp_qos determines whether you allow for lossy or lossless communication between the audit daemon and the dispatcher If you choose lossy the audit daemon might discard some audit messages when the message queue is full These events still get written to disk if log_format is set to raw but t...

Page 16: ...syslog email suspend single and halt ignore tells the audit daemon to ignore the warning and do nothing syslog has it issue a warning to syslog and email sends an e mail to the account specified under action_mail_acct suspend tells the audit daemon to stop writing to disk but remain alive while single triggers the system to be brought down to single user mode halt triggers a full shutdown of the s...

Page 17: ...e disk_full_action is triggered when there is absolutely no more room for any audit logs you should bring the system down to single user mode single or shut it down completely halt disk_error_action Specify which action to take when the audit daemon encounters any kind of disk error while writing the logs to disk or rotating the logs The possible value are the same as for space_left_action NOTE CA...

Page 18: ...The main auditctl commands to control basic audit system parameters are auditctl e to enable or disable audit auditctl f to control the failure flag auditctl r to control the rate limit for audit messages auditctl b to control the backlog limit auditctl s to query the current status of the audit daemon The e f r and b options can also be specified in the audit rules file to avoid having to enter t...

Page 19: ...cify the maximum number of outstand ing audit buffers allowed If all buffers are full the action specified in the failure flag is triggered backlog_limit Count the current number of lost audit messages lost Count the current number of outstanding audit buffers backlog 1 4 Passing Parameters to the Audit System Commands to control the audit system can be invoked individually from the shell using au...

Page 20: ...1000 f 1 r 10 e 1 Specify the maximum number of outstanding audit buffers Depending on the level of logging activity you might need to adjust the number of buffers to avoid causing too heavy an audit load on your system Specify the failure flag to use See Table 1 1 Audit Status Flags page 11 for possible values Specify the maximum number of messages per second that may be issued by the kernel See ...

Page 21: ...ermissions The k option allows you to specify a key to use to filter the audit logs for this particular event later System call auditing lets you track your system s behavior on a level even below the application level When designing these rules consider that auditing a great many system calls may increase your system load and cause you to run out of disk space due Con sider carefully which events...

Page 22: ... have wheel as the group A process is given an audit ID on user login This ID is then handed down to any child process started by the initial process of the user Even if the user changes his identity the audit ID stays the same and allows tracing actions to the original user TIP Filtering System Call Arguments For more details on filtering system call arguments refer to Section 3 6 Filter ing Syst...

Page 23: ...exit always watch etc perm rx LIST_RULES exit always watch etc passwd perm rwxa key fk_passwd LIST_RULES exit always watch etc shadow perm rwxa LIST_RULES entry always syscall mkdir LIST_RULES entry always a1 4 0x4 syscall access LIST_RULES exit always a0 2 0x2 syscall ipc LIST_RULES exit always success 0 syscall open NOTE Creating Filter Rules You can build very sophisticated audit rules by using...

Page 24: ...rote three messages to the log All of them are closely linked together and you would not be able to make sense of one of them without the others The first message reveals the following information type The type of event recorded In this case it assigns the SYSCALL type to an event triggered by a system call less or rather the underlying open The CWD event was recorded to record the current working...

Page 25: ...le this is the file descriptor number This varies by system call a0 to a3 The first four arguments to the system call in numeric form The values of these are totally system call dependent In this example an open system call the fol lowing are used a0 bfba161c a1 8000 a2 0 a3 8000 a0 is the start address of the passed pathname a1 is the flags 8000 in hex notation translates to 100000 in octal notat...

Page 26: ...D set group ID and file system group ID of the user that started the process tty The terminal from which the application is started In this case a pseudoterminal used in an SSH session comm The application name under which it appears in the task list exe The resolved pathname to the binary program subj auditd records whether the process is subject to any security context such as AppArmor unconstra...

Page 27: ... stands for dev hda1 or first partition on the first IDE device mode Numerical representation of the file s access permissions In this case root has read and write permissions and his group root has read access while the entire rest of the world cannot access the file at all ouid and ogid Refer to the UID and GID of the inode itself rdev Not applicable for this example The rdev entry only applies ...

Page 28: ...name earth example com addr 192 168 0 1 terminal dev pts 0 res success type CRED_REFR msg audit 1175508928 548 4504 user pid 28732 uid 0 auid 0 msg PAM setcred acct root exe usr sbin sshd hostname earth example com addr 192 168 0 1 terminal dev pts 0 res success PAM reports that is has successfully requested user authentication for root from a remote host earth example com 192 168 0 1 The terminal...

Page 29: ...s to accounts groups or roles 0 Number of logins 20 Number of failed logins 10 Number of users 3 Number of terminals 11 Number of host names 5 Number of executables 12 Number of files 3 Number of AVC denials 0 Number of MAC events 0 Number of failed syscalls 4 Number of anomaly events 0 Number of responses to anomaly events 0 Number of crypto events 0 Number of process IDs 544 Number of events 279...

Page 30: ... names 5 Number of executables 12 Number of files 3 Number of AVC denials 0 Number of MAC events 0 Number of failed syscalls 4 Number of anomaly events 0 Number of responses to anomaly events 0 Number of crypto events 0 Number of process IDs 544 Number of events 2795 Create a Summary Report of Failed Events If you want to break down the overall statistics of plain aureport to the statistics of fai...

Page 31: ...ailed logins 0 Number of users 3 Number of terminals 10 Number of host names 5 Number of executables 12 Number of files 4 Number of AVC denials 0 Number of MAC events 0 Number of failed syscalls 0 Number of anomaly events 0 Number of responses to anomaly events 0 Number of crypto events 0 Number of process IDs 535 Number of events 2787 Create Summary Reports In addition to the dedicated summary re...

Page 32: ...s ID name of the executable system call audit ID and event number aureport p Process ID Report date time pid exe syscall auid event 1 04 23 2007 08 00 01 PM 13097 usr sbin cron 0 unset 1888 2 04 23 2007 08 00 01 PM 13097 usr sbin cron 0 unset 1889 3 04 23 2007 08 00 01 PM 13097 0 root 1890 Create a Report from All System Call Events To analyze the audit log from a system call s point of view use t...

Page 33: ... file related events including date time name of the accessed file number of the system call accessing it success or failure of the command the executable accessing the file audit ID and event number aureport f File Report date time file syscall success exe auid event 1 04 23 2007 06 16 38 PM var log audit audit log 5 yes usr bin file root 1822 2 04 23 2007 06 16 38 PM var log audit audit log 5 ye...

Page 34: ...ample com dev pts 0 usr sbin sshd yes 1624 2 04 23 2007 01 38 12 PM root earth example com dev pts 1 usr sbin sshd yes 1655 3 04 23 2007 03 32 58 PM root 192 168 0 20 dev pts 0 usr sbin sshd yes 1712 Limit a Report to a Certain Time Frame To analyze the logs for a particular time frame such as only the working hours of April 23 2007 first find out whether this data is contained in the the current ...

Page 35: ...e and time as for ts All reports except the summary ones are printed in column format and sent to stdout which means that this data can be piped to other commands very easily The visualization scripts introduced in Section 1 8 Visualizing Audit Data page 32 are just one ex ample of how to further process the data generated by audit 1 6 Querying the Audit Daemon Logs with ausearch The aureport tool...

Page 36: ...ail of a particular event in the log Most of the report types described in Section 1 5 Understanding the Audit Logs and Generating Reports page 15 include audit event IDs in their output An audit event ID is the second part of an audit message ID which consists of a UNIX epoch time stamp and the audit event ID separated by a colon All events that are logged from one application s system call have ...

Page 37: ... login ID specified pro vided that user had been able to log in successfully Search by User ID View records related to any of the user IDs both user ID and effective user ID with ausearch ua View reports related to a particular user ID with ausearch ui uid Search for records related to a particular effective user ID use the ausearch ue euid Searching for a user ID means the user ID of the user cre...

Page 38: ...call success value with ausearch sv success_value for example ausearch sv yes for all successful system calls Search by Filename View records containing a certain filename with ausearch f filename for example ausearch f foo bar for all records related to the foo bar file Using the filename alone would work as well but using relative paths would not Search by Terminal View records of events related...

Page 39: ...e command autrace works similarly to the strace command but gathers slightly different information The output of autrace is written to var log audit audit log and does not look any different from the standard audit log entries When performing an autrace on a process make sure that any audit rules are purged from the queue to avoid these rules clashing with the ones autrace adds itself Delete the a...

Page 40: ...rans formed into human readable graphics The first example illustrates the relationship of programs and system calls To get to this kind of data you need to determine the appropriate aureport command that delivers the source data from which to generate the final graphic aureport s Syscall Report date time syscall pid comm auid event 1 04 23 2007 08 04 08 PM 5 13374 file root 1900 2 04 23 2007 08 0...

Page 41: ...e have been logged The appropriate aureport command to extract this kind of infor mation is aureport e aureport e i summary Event Summary Report total type 2434 SYSCALL 816 USER_START 816 USER_ACCT 814 CRED_ACQ 810 LOGIN 806 CRED_DISP 779 USER_END 99 CONFIG_CHANGE 52 USER_LOGIN Because this type of report already contains a two column output it is just piped into the the visualization script and t...

Page 42: ...art Common Event Types For background information about the visualization of audit data refer to the Web site of the audit project at http people redhat com sgrubb audit visualize index html 34 The Linux Audit Framework ...

Page 43: ...ptionally audit libs python To use the log visualization as described in Section 2 7 Configuring Log Visualization page 44 install gnuplot from the SUSE Linux Enterprise media and graphviz from the SUSE Linux Enterprise SDK 2 Determine the components to audit Refer to Section 2 1 Determining the Components to Audit page 36 for details 3 Check or modify the basic audit daemon configuration Refer to...

Page 44: ...n audit configuration determine to which degree you want to use it Check the following rules of thumb to determine which use case best applies to you and your requirements If you require a full security audit for CAPP EAL certification enable full audit for system calls and configure watches on various configuration files and directories similar to the rule set featured in Chapter 3 Introducing an...

Page 45: ...ted you might want to reduce the number of log files to keep if they are rotated and you might want get an earlier warning if disk space is running out For a CAPP compliant setup adjust the values for log_file flush max_log_file max_log_file_action space_left space_left_action admin_space_left admin_space_left_action disk_full_action and disk_error_action as described in Section 1 2 Configuring th...

Page 46: ...l components and modules may log audit events outside of the control of auditctl and these appear in the audit log By default the only module that generates audit events is Novell AppArmor Advanced Logging with System Call Auditing To audit system calls and get meaningful file watches you need to enable audit contexts for system calls As you need system call auditing capabilities even when you are...

Page 47: ...es k CFG_audit_rules p rxwa w etc passwd k CFG_passwd p rwxa w etc sysconfig k CFG_sysconfig an example system call rule a entry always S umask add your own rules When configuring the basic audit system parameters such as the backlog parameter b test these settings with your intended audit rule set to determine whether the backlog size is appropriate for the level of logging activity caused by you...

Page 48: ...fy events of this type in the log file Another thing to bear in mind when creating file and directory watches is that audit cannot deal with files that do not when the rules are created Any file that is added to your system while audit is already running are not watched unless you extend the rule set to watch this new file For more information about creating custom rules refer to Section 1 4 Passi...

Page 49: ...o focus on areas of interest and get meaningful statistics on the nature and frequency of the events you are monitoring To analyze individual events in detail use the ausearch tool Before setting up audit reporting consider the following What types of events do you want to monitor by generating regular reports Select the appropriate aureport command lines as described in Section 1 5 2 Generating C...

Page 50: ...umber of failed logins 16 Number of users 5 Number of terminals 17 Number of host names 7 Number of executables 16 Number of files 173 Number of AVC denials 0 Number of MAC events 0 Number of failed syscalls 799 Number of anomaly events 0 Number of responses to anomaly events 0 Number of crypto events 0 Number of process IDs 2382 Number of events 14424 2 Run a summary report for failed events and ...

Page 51: ...le en_US UTF 8 LC_PAPER 13 usr lib locale en_US UTF 8 LC_MESSAGES 13 usr lib locale en_US UTF 8 LC_MONETARY 13 usr lib locale en_US UTF 8 LC_COLLATE 13 usr lib locale en_US UTF 8 LC_TIME 13 usr lib locale en_US UTF 8 LC_NUMERIC 13 usr lib locale en_US UTF 8 LC_CTYPE 13 etc ld so preload To focus this summary report on a few files or directories of interest only such as etc auditd conf etc pam d an...

Page 52: ...s by using start and end dates and times with your aureport com mands ts and te For more information refer to Section 1 5 2 Generating Custom Audit Reports page 20 All steps except for the last one can be run automatically and would easily be scriptable and configured as cron jobs Any of the failed summary reports could be transformed easily into a bar chart that plots files versus failed access a...

Page 53: ...of the above event types just add the failed option to the respective aureport command To cover a certain pe riod of time only use the ts and te options on aureport Any of these commands can be tweaked further by narrowing down its scope using grep or egrep and regular expressions See the comments in Appendix B Creating Bar Charts from the Audit Statistics page 65 for an example Any of the above c...

Page 54: ...rt uniq mkgraph Graphs can also be combined to illustrate complex relationships See the comments in Appendix A Creating Flow Graphs from the Audit Statistics page 61 for further in formation and an example The graphs produced by this script are created in PostScript format by default but you can change the output format by changing the EXT variable from ps to png or jpg To cover a certain period o...

Page 55: ...ion files see Section 3 2 Adding Watches on Audit Log Files and Configuration Files page 49 Monitoring operations on file system objects see Section 3 3 Monitoring File System Objects page 50 Monitoring security databases see Section 3 4 Monitoring Security Configuration Files and Databases page 51 Monitoring miscellaneous system calls Section 3 5 Monitoring Miscellaneous System Calls page 54 Filt...

Page 56: ...xisting rules before starting to define new ones Set the number of buffers to take the audit messages Depending on the level of audit logging on your system increase or decrease this figure Set the failure flag to use when the kernel needs to handle critical errors Possible values are 0 silent 1 printk print a failure message and 2 panic halt the system By emptying the rule queue with the D option...

Page 57: ...figuration files and the log files themselves ensures that you can track any attempt to tamper with the configuration files or detect any at tempted accesses to the log files NOTE Creating Directory and File Watches Creating watches on a directory is not necessarily sufficient if you need events for file access Events on directory access are only triggered when the directory s inode is updated wit...

Page 58: ...diting System Calls Auditing system calls results in a high logging activity This activity in turn puts a heavy load on the kernel With a kernel less responsive than usual the system s backlog and rate limits might be exceeded Carefully evaluate which system calls to include in your audit rule set and adjust the log settings accordingly See Section 1 2 Configuring the Audit Daemon page 5 for detai...

Page 59: ...tem call which creates special device files Enable an audit context for any mount or umount operation For the x64_64 archi tecture disable the umount rule For the ia64 architecture disable the umount2 rule 3 4 Monitoring Security Configuration Files and Databases To make sure that your system is not made to do undesired things track any attempts to change the cron and at configurations or the list...

Page 60: ... etc cron weekly p wa w etc crontab p wa w var spool cron root w etc group p wa w etc passwd p wa w etc shadow w etc login defs p wa w etc securetty w var log faillog w var log lastlog w etc hosts p wa w etc sysconfig w etc inittab p wa w etc init d w etc init d auditd p wa w etc ld so conf p wa w etc localtime p wa w etc sysctl conf p wa w etc modprobe conf d w etc modprobe conf local p wa w etc ...

Page 61: ...guration in etc inittab and the etc init d directory Enable per file watches if you are interested in file events Set watches and labels for any changes to the linker configuration in etc ld so conf Set watches and a label for etc localtime Set watches and labels for the kernel configuration files etc sysctl conf etc modprobe d etc modprobe conf local and etc modprobe conf Set watches on the PAM c...

Page 62: ...racking on the ia64 architecture comment the first rule and enable the second one Add an audit context to the umask system call Track attempts to change the system time adjtimex can be used to skew the time settimeofday sets the absolute time 3 6 Filtering System Call Arguments In addition to the system call auditing introduced in Section 3 3 Monitoring File System Objects page 50 and Section 3 5 ...

Page 63: ... rule filters for all access calls testing for sufficient write permissions to a file or file system object accessed by a user or process Audit the access system call but only if the second argument of the system call mode is 6 meaning 4 OR 2 which translates to R_OK OR W_OK This rule filters for access calls testing for sufficient read and write permissions Audit the access system call but only i...

Page 64: ...ssed to the ipc system call Filtering for these arguments helps you focus on those IPC calls of interest to you Check usr include asm generic ipc h for possible argument values msgctl a entry always S ipc F a0 14 msgget a entry always S ipc F a0 13 Enable if you are interested in these events x86_64 ia64 a entry always S msgctl a entry always S msgget semctl a entry always S ipc F a0 3 semget a en...

Page 65: ... on ipc system calls For these platforms comment the first two rules and add the plain system call rules without argument filtering 3 7 Managing Audit Event Records Using Keys After configuring a few rules generating events and populating the logs you need to find a way to tell one event from the others Using the ausearch command you can filter the logs for various criteria Using ausearch m messag...

Page 66: ...rch k CFG_audit rules time Thu Apr 26 14 56 25 2007 type PATH msg audit 1177592185 922 52 item 0 name etc audit rules inode 444083 dev 03 01 mode 0100644 ouid 0 ogid 0 rdev 00 00 type CWD msg audit 1177592185 922 52 cwd root type SYSCALL msg audit 1177592185 922 52 arch 40000003 syscall 226 success yes exit 0 a0 8175be8 a1 b7e8dc4f a2 81b6de8 a3 1c items 1 ppid 3765 pid 3839 auid 0 uid 0 gid 0 eui...

Page 67: ... 8 auditctl 8 autrace 8 ausearch 8 aureport 8 http people redhat com sgrubb audit index html The home page of the Linux audit project This site contains several specifications relating to different aspects of Linux audit as well as a short FAQ usr share doc packages audit The audit package itself contains a README with basic design information along with some Red Hat specific instructions and a sa...

Page 68: ...ncriteriaportal org The official Web site of the Common Criteria project Learn all about the Common Criteria security certification initiative and which role audit plays in this framework 60 The Linux Audit Framework ...

Page 69: ... commented aureport commands is meant to be written on one continuous line Adjust this if you use the copy method 2 Move the mkgraph file to root s home directory 3 Adjust the file permissions to read write and execute for root bin sh Copyright 2005 Red Hat Inc Durham North Carolina All Rights Reserved This software may be freely redistributed and or modified under the terms of the GNU General Pub...

Page 70: ... printf s s n 5 8 sort uniq mkgraph See who is accessing files aureport f i awk 0 9 printf s s n 8 4 sort uniq mkgraph See what account is running which exes aureport u i awk 0 9 printf s s n 4 7 sort uniq mkgraph See what accounts are being used by remote hosts aureport h i awk 0 9 printf s s n 4 6 sort uniq mkgraph Graphs can be combined too For example to see what host people logged in from and...

Page 71: ...ead t 5 line 2 dev null if ne 0 then break fi if x line x then echo line awk printf t s s n 1 2 DOT_FILE fi done echo DOT_FILE echo DOT_FILE DOT_CMD T EXT o OUT EXT DOT_FILE 1 2 2 dev null if ne 0 then echo Error rendering rm f DOT_FILE exit 1 fi rm f DOT_FILE if EXT ps then echo Gzipping graph rm f OUT ps gz 2 dev null gzip best OUT ps echo Graph was written to OUT EXT gz else echo Graph was writ...

Page 72: ......

Page 73: ...djust this by removing the trailing and merging the two lines if you use the copy method 2 Move the mkbar file to root s home directory 3 Adjust the file permissions to read write and execute for root bin sh Copyright 2005 Red Hat Inc Durham North Carolina All Rights Reserved This software may be freely redistributed and or modified under the terms of the GNU General Public License as published by...

Page 74: ...nfig change aureport e i summary egrep vi syscall change mkbar events2 if x 1 x then OUT 1 else OUT chart fi EXT png gpcommand plot script gpdata OUT dat gpout OUT EXT plotcommand which gnuplot if x plotcommand x then echo gnuplot is not installed exit 1 fi create gnuplot command file echo set terminal EXT small xfdf5e6 x000000 x404040 x0000ff x00ff00 gpcommand echo set grid ytics gpcommand echo s...

Page 75: ... x line x then i expr i 1 echo line awk 0 9 printf s d 2 1 num num i gpcommand echo line awk 0 9 printf d s n 1 num 1 num i gpdata fi done echo e n gpcommand echo plot gpdata with boxes gpcommand Create the chart gnuplot gpcommand Cleanup rm f gpcommand gpdata output results if e gpout then echo Wrote gpout exit 0 fi exit 1 Creating Bar Charts from the Audit Statistics 67 ...

Page 76: ......

Reviews: