lab updates

This commit is contained in:
Z. Cliffe Schreuders
2019-02-06 16:35:13 +00:00
parent e341ddb261
commit 9b662bcd43
9 changed files with 339 additions and 322 deletions

View File

@@ -3,6 +3,7 @@ require_relative '../../../../../lib/objects/local_string_encoder.rb'
class AccountGenerator < StringEncoder
attr_accessor :username
attr_accessor :password
attr_accessor :groups
attr_accessor :super_user
attr_accessor :strings_to_leak
attr_accessor :leaked_filenames
@@ -13,6 +14,7 @@ class AccountGenerator < StringEncoder
self.module_name = 'Account Generator / Builder'
self.username = ''
self.password = ''
self.groups = ''
self.super_user = ''
self.strings_to_leak = []
self.data_to_leak = []
@@ -23,6 +25,7 @@ class AccountGenerator < StringEncoder
account_hash = {}
account_hash['username'] = self.username
account_hash['password'] = self.password
account_hash['groups'] = self.password
account_hash['super_user'] = self.super_user
account_hash['strings_to_leak'] = self.strings_to_leak
account_hash['leaked_filenames'] = self.leaked_filenames
@@ -37,6 +40,7 @@ class AccountGenerator < StringEncoder
['--data_to_leak', GetoptLong::OPTIONAL_ARGUMENT],
['--username', GetoptLong::REQUIRED_ARGUMENT],
['--password', GetoptLong::REQUIRED_ARGUMENT],
['--groups', GetoptLong::REQUIRED_ARGUMENT],
['--super_user', GetoptLong::REQUIRED_ARGUMENT]]
end
@@ -47,6 +51,8 @@ class AccountGenerator < StringEncoder
self.username << arg;
when '--password'
self.password << arg;
when '--groups'
self.groups << arg;
when '--super_user'
self.super_user << arg;
when '--strings_to_leak'
@@ -61,6 +67,7 @@ class AccountGenerator < StringEncoder
def encoding_print_string
'username: ' + self.username.to_s + print_string_padding +
'password: ' + self.password.to_s + print_string_padding +
'groups: ' + self.groups.to_s + print_string_padding +
'super_user: ' + self.super_user.to_s + print_string_padding +
'strings_to_leak: ' + self.strings_to_leak.to_s + print_string_padding +
'leaked_filenames: ' + self.leaked_filenames.to_s + print_string_padding +

View File

@@ -16,6 +16,7 @@
<read_fact>username</read_fact>
<read_fact>password</read_fact>
<read_fact>groups</read_fact>
<read_fact>super_user</read_fact>
<read_fact>strings_to_leak</read_fact>
<read_fact>leaked_filenames</read_fact>
@@ -27,6 +28,8 @@
<default_input into="password">
<generator type="password_generator"/>
</default_input>
<!-- <default_input into="groups">
</default_input> -->
<default_input into="super_user">
<value>false</value>
</default_input>

View File

@@ -215,43 +215,6 @@ chmod *XXX* ~/mysecrets
less /home/student/mysecrets`
```
# Up to here!!!!!!!!!!!!!!!!!!!!!!!!!!
# ------------------------------------
# CONVERT THESE INTO HB CHALLENGES
==Create a file "~/myshare", and grant everyone read-write access.==
> Test whether you have correctly set permissions.
==Create "mygroupshare", grant only read access to everyone in your group.==
> Test whether you have correctly set permissions.
Create a new group called "staff", and create a file that you and the other user can collaborate on (both edit).
> Hint, you should both be added to the group. You may require root access for this task. Your classmate may want to ssh to your system.
>
> Test whether you have correctly set permissions. Both users should be able to edit the file, yet other users should not have write access.
Read and write to the shared files created by others, for example:
```bash
cat /home/*dropbear*/myshare
```
**Challenge**:
```bash
mkdir test
```
```bash
touch test/test1 test/test2 test/test3
```
> Use a single chmod command to recursively set the permissions for all files contained in the new "test" directory.
>
> Hint: `man chmod`
## `umask`
Remember that our newly created file started with permissions that meant that everyone could read the file. This can be avoided by setting the **u**ser file-creation mode **mask** (**umask**). Every process has a umask: an octal that determines the permissions of newly created files. It works by removing permissions from the default `666` for files and `777` for new executables (based on a logical NOT). That is, a umask of `000` would result in new files with permissions `666`. A umask of `022` (which is the default value) gives `644`, that is `rw- -r- -r-`.
@@ -288,234 +251,6 @@ Figure out how to (and do) make that setting apply every time you login.
What would be a safe umask for a shared Linux system? Justify your decision.
# CUT HERE -------------------------------------------
## Set UID (SUID)
Sometimes a user needs to be able to do things that require permissions that they should not always have. For example, the passwd command is used to change your password. It needs read and write access to /etc/shadow. Clearly not every user should have that kind of access! Also, the ping command needs raw network access... Again not something that every user can do. The Unix solution is *set UID (SUID)*.
Using SUID, processes can be given permission to run as another user. For example, when you run passwd, the program actually runs as root (on most Unix systems).
In fact, every process actually has multiple identities, including:
- The real UID (RUID): the user who is running the command
- The effective UID (EUID): the way the process is treated
List all processes real and effective UIDs:
```bash
ps -eo ruser,euser,comm
```
Look through the list of running processes. Most of the time the RUID and EUID matches. Are there any cases in the output where they do not?
Take a look at how the effective UID is specified:
```bash
ls -l /usr/bin/passwd
```
`-rwsr-xr-x 1 root shadow 81792 Oct 29 18:26 /usr/bin/passwd`
The `s` in the file permissions means that the file UID will be used as the effective UID.
The SUID bit is stored in the first permission octet in the inode:
```bash
stat /usr/bin/passwd
```
> Note the octet representation of the file permissions.
Start another Konsole, and open multiple tabs.
In one tab run:
```bash
passwd
```
> (dont type anything, instead leave the prompt open)
Switch to another tab and run:
```bash
ps -o ruser,euser,comm -C passwd
```
Make sure you understand the significance of the ruser and euser outputs not matching.
Run this command to find all SUID programs on the system:
```bash
sudo find / -type d -name ".snapshots" -prune -o +AFw( -perm -004000 -o -perm -002000 +AFw) -type f -print
```
**Identify why each one requires SUID permissions.**
> Hint: look up each command using man.
## Writing a SUID program in C
You are going to create a SUID program, to grant access to the contents of your "mysecret" file to anyone who runs the program, without sharing direct access to the file.
Make sure "~/mysecrets" is only accessible by the owner: ls -la should show `rw-------` for that file.
Create a C program by making a new file "accessmysecret.c":
```bash
vi accessmysecret.c
```
Remember, vi is modal. Press "i" to enter insert mode, then enter this code:
```c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
int main()
{
printf(" UID GID +AFw-n"
"Real %d Real %d +AFw-n"
"Effective %d Effective %d +AFw-n",
getuid (), getgid (),
geteuid(), getegid());
FILE *fp = fopen("mysecrets", "r");
if (fp == NULL) {
printf("Error: Could not open file");
exit(EXIT_FAILURE);
}
char c;
while ((c=getc(fp)) != EOF) {
putchar(c);
}
putchar('+AFw-n');
return EXIT_SUCCESS;
}
```
Save your changes and quit (Esc, ":wq").
Compile the program (which uses the C code to create an executable):
```bash
gcc accessmysecrets.c -o accessmysecrets
```
Set the permissions for the file (using chmod) to setuid:
```bash
chmod u+s accessmysecrets
```
Check the permissions include SUID:
```bash
ls -l accessmysecrets
```
Run the program:
```bash
./accessmysecrets
```
Note that the program outputs its real and effective identity.
Change to another user, and execute the program:
```bash
/home/student/accessmysecrets
```
Note that the effective ID is that of the owner of the program. You should also see the contents of the mysecrets file, even though you don't have access to the secrets file directly.
Think about the security of this solution. How secure is it? Would it be safe for root to be the owner of this program? Why not?
**Challenge**: switch to another user and use the SUID accessmysecrets program to get read access to any one of the owner user's files!
> Hint: there is a security problem with this code.
>
> Another hint: think about hard links.
**Solution:**
**SPOILER ALERT! SPOILER ALERT! SPOILER ALERT!**
There is a security problem caused by not using an absolute filename when opening the file, it opens "mysecrets" rather than "/home/user/mysecrets". Remember, any user can create a hard link to a file (therefore they can make a "copy" of the SUID program wherever they like).
Make a hard link to the SUID program in a directory that the attacker can write to, then also make a hard link to any file the SUID user owns, and name it "mysecrets" in the same directory as the program, then when you execute the program it will write out the contents of the file.
You can exploit this vulnerability as follows:
```bash
su - student
ln /home/user/accessmysecrets /tmp/access
ln /home/user/someotherfile /tmp/mysecrets
/tmp/access
```
**SPOILER ALERT! SPOILER ALERT! SPOILER ALERT!**
**Challenge**: Modify the program to correct the above vulnerability.
**Challenge**: Modify the program so that only the first line of the mysecrets file is displayed to others.
**Challenge**: Modify the program so that the script checks the UID and only continues for a specific user (for example, if the user is root).
> Hint: `man getuid`
## Linux Extended ACLs
We have explored standard Unix permissions. Modern Linux systems (and some other Unix-based systems) now have more complete (and complicated) ACL support.
As previously mentioned, an *access control list (ACL)* is attached to an object (resource) and lists all the subjects (users / active entities) that are allowed access, along with the kind of access that is authorised.
Set a file ACL on your mysecrets file, using the setfacl command:
```bash
setfacl -m u:student:r ~/mysecrets
```
This grants the "student" user read access to the file.
Note that the stat program is not usually ACL aware, so won't report anything out of the usual:
```bash
stat ~/mysecrets
```
The ls program can be used to detect File ACLs:
```bash
ls -la ~/mysecrets
```
`-rw-r-----+ 1 cliffe users 22 Feb 28 11:47 mysecrets`
Note that the output includes a `+`. This indicates an ACL is in place.
Use getfacl to display the permissions:
```bash
getfacl ~/mysecrets
```
Use Linux File ACLs to grant one or more specific users (other class members) read access to your mysecrets file.
Using ACLs, grant any other group (you choose) read-write access to your mygroupshare file.
Remove the group permission you just added.
> Example: `setfacl -x g:staff file`
## Conclusion
At this point you have:
@@ -528,12 +263,6 @@ At this point you have:
- Used umask to change the permissions applied to new files
- Learned about Set UID (SUID), become more familiar with C, and compiled a SUID C program
- You may have also done some more programming of your own, (congratulations, if you spotted and/or fixed the security problem)
- Used Linux Extended ACLs to configure more advanced security policies
Well done!
[^1]: The name `ls` is from the old Multix command which was named after "list segments", although it can be thought of as "list" (since the term "segment" is no longer meaningful for Unix), it is similar in use to the dir command on Windows.

View File

@@ -10,12 +10,17 @@
end
$first_account = JSON.parse(self.accounts.first)
$main_user = $first_account['username'].to_s
$main_user_pass = $first_account['password'].to_s
$second_account = JSON.parse(self.accounts[1])
$second_user = $second_account['username'].to_s
$second_password = $second_account['password'].to_s
$main_user = $first_account['username'].to_s
$main_user_pass = $first_account['password'].to_s
$third_account = JSON.parse(self.accounts[2])
$third_user = $second_account['username'].to_s
$third_password = $second_account['password'].to_s
$server_ip = self.server_ip.first
$root_password = self.root_password
@@ -100,8 +105,11 @@ Randomised instance generated by [SecGen](http://github.com/cliffe/SecGen) (<%=
<attack>
<prompt>Configure your desktop so that passwords are required to be at least 10 characters long (and this should also apply for root).</prompt>
<post_command>echo -e 'shorter8\nshorter8' | passwd <%= $second_user %> ; echo -$?-</post_command>
<prompt>I'm going to create some groups on the server.</prompt>
<get_shell>sshpass -p <%= $root_password %> ssh -oStrictHostKeyChecking=no root@<%= $server_ip %> /bin/bash</get_shell>
<post_command>ls ; echo -$?-</post_command>
<condition>
<output_matches>password is shorter than 10</output_matches>
@@ -116,47 +124,11 @@ Randomised instance generated by [SecGen](http://github.com/cliffe/SecGen) (<%=
<message>:( Something was not right</message>
</else_condition>
</attack>
<attack>
<prompt>Configure your desktop so that passwords are required to include numbers.</prompt>
<post_command>echo -e 'tiaspbiqetr\ntiaspbiqetr' | passwd <%= $second_user %> ; echo "p1-$?-"; echo -e 'tiaspbiqe2r\ntiaspbiqe2r' | passwd <%= $second_user %> ; echo "p2-$?-"; </post_command>
<condition>
<output_matches>p1-0-</output_matches>
<message>:( I set a password without including numbers. It looks like you forgot to add the rule, or enforce_for_root?</message>
</condition>
<condition>
<output_matches>p2-0-</output_matches>
<message>:) Well done! <%= $flags.pop %></message>
<trigger_next_attack />
</condition>
<else_condition>
<message>:( I couldn't set a password without numbers... OR WITH THEM?</message>
</else_condition>
<tutorial><%= ERB.new(File.read self.templates_path + 'access_controls.md.erb').result(self.get_binding) %></tutorial>
</attack>
<!-- <attack>
<prompt>Configure your desktop so that failed login attempts create a 5 min lockout after 4 failed attempts to login. Trigger the <%= $second_user %> by attempting logins.</prompt>
<post_command>echo "echo wrongpass | script -c 'su <%= $second_user %>'; echo wrongpass | script -c 'su <%= $second_user %>'; echo wrongpass | script -c 'su <%= $second_user %>'; echo wrongpass | script -c 'su <%= $second_user %>'; echo wrongpass | script -c 'su <%= $second_user %>'" | script -c 'su <%= $second_user %>' </post_command>
<condition>
<output_matches>locked</output_matches>
<message>:) Well done! <%= $flags.pop %></message>
<trigger_next_attack />
</condition>
<condition>
<output_matches>.*</output_matches>
<message>:( Didn't lock out after failed attempts. Hint: Log-tally lockouts can be achieved using pam_tally2</message>
</condition>
<else_condition>
<message>:( Nope</message>
</else_condition>
</attack> -->
</hackerbot>

View File

@@ -0,0 +1,249 @@
## Set UID (SUID)
Sometimes a user needs to be able to do things that require permissions that they should not always have. For example, the passwd command is used to change your password. It needs read and write access to /etc/shadow. Clearly not every user should have that kind of access! Also, the ping command needs raw network access... Again not something that every user can do. The Unix solution is *set UID (SUID)*.
Using SUID, processes can be given permission to run as another user. For example, when you run passwd, the program actually runs as root (on most Unix systems).
In fact, every process actually has multiple identities, including:
- The real UID (RUID): the user who is running the command
- The effective UID (EUID): the way the process is treated
List all processes real and effective UIDs:
```bash
ps -eo ruser,euser,comm
```
Look through the list of running processes. Most of the time the RUID and EUID matches. Are there any cases in the output where they do not?
Take a look at how the effective UID is specified:
```bash
ls -l /usr/bin/passwd
```
`-rwsr-xr-x 1 root shadow 81792 Oct 29 18:26 /usr/bin/passwd`
The `s` in the file permissions means that the file UID will be used as the effective UID.
The SUID bit is stored in the first permission octet in the inode:
```bash
stat /usr/bin/passwd
```
> Note the octet representation of the file permissions.
Start another Konsole, and open multiple tabs.
In one tab run:
```bash
passwd
```
> (dont type anything, instead leave the prompt open)
Switch to another tab and run:
```bash
ps -o ruser,euser,comm -C passwd
```
Make sure you understand the significance of the ruser and euser outputs not matching.
Run this command to find all SUID programs on the system:
```bash
sudo find / -type d -name ".snapshots" -prune -o +AFw( -perm -004000 -o -perm -002000 +AFw) -type f -print
```
**Identify why each one requires SUID permissions.**
> Hint: look up each command using man.
## Writing a SUID program in C
You are going to create a SUID program, to grant access to the contents of your "mysecret" file to anyone who runs the program, without sharing direct access to the file.
Make sure "~/mysecrets" is only accessible by the owner: ls -la should show `rw-------` for that file.
Create a C program by making a new file "accessmysecret.c":
```bash
vi accessmysecret.c
```
Remember, vi is modal. Press "i" to enter insert mode, then enter this code:
```c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
int main()
{
printf(" UID GID +AFw-n"
"Real %d Real %d +AFw-n"
"Effective %d Effective %d +AFw-n",
getuid (), getgid (),
geteuid(), getegid());
FILE *fp = fopen("mysecrets", "r");
if (fp == NULL) {
printf("Error: Could not open file");
exit(EXIT_FAILURE);
}
char c;
while ((c=getc(fp)) != EOF) {
putchar(c);
}
putchar('+AFw-n');
return EXIT_SUCCESS;
}
```
Save your changes and quit (Esc, ":wq").
Compile the program (which uses the C code to create an executable):
```bash
gcc accessmysecrets.c -o accessmysecrets
```
Set the permissions for the file (using chmod) to setuid:
```bash
chmod u+s accessmysecrets
```
Check the permissions include SUID:
```bash
ls -l accessmysecrets
```
Run the program:
```bash
./accessmysecrets
```
Note that the program outputs its real and effective identity.
Change to another user, and execute the program:
```bash
/home/student/accessmysecrets
```
Note that the effective ID is that of the owner of the program. You should also see the contents of the mysecrets file, even though you don't have access to the secrets file directly.
Think about the security of this solution. How secure is it? Would it be safe for root to be the owner of this program? Why not?
**Challenge**: switch to another user and use the SUID accessmysecrets program to get read access to any one of the owner user's files!
> Hint: there is a security problem with this code.
>
> Another hint: think about hard links.
**Solution:**
**SPOILER ALERT! SPOILER ALERT! SPOILER ALERT!**
There is a security problem caused by not using an absolute filename when opening the file, it opens "mysecrets" rather than "/home/user/mysecrets". Remember, any user can create a hard link to a file (therefore they can make a "copy" of the SUID program wherever they like).
Make a hard link to the SUID program in a directory that the attacker can write to, then also make a hard link to any file the SUID user owns, and name it "mysecrets" in the same directory as the program, then when you execute the program it will write out the contents of the file.
You can exploit this vulnerability as follows:
```bash
su - student
ln /home/user/accessmysecrets /tmp/access
ln /home/user/someotherfile /tmp/mysecrets
/tmp/access
```
**SPOILER ALERT! SPOILER ALERT! SPOILER ALERT!**
**Challenge**: Modify the program to correct the above vulnerability.
**Challenge**: Modify the program so that only the first line of the mysecrets file is displayed to others.
**Challenge**: Modify the program so that the script checks the UID and only continues for a specific user (for example, if the user is root).
> Hint: `man getuid`
## Linux Extended ACLs
We have explored standard Unix permissions. Modern Linux systems (and some other Unix-based systems) now have more complete (and complicated) ACL support.
As previously mentioned, an *access control list (ACL)* is attached to an object (resource) and lists all the subjects (users / active entities) that are allowed access, along with the kind of access that is authorised.
Set a file ACL on your mysecrets file, using the setfacl command:
```bash
setfacl -m u:student:r ~/mysecrets
```
This grants the "student" user read access to the file.
Note that the stat program is not usually ACL aware, so won't report anything out of the usual:
```bash
stat ~/mysecrets
```
The ls program can be used to detect File ACLs:
```bash
ls -la ~/mysecrets
```
`-rw-r-----+ 1 cliffe users 22 Feb 28 11:47 mysecrets`
Note that the output includes a `+`. This indicates an ACL is in place.
Use getfacl to display the permissions:
```bash
getfacl ~/mysecrets
```
Use Linux File ACLs to grant one or more specific users (other class members) read access to your mysecrets file.
Using ACLs, grant any other group (you choose) read-write access to your mygroupshare file.
Remove the group permission you just added.
> Example: `setfacl -x g:staff file`
## Conclusion
At this point you have:
- Learned about file permissions, hard links, and inodes
- Learned about octal representations of permissions
- Changed Unix file permissions to grant access to specific users and groups, using chmod
- Used umask to change the permissions applied to new files
- Learned about Set UID (SUID), become more familiar with C, and compiled a SUID C program
- You may have also done some more programming of your own, (congratulations, if you spotted and/or fixed the security problem)
- Used Linux Extended ACLs to configure more advanced security policies
Well done!
[^1]: The name `ls` is from the old Multix command which was named after "list segments", although it can be thought of as "list" (since the term "segment" is no longer meaningful for Unix), it is similar in use to the dir command on Windows.
[^2]: The `~` character is interpreted by Bash as the location of your own home directory, such as /home/*dropbear*/

View File

@@ -0,0 +1,35 @@
# CONVERT THESE INTO HB CHALLENGES
==Create a file "~/myshare", and grant everyone read-write access.==
> Test whether you have correctly set permissions.
==Create "mygroupshare", grant only read access to everyone in your group.==
> Test whether you have correctly set permissions.
Create a new group called "staff", and create a file that you and the other user can collaborate on (both edit).
> Hint, you should both be added to the group. You may require root access for this task. Your classmate may want to ssh to your system.
>
> Test whether you have correctly set permissions. Both users should be able to edit the file, yet other users should not have write access.
Read and write to the shared files created by others, for example:
```bash
cat /home/*dropbear*/myshare
```
**Challenge**:
```bash
mkdir test
```
```bash
touch test/test1 test/test2 test/test3
```
> Use a single chmod command to recursively set the permissions for all files contained in the new "test" directory.
>
> Hint: `man chmod`

View File

@@ -1,6 +1,7 @@
define parameterised_accounts::account (
$username,
$password,
$groups,
$super_user,
$strings_to_leak,
$leaked_filenames,
@@ -27,6 +28,7 @@ define parameterised_accounts::account (
# Add user account
::accounts::user { $username:
shell => '/bin/bash',
groups => $groups,
password => pw_hash($password, 'SHA-512', 'mysalt'),
managehome => true,
before => $misconfigurations,
@@ -68,4 +70,4 @@ define parameterised_accounts::account (
leaked_from => "accounts_$username",
}
}
}
}

View File

@@ -6,9 +6,10 @@ class parameterised_accounts::init {
$accounts.each |$raw_account| {
$account = parsejson($raw_account)
$username = $account['username']
parameterised_accounts::account { "parameterised_$username":
parameterised_accounts::account { "parameterised_user_$username":
username => $username,
password => $account['password'],
groups => $account['groups'],
super_user => str2bool($account['super_user']),
strings_to_leak => $account['strings_to_leak'],
leaked_filenames => $account['leaked_filenames'],
@@ -16,4 +17,4 @@ class parameterised_accounts::init {
}
}
}
}
}

View File

@@ -191,6 +191,10 @@
<input into="super_user">
<value>false</value>
</input>
<input into="groups">
<value>staff</value>
<value>team_one</value>
</input>
</generator>
<!-- other users, with the SAME weak passwords, WITH flags -->
<generator type="account">
@@ -200,13 +204,10 @@
<input into="password">
<datastore access="0">weak_passwords</datastore>
</input>
</generator>
<generator type="account">
<input into="username">
<datastore access="next">usernames</datastore>
</input>
<input into="password">
<datastore access="next">weak_passwords</datastore>
<input into="groups">
<value>staff</value>
<value>team_one</value>
<value>team_two</value>
</input>
</generator>
<generator type="account">
@@ -216,6 +217,10 @@
<input into="password">
<datastore access="next">weak_passwords</datastore>
</input>
<input into="groups">
<value>staff</value>
<value>team_two</value>
</input>
</generator>
<generator type="account">
<input into="username">
@@ -224,6 +229,20 @@
<input into="password">
<datastore access="next">weak_passwords</datastore>
</input>
<input into="groups">
<value>staff</value>
</input>
</generator>
<generator type="account">
<input into="username">
<datastore access="next">usernames</datastore>
</input>
<input into="password">
<datastore access="next">weak_passwords</datastore>
</input>
<input into="groups">
<value>staff</value>
</input>
</generator>
</input>