donderdag 17 september 2009

AVC Denials: Example

SELinux logs policy violations to /var/log/audit/audit.log if audit is installed and enabled. If audit is
not installed or enabled, than SELinux sends policy violation notices to dmesg or /var/log/messages.

The policy violations that SELinux logs are called AVC denials. AVC is an abbreviation for Access Vector
Cache. Which is the SELinux cache with Access Vectors. Access vectors are the rules that govern access.

Reading AVC denials properly helps troubleshoot issues. In this article i will talk about, and highlight
some of the information you can retrieve from AVC denials. I will also touch on some of the tools that
assist in listing, parsing and translating SELinux Access Vector Cache denials.

Example of a AVC denial:

avc: denied { getattr } for pid=7604 comm="firefox" path="/usr/lib64/firefox-3.5.3/firefox" dev=dm-2 ino=1311607
scontext=dgrift_u:dgrift_r:gwibber_t:s0-s0:c0.c1023 tcontext=system_u:object_r:mozilla_exec_t:s0 tclass=file

The line above provides much information about what has been denied:

1. What process was denied access.
2. What domain type did the source process operate in when it was denied access.
3. What object or subject was the source process denied access to.
4. What was the object/subject type of the target.
5. What permission was denied.
6. What is the class of the target.
7. What was the process identity of the source.
8. What was the inode number of the target object.
9. What happened.

Security is about managing interaction. Interaction has a source and a target. Interaction involves atleast
a subject as a source (an interacting party) and a subject or object as a target. The target of the
interaction. Subjects are interacting entities, and object non-interacting entities. Subjects can interact
with object, but subjects can also interact with other subjects.

The target class in a AVC denial tells us what the class (origin) of the target in an interaction is.
A source of a interaction is always a subject (interacting entity). Object can not interact and thus can
never be a source of an interaction.

Lets try and connect the dots and see if we can make sense of the example AVC denial above. We will try to
answer each of our 9 questions in the check list:

1. What process was denied access.

comm="firefox" shows use the name of the command that was run. The firefox program was denied access.

2. What domain type did the source
process operate in when it was denied access.

scontext=dgrift_u:dgrift_r:gwibber_t:s0-s0:c0.c1023 shows that the source firefox was operating with the
gwibber_t domain type. The type is the third field in the security context tuple.

3. What object or subject was the source process denied access to.

path="/usr/lib64/firefox-3.5.3/firefox" Shows what the target of the source in this interaction was.

4. What was the object/subject type of the target.

tcontext=system_u:object_r:mozilla_exec_t:s0 shows the type of the target.

5. What permission was denied.

{ getattr } Shows the syscall (permission) that was denied.

6. What is the class of the target.

tclass=file shows that the class of the target in our interaction was file.

7. What was the process identity of the source.

pid=7604 shows that the process id of the source of our interaction was 7604

8. What was the inode number of the target object.

ino=131160 shows that the inode number of the target object in our interaction was 131160.

9. What happened.

denied shows that the particular Access Vector was denied.

We have all the detail that we need to established *what* happend.

1. The command /usr/bin/firefox was executed but some interacting entity.
2. This command was executed with the gwibber_t domain type.
3. The target of the source /usr/bin/firefox was /usr/lib64/firefox-3.5.3/firefox
4. The type of the target was mozilla_exec_t
5. The source /usr/bin/firefox that operated with the gwibber_t domain type was denied the "getattr"
syscall on the target /usr/lib64/firefox-3.5.3/firefox that had type mozilla_exec_t.
6. The class of the target /usr/lib64/firefox-3.5.3/firefox is a file (the target is a file object)
7. The process of /usr/bin/firefox had the process id of 7604 when this Access vector occured.
8. The inode number of the target file object is 131160
9. Access was denied.

These are the SELinux facts:

the /usr/bin/firefox command was denied to get the attributes of the /usr/lib64/firefox-3.5.3/firefox file
source domain type gwibber_t was denied get attribute of a file object with type mozilla_exec_t

What this means is that there was no rule to allow this access, thus access was denied.

From here on out things get less obvious:

We know some facts but this has raised other questions:

1. Are the types of the source and target correct?
2. We know what was denied but we dont know why.
3. Should we allow this access?
4. Does it signal intrusion?
5. If we allow it access what would be the best way to do it.
6. What are the problems if we do it the other way?

The reason that these questions are harder to answer is because it depends on the policy that is created by
the policy author. But if you see an AVC denial we can usually narrow the cause down to:

a. The source and/or the target is mislabelled (wrong type)
b. It is a bug in policy.
c. Intrusion was detected and prevented.

So let's try to answer all these questions:

1. Are the types of the source and target correct?

This is the first thing we must verify. If the types are incorrect than we must correct them first to be able to learn the real reason
about what happend. Objects sometimes get mislabelled. For example if created the object whilst you had SELinux disabled and forgot to
restore the context. Another reason might be that you have moved the file from another location as opposed to copying it, and forgot
the restore the context.

How do we determine whether the types are correct? Well the answer is that we have to dig into some of the properties of the policy.
We have to put ourselves into the shoes of the policy author.

To verify whether the type of the source (gwibber_t) is correct we have to ask ourselves which policy module owns this type?
This is a hard question to answer. Really the only way to figure this out is to grep for the gwibber_t type in the source of the
policy. In this case there is a policy module installed called gwibber.

For example:

grep -r "type gwibber_t" Modules/

We are looking for the declaration of the gwibber_t type. Types are usually declared in files with .te suffixes (type enforcement
source policy files)

So we could narrow our grep a bit:

grep -r "type gwibber_t" Modules/ | grep "\.te"

Modules/gwibber.te:type gwibber_t;
Modules/gwibber.te:type gwibber_tmpfs_t;

The type is declared in the gwibber.te source policy type enforcement file. We can now grep this file for the policy_module
declaration to figure out what the name of the module is:

grep policy_module Modules/gwibber.te
policy_module(gwibber, 0.0.1)

The policy module name is gwibber and the version number is 0.0.1, Now we can determine whether this module is installed:

sudo /usr/sbin/semodule -l | grep gwibber
gwibber 0.0.1

The module is installed, we know that the type gwibber_t is owned by the gwibber module.

Now we should figure out what the type of the firefox command is. the firefox command is located in /usr/bin/firefox.
We can use ls -alZ /usr/sbin/firefox to determine the type of this command:

-rwxr-xr-x. root root system_u:object_r:bin_t:s0 /usr/bin/firefox

The type of the firefox command is bin_t. This type has a special property that is specific to the policy model. You could look up the
properties of this type the same way that we are currently looking up the properties of type gwibber_t.

But to not overly complicate things i will explain the main property of the bin_t type.

The bin_t type is a generic type for executable files in bin and sbin directories. These commands get run with the domain type of the
subject that executed the command. So if a process that was operating with the gwibber_t domain type executed a command with the bin_t
type, than that command would run with the gwibber_t domain type.

With this in we have to figure out whether processes with the gwibber_t domain type are allowed to execute files with the bin_t type:

sudo sesearch --allow -s gwibber_t -t bin_t -c file -p execute
Found 1 semantic av rules:
allow gwibber_t bin_t : file { ioctl read getattr lock execute execute_no_trans open } ;

The sesearch command queries the policy store and looks if there is a rule which allows the source gwibber_t domain type to execute
target objects of the files class with type bin_t.

A line is returned confirming that this is allowed. This tells us that the source in our interaction is likely correclty labelled.
This is what happened. Some process that run with the gwibber_t domain type ran /usr/bin/firefox which has the bin_t type causing the
firefox command to run with the gwibber_t domain type.

Now we need to determine whether the type of our target is correct. In our interaction that fortunatly is pretty easy.
We know the path of our target: /usr/lib64/firefox-3.5.3/firefox
We can run the matchpathcon command to see what type is defined for this location and if that defined type corresponds to the target
type in our avc denial: mozilla_exec_t.

sudo /sbin/matchpathcon /usr/lib64/firefox-3.5.3/firefox
/usr/lib64/firefox-3.5.3/firefox system_u:object_r:mozilla_exec_t:s0

This confirms that the labelling in the interaction is correct for both source and target.

Sometimes however, the full path of the target is not shown in a avc denial. In that case you can use the inode number to find the
full path:

find / -inum 131160
/usr/lib64/firefox-3.5.3/firefox

2. We know what was denied but we dont know why.

This is another hard question to solve. We are no psychics. We cannot read the mind of the policy author.
We can try:

Should gwibber be able to run firefox? It should be able to run the default browser yes but in this case (the case where i am the
policy author of the gwibber policy module) it was decided to not allow this funcionality. It is obvious that the gwibber_t domain
type was not allowed the access/see (get attributes) the mozilla executable file with type mozilla_exec_t. So either that was done on
purpose or it is a bug in the policy.

3. Should we allow this access?
3. Should we allow this access?
4. Does it signal intrusion?
5. If we allow it access what would be the best way to do it.
6. What are the problems if we do it the other way?

Another tough question. if we allow gwibber_t to get attributes of files with type mozilla_exec_t it will probably want more after
that. Chances are that gwibber wants to execute the file (run firefox), since gwibber is designed to open pages in the default
browser.

If we want gwibber to be able to open the browser, do we want to allow gwibber_t to run the browser with the gwibber_t type or should
we lets gwibber_t domain transition to the mozilla_t domain type? Well my personal opinion is to domain transition where ever possible
but it depends on the situation. In this case a domain transition from gwibber_t to mozilla_t via mozilla_exec_t would likely be the
best decision. However this requires that policy is written manually to make it do what we want it to do.

But what if we just want to allow this single access vector? We could use the audit2allow tool to translate the avc denial into policy
language and to create a module. Than we could load the created policy module into the policy store with the semodule command.

echo "avc: denied { getattr } for pid=7604 comm="firefox" path="/usr/lib64/firefox-3.5.3/firefox" dev=dm-2 ino=1311607
scontext=dgrift_u:dgrift_r:gwibber_t:s0-s0:c0.c1023 tcontext=system_u:object_r:mozilla_exec_t:s0 tclass=file" | audit2allow -M
mygwibber; sudo semodule -i mygwibber.pp

Or we could do it ourselves:
echo "policy_module(mygwibber, 0.0.1)" > mygwibber.te;
echo "require { type gwibber_t, mozilla_exec_t; }" >> mygwibber.te;
echo "allow gwibber.te mozilla_exec_t:file getattr;" >> mygwibber.te;
make -f /usr/share/selinux/devel/Makefile mygwibber.pp
sudo semodule -i mygwibber.pp

So:

a. The source and/or the target is mislabelled (wrong type)

The types were correct.

b. It is a bug in policy.

It is a bug in policy because we determined that it is usually behaviour for gwibber to try to run the default browser to display
pages. Either we should allow it gwibber to run the browser (be it with the gwibber_t domain type or by domain transition with the
mozilla_t domain type) or we should make sure that no AVC denials are displayed when gwibber_t tries to access the mozilla executable
file with type mozilla_exec_t.

The rule that i am going to implement is this:

dontaudit gwibber_t mozilla_exec_t:file getattr;

Which says if domain type gwibber_t tries to get attributes of files with type mozilla_exec_t than "dontaudit" which means do not
print an avc denials (e.g. silently deny this)

That is just my personal preference. Its not something fixed. It is my security decision, whether good or bad.

c. Intrusion was detected and prevented.

No not really an intrusion since gwibber is designed to open pages in the default web browser which is firefox. So it is expected
behaviour. However i dont want to allow it. But i dont want to log the AVC denial when it happens either because its not important.


출처 - http://selinux-mac.blogspot.kr/2009/09/avc-denials-example.html



'System > Linux' 카테고리의 다른 글

리눅스 CPU당 코어(core) 수 확인  (0) 2013.02.03
linux - systemd, systemctl  (0) 2013.01.08
linux - audit2allow  (0) 2013.01.08
고급 Bash 스크립팅 가이드  (0) 2013.01.02
Linux VFS(Virtual File System Switch) 해부  (0) 2012.10.29
Posted by linuxism
,

linux - audit2allow

System/Linux 2013. 1. 8. 10:58


audit2allow라는 프로그램은 이 에러를 가지고 해당하는 프로세서에 권한을 주는 정책 파일을 자동으로 생성시켜준다. 예를 들면 이런 식으로 사용한다.

   1  grep httpd audit.log | audit2allow -M httpd

이 명령은 audit.log에서 httpd가 나온 로그를 전부 audit2allow로 넘겨서 권한 정책 파일을 출력하도록 한다. 이렇게 하면 .pp 파일과 .te 파일이 만들어진다. pp파일은 새로운 권한 정책을 적용하는 하는 데 사용하고, .te 파일은 새로 어떤 권한 정책이 추가되는지를 담고 있다. audit2allow가 제대로 실행됐으면 그 다음에 .pp 파일을 어떻게 적용하는지 보여주는데 다음과 같다.

   1  semodule -i httpd.pp

조금 시간이 걸리는데, 이렇게 하면 새로운 권한 정책이 적용된다. 조금 팁을 더해보자면 audit2allow로 생성되는 권한 정책은 에러메시지가 난 부분에 대해서만 정책을 생성한다. 예를 들어 파일을 생성하다 에러가 났으면 파일 생성 권한만 추가하고 삭제나 변경 읽기 등은 여전히 불가능할 수 있다. 이런 명령들을 하나하나 에러를 내고 .pp 파일을 만들면 권한 설정이 가능하다. 마찬가지로 일일이 권한이 필요한 에러만 찾아서 audit2allow에 보낼 수도 있다. 꽤나 무식한 방법이긴 한데, selinux의 권한 편집이란 게 텍스트 파일 편집하는 식이 아니라서 이런 방법이 제일 쉬울지도 모른다

 

그리고 정책 파일들은 가능하면 보존해두는 게 좋다.

 

semodule -r httpd.pp

같은 방식으로 수정한 정책을 다시 되돌릴 수도 있기 때문이다.

 

아마 이게 가장 기본적으로 알아둬야할 selinux 정책 설정 방법. 그 외에도 getsebool이라던가 setsebool라는 명령어도 있는데, 몇몇 부분에 대해 옵션 형식으로 권한 설정할 수 있는 프로그램.


출처 - http://linuking.com/GNHome/index.php?document_srl=259&mid=jayou&sort_index=readed_count&order_type=desc&listStyle=viewer&page=3







'System > Linux' 카테고리의 다른 글

linux - systemd, systemctl  (0) 2013.01.08
SELinux - AVC Denials  (0) 2013.01.08
고급 Bash 스크립팅 가이드  (0) 2013.01.02
Linux VFS(Virtual File System Switch) 해부  (0) 2012.10.29
linux - logrotate  (0) 2012.09.07
Posted by linuxism
,


The include (or require) statement takes all the text/code/markup that exists in the specified file and copies it into the file that uses the include statement.

Including files is very useful when you want to include the same PHP, HTML, or text on multiple pages of a website.


PHP include and require Statements

It is possible to insert the content of one PHP file into another PHP file (before the server executes it), with the include or require statement.

The include and require statements are identical, except upon failure:

  • require will produce a fatal error (E_COMPILE_ERROR) and stop the script
  • include will only produce a warning (E_WARNING) and the script will continue

So, if you want the execution to go on and show users the output, even if the include file is missing, use the include statement. Otherwise, in case of FrameWork, CMS, or a complex PHP application coding, always use the require statement to include a key file to the flow of execution. This will help avoid compromising your application's security and integrity, just in-case one key file is accidentally missing.

Including files saves a lot of work. This means that you can create a standard header, footer, or menu file for all your web pages. Then, when the header needs to be updated, you can only update the header include file.

Syntax

include 'filename';

or

require 'filename';


PHP include vs. require

The require statement is also used to include a file into the PHP code.

However, there is one big difference between include and require; when a file is included with the include statement and PHP cannot find it, the script will continue to execute:

Example

<html>
<body>

<h1>Welcome to my home page!</h1>
<?php include 'noFileExists.php';
echo "I have a $color $car.";
?>

</body>
</html>

Run example »

If we do the same example using the require statement, the echo statement will not be executed because the script execution dies after the require statement returned a fatal error:

Example

<html>
<body>

<h1>Welcome to my home page!</h1>
<?php require 'noFileExists.php';
echo "I have a $color $car.";
?>

</body>
</html>

Run example »


Use require when the file is required by the application.

Use include when the file is not required and application should continue when file is not found.



source - http://www.w3schools.com/php/php_includes.asp








다른 파일을 불러들인다는 점에서 include와 require는 같다. 하지만 오류가 있을 경우 그걸 처리하는 방식이 다르다.

include는 오류가 있으면 오류 내용을 경고로 알린 뒤, 그 나머지 부분을 제대로 실행한다. 반면 require는 오류가 있으면 오류 내용을 알린 뒤 그걸로 끝이다. 일단 오류가 일어나면 더 이상 프로그램을 실행하지 않는다.

include의 오류 예

예를 들어, 아래와 같은 코드를 생각해 보자.


sample.php

<html>
<body>

<?php
echo "<p>안녕하신감</p>";
include "../footer.php";
echo "<p>안녕 못하당</p>";
?>

<p>안 됐당</p>

</body>
</html>

해당 경로에 footer.php 파일이 없을 경우 sample.php 파일은 브라우저에 다음과 같은 결과를 보여준다.

안녕하신감

Warning: main(../footer.php): failed to open stream: No such file or directory in /example/sample.php on line 6

Warning: main(../footer.php): failed to open stream: No such file or directory in /example/sample.php on line 6

Warning: main(): Failed opening '../footer.php' for inclusion (include_path='.:/example') in /example/sample.php on line 6

안녕 못하당

안 됐당

오류 내용에서 경로명은 임의로 바꾼 것이고, 하여튼 중요한 건 오류가 있는 부분은 실행되지 않지만 앞뒤로 그 나머지는 모두 실행된다는 점이다.

require의 오류 예

하지만 require의 경우엔 다르다. 예를 들어, 아래와 같은 코드를 짰다고 하자.


sample.php

<html>
<body>

<?php
echo "<p>안녕하신감</p>";
require "../footer.php";
echo "<p>안녕 못하당</p>";
?>

<p>안 됐당</p>

</body>
</html>

그런데 해당 경로에 footer.php 파일이 없다면 sample.php 파일은 브라우저에 다음과 같은 결과를 보여준다.

안녕하신감

Warning: main(../footer.php): failed to open stream: No such file or directory in /example/sample.php on line 6

Warning: main(../footer.php): failed to open stream: No such file or directory in example/sample.php on line 6

Fatal error: main(): Failed opening required '../footer.php' (include_path='.:/example') in /example/sample.php on line 6

include 때와는 달리 '안녕 못하당'과 '안 됐당'이 출력되지 않았다. 그러니까 require는 오류가 있으면 거기부터 그 나머지는 실행하지 않는다는 것을 알 수 있다. 게다가 오류도 include에서는 그냥 경고 (Warning)라고만 하는데, require에서는 치명적인 오류 (Fatal error)라고 한다.




'Development > PHP' 카테고리의 다른 글

php - mail  (0) 2013.04.06
copyright 년도 자동표기하기  (0) 2013.03.06
php - date() 오류  (0) 2012.07.21
php - mail 함수  (1) 2012.07.11
PHP Framework - CodeIgniter  (0) 2012.05.07
Posted by linuxism
,