mirror of
https://github.com/cliffe/SecGen.git
synced 2026-02-21 11:18:06 +00:00
lab updates (and related modules)
This commit is contained in:
@@ -208,37 +208,42 @@ class System
|
||||
datastore_access = datastore_variablename_and_access_type['access']
|
||||
datastore_variablename = datastore_variablename_and_access_type['variablename']
|
||||
datastore_retrieved = []
|
||||
if datastore_access == 'first'
|
||||
datastore_retrieved = [$datastore[datastore_variablename].first]
|
||||
elsif datastore_access == 'next'
|
||||
last_accessed = $datastore_iterators[datastore_variablename]
|
||||
# first use? start at beginning
|
||||
if last_accessed == nil
|
||||
index_to_access = 0
|
||||
begin
|
||||
if datastore_access == 'first'
|
||||
datastore_retrieved = [$datastore[datastore_variablename].first]
|
||||
elsif datastore_access == 'next'
|
||||
last_accessed = $datastore_iterators[datastore_variablename]
|
||||
# first use? start at beginning
|
||||
if last_accessed == nil
|
||||
index_to_access = 0
|
||||
else
|
||||
index_to_access = last_accessed + 1
|
||||
end
|
||||
$datastore_iterators[datastore_variablename] = index_to_access
|
||||
datastore_retrieved = [$datastore[datastore_variablename][index_to_access]]
|
||||
elsif datastore_access == 'previous'
|
||||
last_accessed = $datastore_iterators[datastore_variablename]
|
||||
# first use? start at end
|
||||
if last_accessed == nil
|
||||
index_to_access = $datastore[datastore_variablename].size - 1
|
||||
else
|
||||
index_to_access = last_accessed - 1
|
||||
end
|
||||
$datastore_iterators[datastore_variablename] = index_to_access
|
||||
datastore_retrieved = [$datastore[datastore_variablename][index_to_access]]
|
||||
elsif datastore_access.to_s == datastore_access.to_i.to_s
|
||||
# Test for a valid element key (integer)
|
||||
index_to_access = datastore_access.to_i
|
||||
$datastore_iterators[datastore_variablename] = index_to_access
|
||||
datastore_retrieved = [$datastore[datastore_variablename][index_to_access]]
|
||||
elsif datastore_access == "all"
|
||||
datastore_retrieved = $datastore[datastore_variablename]
|
||||
else
|
||||
index_to_access = last_accessed + 1
|
||||
Print.err "Error: invalid access value (#{datastore_access})"
|
||||
raise 'failed'
|
||||
end
|
||||
$datastore_iterators[datastore_variablename] = index_to_access
|
||||
datastore_retrieved = [$datastore[datastore_variablename][index_to_access]]
|
||||
elsif datastore_access == 'previous'
|
||||
last_accessed = $datastore_iterators[datastore_variablename]
|
||||
# first use? start at end
|
||||
if last_accessed == nil
|
||||
index_to_access = $datastore[datastore_variablename].size - 1
|
||||
else
|
||||
index_to_access = last_accessed - 1
|
||||
end
|
||||
$datastore_iterators[datastore_variablename] = index_to_access
|
||||
datastore_retrieved = [$datastore[datastore_variablename][index_to_access]]
|
||||
elsif datastore_access.to_s == datastore_access.to_i.to_s
|
||||
# Test for a valid element key (integer)
|
||||
index_to_access = datastore_access.to_i
|
||||
$datastore_iterators[datastore_variablename] = index_to_access
|
||||
datastore_retrieved = [$datastore[datastore_variablename][index_to_access]]
|
||||
elsif datastore_access == "all"
|
||||
datastore_retrieved = $datastore[datastore_variablename]
|
||||
else
|
||||
Print.err "Error: invalid access value (#{datastore_access})"
|
||||
rescue NoMethodError, SyntaxError => err
|
||||
Print.err "Error accessing element (#{datastore_access}) from datastore (#{datastore_variablename}): #{err}"
|
||||
raise 'failed'
|
||||
end
|
||||
if datastore_retrieved && datastore_retrieved != [nil]
|
||||
@@ -454,4 +459,4 @@ class System
|
||||
modules_to_add
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,494 +0,0 @@
|
||||
# Authentication
|
||||
|
||||
## Getting started
|
||||
### VMs in this lab
|
||||
|
||||
==Start these VMs== (if you haven't already):
|
||||
- hackerbot_server (leave it running, you don't log into this)
|
||||
- desktop
|
||||
|
||||
### Your login details for the "desktop" and "server" VMs
|
||||
User: <%= $main_user %>
|
||||
Password: tiaspbiqe2r (**t**his **i**s **a** **s**ecure **p**assword **b**ut **i**s **q**uite **e**asy **2** **r**emember)
|
||||
|
||||
You won't login to the hackerbot_server, but the VM needs to be running to complete the lab.
|
||||
|
||||
### For marks in the module
|
||||
1. **You need to submit flags**. Note that the flags and the challenges in your VMs are different to other's in the class. Flags will be revealed to you as you complete challenges throughout the module. Flags look like this: ==flag{*somethingrandom*}==. Follow the link on the module page to submit your flags.
|
||||
2. **You need to document the work and your solutions in a Log Book**. This needs to include screenshots (including the flags) of how you solved each Hackerbot challenge and a writeup describing your solution to each challenge, and answering any "Log Book Questions". The Log Book will be submitted later in the semester.
|
||||
|
||||
## Meet Hackerbot!
|
||||

|
||||
|
||||
This exercise involves interacting with Hackerbot, a chatbot who will attack your system. If you satisfy Hackerbot by completing the challenges she will reveal flags to you.
|
||||
|
||||
**On the desktop VM:**
|
||||
|
||||
==Open Pidgin and send some messages to Hackerbot:==
|
||||
|
||||
- Try asking Hackerbot some questions
|
||||
- Send "help"
|
||||
- Send "list"
|
||||
- Send "hello"
|
||||
> If Hackerbot seems to be waiting/halted, simply say 'hi'
|
||||
|
||||
Work through the below exercises, completing the Hackerbot challenges as noted.
|
||||
|
||||
---
|
||||
|
||||
## Introduction to authentication
|
||||
|
||||
Authentication plays the important role of verifying an identity. For example, when someone gets into an airplane, sits down at a computer, picks up a mobile device, or uses a website, authentication is what is used to confirm that the person is who they claim to be. Authentication is an important first step *before* deciding how the system should act and what to allow.
|
||||
|
||||
### Identity: users and groups
|
||||
|
||||
Most computer systems have the concept of a user account. Although some devices such as mobile phones typically only have one user account, most modern computers can support having multiple users, each with their own identity. For example, a computer can have a separate account for each person that uses it, and if configured to do so may enable each user to have their own account preferences, and access to different resources.
|
||||
|
||||
On Unix/Linux systems every user account is identified by a user ID number (UID), which is a 32-bit integer (whole number), and can have one or more user names, which are human readable strings of text.
|
||||
|
||||
Open a terminal console.
|
||||
|
||||
> One way to do this is to start Konsole from KDEMenu
|
||||
|
||||
Assuming you have already logged in, you have already authenticated yourself on this system.
|
||||
|
||||
==Log Book Question: When and how did you authenticate yourself?==
|
||||
|
||||
Use these commands to find out about your current identity (or more accurately the identity of the software you are interacting with):
|
||||
|
||||
```bash
|
||||
whoami
|
||||
|
||||
groups
|
||||
|
||||
id
|
||||
```
|
||||
|
||||
==Make a note of your UID and username.==
|
||||
|
||||
Note that your account is also a member of one or more groups. A primary group, and a list of other groups. Some Linux systems, such as Debian, create a new seperate primary group for each user, others such as openSUSE have a shared group (named "users") that all normal users are a member of. Similar to the relationship between user names and UIDs, each group has a group name, and a group ID (GID).
|
||||
|
||||
Information about user accounts is stored in the /etc/passwd file, which typically all users can read.
|
||||
|
||||
==View the /etc/passwd file:==
|
||||
|
||||
```bash
|
||||
less /etc/passwd
|
||||
```
|
||||
|
||||
==Find the line that describes your user account.==
|
||||
|
||||
This line defines the username, password (well, it used to be stored here… we will come back to this), UID, primary group GID, full name, home directory, and shell for your account.
|
||||
|
||||
Confirm this matches the information you recorded earlier.
|
||||
|
||||
==Find the line that describes the root user account.==
|
||||
|
||||
Where is the root user's home directory?
|
||||
|
||||
> Press 'q' to quit less.
|
||||
|
||||
==View the /etc/group file:==
|
||||
|
||||
```bash
|
||||
less /etc/group
|
||||
```
|
||||
|
||||
Groups are defined in this file, along with which users are members.
|
||||
|
||||
==Which users are members of the "tftp" group?
|
||||
|
||||
Remember, primary groups do not appear in this file; for example, on openSUSE the "users" group, which all normal users are a member of, may not appear in the /etc/group file.
|
||||
|
||||
The "su" program can be used to run a program (usually a shell; that is, a command prompt) as another user, effectively enabling users to switch between user accounts at the command prompt.
|
||||
|
||||
==Change your identity to root==. Run:
|
||||
|
||||
```bash
|
||||
su -
|
||||
```
|
||||
|
||||
Enter the root password.
|
||||
|
||||
Use these commands to ==find out about your new identity:==
|
||||
|
||||
```bash
|
||||
whoami
|
||||
|
||||
groups
|
||||
|
||||
id
|
||||
```
|
||||
|
||||
==What is the UID of root? What does this mean about this user?==
|
||||
|
||||
==Lab Book Question: What gives this user special privileges: the name of the account, or the UID?==
|
||||
|
||||
==Use the useradd command to create a new user account "fred"==
|
||||
|
||||
> Hint: refer to the man page for useradd, by running "man useradd".
|
||||
|
||||
==Set a password for the user fred.==
|
||||
|
||||
> Hint: `sudo passwd fred`
|
||||
|
||||
==Change identity to fred.==
|
||||
|
||||
> Hint: `su - fred`
|
||||
|
||||
==Run:(after su)==
|
||||
|
||||
```bash
|
||||
id
|
||||
```
|
||||
|
||||
==Compare the result to the previous output.==
|
||||
|
||||
==How does this compare to your other normal user account? What is different, and what about it is the same?==
|
||||
|
||||
Run the single command "id" as root:
|
||||
|
||||
```bash
|
||||
sudo id
|
||||
```
|
||||
|
||||
==Log Book Question: What is the difference between sudo and su? Which is most likely protect against accidental damage and also log the commands used?==
|
||||
|
||||
### Users and SSH
|
||||
|
||||
==Log in to the server via ssh:==
|
||||
|
||||
```bash
|
||||
ssh <%= $main_user %>@<%= $server_ip %>
|
||||
```
|
||||
|
||||
==Display details of all users logged on to the system:==
|
||||
|
||||
```bash
|
||||
who
|
||||
```
|
||||
|
||||
==List all the processes run by all users:==
|
||||
|
||||
```bash
|
||||
ps -eo user,comm
|
||||
```
|
||||
|
||||
==List all the processes running as root:==
|
||||
|
||||
```bash
|
||||
ps -o user,comm -u root
|
||||
```
|
||||
|
||||
==Run a command to list all the processes running as *your* normal user.==
|
||||
|
||||
==Lab Book Question: How is this server authenticating users? What user accounts exist?==
|
||||
|
||||
### Passwords, hashes and salt
|
||||
|
||||
Given that important security decisions are made based on the user accounts, it is important to authenticate users, to ensure that the subjects are associated with the correct identity.
|
||||
|
||||
==What are the kinds of factors that can be used to verify a user's identity? Hint: for example, "something they have".==
|
||||
|
||||
==Which category of authentication factors is a password considered to be?==
|
||||
|
||||
Originally passwords were stored "in the clear" (not enciphered). For example, Multics stored passwords in a file, and once at MIT a software bug caused the password file to be copied to the motd file (message of the day), which was printed every time anyone logged into the system. A solution is not to store the password in the clear. Instead a hash can be computed, using a one way hash function, and stored. When the user enters a password, a new hash is computed and compared to the original.
|
||||
|
||||
On Linux, the command "shasum" can be used to check the integrity of files (hash functions have many uses), and works on the same principle. We can use it to generate a hash for any given string, for example a password:
|
||||
|
||||
```bash
|
||||
shasum
|
||||
```
|
||||
|
||||
> Type "hello" without the quotes. Press Ctrl-D (which indicates "EOF"; that is, end of input).
|
||||
|
||||
Repeat the above, with the same password ("hello"), and with a slight difference ("hello.").
|
||||
|
||||
Are the outputs the same?
|
||||
|
||||
Are the different hashes similar?
|
||||
|
||||
Is this good? Why?
|
||||
|
||||
Which one-way hash function does the shasum program use? Would this be a good option for hashing passwords?
|
||||
|
||||
For password authentication, the hash still needs to be stored. On Unix, password hashes were once stored in the world-readable file /etc/passwd, now they are typically stored in /etc/shadow, which only root (the superuser) can access.
|
||||
|
||||
==View the shadow file:==
|
||||
|
||||
```bash
|
||||
sudo less /etc/shadow
|
||||
```
|
||||
|
||||
The format of the shadow file is:
|
||||
|
||||
> username:**password**:last-changed(since 1-1-1970):days-until-may-change:days-until-must-change:days-warning-notice:days-since-expired-account-disabled:date-disable:reserved-field
|
||||
|
||||
==Find the hash of your user account's password.==
|
||||
|
||||
> Exit less ("q").
|
||||
|
||||
Use the passwd command to ==change your password:==
|
||||
|
||||
```bash
|
||||
passwd
|
||||
```
|
||||
|
||||
> When prompted, enter a new password of your choosing.
|
||||
|
||||
View the shadow file, and confirm that the stored password has changed.
|
||||
|
||||
With reference to the shadow file, and the man page for crypt (Hint: "man crypt"), ==answer these Log Book questions==:
|
||||
|
||||
- On Linux, the password hash stored in /etc/shadow has a prefix that specifies the hash function used.\
|
||||
> ==What hash function is used for your password?==
|
||||
|
||||
- ==When was the root password last changed?==
|
||||
|
||||
- ==Do any accounts have a setting that will force a password change at a specific date?==
|
||||
|
||||
A salt is a random string, used as further input into a one-way hash function (concatenated to the password). The salt is typically stored along with the hash. As a result the same password will have different hashes, so long as the salt is different.
|
||||
|
||||
Why is that a good thing?
|
||||
|
||||
What kind of attack does a salt defend against?
|
||||
|
||||
What is the current salt for your account? Hint: it is stored after the second "\$".
|
||||
|
||||
### Password weaknesses
|
||||
|
||||
The strength of a password depends on its entropy: its degree of randomness. If a user chooses a word from a dictionary, it would not take long to attempt every dictionary word until finding one that results in the same hash.
|
||||
|
||||
Try your hand at cracking passwords using the Kali virtual machine.
|
||||
|
||||
Add some new users with these passwords:
|
||||
> Hello
|
||||
>
|
||||
> hellothere
|
||||
>
|
||||
> H3ll0
|
||||
>
|
||||
> hello1
|
||||
>
|
||||
> 12hell012356
|
||||
|
||||
==Use john the ripper to crack the passwords.==
|
||||
> Hint: `man john`, on the Kali Linux system.
|
||||
|
||||
- Which passwords are cracked the fastest?
|
||||
|
||||
- How long did they take?
|
||||
|
||||
# ------
|
||||
# ------
|
||||
# ------
|
||||
|
||||
### Pluggable Authentication Modules (PAM)
|
||||
|
||||
In the past all Linux/Unix programs that required the user to enter a password for authentication (such as su, sudo, and login) would access and interpret /etc/passwd using its own code. However, it was hard to maintain all this code, since any change in the way the passwords were stored (such as using a shadow file, or using new hash functions) would mean all the software that provides authentication needed to be changed. The solution to the problem was PAM.
|
||||
|
||||
*Pluggable Authentication Modules (PAM)* enables applications that make use of authentication to be independent of the specific authentication schemes in use. For example, a program such as a login screen that uses PAM can be configured to authenticate using a password, smartcard, and/or biometrics, simply by changing PAM configuration files.
|
||||
|
||||
PAM is supported in most distributions of Linux, Mac OS X, FreeBSD, and many other Unix-like systems.
|
||||
|
||||
View which PAM modules are available on the desktop system:
|
||||
|
||||
> /usr/sbin/pam-config --list-modules
|
||||
|
||||
The .so files are typically in /lib/security or /lib64/security. List them:
|
||||
|
||||
> ls /lib\*/security/
|
||||
|
||||
As you can see, there are lots of different features and authentication schemes, and these can be used with *any* PAM compatible program. This includes not only typical authentication schemes, such as pam\_unix2.so, which does the usual password comparison with /etc/passwd and /etc/shadow, but also can impose time limits (pam\_time.so) or simply display messages to the user (pam\_motd.so).
|
||||
|
||||
It is possible to determine whether a specific program is compiled to use PAM, by checking what dynamic libraries it uses. (On Linux .so shared objects are similar to DLL files on Windows, they contain library code that programs can reuse). Check what shared objects the passwd program uses:
|
||||
|
||||
```bash
|
||||
which passwd
|
||||
>
|
||||
> ldd *path\_to\_passwd*
|
||||
```
|
||||
|
||||
> Where path\_to\_password is the output from the "which passwd" command above, which identifies the absolute path to a program. For example, `ldd /usr/bin/passwd`
|
||||
|
||||
Note that the output will include a line starting with "libpam.so", such as:
|
||||
|
||||
> **libpam.so**.0 => /lib64/libpam.so.0 (0x00007fcc4afe6000)
|
||||
|
||||
This would indicate that the program loads code from "/lib64/libpam.so.0", and does indeed make use of PAM.
|
||||
|
||||
PAM configuration is located in /etc/pam.d. Take a look at which programs currently have pam configuration files:
|
||||
|
||||
```bash
|
||||
ls /etc/pam.d
|
||||
```
|
||||
|
||||
Depending on what is installed on the system, there will be a few configuration files. Each file contains a PAM configuration for the program it is named after. If a PAM-aware program does not have a configuration file the "other" file is used, which should deny access by default.
|
||||
|
||||
View the "other" file:
|
||||
|
||||
```bash
|
||||
less /etc/pam.d/other
|
||||
```
|
||||
|
||||
{width="3.53125in" height="2.0416666666666665in"}
|
||||
|
||||
The output contains instructions to log the attempt to Syslog (which is what pam\_warn.so does) and deny access (using pam\_deny.so) any attempt to authenticate (the lines starting with "auth"), request access to anything (account), change passwords (password), or starting a session (session).
|
||||
|
||||
The syntax of the configuration file is that each line starts with is typically:
|
||||
|
||||
> *type control module-path module-arguments*
|
||||
|
||||
The type is auth, password, account or session. The control (such as "required" or "optional") defines whether the module needs to pass or not before moving on to the next module, then the module name is defined. It is not shown in this example, but the module-path can be followed with some settings for the module.
|
||||
|
||||
All the modules for a type (such as auth) are called a module stack. When the program requests PAM perform authentication each of the auth modules in the module stack are run in the order they appear. If a "required" module fails, the authentication process tries the next module to see if it passes, if no required modules pass, then the authentication fails. Note that in the example above, pam\_warn.so returns "PAM\_IGNORE". Therefore the next module pam\_deny.so is started, which returns an error, and the authentication fails.
|
||||
|
||||
Possible control values include:
|
||||
|
||||
> **required**
|
||||
>
|
||||
> failure of such a PAM will ultimately lead to the PAM-API returning failure but only after the remaining stacked modules (for this service and type) have been invoked.
|
||||
>
|
||||
> **requisite**
|
||||
>
|
||||
> like required, however, in the case that such a module returns a failure, control is directly returned to the application.
|
||||
>
|
||||
> **sufficient**
|
||||
>
|
||||
> success of such a module is enough to satisfy the authentication requirements of the stack of modules (if a prior required module has failed the success of this one is ignored). A failure of this module is not deemed as fatal to satisfying the application that this type has succeeded. If the module succeeds the PAM framework returns success to the application immediately without trying any other modules.
|
||||
>
|
||||
> **optional**
|
||||
>
|
||||
> the success or failure of this module is only important if it is the only module in the stack associated with this service+type.
|
||||
>
|
||||
> **include**
|
||||
>
|
||||
> include all lines of given type from the configuration file specified as an argument to this control.
|
||||
>
|
||||
> -- from the man page for pam.conf
|
||||
|
||||
There is also a more complex rule syntax available, described in the man page.
|
||||
|
||||
Information about each module is available in The Linux-PAM System Administrators' Guide:
|
||||
|
||||
> [*http://linux-pam.org/Linux-PAM-html/Linux-PAM\_SAG.html*](http://linux-pam.org/Linux-PAM-html/Linux-PAM_SAG.html)
|
||||
|
||||
Look at which authentication methods are used by passwd:
|
||||
|
||||
```bash
|
||||
less /etc/pam.d/passwd
|
||||
```
|
||||
|
||||
Note that this indicates that PAM will apply the rules in "/etc/pam.d/common-auth", "common-account", "common-password", and "common-session" for the passwd program.
|
||||
|
||||
Edit the rules in common-password:
|
||||
|
||||
```bash
|
||||
sudo vi /etc/pam.d/common-password
|
||||
```
|
||||
|
||||
Edit the line (adding "minlen=10" to the end of the line):
|
||||
|
||||
> password requisite pam\_cracklib.so **minlen=10**
|
||||
|
||||
**Reminder**: Vi is 'modal': it has an insert mode, where you can type text into the file, and normal mode, where what you type is interpreted as commands. Press the "i" key to enter "insert mode". Type your changes to the file, then exit back to "normal mode" by pressing the Esc key. Now to exit and save the file press the ":" key, followed by "wq" (write quit), and press Enter.
|
||||
|
||||
Change a password using passwd.
|
||||
|
||||
Confirm that normal users can no longer use a password that is less than 10 characters long.
|
||||
|
||||
View the man page for this PAM module[^1]:
|
||||
|
||||
```bash
|
||||
man pam_cracklib
|
||||
```
|
||||
|
||||
Based on the options described in the man page, configure the pam\_cracklib module to require at least one non-alphanumeric character.
|
||||
|
||||
Confirm that normal users can no longer use passwords that contain only alphanumeric characters.
|
||||
|
||||
Note that there is likely no lockout for failed password attempts when using su to change user. Confirm this by running this command a few times:
|
||||
|
||||
```bash
|
||||
su - student; su - student; su - student; su - student;
|
||||
```
|
||||
|
||||
When prompted each time, enter an incorrect password.
|
||||
|
||||
Now, let's assume our aim is to add a 5 minute lockout time for when a user enters the wrong password 3 times in a row when using "su". Log-tally lockouts can be achieved using pam\_tally2.
|
||||
|
||||
View the man page for this PAM module:
|
||||
|
||||
```bash
|
||||
man pam\_tally2
|
||||
```
|
||||
|
||||
Edit /etc/pam.d/su-l, and insert this line as the first module (after the comment at the start of the file):
|
||||
|
||||
auth required pam\_tally2.so deny=3 unlock\_time=300
|
||||
|
||||
Verify that this change has been successful by running the following command again:
|
||||
|
||||
```bash
|
||||
su - student; su - student; su - student; su - student;
|
||||
```
|
||||
|
||||
Enter the wrong password the first 3 times, and then the correct password on the 4th attempt.
|
||||
|
||||
Create a new user named "dropbear".
|
||||
|
||||
Finally, apply what you have learned to **configure PAM to only allow:**
|
||||
|
||||
- **The user "dropbear" to login between 9am and 5pm**
|
||||
|
||||
- **And only on a Tuesday**
|
||||
|
||||
For testing purposes add another rule that allows a user to log in only 10 minutes from the current time
|
||||
|
||||
> Hint: use pam\_time.so and edit /etc/security/time.conf (and read the documentation in the configuration file to figure out how to set the correct limits)
|
||||
>
|
||||
> Another hint: try the "account" type.
|
||||
|
||||
Configure a cron job to force the user to logout at the end of their allowed time
|
||||
|
||||
> Hint: as root, "crontab -e" and add a job to run at 5pm on Tuesday killing all of their processes
|
||||
>
|
||||
> For example, to disconnect dropbear on Wednesday at 4pm, add this line to cron (run "crontab -e", then press "i" to add):
|
||||
>
|
||||
> 00 16 \* root \* wed skill-KILL-u dropbear
|
||||
>
|
||||
> Try to figure out how to also send a warning to the user 10 minutes before they are kicked off (Hint: add another cron job, you could send a message via "wall", etc)
|
||||
|
||||
### securetty and security
|
||||
|
||||
Backup the "securetty" file, which specifies which virtual terminals root is allowed to login to:
|
||||
|
||||
```bash
|
||||
cp /etc/securetty /etc/securetty.backup
|
||||
```
|
||||
|
||||
Edit /etc/securetty and place a "\#" in front of "tty3"
|
||||
|
||||
Press Ctrl-Alt-F3 and try to login as root
|
||||
|
||||
Press Ctrl-Alt-F4 and try to login as root
|
||||
|
||||
Press Ctrl-Alt-F7 to return to the desktop
|
||||
|
||||
### Conclusion
|
||||
|
||||
At this point you have:
|
||||
|
||||
- Applied authentication concepts to Unix/Linux
|
||||
|
||||
- Experimented with user accounts and identity
|
||||
|
||||
- Experimented with one-way hash functions, salts, and password storage
|
||||
|
||||
- Cracked passwords with low entropy using dictionary attacks
|
||||
|
||||
- Configured PAM to apply various authentication techniques to programs such as passwd
|
||||
|
||||
Well done!
|
||||
|
||||
[^1]: Yes, this makes it a "Pluggable Authentication Modules module", an unfortunate redundancy...
|
||||
@@ -1,89 +0,0 @@
|
||||
### Protecting integrity with file permissions
|
||||
#### Getting to know file permissions
|
||||
|
||||
File permissions enable users to control the access that other users have to their files.
|
||||
|
||||
We will cover the topic in depth elsewhere. This just provides an introduction to Unix file permissions.
|
||||
|
||||
Open a terminal console (such as "Konsole" from KDEMenu / Applications / System / Konsole).
|
||||
|
||||
Start by creating a file with some content.
|
||||
|
||||
==Run:==
|
||||
|
||||
```bash
|
||||
cat > /home/<%= $main_user %>/example
|
||||
```
|
||||
> (Type some content, then press Ctrl-D to finish and return to the
|
||||
prompt.)
|
||||
> The output is sent to the file /home/<%= $main_user %>/example
|
||||
>
|
||||
> Note that in bash **you can type *~* as shorthand for your home directory** ("/home/*<%= $main_user %>*"), but for the sake of clarity these instructions list the entire name.
|
||||
|
||||
You can read the content:
|
||||
|
||||
```bash
|
||||
cat /home/<%= $main_user %>/example
|
||||
```
|
||||
|
||||
Or replace the content:
|
||||
|
||||
```bash
|
||||
cat > /home/<%= $main_user %>/example
|
||||
```
|
||||
> (Type some content, then press Ctrl-D to finish and return to the
|
||||
prompt.)
|
||||
|
||||
You can view the file permissions with:
|
||||
|
||||
```bash
|
||||
ls -la /home/<%= $main_user %>/example
|
||||
```
|
||||
`` -rw-r--r-- 1 user user 20 Feb 7 17:38 /home/<%= $main_user %>/example ``
|
||||
|
||||
This shows that the file is owned by *user*, and that the user has read-write access ("rw-"), others on the system have read access ("r--").
|
||||
|
||||
By default new files can only be edited by the owner of the file (more on file permissions and umask another time). However, by default other users of the system can likely *read* your files.
|
||||
|
||||
You can remove the ability of *anyone* changing the content. ==Run:==
|
||||
|
||||
```bash
|
||||
chmod -w /home/<%= $main_user %>/example
|
||||
```
|
||||
> -w means "remove write access (for everyone)"
|
||||
|
||||
Try changing the content. ==Run:==
|
||||
|
||||
```bash
|
||||
cat > /home/<%= $main_user %>/example
|
||||
```
|
||||
|
||||
You can't.
|
||||
|
||||
You can remove the ability of **everyone else** changing the content. ==Run:==
|
||||
|
||||
```bash
|
||||
chmod u+w,go-rw /home/<%= $main_user %>/example
|
||||
```
|
||||
> u+w: user who owns the file, add write access
|
||||
> go-rw: group and others, remove read and write access
|
||||
|
||||
|
||||
You can view the file permissions with:
|
||||
|
||||
```bash
|
||||
ls -la /home/<%= $main_user %>/example
|
||||
```
|
||||
`` -rw-------- 1 user user 20 Feb 7 17:38 /home/<%= $main_user %>/example ``
|
||||
|
||||
Note that **the root user can access any files**, regardless of file permissions.
|
||||
|
||||
```bash
|
||||
chmod -w /home/<%= $main_user %>/example
|
||||
sudo cat /home/<%= $main_user %>/example
|
||||
```
|
||||
> Enter your password, and note that as root you can access the file regardless of permissions.
|
||||
|
||||
"sudo" runs a command as another user (typically root). On Unix the root user (or any user with an uid of 0) is a superuser (i.e. administator) with extra privileges.
|
||||
|
||||
Exploring Unix file permissions further is outside the scope of this lab, but will be covered elsewhere.
|
||||
@@ -1,959 +0,0 @@
|
||||
# Integrity Management: Protecting Against and Detecting Change
|
||||
|
||||
## Introduction
|
||||
|
||||
These tasks can be completed on the openSUSE\_42.1 VM.
|
||||
|
||||
This lab could be completed on most RPM-based Linux systems with these
|
||||
tools installed: rsync, md5sum, md5deep, Perl, ssh server (if working
|
||||
together).
|
||||
|
||||
## Preparation
|
||||
|
||||
If you are working on campus in the IMS labs using the oVirt online
|
||||
labs, [*click here for instructions on how to login on campus in the IMS
|
||||
labs and create VMs from
|
||||
templates*](https://docs.google.com/document/d/1SZQmZ8tEmwqzlya5zMCuwTh_C1EqHfMRif09CyilYAE/edit?usp=sharing).
|
||||
|
||||
If you are working remotely using the oVirt online labs, [*click here
|
||||
for instructions on how to login via VPN and create VMs from
|
||||
templates*](https://docs.google.com/document/d/1zhANC_pz7fNwc_cALxGwPEn3_vls2YjWJUAkUV0BwlI/edit?usp=sharing).
|
||||
|
||||
The oVirt system is a new online lab infrastructure hosted here at Leeds
|
||||
Beckett. This infrastructure is **currently on trial, as a pilot**.
|
||||
There is a good chance there will be some technical issues, and not
|
||||
every lab will be available via this system. However, if you are happy
|
||||
to benefit from this experiment, please keep in mind that you may need
|
||||
to fall back to one of the above methods.
|
||||
|
||||
If you are working remotely having downloaded our VMs or by copying them
|
||||
when you were on campus, [*click here for instructions on how to
|
||||
download VMware Player and configure the VMs to run
|
||||
remotely*](https://drive.google.com/open?id=1mZSvF9Gc76mKQ5mW9Lsq2fWGIZd8-rE7RqmRXy1ICLY).
|
||||
|
||||
If you are on campus using the IMS system, [*click here for instructions
|
||||
on how to use the IMS system and VM download
|
||||
scripts*](https://drive.google.com/open?id=1E03Q7cPrUEk_YZ8syvo-sk6FGv2SlJT1u9KwGOFWdFA).
|
||||
|
||||
Start these VMs:
|
||||
|
||||
- openSUSE\_42.1 (user: student password: student)
|
||||
|
||||
- Two copies if working alone (Hint: change the desktop background
|
||||
> of one VM so that you can easily keep track of which VM you
|
||||
> are working on)
|
||||
|
||||
Note: The root password on the openSUSE\_Leap\_42.1-- **which should NOT
|
||||
be used to log in graphically** -- is “tiaspbiqe2r” (**t**his **i**s **a** **s**ecure **p**assword **b**ut **i**s **q**uite **e**asy **2** **r**emember). Again, never log in to the desktop environment using the
|
||||
root account -- that is bad practice, and should always be avoided.
|
||||
|
||||
Some of these exercises can be completed with a classmate (or simply
|
||||
using two VMs), and assumes root access is available to each other's
|
||||
systems via an ssh server.
|
||||
|
||||
> *Distance learning students*: If you would like to work with someone
|
||||
> else from the course, please contact each other via the course Google
|
||||
> group and share IP addresses.
|
||||
|
||||
**On openSUSE**:
|
||||
|
||||
Install the required packages:
|
||||
|
||||
> sudo zypper install rsync md5deep perl openssh
|
||||
|
||||
## Integrity
|
||||
|
||||
Security is often described in terms of confidentiality, integrity, and
|
||||
availability. Protecting the integrity of information involves
|
||||
preventing and detecting unauthorised changes. In many commercial
|
||||
organisations integrity of information is the highest priority security
|
||||
goal. Managing who is authorised to make changes to databases or files,
|
||||
and monitoring the integrity of resources for unauthorised changes is an
|
||||
important task in managing information security.
|
||||
|
||||
## Protecting integrity
|
||||
|
||||
Protecting the integrity of resources, such as the files on a system,
|
||||
involves successfully managing a variety of security mechanisms, such as
|
||||
authentication, access controls and file permissions, firewalls, and so
|
||||
on.
|
||||
|
||||
> On Linux systems this can include managing passwords, packet filtering
|
||||
> IPTables rules, standard Unix file permissions (rwx), Linux extended
|
||||
> attributes (including ACLs for detailed authentication, labels for
|
||||
> mandatory access control (MAC), and Linux Capabilities). Linux (like
|
||||
> other Unix-like and Unix-based systems) has a long history of adding
|
||||
> new security features as and when they are required.
|
||||
>
|
||||
> Note that many security controls such as those listed above are very
|
||||
> important for protecting the integrity of files, but are beyond the
|
||||
> scope of this lab. Here the focus is on techniques that are *entirely*
|
||||
> focussed on integrity rather than confidentiality or availability.
|
||||
|
||||
There are precautions that can be taken to reduce the chances of
|
||||
unauthorised changes.
|
||||
|
||||
### Protecting integrity with file attributes
|
||||
|
||||
Unix systems (such as Linux or FreeBSD) include file attributes that,
|
||||
amongst other features, can make files immutable or append only. Setting
|
||||
these file attributes can provide an effective layer of security, and
|
||||
yet could be considered one of the more obscure Unix security
|
||||
features[^1]. Note that this feature is dependent on the use of a
|
||||
compatible filesystem (most Unix filesystems, such as ext, are
|
||||
compatible with file attributes). Once configured, file attributes can
|
||||
even prevent root (the all-powerful Unix superuser) from making changes
|
||||
to certain files.
|
||||
|
||||
Open a terminal console (such as Konsole from
|
||||
 KDEMenu → System → Konsole).
|
||||
|
||||
Start by creating a file with some content. Run:
|
||||
|
||||
``
|
||||
sudo bash -c 'cat > /var/log/mylogfile'
|
||||
``
|
||||
>
|
||||
> (Type some content, then press Ctrl-D to finish and return to the
|
||||
> prompt.)
|
||||
|
||||
Look at the details of the file:
|
||||
|
||||
> ls -la /var/log/mylogfile
|
||||
>
|
||||
> -rw-r--r-- 1 root root 20 Feb 7 17:38 /var/log/mylogfile
|
||||
|
||||
As we can see above, the file is owned by root, who has read-write
|
||||
access – exploring Unix file permissions further is outside the scope of
|
||||
this lab, but will be covered elsewhere.
|
||||
|
||||
Run:
|
||||
|
||||
> lsattr /var/log/mylogfile
|
||||
>
|
||||
> -------------e- /var/log/mylogfile
|
||||
|
||||
The ‘e’ flag is common on ext filesystems, may or may not be present
|
||||
when you run the above, and does not really concern us. From a security
|
||||
perspective the ‘a’ and ‘i’ flags are the most interesting. Read the man
|
||||
page for chattr to find out more about these flags and what they do:
|
||||
|
||||
> man chattr
|
||||
>
|
||||
> (Press q to leave the manual page)
|
||||
|
||||
Set the ‘i’ flag using the chattr command:
|
||||
|
||||
> sudo chattr +i /var/log/mylogfile
|
||||
|
||||
Now try to delete the file and see what happens:
|
||||
|
||||
> rm /var/log/mylogfile
|
||||
|
||||
Denied! Opps, that’s right, root owns the file (since you created it
|
||||
with sudo)! Use root to try to delete the file:
|
||||
|
||||
> sudo rm /var/log/mylogfile
|
||||
|
||||
It still didn’t work! That’s right, even root can’t delete the file,
|
||||
without changing the file’s attributes back first.
|
||||
|
||||
Use some commands to remove the ‘i’ flag (hint: “-i”, instead of “+i”).
|
||||
|
||||
Now run a command to set the ‘a’ flag on /var/log/mylogfile.
|
||||
|
||||
If you have done so correctly, attempting to overwrite the file with a
|
||||
test message should fail:
|
||||
|
||||
> sudo bash -c 'echo "test message" > /var/log/mylogfile'
|
||||
>
|
||||
> This should produce an error, since ‘>’ causes the output of the
|
||||
> program to be written to the specified log file, which is not allowed
|
||||
> due to the chattr command you have run.
|
||||
|
||||
Yet you should be able to append messages to the end of the file:
|
||||
|
||||
> sudo bash -c 'echo "*your-name*: test message" **>>**
|
||||
> /var/log/mylogfile'
|
||||
>
|
||||
> This should succeed, since ‘>>’ causes the output of the program
|
||||
> to be appended (added to the end of) to the specified log file, which
|
||||
> is allowed. Use your name above, for example “echo "Cliffe: test
|
||||
> message" >> /var/log/mylogfile”.
|
||||
|
||||
View your changes at the end of the file:
|
||||
|
||||
> tail /var/log/mylogfile
|
||||
|
||||
This has obvious security benefits, this feature can be used to allow
|
||||
files to be written to without altering existing content. For example,
|
||||
for ensuring that log files can be written to, but avoiding giving
|
||||
everyone who can write to the file the ability to alter its contents.
|
||||
|
||||
|
||||
### Protecting integrity with read-only filesystems
|
||||
|
||||
On Unix, a filesystem is mounted to a particular point in the directory
|
||||
structure; for example, a USB thumb drive may be mounted to
|
||||
/media/myUSB/. Some filesystems will automatically mount read-only; for
|
||||
example, if you insert a CD-ROM, since those disks are physically
|
||||
read-only. It is possible to optionally mount almost any filesystem,
|
||||
such as a USB or even a directory, in read-only mode, which will make it
|
||||
practically impossible to write changes to it (without remounting or
|
||||
accessing the drive/directory in other ways, which normally only root
|
||||
can do).
|
||||
|
||||
> In a command prompt, run:
|
||||
>
|
||||
> mount
|
||||
>
|
||||
> Note that many of the devices and directories have been mounted for
|
||||
> read and write access (**rw**). For security reasons, it can be safer
|
||||
> to mount things as read-only, when we don’t need to be able to make
|
||||
> changes to the contents.
|
||||
>
|
||||
> Ordinary users can only read the /etc directory but the superuser root
|
||||
> who owns the /etc directory can read and write to it. In the following
|
||||
> example, you are going to mount the /etc directory to a mount point
|
||||
> (another directory within the filesystem) and the contents of the /etc
|
||||
> directory will be accessible via the mount point.
|
||||
>
|
||||
> List the contents of the /etc directory so you are familiar with its
|
||||
> contents:
|
||||
>
|
||||
> ls /etc
|
||||
>
|
||||
> Create a new directory to be the mount point:
|
||||
>
|
||||
> mkdir /home/student/test
|
||||
>
|
||||
> Mount the /etc directory to the new mount point:
|
||||
>
|
||||
> sudo mount -o bind /etc /home/student/test
|
||||
>
|
||||
> Make sure the /etc directory is accessible via the test directory
|
||||
> mount point:
|
||||
>
|
||||
> ls /home/student/test
|
||||
>
|
||||
> Ordinary users can only read but the superuser root can still write to
|
||||
> the directory. Test this by creating a new file as the superuser root
|
||||
> in the /home/student/test directory:
|
||||
>
|
||||
> sudo touch /home/student/test/file1
|
||||
>
|
||||
> Check that a new file has been created using the following commands
|
||||
>
|
||||
> ls -l /home/student/test/fi\*
|
||||
>
|
||||
> ls -l /etc/fi\*
|
||||
>
|
||||
> We can use this techniques to make filesystems and directories
|
||||
> read-only. In the next example you will remount the etc in read-only
|
||||
> mode so that even the superuser root who owns the /etc directory
|
||||
> cannot make changes to its contents via the mount point.
|
||||
>
|
||||
> sudo mount -o remount,ro,bind /etc /home/student/test
|
||||
>
|
||||
> Test this by trying creating a new file as the superuser root in the
|
||||
> /home/student/test directory:
|
||||
>
|
||||
> sudo touch /home/student/test/file2
|
||||
>
|
||||
> This should prevent changes being accidently being made to important
|
||||
> configuration files in the /etc directory.
|
||||
>
|
||||
> Remount the the /etc directory as read-only to itself:
|
||||
>
|
||||
> sudo mount -o remount,ro,bind /etc /etc
|
||||
|
||||
Mounting read-only can be an effective way of protecting resources that
|
||||
you don’t need to make any changes to. Read-only mounting is
|
||||
particularly effective when an actual disk resides externally, and can
|
||||
be enforced remotely. For example, when sharing files over the network.
|
||||
|
||||
Note that mounting read-only may be circumvented by root (or a user with
|
||||
enough privilege) via direct access to the device files (/dev/sdc1 in
|
||||
the example above), or by re-mounting as read-write.
|
||||
|
||||
Aside: in new versions of Linux, it is also possible to have a directory
|
||||
(one part of what is on a disk) present in the directory structure twice
|
||||
with different mount options (for example, /home/cliffe and
|
||||
/home/cliffe-read-only). This can be achieved by bind mounting, and then
|
||||
remounting to set the bind mount to read only. More information:
|
||||
[*http://lwn.net/Articles/281157/*](http://lwn.net/Articles/281157/)
|
||||
|
||||
## Detecting changes to resources
|
||||
|
||||
Although we can aim to protect integrity, eventually even the strongest
|
||||
defenses can fail, and when they do we want to know about it! In order
|
||||
to respond to a security incident we need to detect that one has
|
||||
occurred. One way we do so, is to detect changes to files on our system.
|
||||
|
||||
### Detecting changes to resources using backups
|
||||
|
||||
One technique is to compare files to a backup known to represent the
|
||||
system or resources in a clean state. One advantage of this approach is
|
||||
that we cannot only detect that files have changed, but also see exactly
|
||||
how they differ.
|
||||
|
||||
You can (and, if possible, should) **conduct this exercise with a
|
||||
classmate**.
|
||||
|
||||
Make a backup of your /etc/passwd file:
|
||||
|
||||
> cp /etc/passwd /tmp/passwd\_backup
|
||||
|
||||
This file (/etc/passwd) is an important file on Unix systems, which
|
||||
lists the user accounts on the system. Although historically the hashes
|
||||
of passwords were once stored here, they are now typically stored in
|
||||
/etc/shadow. Changes to the /etc/passwd file are usually infrequent –
|
||||
such as when new user accounts are created – and changes should only be
|
||||
made for authorised purposes.
|
||||
|
||||
At this point, also make sure you have a backup of any work.
|
||||
|
||||
If you are working with a classmate or using two VMs, once you (and your
|
||||
classmate or on the other VM) have saved a backup copy of your own
|
||||
passwd file using the above command, then connect to your classmate’s
|
||||
computer (other VM) using ssh:
|
||||
|
||||
> Set your root password to a password you will share with your
|
||||
> classmate:
|
||||
>
|
||||
> sudo passwd
|
||||
>
|
||||
> Enable your SSH server:
|
||||
>
|
||||
> sudo /sbin/service sshd start
|
||||
>
|
||||
> Open port 22 for ssh access to your computer
|
||||
>
|
||||
> Click KDEMenu → System → Yast
|
||||
>
|
||||
> Click Firewall in the Security and Users section
|
||||
>
|
||||
> Click “Allowed Services”
|
||||
>
|
||||
> Choose “Secure Shell Server” from the “Service to Allow” drop down
|
||||
> list
|
||||
>
|
||||
> Click Add to add ssh to the list of allowed services.
|
||||
>
|
||||
> Click Next → Finish and close Yast
|
||||
>
|
||||
> Find your IP address using ifconfig, and tell your classmate your IP
|
||||
> address and root password.
|
||||
>
|
||||
> ssh *their-ip-address*
|
||||
>
|
||||
> (Where *their-ip-address* is as noted earlier.) You will be prompted
|
||||
> for student account password.
|
||||
>
|
||||
> Switch to the root user (you will be prompted for the root password):
|
||||
>
|
||||
> su -
|
||||
>
|
||||
> If you do not know each other’s root password, then feel free to log
|
||||
> each other in on an ssh session as root.
|
||||
|
||||
Now that you have root access to their system[^2], add a new user to
|
||||
their computer... Your aim is to make the new account hard to notice. If
|
||||
you are working alone, just do this on your own system:
|
||||
|
||||
> useradd *new-username*
|
||||
>
|
||||
> Where new-username, is some new name. Don’t tell your classmate the
|
||||
> name of the account you have created. You may want to create a
|
||||
> username that looks innocent.
|
||||
|
||||
To make things even more interesting, edit the /etc/passwd file and move
|
||||
the new user account line somewhere other than right at the bottom, so
|
||||
that it is less obvious:
|
||||
|
||||
> vi /etc/passwd
|
||||
>
|
||||
> Move the cursor onto the line representing your new account (probably
|
||||
> at the bottom).
|
||||
>
|
||||
> In vi type:
|
||||
>
|
||||
> :m *-number*
|
||||
>
|
||||
> Where number is the number of lines to move up, for example: “:m -20”
|
||||
> will move the currently selected line up 20 lines, “hiding” the new
|
||||
> user account amongst the others.
|
||||
>
|
||||
> Save your changes and exit vi by typing:
|
||||
>
|
||||
> :wq
|
||||
|
||||
Now exit ssh:
|
||||
|
||||
> exit
|
||||
|
||||
If you are working with a together, look at the changes your classmate
|
||||
made on your computer, and try to spot the new user account:
|
||||
|
||||
> less /etc/passwd
|
||||
>
|
||||
> (q to exit)
|
||||
|
||||
It’s not as easy as it sounds, especially if your system has lots of
|
||||
user accounts.
|
||||
|
||||
Since you have a backup of your passwd file, you can compare the backup
|
||||
with the current passwd file to determine it has been modified. One such
|
||||
tool for determining changes is diff. Diff is a standard Unix command.
|
||||
Run:
|
||||
|
||||
> diff -q /tmp/passwd\_backup /etc/passwd
|
||||
|
||||
Diff should report that the two files differ. Diff can also produce an
|
||||
easy to read description of exactly how the file has changed. This is a
|
||||
popular format used by programmers for sharing changes to source code:
|
||||
|
||||
> diff -u /tmp/passwd\_backup /etc/passwd
|
||||
|
||||
There are many advantages to the comparison of backups approach to
|
||||
detecting changes, but it also has its limitations. To apply this
|
||||
approach to an entire system, you will need a fairly large amount of
|
||||
either local or network shared storage, and writes need to be controlled
|
||||
to protect the backups, yet written to whenever authorised changes are
|
||||
made to keep the backup up-to-date. Also, when the comparisons are made
|
||||
substantial disk/network access is involved, since both both sources
|
||||
need to be read at the same time in order to do the comparison.
|
||||
|
||||
In the example above, the backup was stored on the same computer. Did
|
||||
you think of editing your classmates backup passwd file? This is related
|
||||
to a major issue when checking for changes to the system: if your system
|
||||
has been compromised, then you can’t necessarily trust any of the local
|
||||
software or files, since they may have been replaced or modified by an
|
||||
attacker. For that reason, it can be safer to run software (such as
|
||||
diff) from a separate read-only storage. Yet that still may not be
|
||||
enough, the entire operating system could be infected by a rootkit.
|
||||
|
||||
Aside: Filesystems, such as btrfs, that support history and snapshots
|
||||
can also be helpful for investigating breaches in integrity.
|
||||
|
||||
### Detecting changes to resources using hashes and file integrity checkers
|
||||
|
||||
Another technique for detecting modifications to files is to use hashes
|
||||
of files in their known good state. Rather than storing and comparing
|
||||
complete copies, a one way hash function can be used to produce a fixed
|
||||
length hash (or “digest”), which can be used for later comparisons.
|
||||
Hashes have security properties that enable this use:
|
||||
|
||||
- Each hash is unique to the input
|
||||
|
||||
- It is extremely difficult (practically impossible) to find another
|
||||
> input that produces the same hash output
|
||||
|
||||
- Any change to the input (no matter how minor) changes the output
|
||||
> hash dramatically
|
||||
|
||||
We can store a hash and later recompute the hash, to determine whether
|
||||
the file has changed (if the hash is different), or it is exactly the
|
||||
same (if the hash is the same). If you have studied digital forensics,
|
||||
many of these concepts will be familiar to you, since hashes are also
|
||||
commonly used for verifying the integrity of digital evidence.
|
||||
|
||||
Generate an MD5 hash of your backup password file, which you copied
|
||||
above:
|
||||
|
||||
> md5sum /tmp/passwd\_backup
|
||||
|
||||
Now calculate a hash of your current passwd file:
|
||||
|
||||
> md5sum /etc/passwd
|
||||
|
||||
If the generated hashes are different, you know the files do not have
|
||||
exactly the same content.
|
||||
|
||||
Note that using hashes, there is no need to have the backup on-hand in
|
||||
order to check the integrity of files, you can just compare a newly
|
||||
generated hash to a previous one.
|
||||
|
||||
Repeat the above two commands using shasum rather than md5sum. SHA1 and
|
||||
SHA2 are considered to be more secure than the “cryptographically
|
||||
broken” MD5 algorithm. Although MD5 is still in use today, it is safer
|
||||
to use a stronger hash algorithm, since MD5 is not collision-resistant,
|
||||
meaning it is possible to find multiple files that result in the same
|
||||
hash. SHA1 is considered partially broken, so a new algorithm such as
|
||||
SHA2 is currently a good option. There are a number of related commands
|
||||
for generating hashes, named md5sum, shasum, sha224sum, sha256sum, and
|
||||
so on. These commands (as well as those in the next section) are readily
|
||||
available on most Unix systems, and are also available for Windows.
|
||||
|
||||
#### File integrity checkers
|
||||
|
||||
A file integrity checker is a program that compares files to previously
|
||||
generated hashes. A number of these kinds of tools exist, and these can
|
||||
be considered a form of host-based intrusion detection system (HIDS),
|
||||
particularly if the checking happens automatically. One of the most well
|
||||
known integrity checkers is Tripwire, which was previously released open
|
||||
source; although, new versions are closed source and maintained by
|
||||
Tripwire, Inc, with a more holistic enterprise ICT change management
|
||||
focus. There are other tools similar to Tripwire, such as AIDE (Advanced
|
||||
Intrusion Detection Environment), and OSSEC (Open Source Host-based
|
||||
Intrusion Detection System).
|
||||
|
||||
The above md5sum, shasum (and so on) programs can also be used to check
|
||||
a list of file hashes.
|
||||
|
||||
Create an empty file, where *your-name*, is your actual name:
|
||||
|
||||
> touch *your-name*
|
||||
|
||||
Run the following to generate a file containing hashes of files we can
|
||||
later check against:
|
||||
|
||||
> shasum *your-name* >> /tmp/hash.sha
|
||||
>
|
||||
> shasum /etc/passwd >> /tmp/hash.sha
|
||||
>
|
||||
> sudo shasum /etc/shadow >> /tmp/hash.sha
|
||||
>
|
||||
> shasum /bin/bash >> /tmp/hash.sha
|
||||
>
|
||||
> shasum /bin/ls >> /tmp/hash.sha
|
||||
|
||||
Look at the contents of our new hashes file (Q to quit when done):
|
||||
|
||||
> less /tmp/hash.sha
|
||||
|
||||
Now use your new hash list to check that nothing has changed since we
|
||||
generated the hashes:
|
||||
|
||||
> shasum -c /tmp/hash.sha
|
||||
|
||||
Why does shasum fail to check the integrity of the shadow file?
|
||||
|
||||
Make a change to our empty “*your-name*” file:
|
||||
|
||||
> echo "hello" > *your-name*
|
||||
|
||||
Check whether anything has changed since we generated hashes:
|
||||
|
||||
> shasum -c /tmp/hash.sha
|
||||
|
||||
You should see a nice explanation of the files that have changed since
|
||||
generating the hashes.
|
||||
|
||||
#### Scripted integrity checking
|
||||
|
||||
The above can also be accomplished via a simple script (in this case a
|
||||
Perl script):
|
||||
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Copyleft 2012, Z. Cliffe Schreuders
|
||||
|
||||
# Licenced under the terms of the GPLv3
|
||||
|
||||
use warnings;
|
||||
|
||||
use strict;
|
||||
|
||||
my %files\_hashes = (
|
||||
|
||||
"/bin/ls"=>"9304c5cba4e2a7dc25c2d56a6da6522e929eb848",
|
||||
|
||||
"/bin/bash"=>"54d0d9610e49a654843497c19f6211b3ae41b7c0",
|
||||
|
||||
"/etc/passwd"=>"69773dcef97bca8f689c5bc00e9335f7dd3d9e08"
|
||||
|
||||
);
|
||||
|
||||
foreach my \$file\_entry (keys %files\_hashes) {
|
||||
|
||||
my \$hash = \`sha1sum \$file\_entry|awk '{print \\\$1}'|head -n1\`;
|
||||
|
||||
chomp(\$hash);
|
||||
|
||||
if(\$hash ne \$files\_hashes{\$file\_entry}){
|
||||
|
||||
warn "FILE CHANGED: \$file\_entry (hash was \$hash, expected
|
||||
\$files\_hashes{\$file\_entry})\\n";
|
||||
|
||||
} else {
|
||||
|
||||
print "File unmodified: \$file\_entry (hash was \$hash, as
|
||||
expected)\\n";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
This script simply iterates over a list of file paths with SHA1 hashes
|
||||
(stored in an associative array), and runs sha1sum for each one to check
|
||||
whether the files are still the same.
|
||||
|
||||
Save the script as checker.pl (Help: you may wish to install the default
|
||||
KDE GUI text editor Kate, if it is not already installed under the
|
||||
Utlities menu. You should be able to copy the script and paste it into
|
||||
Kate to save it as checker.pl. Kate can be installed using the following
|
||||
command: “sudo zypper install kate”)
|
||||
|
||||
Then run the script with:
|
||||
|
||||
> perl checker.pl
|
||||
|
||||
Are the files reported as unmodified, or have they changed? Why might
|
||||
they be different to when I wrote the script?
|
||||
|
||||
##### Recursive file integrity checkers
|
||||
|
||||
The md5deep program (also known as sha1deep, sha256deep, and so on for
|
||||
different hash algorithms) can recursively walk through directories (and
|
||||
into all contained subdirectories) to generate and check lists of
|
||||
hashes.
|
||||
|
||||
Run:
|
||||
|
||||
> sudo sha1deep -r /etc
|
||||
>
|
||||
> If the md5deep command is not available, install it:
|
||||
>
|
||||
> On openSUSE this can be done by first running “cnf sha1deep”, to find
|
||||
> the name of the package containing the program, then run the install
|
||||
> command it gives you, such as “sudo zypper install md5deep”.
|
||||
>
|
||||
> If you get “PackageKit is blocking zypper”, then select “no”, and kill
|
||||
> PackageKit, by running “kill -9 *pid*”, where *pid* is the number
|
||||
> reported by the previous command. Now run the above again.
|
||||
>
|
||||
> If the zypper command is stuck on refreshing a repository, then press
|
||||
> “Ctrl-C”, “a” (for abort), then proceed with the installation as per
|
||||
> normal.
|
||||
>
|
||||
> Once the required software is installed, try the sha1deep command
|
||||
> again.
|
||||
|
||||
The output of the above command will include hashes of every file in
|
||||
/etc, which is where system-wide configuration files are stored on Unix.
|
||||
|
||||
Read the sha1deep manual to understand the above command:
|
||||
|
||||
> man sha1deep
|
||||
>
|
||||
> Figure out what the -r flag does.
|
||||
>
|
||||
> (Q to quit)
|
||||
|
||||
We can save (redirect) this output to a file so that we have a record of
|
||||
the current state of our system’s configuration:
|
||||
|
||||
> sudo sha1deep -r /etc > /tmp/etc\_hashes
|
||||
|
||||
This may take a minute or so, while the program calculates the hashes
|
||||
and sends them to standard out (known as stdout), which is then
|
||||
redirected to the etc\_hashes file.
|
||||
|
||||
Next, let's compare the size of our list of hashes, with the actual
|
||||
content that we have hashed...
|
||||
|
||||
See how big our list of hashes is:
|
||||
|
||||
> ls -hs /tmp/etc\_hashes
|
||||
>
|
||||
> (-h = human readable, -s = size)
|
||||
|
||||
This is likely to be in the Kilobytes.
|
||||
|
||||
And for the size of all of the files in /etc:
|
||||
|
||||
> sudo du -hs /etc
|
||||
>
|
||||
> (-h = human readable, -s summarise)
|
||||
|
||||
This is likely in the Megabytes (or maybe even Gigabytes).
|
||||
|
||||
Clearly, the list of hashes is much smaller.
|
||||
|
||||
If you are **working with a classmate**, log into their system using ssh
|
||||
(as done previously). If you are working alone, simply run all the
|
||||
commands on your own system.
|
||||
|
||||
Create a new file somewhere in /etc/, containing your name. Name the
|
||||
file whatever you like (for example /etc/test), although the more
|
||||
inconspicuous the better.
|
||||
|
||||
> Hint: “sudo vi /etc/test”, “i” to enter insert mode, and after typing
|
||||
> your name, “Esc”, “:wq”.
|
||||
|
||||
Also, change an existing file in /etc on their system, but please do be
|
||||
careful to only make a minor change that will **not cause damage to
|
||||
their system**. For example, you could use vi to edit /etc/hostname
|
||||
(“sudo vi /etc/hostname”), and add a comment to the file such as
|
||||
“\#your-name: bet you can’t find this comment!”
|
||||
|
||||
You can now “exit” the ssh session.
|
||||
|
||||
**On your own system**, lets try to identify what the “attacker” has
|
||||
done to our system...
|
||||
|
||||
Now that we have a list of hashes of our files, use shasum to check if
|
||||
anything has changed using our newly generated list of hashes
|
||||
(/tmp/etc\_hashes).
|
||||
|
||||
> Hint: look at the previous command using shasum to check hashes.
|
||||
|
||||
Does this detect our the changed file AND the new file? Why not?
|
||||
|
||||
Md5deep/sha1deep takes a different approach to checking integrity, by
|
||||
checking all of the files it is told to check (possibly recursing over
|
||||
all files in a directory) against a list of hashes, and reporting
|
||||
whether any files it checked did not (or did, depending on the flags
|
||||
used) have its hash somewhere in the hash list.
|
||||
|
||||
Run sha1deep to check whether any files in /etc/ do not match a hash
|
||||
previously generated:
|
||||
|
||||
> sudo sha1deep -X /tmp/etc\_hashes -r /etc
|
||||
|
||||
This should detect both modified files, both new and modified.
|
||||
|
||||
But would sha1deep detect a copy of an existing file, to a new location?
|
||||
|
||||
Try it:
|
||||
|
||||
> sudo cp /etc/passwd /etc/passwd.backup
|
||||
|
||||
Now rerun the previous sha1deep command. Was the copy detected? Why not?
|
||||
|
||||
What about copying one file over another? Which out of shasum or
|
||||
sha1deep would detect that?
|
||||
|
||||
Another tool, hashdeep, which is included with md5deep, provides more
|
||||
coverage when it comes to detecting files that have moved, changed, or
|
||||
created.
|
||||
|
||||
Generate a hash list for /etc using hashdeep:
|
||||
|
||||
> sudo hashdeep -r /etc > /tmp/etc\_hashdeep\_hashes
|
||||
|
||||
Hashdeep stores hashes in a different format than the previous tools.
|
||||
Have a look:
|
||||
|
||||
> less /tmp/etc\_hashdeep\_hashes
|
||||
>
|
||||
> (q to quit)
|
||||
>
|
||||
> Note that the output includes some more information, such as the file
|
||||
> size for each file.
|
||||
|
||||
Delete the new file that your “attacker” (the person who sshed into your
|
||||
system) created earlier:
|
||||
|
||||
> sudo rm /etc/*whatever-the-filename-was*
|
||||
|
||||
Conduct a hashdeep audit to detect any changes:
|
||||
|
||||
> sudo hashdeep -r -a -k /tmp/etc\_hashdeep\_hashes /etc
|
||||
>
|
||||
> Note, that this can take a while, so feel free to start working
|
||||
> through the next section in another terminal, if you like.
|
||||
|
||||
After, run it again, this time asking for more details, since the
|
||||
default message does not provide any information as to why an audit has
|
||||
failed:
|
||||
|
||||
> sudo hashdeep -ra**vv** -k /tmp/etc\_hashdeep\_hashes /etc
|
||||
|
||||
Consult the man page for information about what each of the above flags
|
||||
do.
|
||||
|
||||
#### Detecting changes to resources using package management
|
||||
|
||||
On Linux systems, package management systems are used to organise,
|
||||
install, and update software. The package management system has a
|
||||
database that keeps track of all the files for each program or software
|
||||
package. Depending on the package management system used, the database
|
||||
may maintain hashes in order to detect changes to files since install.
|
||||
RPM-based systems (such as Red Hat, Fedora, and OpenSUSE), store hashes
|
||||
of each file that is included in software packages. There are commands
|
||||
that can be used to detect changes to files that have occurred since
|
||||
being installed by the package management software.
|
||||
|
||||
Note that there are times where it is perfectly normal for a number of
|
||||
files to not match the “fresh” versions that were installed: for
|
||||
example, configuring a system for use will involve editing configuration
|
||||
files that were distributed with software packages.
|
||||
|
||||
The “rpm” command has a -V flag for verifying the integrity of packages.
|
||||
|
||||
Choose any system file on the computer, such as /etc/securetty. To
|
||||
determine which package the file belongs to:
|
||||
|
||||
> rpm -q --whatprovides *any-file-you-chose*
|
||||
>
|
||||
> Where any-file-you-chose is any file such as /etc/securetty.
|
||||
|
||||
The output of that command the package-name, and is required in the next
|
||||
step.
|
||||
|
||||
Check the integrity of the file:
|
||||
|
||||
> rpm -V *package-name*
|
||||
>
|
||||
> Where package-name is the output from the previous command.
|
||||
|
||||
An example from the output would be:
|
||||
|
||||
> 5S.T..... c /etc/securetty
|
||||
|
||||
Which means, it is a config file (c), and:
|
||||
|
||||
- S – file Size differs
|
||||
|
||||
- M – Mode differs (includes permissions and file type)
|
||||
|
||||
- 5 – MD5 sum differs
|
||||
|
||||
- D – Device major/minor number mismatch
|
||||
|
||||
- L – readLink(2) path mismatch
|
||||
|
||||
- U – User ownership differs
|
||||
|
||||
- G – Group ownership differs
|
||||
|
||||
- T – mTime differs
|
||||
|
||||
- P – caPabilities differ
|
||||
|
||||
Use the above information to understand the output from your above rpm
|
||||
-V command.
|
||||
|
||||
Next verify the integrity of all of the packages on the entire system
|
||||
(this may take a while):
|
||||
|
||||
> rpm -Va
|
||||
|
||||
Try to understand the cause of any files failing the integrity checks.
|
||||
|
||||
Consider the limitations of this approach: what files will (and won’t)
|
||||
this approach to integrity management cover?
|
||||
|
||||
#### Limitations of integrity checking
|
||||
|
||||
Perhaps the greatest limitation to all of these approaches, is that if a
|
||||
system is compromised, you may not be able to trust any of the tools on
|
||||
the system, or even the operating system itself to behave as expected.
|
||||
In the case of a security compromise, your configuration files may have
|
||||
been altered, including any hashes you have stored locally, and tools
|
||||
may have been replaced by Trojan horses. For this reason it is safer to
|
||||
run tools over the network or from a removable drive, with read-only
|
||||
access to protect your backups and hashes. Even then, the
|
||||
OS/kernel/shell may not be telling you the truth about what is
|
||||
happening, since a rootkit could be concealing the truth from other
|
||||
programs.
|
||||
|
||||
### Problem-based tasks
|
||||
|
||||
#### Choosing files for integrity checking
|
||||
|
||||
Fill in the table below with a number of files on a Unix or Windows
|
||||
system whose integrity should be monitored for security purposes:
|
||||
|
||||
**Filename** **Description** **Security reason for monitoring integrity**
|
||||
--------------------- ------------------------- ---------------------------------------------------------------------------------------------------------------------
|
||||
*Unix: /etc/passwd* *List of user accounts* *Adding or modifying users is security sensitive, since rogue user accounts could present a backdoor to the system*
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
**Complete the table above, with a number of Unix/Windows files that
|
||||
should be monitored for integrity, as evidence that you have completed
|
||||
this part of the task.**
|
||||
|
||||
**Label it or save it as “Integrity-A1”.**
|
||||
|
||||
Add an integrity monitoring solution (md5sum, md5deep, or hashdeep) to a
|
||||
cron job, so that every hour the integrity of some important files are
|
||||
checked, and any errors are emailed to root.
|
||||
|
||||
Hints: Any output on standard error (stderr) on a cron job results in a
|
||||
local email to root. As root, type “mail” to read the local emails. Run
|
||||
“crontab -e” to add scheduled tasks. Google will certainly help here.
|
||||
|
||||
Help: You may find the following links if you have not used cron before
|
||||
to run scheduled tasks.
|
||||
|
||||
[*Click here for an openSUSE
|
||||
Video*](https://www.youtube.com/watch?v=bQfza9aLjss)
|
||||
|
||||
[*Click here for a cron
|
||||
tutorial*](http://www.computerhope.com/unix/ucrontab.htm)
|
||||
|
||||
[*Click here for cron
|
||||
examples*](http://www.thegeekstuff.com/2009/06/15-practical-crontab-examples/comment-page-1/)
|
||||
|
||||
**Take screenshots of an hourly cronjob rule, and email with an
|
||||
integrity report from md5sum/deep or hashdeep, as evidence that you have
|
||||
completed this part of the task.**
|
||||
|
||||
**Label it or save it as “Integrity-A2”.**
|
||||
|
||||
Add to your above solution, by considering and implementing some
|
||||
protection against modifications to your hash file/database.
|
||||
|
||||
**Take a screenshot of your configuration for protection of the hash
|
||||
file (and include a one sentence description), as evidence that you have
|
||||
completed this part of the task.**
|
||||
|
||||
**Label it or save it as “Integrity-A3”.**
|
||||
|
||||
Install either OSSEC (Open Source Host-based Intrusion Detection
|
||||
System), AIDE (Advanced Intrusion Detection Environment), or Tripwire
|
||||
(if you can find a copy), and use it to monitor the integrity of your
|
||||
files. Modify a file named *your-name* (your actual name) and view a
|
||||
report or alert that the integrity of the file has been compromised.
|
||||
|
||||
**Take a screenshot of a report from OSSEC or AIDE that a file named
|
||||
after you has been altered, as evidence that you have completed this
|
||||
part of the task.**
|
||||
|
||||
**Label it or save it as “Integrity-A4”.**
|
||||
|
||||
Add to the integrity monitoring script given earlier, to store and
|
||||
retrieve the hashes from a file.
|
||||
|
||||
For extra marks, protect the hashes using a HMAC, with user interaction
|
||||
to enter a password.
|
||||
|
||||
**Save your modifications of the script, as evidence that you have
|
||||
completed this part of the task.**
|
||||
|
||||
**Label it or save it as “Integrity-A5”.**
|
||||
|
||||
### Resources
|
||||
|
||||
An excellent resource on the subject of integrity management is Chapter
|
||||
20 of the excellent book *Practical Unix & Internet Security, 3rd Ed*,
|
||||
by Garfinkel et al (2003).
|
||||
|
||||
[^1]: Setting a file to immutable (and therefore impossible to simply
|
||||
delete) can be an effective prank against the uninitiated in Unix
|
||||
ways.
|
||||
|
||||
[^2]: It is obvious that there are risks associated with knowing each
|
||||
other’s root passwords! Obviously, use this knowledge responsibly to
|
||||
work together to complete the tasks.
|
||||
|
||||
## License
|
||||
|
||||

|
||||
|
||||
This work by [*Z. Cliffe Schreuders*](http://z.cliffe.schreuders.org) at Leeds Beckett University is licensed under a [*Creative Commons
|
||||
Attribution-ShareAlike 3.0 Unported License*](http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB).
|
||||
|
||||
|
||||
@@ -1,494 +0,0 @@
|
||||
# Authentication
|
||||
|
||||
## Getting started
|
||||
### VMs in this lab
|
||||
|
||||
==Start these VMs== (if you haven't already):
|
||||
- hackerbot_server (leave it running, you don't log into this)
|
||||
- desktop
|
||||
|
||||
### Your login details for the "desktop" and "server" VMs
|
||||
User: <%= $main_user %>
|
||||
Password: tiaspbiqe2r (**t**his **i**s **a** **s**ecure **p**assword **b**ut **i**s **q**uite **e**asy **2** **r**emember)
|
||||
|
||||
You won't login to the hackerbot_server, but the VM needs to be running to complete the lab.
|
||||
|
||||
### For marks in the module
|
||||
1. **You need to submit flags**. Note that the flags and the challenges in your VMs are different to other's in the class. Flags will be revealed to you as you complete challenges throughout the module. Flags look like this: ==flag{*somethingrandom*}==. Follow the link on the module page to submit your flags.
|
||||
2. **You need to document the work and your solutions in a Log Book**. This needs to include screenshots (including the flags) of how you solved each Hackerbot challenge and a writeup describing your solution to each challenge, and answering any "Log Book Questions". The Log Book will be submitted later in the semester.
|
||||
|
||||
## Meet Hackerbot!
|
||||

|
||||
|
||||
This exercise involves interacting with Hackerbot, a chatbot who will attack your system. If you satisfy Hackerbot by completing the challenges she will reveal flags to you.
|
||||
|
||||
**On the desktop VM:**
|
||||
|
||||
==Open Pidgin and send some messages to Hackerbot:==
|
||||
|
||||
- Try asking Hackerbot some questions
|
||||
- Send "help"
|
||||
- Send "list"
|
||||
- Send "hello"
|
||||
> If Hackerbot seems to be waiting/halted, simply say 'hi'
|
||||
|
||||
Work through the below exercises, completing the Hackerbot challenges as noted.
|
||||
|
||||
---
|
||||
|
||||
## Introduction to authentication
|
||||
|
||||
Authentication plays the important role of verifying an identity. For example, when someone gets into an airplane, sits down at a computer, picks up a mobile device, or uses a website, authentication is what is used to confirm that the person is who they claim to be. Authentication is an important first step *before* deciding how the system should act and what to allow.
|
||||
|
||||
### Identity: users and groups
|
||||
|
||||
Most computer systems have the concept of a user account. Although some devices such as mobile phones typically only have one user account, most modern computers can support having multiple users, each with their own identity. For example, a computer can have a separate account for each person that uses it, and if configured to do so may enable each user to have their own account preferences, and access to different resources.
|
||||
|
||||
On Unix/Linux systems every user account is identified by a user ID number (UID), which is a 32-bit integer (whole number), and can have one or more user names, which are human readable strings of text.
|
||||
|
||||
Open a terminal console.
|
||||
|
||||
> One way to do this is to start Konsole from KDEMenu
|
||||
|
||||
Assuming you have already logged in, you have already authenticated yourself on this system.
|
||||
|
||||
==Log Book Question: When and how did you authenticate yourself?==
|
||||
|
||||
Use these commands to find out about your current identity (or more accurately the identity of the software you are interacting with):
|
||||
|
||||
```bash
|
||||
whoami
|
||||
|
||||
groups
|
||||
|
||||
id
|
||||
```
|
||||
|
||||
==Make a note of your UID and username.==
|
||||
|
||||
Note that your account is also a member of one or more groups. A primary group, and a list of other groups. Some Linux systems, such as Debian, create a new seperate primary group for each user, others such as openSUSE have a shared group (named "users") that all normal users are a member of. Similar to the relationship between user names and UIDs, each group has a group name, and a group ID (GID).
|
||||
|
||||
Information about user accounts is stored in the /etc/passwd file, which typically all users can read.
|
||||
|
||||
==View the /etc/passwd file:==
|
||||
|
||||
```bash
|
||||
less /etc/passwd
|
||||
```
|
||||
|
||||
==Find the line that describes your user account.==
|
||||
|
||||
This line defines the username, password (well, it used to be stored here… we will come back to this), UID, primary group GID, full name, home directory, and shell for your account.
|
||||
|
||||
Confirm this matches the information you recorded earlier.
|
||||
|
||||
==Find the line that describes the root user account.==
|
||||
|
||||
Where is the root user's home directory?
|
||||
|
||||
> Press 'q' to quit less.
|
||||
|
||||
==View the /etc/group file:==
|
||||
|
||||
```bash
|
||||
less /etc/group
|
||||
```
|
||||
|
||||
Groups are defined in this file, along with which users are members.
|
||||
|
||||
==Which users are members of the "tftp" group?
|
||||
|
||||
Remember, primary groups do not appear in this file; for example, on openSUSE the "users" group, which all normal users are a member of, may not appear in the /etc/group file.
|
||||
|
||||
The "su" program can be used to run a program (usually a shell; that is, a command prompt) as another user, effectively enabling users to switch between user accounts at the command prompt.
|
||||
|
||||
==Change your identity to root==. Run:
|
||||
|
||||
```bash
|
||||
su -
|
||||
```
|
||||
|
||||
Enter the root password.
|
||||
|
||||
Use these commands to ==find out about your new identity:==
|
||||
|
||||
```bash
|
||||
whoami
|
||||
|
||||
groups
|
||||
|
||||
id
|
||||
```
|
||||
|
||||
==What is the UID of root? What does this mean about this user?==
|
||||
|
||||
==Lab Book Question: What gives this user special privileges: the name of the account, or the UID?==
|
||||
|
||||
==Use the useradd command to create a new user account "fred"==
|
||||
|
||||
> Hint: refer to the man page for useradd, by running "man useradd".
|
||||
|
||||
==Set a password for the user fred.==
|
||||
|
||||
> Hint: `sudo passwd fred`
|
||||
|
||||
==Change identity to fred.==
|
||||
|
||||
> Hint: `su - fred`
|
||||
|
||||
==Run:(after su)==
|
||||
|
||||
```bash
|
||||
id
|
||||
```
|
||||
|
||||
==Compare the result to the previous output.==
|
||||
|
||||
==How does this compare to your other normal user account? What is different, and what about it is the same?==
|
||||
|
||||
Run the single command "id" as root:
|
||||
|
||||
```bash
|
||||
sudo id
|
||||
```
|
||||
|
||||
==Log Book Question: What is the difference between sudo and su? Which is most likely protect against accidental damage and also log the commands used?==
|
||||
|
||||
### Users and SSH
|
||||
|
||||
==Log in to the server via ssh:==
|
||||
|
||||
```bash
|
||||
ssh <%= $main_user %>@<%= $server_ip %>
|
||||
```
|
||||
|
||||
==Display details of all users logged on to the system:==
|
||||
|
||||
```bash
|
||||
who
|
||||
```
|
||||
|
||||
==List all the processes run by all users:==
|
||||
|
||||
```bash
|
||||
ps -eo user,comm
|
||||
```
|
||||
|
||||
==List all the processes running as root:==
|
||||
|
||||
```bash
|
||||
ps -o user,comm -u root
|
||||
```
|
||||
|
||||
==Run a command to list all the processes running as *your* normal user.==
|
||||
|
||||
==Lab Book Question: How is this server authenticating users? What user accounts exist?==
|
||||
|
||||
### Passwords, hashes and salt
|
||||
|
||||
Given that important security decisions are made based on the user accounts, it is important to authenticate users, to ensure that the subjects are associated with the correct identity.
|
||||
|
||||
==What are the kinds of factors that can be used to verify a user's identity? Hint: for example, "something they have".==
|
||||
|
||||
==Which category of authentication factors is a password considered to be?==
|
||||
|
||||
Originally passwords were stored "in the clear" (not enciphered). For example, Multics stored passwords in a file, and once at MIT a software bug caused the password file to be copied to the motd file (message of the day), which was printed every time anyone logged into the system. A solution is not to store the password in the clear. Instead a hash can be computed, using a one way hash function, and stored. When the user enters a password, a new hash is computed and compared to the original.
|
||||
|
||||
On Linux, the command "shasum" can be used to check the integrity of files (hash functions have many uses), and works on the same principle. We can use it to generate a hash for any given string, for example a password:
|
||||
|
||||
```bash
|
||||
shasum
|
||||
```
|
||||
|
||||
> Type "hello" without the quotes. Press Ctrl-D (which indicates "EOF"; that is, end of input).
|
||||
|
||||
Repeat the above, with the same password ("hello"), and with a slight difference ("hello.").
|
||||
|
||||
Are the outputs the same?
|
||||
|
||||
Are the different hashes similar?
|
||||
|
||||
Is this good? Why?
|
||||
|
||||
Which one-way hash function does the shasum program use? Would this be a good option for hashing passwords?
|
||||
|
||||
For password authentication, the hash still needs to be stored. On Unix, password hashes were once stored in the world-readable file /etc/passwd, now they are typically stored in /etc/shadow, which only root (the superuser) can access.
|
||||
|
||||
==View the shadow file:==
|
||||
|
||||
```bash
|
||||
sudo less /etc/shadow
|
||||
```
|
||||
|
||||
The format of the shadow file is:
|
||||
|
||||
> username:**password**:last-changed(since 1-1-1970):days-until-may-change:days-until-must-change:days-warning-notice:days-since-expired-account-disabled:date-disable:reserved-field
|
||||
|
||||
==Find the hash of your user account's password.==
|
||||
|
||||
> Exit less ("q").
|
||||
|
||||
Use the passwd command to ==change your password:==
|
||||
|
||||
```bash
|
||||
passwd
|
||||
```
|
||||
|
||||
> When prompted, enter a new password of your choosing.
|
||||
|
||||
View the shadow file, and confirm that the stored password has changed.
|
||||
|
||||
With reference to the shadow file, and the man page for crypt (Hint: "man crypt"), ==answer these Log Book questions==:
|
||||
|
||||
- On Linux, the password hash stored in /etc/shadow has a prefix that specifies the hash function used.\
|
||||
> ==What hash function is used for your password?==
|
||||
|
||||
- ==When was the root password last changed?==
|
||||
|
||||
- ==Do any accounts have a setting that will force a password change at a specific date?==
|
||||
|
||||
A salt is a random string, used as further input into a one-way hash function (concatenated to the password). The salt is typically stored along with the hash. As a result the same password will have different hashes, so long as the salt is different.
|
||||
|
||||
Why is that a good thing?
|
||||
|
||||
What kind of attack does a salt defend against?
|
||||
|
||||
What is the current salt for your account? Hint: it is stored after the second "\$".
|
||||
|
||||
### Password weaknesses
|
||||
|
||||
The strength of a password depends on its entropy: its degree of randomness. If a user chooses a word from a dictionary, it would not take long to attempt every dictionary word until finding one that results in the same hash.
|
||||
|
||||
Try your hand at cracking passwords using the Kali virtual machine.
|
||||
|
||||
Add some new users with these passwords:
|
||||
> Hello
|
||||
>
|
||||
> hellothere
|
||||
>
|
||||
> H3ll0
|
||||
>
|
||||
> hello1
|
||||
>
|
||||
> 12hell012356
|
||||
|
||||
==Use john the ripper to crack the passwords.==
|
||||
> Hint: `man john`, on the Kali Linux system.
|
||||
|
||||
- Which passwords are cracked the fastest?
|
||||
|
||||
- How long did they take?
|
||||
|
||||
# ------
|
||||
# ------
|
||||
# ------
|
||||
|
||||
### Pluggable Authentication Modules (PAM)
|
||||
|
||||
In the past all Linux/Unix programs that required the user to enter a password for authentication (such as su, sudo, and login) would access and interpret /etc/passwd using its own code. However, it was hard to maintain all this code, since any change in the way the passwords were stored (such as using a shadow file, or using new hash functions) would mean all the software that provides authentication needed to be changed. The solution to the problem was PAM.
|
||||
|
||||
*Pluggable Authentication Modules (PAM)* enables applications that make use of authentication to be independent of the specific authentication schemes in use. For example, a program such as a login screen that uses PAM can be configured to authenticate using a password, smartcard, and/or biometrics, simply by changing PAM configuration files.
|
||||
|
||||
PAM is supported in most distributions of Linux, Mac OS X, FreeBSD, and many other Unix-like systems.
|
||||
|
||||
View which PAM modules are available on the desktop system:
|
||||
|
||||
> /usr/sbin/pam-config --list-modules
|
||||
|
||||
The .so files are typically in /lib/security or /lib64/security. List them:
|
||||
|
||||
> ls /lib\*/security/
|
||||
|
||||
As you can see, there are lots of different features and authentication schemes, and these can be used with *any* PAM compatible program. This includes not only typical authentication schemes, such as pam\_unix2.so, which does the usual password comparison with /etc/passwd and /etc/shadow, but also can impose time limits (pam\_time.so) or simply display messages to the user (pam\_motd.so).
|
||||
|
||||
It is possible to determine whether a specific program is compiled to use PAM, by checking what dynamic libraries it uses. (On Linux .so shared objects are similar to DLL files on Windows, they contain library code that programs can reuse). Check what shared objects the passwd program uses:
|
||||
|
||||
```bash
|
||||
which passwd
|
||||
>
|
||||
> ldd *path\_to\_passwd*
|
||||
```
|
||||
|
||||
> Where path\_to\_password is the output from the "which passwd" command above, which identifies the absolute path to a program. For example, `ldd /usr/bin/passwd`
|
||||
|
||||
Note that the output will include a line starting with "libpam.so", such as:
|
||||
|
||||
> **libpam.so**.0 => /lib64/libpam.so.0 (0x00007fcc4afe6000)
|
||||
|
||||
This would indicate that the program loads code from "/lib64/libpam.so.0", and does indeed make use of PAM.
|
||||
|
||||
PAM configuration is located in /etc/pam.d. Take a look at which programs currently have pam configuration files:
|
||||
|
||||
```bash
|
||||
ls /etc/pam.d
|
||||
```
|
||||
|
||||
Depending on what is installed on the system, there will be a few configuration files. Each file contains a PAM configuration for the program it is named after. If a PAM-aware program does not have a configuration file the "other" file is used, which should deny access by default.
|
||||
|
||||
View the "other" file:
|
||||
|
||||
```bash
|
||||
less /etc/pam.d/other
|
||||
```
|
||||
|
||||
{width="3.53125in" height="2.0416666666666665in"}
|
||||
|
||||
The output contains instructions to log the attempt to Syslog (which is what pam\_warn.so does) and deny access (using pam\_deny.so) any attempt to authenticate (the lines starting with "auth"), request access to anything (account), change passwords (password), or starting a session (session).
|
||||
|
||||
The syntax of the configuration file is that each line starts with is typically:
|
||||
|
||||
> *type control module-path module-arguments*
|
||||
|
||||
The type is auth, password, account or session. The control (such as "required" or "optional") defines whether the module needs to pass or not before moving on to the next module, then the module name is defined. It is not shown in this example, but the module-path can be followed with some settings for the module.
|
||||
|
||||
All the modules for a type (such as auth) are called a module stack. When the program requests PAM perform authentication each of the auth modules in the module stack are run in the order they appear. If a "required" module fails, the authentication process tries the next module to see if it passes, if no required modules pass, then the authentication fails. Note that in the example above, pam\_warn.so returns "PAM\_IGNORE". Therefore the next module pam\_deny.so is started, which returns an error, and the authentication fails.
|
||||
|
||||
Possible control values include:
|
||||
|
||||
> **required**
|
||||
>
|
||||
> failure of such a PAM will ultimately lead to the PAM-API returning failure but only after the remaining stacked modules (for this service and type) have been invoked.
|
||||
>
|
||||
> **requisite**
|
||||
>
|
||||
> like required, however, in the case that such a module returns a failure, control is directly returned to the application.
|
||||
>
|
||||
> **sufficient**
|
||||
>
|
||||
> success of such a module is enough to satisfy the authentication requirements of the stack of modules (if a prior required module has failed the success of this one is ignored). A failure of this module is not deemed as fatal to satisfying the application that this type has succeeded. If the module succeeds the PAM framework returns success to the application immediately without trying any other modules.
|
||||
>
|
||||
> **optional**
|
||||
>
|
||||
> the success or failure of this module is only important if it is the only module in the stack associated with this service+type.
|
||||
>
|
||||
> **include**
|
||||
>
|
||||
> include all lines of given type from the configuration file specified as an argument to this control.
|
||||
>
|
||||
> -- from the man page for pam.conf
|
||||
|
||||
There is also a more complex rule syntax available, described in the man page.
|
||||
|
||||
Information about each module is available in The Linux-PAM System Administrators' Guide:
|
||||
|
||||
> [*http://linux-pam.org/Linux-PAM-html/Linux-PAM\_SAG.html*](http://linux-pam.org/Linux-PAM-html/Linux-PAM_SAG.html)
|
||||
|
||||
Look at which authentication methods are used by passwd:
|
||||
|
||||
```bash
|
||||
less /etc/pam.d/passwd
|
||||
```
|
||||
|
||||
Note that this indicates that PAM will apply the rules in "/etc/pam.d/common-auth", "common-account", "common-password", and "common-session" for the passwd program.
|
||||
|
||||
Edit the rules in common-password:
|
||||
|
||||
```bash
|
||||
sudo vi /etc/pam.d/common-password
|
||||
```
|
||||
|
||||
Edit the line (adding "minlen=10" to the end of the line):
|
||||
|
||||
> password requisite pam\_cracklib.so **minlen=10**
|
||||
|
||||
**Reminder**: Vi is 'modal': it has an insert mode, where you can type text into the file, and normal mode, where what you type is interpreted as commands. Press the "i" key to enter "insert mode". Type your changes to the file, then exit back to "normal mode" by pressing the Esc key. Now to exit and save the file press the ":" key, followed by "wq" (write quit), and press Enter.
|
||||
|
||||
Change a password using passwd.
|
||||
|
||||
Confirm that normal users can no longer use a password that is less than 10 characters long.
|
||||
|
||||
View the man page for this PAM module[^1]:
|
||||
|
||||
```bash
|
||||
man pam_cracklib
|
||||
```
|
||||
|
||||
Based on the options described in the man page, configure the pam\_cracklib module to require at least one non-alphanumeric character.
|
||||
|
||||
Confirm that normal users can no longer use passwords that contain only alphanumeric characters.
|
||||
|
||||
Note that there is likely no lockout for failed password attempts when using su to change user. Confirm this by running this command a few times:
|
||||
|
||||
```bash
|
||||
su - student; su - student; su - student; su - student;
|
||||
```
|
||||
|
||||
When prompted each time, enter an incorrect password.
|
||||
|
||||
Now, let's assume our aim is to add a 5 minute lockout time for when a user enters the wrong password 3 times in a row when using "su". Log-tally lockouts can be achieved using pam\_tally2.
|
||||
|
||||
View the man page for this PAM module:
|
||||
|
||||
```bash
|
||||
man pam\_tally2
|
||||
```
|
||||
|
||||
Edit /etc/pam.d/su-l, and insert this line as the first module (after the comment at the start of the file):
|
||||
|
||||
auth required pam\_tally2.so deny=3 unlock\_time=300
|
||||
|
||||
Verify that this change has been successful by running the following command again:
|
||||
|
||||
```bash
|
||||
su - student; su - student; su - student; su - student;
|
||||
```
|
||||
|
||||
Enter the wrong password the first 3 times, and then the correct password on the 4th attempt.
|
||||
|
||||
Create a new user named "dropbear".
|
||||
|
||||
Finally, apply what you have learned to **configure PAM to only allow:**
|
||||
|
||||
- **The user "dropbear" to login between 9am and 5pm**
|
||||
|
||||
- **And only on a Tuesday**
|
||||
|
||||
For testing purposes add another rule that allows a user to log in only 10 minutes from the current time
|
||||
|
||||
> Hint: use pam\_time.so and edit /etc/security/time.conf (and read the documentation in the configuration file to figure out how to set the correct limits)
|
||||
>
|
||||
> Another hint: try the "account" type.
|
||||
|
||||
Configure a cron job to force the user to logout at the end of their allowed time
|
||||
|
||||
> Hint: as root, "crontab -e" and add a job to run at 5pm on Tuesday killing all of their processes
|
||||
>
|
||||
> For example, to disconnect dropbear on Wednesday at 4pm, add this line to cron (run "crontab -e", then press "i" to add):
|
||||
>
|
||||
> 00 16 \* root \* wed skill-KILL-u dropbear
|
||||
>
|
||||
> Try to figure out how to also send a warning to the user 10 minutes before they are kicked off (Hint: add another cron job, you could send a message via "wall", etc)
|
||||
|
||||
### securetty and security
|
||||
|
||||
Backup the "securetty" file, which specifies which virtual terminals root is allowed to login to:
|
||||
|
||||
```bash
|
||||
cp /etc/securetty /etc/securetty.backup
|
||||
```
|
||||
|
||||
Edit /etc/securetty and place a "\#" in front of "tty3"
|
||||
|
||||
Press Ctrl-Alt-F3 and try to login as root
|
||||
|
||||
Press Ctrl-Alt-F4 and try to login as root
|
||||
|
||||
Press Ctrl-Alt-F7 to return to the desktop
|
||||
|
||||
### Conclusion
|
||||
|
||||
At this point you have:
|
||||
|
||||
- Applied authentication concepts to Unix/Linux
|
||||
|
||||
- Experimented with user accounts and identity
|
||||
|
||||
- Experimented with one-way hash functions, salts, and password storage
|
||||
|
||||
- Cracked passwords with low entropy using dictionary attacks
|
||||
|
||||
- Configured PAM to apply various authentication techniques to programs such as passwd
|
||||
|
||||
Well done!
|
||||
|
||||
[^1]: Yes, this makes it a "Pluggable Authentication Modules module", an unfortunate redundancy...
|
||||
@@ -1,5 +0,0 @@
|
||||
## Resources
|
||||
|
||||
An excellent resource on the subject of integrity management is Chapter 20 of the excellent book *Practical Unix & Internet Security, 3rd Ed*, by Garfinkel et al (2003).
|
||||
|
||||
Bind mounting: [http://lwn.net/Articles/281157/](http://lwn.net/Articles/281157/)
|
||||
@@ -3,14 +3,16 @@ require_relative '../../../../../../lib/objects/local_hackerbot_config_generator
|
||||
|
||||
class HB < HackerbotConfigGenerator
|
||||
|
||||
attr_accessor :server_ip
|
||||
|
||||
def initialize
|
||||
super
|
||||
self.module_name = 'Hackerbot Config Generator Integrity'
|
||||
self.title = 'Integrity management: protecting integrity'
|
||||
self.module_name = 'Hackerbot Config Generator Authentication'
|
||||
self.title = 'Authentication'
|
||||
|
||||
self.local_dir = File.expand_path('../../',__FILE__)
|
||||
self.templates_path = "#{self.local_dir}/templates/"
|
||||
self.config_template_path = "#{self.local_dir}/templates/integrity_lab.xml.erb"
|
||||
self.config_template_path = "#{self.local_dir}/templates/lab.xml.erb"
|
||||
self.html_template_path = "#{self.local_dir}/templates/labsheet.html.erb"
|
||||
|
||||
self.server_ip = []
|
||||
@@ -28,10 +28,6 @@
|
||||
|
||||
<default_input into="flags">
|
||||
<generator type="flag_generator"/>
|
||||
<generator type="flag_generator"/>
|
||||
<generator type="flag_generator"/>
|
||||
<generator type="flag_generator"/>
|
||||
<generator type="flag_generator"/>
|
||||
</default_input>
|
||||
|
||||
<default_input into="root_password">
|
||||
@@ -0,0 +1,299 @@
|
||||
# Authentication
|
||||
|
||||
## Getting started
|
||||
### VMs in this lab
|
||||
|
||||
==Start these VMs== (if you haven't already):
|
||||
- hackerbot_server (leave it running, you don't log into this)
|
||||
- desktop (you can sudo to get superuser access)
|
||||
- server (<%= $server_ip %>, you can ssh to this machine, but you don't have superuser access)
|
||||
- kali_cracker (you will use this to crack the hashes you find)
|
||||
|
||||
### Your login details for the "desktop" and "server" VMs
|
||||
User: <%= $main_user %>
|
||||
Password: tiaspbiqe2r (**t**his **i**s **a** **s**ecure **p**assword **b**ut **i**s **q**uite **e**asy **2** **r**emember)
|
||||
|
||||
You won't login to the hackerbot_server, but the VM needs to be running to complete the lab.
|
||||
|
||||
### For marks in the module
|
||||
1. **You need to submit flags**. Note that the flags and the challenges in your VMs are different to other's in the class. Flags will be revealed to you as you complete challenges throughout the module. Flags look like this: ==flag{*somethingrandom*}==. Follow the link on the module page to submit your flags.
|
||||
2. **You need to document the work and your solutions in a Log Book**. This needs to include screenshots (including the flags) of how you solved each Hackerbot challenge and a writeup describing your solution to each challenge, and answering any "Log Book Questions". The Log Book will be submitted later in the semester.
|
||||
|
||||
## Meet Hackerbot!
|
||||

|
||||
|
||||
This exercise involves interacting with Hackerbot, a chatbot who will attack your system. If you satisfy Hackerbot by completing the challenges she will reveal flags to you.
|
||||
|
||||
**On the desktop VM:**
|
||||
|
||||
==Open Pidgin and send some messages to Hackerbot:==
|
||||
|
||||
- Try asking Hackerbot some questions
|
||||
- Send "help"
|
||||
- Send "list"
|
||||
- Send "hello"
|
||||
|
||||
> If Hackerbot seems to be waiting or halted, simply say 'hi'
|
||||
|
||||
Work through the below exercises, completing the Hackerbot challenges as noted.
|
||||
|
||||
---
|
||||
|
||||
## Introduction to authentication
|
||||
|
||||
Authentication plays the important role of verifying an identity. For example, when someone gets into an airplane, sits down at a computer, picks up a mobile device, or uses a website, authentication is what is used to confirm that the person is who they claim to be. Authentication is an important first step *before* deciding how the system should act and what to allow.
|
||||
|
||||
## Identity: users and groups
|
||||
|
||||
Most computer systems have the concept of a user account. Although some devices such as mobile phones typically only have one user account, most modern computers can support having multiple users, each with their own identity. For example, a computer can have a separate account for each person that uses it, and if configured to do so may enable each user to have their own account preferences, and access to different resources.
|
||||
|
||||
On Unix/Linux systems every user account is identified by a user ID number (UID), which is a 32-bit integer (whole number), and can have one or more user names, which are human readable strings of text.
|
||||
|
||||
**On the desktop VM:**
|
||||
|
||||
Open a terminal console.
|
||||
|
||||
Assuming you have already logged in, you have already authenticated yourself on this system.
|
||||
|
||||
==Log Book Question: When and how did you authenticate yourself?==
|
||||
|
||||
Use these commands to find out about your current identity (or more accurately the identity of the software you are interacting with):
|
||||
|
||||
```bash
|
||||
whoami
|
||||
|
||||
groups
|
||||
|
||||
id
|
||||
```
|
||||
|
||||
==Make a note of your UID and username.==
|
||||
|
||||
Note that your account is also a member of one or more groups. A primary group, and a list of other groups. Some Linux systems, such as Debian, create a new seperate primary group for each user, others such as openSUSE have a shared group (named "users") that all normal users are a member of. Similar to the relationship between user names and UIDs, each group has a group name, and a group ID (GID).
|
||||
|
||||
Information about user accounts is stored in the /etc/passwd file, which typically all users can read.
|
||||
|
||||
==View the /etc/passwd file:==
|
||||
|
||||
```bash
|
||||
less /etc/passwd
|
||||
```
|
||||
|
||||
==Find the line that describes your user account.==
|
||||
|
||||
This line defines the username, password (well, it used to be stored here... we will come back to this), UID, primary group GID, full name, home directory, and shell for your account.
|
||||
|
||||
Confirm this matches the information you recorded earlier.
|
||||
|
||||
==Find the line that describes the root user account.==
|
||||
|
||||
==Where is the root user's home directory?==
|
||||
|
||||
> Press 'q' to quit less.
|
||||
|
||||
==View the /etc/group file:==
|
||||
|
||||
```bash
|
||||
less /etc/group
|
||||
```
|
||||
|
||||
Groups are defined in this file, along with which users are members.
|
||||
|
||||
==Which users are members of the audio group?==
|
||||
|
||||
Remember, primary groups do not appear in this file; for example, on openSUSE the "users" group, which all normal users are a member of, may not appear in the /etc/group file.
|
||||
|
||||
The "su" program can be used to run a program (usually a shell; that is, a command prompt) as another user, effectively enabling users to switch between user accounts at the command prompt.
|
||||
|
||||
==Change your identity to root==. Run:
|
||||
|
||||
```bash
|
||||
su -
|
||||
```
|
||||
|
||||
Enter the root password.
|
||||
|
||||
Use these commands to ==find out about your new identity:==
|
||||
|
||||
```bash
|
||||
whoami
|
||||
|
||||
groups
|
||||
|
||||
id
|
||||
```
|
||||
|
||||
==What is the UID of root? What does this mean about this user?==
|
||||
|
||||
==Lab Book Question: What gives this user special privileges: the name of the account, or the UID?==
|
||||
|
||||
==Use the useradd command to create a new user account "fred"==
|
||||
|
||||
> Hint: refer to the man page for useradd, by running "man useradd".
|
||||
|
||||
==Set a password for the user fred.==
|
||||
|
||||
> Hint: `sudo passwd fred`
|
||||
|
||||
==Change identity to fred.==
|
||||
|
||||
> Hint: `su - fred`
|
||||
|
||||
==Run:(after su)==
|
||||
|
||||
```bash
|
||||
id
|
||||
```
|
||||
|
||||
==Compare the result to the previous output.==
|
||||
|
||||
==How does this compare to your other normal user account? What is different, and what about it is the same?==
|
||||
|
||||
Run the single command "id" as root:
|
||||
|
||||
```bash
|
||||
sudo id
|
||||
```
|
||||
|
||||
==Log Book Question: What is the difference between sudo and su? Which is most likely protect against accidental damage and also log the commands used?==
|
||||
|
||||
## Users and SSH
|
||||
|
||||
==Log in to the server via ssh:==
|
||||
|
||||
```bash
|
||||
ssh <%= $main_user %>@<%= $server_ip %>
|
||||
```
|
||||
|
||||
==Display details of all users logged on to the system:==
|
||||
|
||||
```bash
|
||||
who
|
||||
```
|
||||
|
||||
==List all the processes run by all users:==
|
||||
|
||||
```bash
|
||||
ps -eo user,comm
|
||||
```
|
||||
|
||||
==List all the processes running as root:==
|
||||
|
||||
```bash
|
||||
ps -o user,comm -u root
|
||||
```
|
||||
|
||||
==Run a command to list all the processes running as *your* normal user.==
|
||||
|
||||
==Lab Book Question: How is this server authenticating users? What user accounts exist?==
|
||||
|
||||
## Passwords, hashes and salt
|
||||
|
||||
Given that important security decisions are made based on the user accounts, it is important to authenticate users, to ensure that the subjects are associated with the correct identity.
|
||||
|
||||
==What are the kinds of factors that can be used to verify a user's identity? Hint: for example, "something they have".==
|
||||
|
||||
==Which category of authentication factors is a password considered to be?==
|
||||
|
||||
Originally passwords were stored "in the clear" (not enciphered). For example, Multics stored passwords in a file, and once at MIT a software bug caused the password file to be copied to the motd file (message of the day), which was printed every time anyone logged into the system. A solution is not to store the password in the clear. Instead a hash can be computed, using a one way hash function, and stored. When the user enters a password, a new hash is computed and compared to the original.
|
||||
|
||||
On Linux, the command "shasum" can be used to check the integrity of files (hash functions have many uses), and works on the same principle. We can use it to generate a hash for any given string, for example a password:
|
||||
|
||||
```bash
|
||||
shasum
|
||||
```
|
||||
|
||||
> Type "hello" without the quotes. Press Ctrl-D (which indicates "EOF"; that is, end of input).
|
||||
|
||||
Repeat the above, with the same password ("hello"), and with a slight difference ("hello.").
|
||||
|
||||
Are the outputs the same?
|
||||
|
||||
Are the different hashes similar?
|
||||
|
||||
Is this good? Why?
|
||||
|
||||
Which one-way hash function does the shasum program use? Would this be a good option for hashing passwords?
|
||||
|
||||
For password authentication, the hash still needs to be stored. On Unix, password hashes were once stored in the world-readable file /etc/passwd, now they are typically stored in /etc/shadow, which only root (the superuser) can access.
|
||||
|
||||
==View the shadow file:==
|
||||
|
||||
```bash
|
||||
sudo less /etc/shadow
|
||||
```
|
||||
|
||||
The format of the shadow file is:
|
||||
|
||||
> username:**password**:last-changed(since 1-1-1970):days-until-may-change:days-until-must-change:days-warning-notice:days-since-expired-account-disabled:date-disable:reserved-field
|
||||
|
||||
==Find the hash of your user account's password.==
|
||||
|
||||
> Exit less ("q").
|
||||
|
||||
Use the passwd command to ==change your password:==
|
||||
|
||||
```bash
|
||||
passwd
|
||||
```
|
||||
|
||||
> When prompted, enter a new password of your choosing.
|
||||
|
||||
View the shadow file, and confirm that the stored password has changed.
|
||||
|
||||
With reference to the shadow file, and the man page for crypt (Hint: "man crypt"), ==answer these Log Book questions==:
|
||||
|
||||
- On Linux, the password hash stored in /etc/shadow has a prefix that specifies the hash function used.\
|
||||
> ==What hash function is used for your password?==
|
||||
> Hint: the `hash-identifier` command line tool may also help.
|
||||
|
||||
- ==When was the root password last changed?==
|
||||
|
||||
- ==Do any accounts have a setting that will force a password change at a specific date?==
|
||||
|
||||
A salt is a random string, used as further input into a one-way hash function (concatenated to the password). The salt is typically stored along with the hash. As a result the same password will have different hashes, so long as the salt is different.
|
||||
|
||||
Why is that a good thing?
|
||||
|
||||
What kind of attack does a salt defend against?
|
||||
|
||||
What is the current salt for your account? Hint: it is stored after the second "\$".
|
||||
|
||||
## Password weaknesses
|
||||
|
||||
The strength of a password depends on its entropy: its degree of randomness. If a user chooses a word from a dictionary, it would not take long to attempt every dictionary word until finding one that results in the same hash.
|
||||
|
||||
Try your hand at cracking passwords using the Kali virtual machine.
|
||||
|
||||
**On your desktop VM:**
|
||||
Add some new users with these passwords:
|
||||
> Hello
|
||||
>
|
||||
> hellothere
|
||||
>
|
||||
> password1
|
||||
|
||||
**On your Kali VM:**
|
||||
==Use John the Ripper (or Johnny a GUI for the John the Ripper) to crack the passwords.==
|
||||
> Hint: `man john`, on the Kali Linux system.
|
||||
> You will need to combine the passwd and shadow files (manually or with the kali `unshadow` command.)
|
||||
|
||||
==Log Book Questions:==
|
||||
- Which passwords are cracked the fastest?
|
||||
|
||||
- How long did they take?
|
||||
|
||||
|
||||
## Conclusion
|
||||
|
||||
At this point you have:
|
||||
|
||||
- Applied authentication concepts to Unix/Linux
|
||||
|
||||
- Experimented with user accounts and identity
|
||||
|
||||
- Experimented with one-way hash functions, salts, and password storage
|
||||
|
||||
- Cracked passwords with low entropy using dictionary attacks
|
||||
|
||||
Well done!
|
||||
@@ -18,7 +18,7 @@
|
||||
$root_password = self.root_password
|
||||
$flags = self.flags
|
||||
|
||||
REQUIRED_FLAGS = 2
|
||||
REQUIRED_FLAGS = 1
|
||||
while $flags.length < REQUIRED_FLAGS
|
||||
$flags << "flag{#{SecureRandom.hex}}"
|
||||
Print.err "Warning: Not enough flags provided to hackerbot_config generator, some flags won't be tracked/marked!"
|
||||
@@ -45,7 +45,7 @@
|
||||
<messages>
|
||||
<show_attack_numbers />
|
||||
|
||||
<greeting>Hi there. I'm your boss of sorts. I need you to do some system adminstration for me and check the security of our server. Help out and I'll give you some flags.</greeting>
|
||||
<greeting>Hi there. Today I'm your boss of sorts. I need you to test the security of our server. Help out and I'll give you some flags.</greeting>
|
||||
|
||||
<!--Must provide alternatives for each message-->
|
||||
<say_ready>When you are ready, simply say 'ready'.</say_ready>
|
||||
@@ -95,21 +95,64 @@ Randomised instance generated by [SecGen](http://github.com/cliffe/SecGen) (<%=
|
||||
|
||||
</tutorial_info>
|
||||
|
||||
<attack>
|
||||
<% $rand_name1 = SecureRandom.hex(3)
|
||||
$flag1 = $flags.pop
|
||||
$flag2 = $flags.pop
|
||||
%>
|
||||
|
||||
<prompt>Create a list of the potentially trojanised executables on the compromised system, save to your Desktop VM in /home/<%= $main_user %>/evidence/<%= $rand_name1 %>. Use full pathnames, one per line.</prompt>
|
||||
<attack>
|
||||
<% $newuser = "user#{SecureRandom.hex(2)}" -%>
|
||||
|
||||
<prompt>Add a user to the system, named "<%= $newuser %>".</prompt>
|
||||
<post_command>grep <%= $newuser %> /etc/shadow; echo $?</post_command>
|
||||
|
||||
<condition>
|
||||
<output_matches>asdfasdf</output_matches>
|
||||
<message>:( Only include the programs that are typically found on a Linux system, but that seem to have been replaced with Trojans horses.</message>
|
||||
<output_matches>0</output_matches>
|
||||
<message>:) Well done! <%= $flags.pop %></message>
|
||||
<trigger_next_attack />
|
||||
</condition>
|
||||
<condition>
|
||||
<output_matches>1</output_matches>
|
||||
<message>:( It looks like you forgot to create the user?</message>
|
||||
</condition>
|
||||
<else_condition>
|
||||
<message>:( User not found</message>
|
||||
</else_condition>
|
||||
|
||||
</attack>
|
||||
|
||||
<attack>
|
||||
|
||||
<prompt>Add the new <%= $newuser %> user to the 'users' group.</prompt>
|
||||
<post_command>id <%= $newuser %> | grep users; echo $?</post_command>
|
||||
|
||||
<condition>
|
||||
<output_matches>0</output_matches>
|
||||
<message>:) Well done! <%= $flags.pop %></message>
|
||||
<trigger_next_attack />
|
||||
</condition>
|
||||
<condition>
|
||||
<output_matches>1</output_matches>
|
||||
<message>:( It looks like you forgot to add the user to the group?</message>
|
||||
</condition>
|
||||
<else_condition>
|
||||
<message>:( Group not found</message>
|
||||
</else_condition>
|
||||
|
||||
</attack>
|
||||
|
||||
<attack>
|
||||
|
||||
<prompt>Crack the passwords of the users on the desktop VM, and use those credentials to SSH to the server, where you will find flags (ssh username@<%= $server_ip %> for each username you crack the password for.) This is the end.</prompt>
|
||||
|
||||
<condition>
|
||||
<output_matches>.*</output_matches>
|
||||
<message>:)</message>
|
||||
<trigger_next_attack />
|
||||
</condition>
|
||||
<condition>
|
||||
<output_matches>.*</output_matches>
|
||||
<message>:)</message>
|
||||
<trigger_next_attack />
|
||||
</condition>
|
||||
<else_condition>
|
||||
<message>:( List is incomplete...</message>
|
||||
<message>:)</message>
|
||||
</else_condition>
|
||||
|
||||
</attack>
|
||||
@@ -29,10 +29,7 @@
|
||||
|
||||
<default_input into="flags">
|
||||
<generator type="flag_generator"/>
|
||||
<generator type="flag_generator"/>
|
||||
<generator type="flag_generator"/>
|
||||
<generator type="flag_generator"/>
|
||||
<generator type="flag_generator"/>
|
||||
|
||||
</default_input>
|
||||
|
||||
<default_input into="root_password">
|
||||
@@ -41,4 +38,4 @@
|
||||
|
||||
<output_type>hackerbot</output_type>
|
||||
|
||||
</generator>
|
||||
</generator>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
include kali_forensic::install
|
||||
@@ -0,0 +1,5 @@
|
||||
class kali_forensic::install{
|
||||
package { ['kali-linux-forensic']:
|
||||
ensure => 'installed',
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<utility xmlns="http://www.github/cliffe/SecGen/utility"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/utility">
|
||||
<name>Kali Linux Metapackage: kali-linux-forensic</name>
|
||||
<author>Z. Cliffe Schreuders</author>
|
||||
<module_license>GPLv3</module_license>
|
||||
<description>Installs a collection of software onto Kali.
|
||||
kali-linux-forensic
|
||||
If you are doing forensics work, you don’t want your analysis system to contain a bunch of unnecessary tools. To the rescue comes the kali-linux-forensic metapackage, which only contains the forensics tools in Kali.
|
||||
Installation Size: 3.1 GB</description>
|
||||
|
||||
<type>attack_tools</type>
|
||||
<platform>linux</platform>
|
||||
|
||||
<requires>
|
||||
<name>Kali Light.*</name>
|
||||
<type>attack</type>
|
||||
<type>desktop</type>
|
||||
</requires>
|
||||
<requires>
|
||||
<type>update</type>
|
||||
</requires>
|
||||
</utility>
|
||||
@@ -0,0 +1 @@
|
||||
include kali_full::install
|
||||
@@ -0,0 +1,5 @@
|
||||
class kali_full::install{
|
||||
package { ['kali-linux-full']:
|
||||
ensure => 'installed',
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<utility xmlns="http://www.github/cliffe/SecGen/utility"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/utility">
|
||||
<name>Kali Linux Metapackage: kali-linux-full</name>
|
||||
<author>Z. Cliffe Schreuders</author>
|
||||
<module_license>GPLv3</module_license>
|
||||
<description>Installs a collection of software onto Kali.
|
||||
kali-linux-full
|
||||
When you download a Kali Linux ISO, you are essentially downloading an installation that has the kali-linux-full metapackage installed. This package includes all of the tools you are familiar with in Kali.
|
||||
Installation Size: 9.0 GB</description>
|
||||
|
||||
<type>attack_tools</type>
|
||||
<platform>linux</platform>
|
||||
|
||||
<requires>
|
||||
<name>Kali Light.*</name>
|
||||
<type>attack</type>
|
||||
<type>desktop</type>
|
||||
</requires>
|
||||
<requires>
|
||||
<type>update</type>
|
||||
</requires>
|
||||
</utility>
|
||||
@@ -0,0 +1 @@
|
||||
include kali_pwtools::install
|
||||
@@ -0,0 +1,5 @@
|
||||
class kali_pwtools::install{
|
||||
package { ['kali-linux-pwtools']:
|
||||
ensure => 'installed',
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<utility xmlns="http://www.github/cliffe/SecGen/utility"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/utility">
|
||||
<name>Kali Linux Metapackage: kali-linux-pwtools</name>
|
||||
<author>Z. Cliffe Schreuders</author>
|
||||
<module_license>GPLv3</module_license>
|
||||
<description>Installs a collection of software onto Kali.
|
||||
kali-linux-pwtools
|
||||
The kali-linux-pwtools metapackage contains over 40 different password cracking utilities as well as the GPU tools contained in kali-linux-gpu.
|
||||
Installation Size: 6.0 GB</description>
|
||||
|
||||
<type>attack_tools</type>
|
||||
<platform>linux</platform>
|
||||
|
||||
<requires>
|
||||
<name>Kali Light.*</name>
|
||||
<type>attack</type>
|
||||
<type>desktop</type>
|
||||
</requires>
|
||||
<requires>
|
||||
<type>update</type>
|
||||
</requires>
|
||||
</utility>
|
||||
@@ -0,0 +1 @@
|
||||
include kali_top10::install
|
||||
@@ -0,0 +1,5 @@
|
||||
class kali_top10::install{
|
||||
package { ['kali-linux-top10']:
|
||||
ensure => 'installed',
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<utility xmlns="http://www.github/cliffe/SecGen/utility"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/utility">
|
||||
<name>Kali Linux Metapackage: kali-linux-top10</name>
|
||||
<author>Z. Cliffe Schreuders</author>
|
||||
<module_license>GPLv3</module_license>
|
||||
<description>Installs a collection of software onto Kali.
|
||||
kali-linux-top10
|
||||
In Kali Linux, we have a sub-menu called “Top 10 Security Tools”. The kali-linux-top10 metapackage will install all of these tools for you in one fell swoop.
|
||||
Installation Size: 3.5 GB</description>
|
||||
|
||||
<type>attack_tools</type>
|
||||
<platform>linux</platform>
|
||||
|
||||
<requires>
|
||||
<name>Kali Light.*</name>
|
||||
<type>attack</type>
|
||||
<type>desktop</type>
|
||||
</requires>
|
||||
<requires>
|
||||
<type>update</type>
|
||||
</requires>
|
||||
</utility>
|
||||
@@ -0,0 +1 @@
|
||||
include kali_web::install
|
||||
@@ -0,0 +1,5 @@
|
||||
class kali_web::install{
|
||||
package { ['kali-linux-web']:
|
||||
ensure => 'installed',
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<utility xmlns="http://www.github/cliffe/SecGen/utility"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/utility">
|
||||
<name>Kali Linux Metapackage: kali-linux-web</name>
|
||||
<author>Z. Cliffe Schreuders</author>
|
||||
<module_license>GPLv3</module_license>
|
||||
<description>Installs a collection of software onto Kali.
|
||||
kali-linux-web
|
||||
Web application assessments are very common in the field of penetration testing and for this reason, Kali includes the kali-linux-web metapackage containing dozens of tools related to web application hacking.
|
||||
Installation Size: 4.9 GB</description>
|
||||
|
||||
<type>attack_tools</type>
|
||||
<platform>linux</platform>
|
||||
|
||||
<requires>
|
||||
<name>Kali Light.*</name>
|
||||
<type>attack</type>
|
||||
<type>desktop</type>
|
||||
</requires>
|
||||
<requires>
|
||||
<type>update</type>
|
||||
</requires>
|
||||
</utility>
|
||||
@@ -1,12 +1,12 @@
|
||||
#!/bin/bash
|
||||
: <<'END'
|
||||
This software was created by United States Government employees at
|
||||
The Center for the Information Systems Studies and Research (CISR)
|
||||
at the Naval Postgraduate School NPS. Please note that within the
|
||||
United States, copyright protection is not available for any works
|
||||
created by United States Government employees, pursuant to Title 17
|
||||
United States Code Section 105. This software is in the public
|
||||
domain and is not subject to copyright.
|
||||
This software was created by United States Government employees at
|
||||
The Center for the Information Systems Studies and Research (CISR)
|
||||
at the Naval Postgraduate School NPS. Please note that within the
|
||||
United States, copyright protection is not available for any works
|
||||
created by United States Government employees, pursuant to Title 17
|
||||
United States Code Section 105. This software is in the public
|
||||
domain and is not subject to copyright.
|
||||
END
|
||||
#
|
||||
#Install Docker on a Debian system, along with other packages required by Labtainers
|
||||
@@ -15,9 +15,9 @@ type sudo >/dev/null 2>&1 || { echo >&2 "Please install sudo. Aborting."; exit
|
||||
sudo -v || { echo >&2 "Please make sure user is sudoer. Aborting."; exit 1; }
|
||||
#needed packages for Docker install
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common
|
||||
sudo apt-get -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common
|
||||
|
||||
#adds Docker<65>s official GPG Key
|
||||
#adds Docker<65>s official GPG Key
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
|
||||
|
||||
#used to verify matching Key ID (optional)
|
||||
@@ -28,7 +28,8 @@ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debi
|
||||
|
||||
#installs Docker:Community Edition
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install docker-ce
|
||||
# SecGen change: repo is unauthenticated
|
||||
sudo apt-get -y --allow-unauthenticated install docker-ce
|
||||
|
||||
#gives user access to docker commands
|
||||
sudo groupadd docker
|
||||
@@ -39,8 +40,8 @@ sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
|
||||
#additional packages needed for labtainers
|
||||
sudo apt-get -y install python-pip
|
||||
sudo pip install --upgrade pip
|
||||
sudo apt-get -y install python-pip
|
||||
sudo pip install --upgrade pip
|
||||
sudo pip install netaddr parse python-dateutil
|
||||
sudo apt-get -y install openssh-server
|
||||
|
||||
@@ -54,10 +55,10 @@ do
|
||||
packagecheck=$(dpkg -s $i 2> /dev/null | grep Status)
|
||||
#echo $packagecheck
|
||||
if [ "$packagecheck" != "Status: install ok installed" ]; then
|
||||
if [ $i = docker-ce ];then
|
||||
if [ $i = docker-ce ];then
|
||||
echo "ERROR: '$i' package did not install properly. Please check the terminal output above for any errors related to the pacakge installation. Run the install script two more times. If the issue persists, go to docker docs and follow the instructions for installing docker. (Make sure the instructions is CE and is for your Linux distribution,e.g., Ubuntu and Fedora.)"
|
||||
else
|
||||
echo "ERROR: '$i' package did not install properly. Please check the terminal output above for any errors related to the pacakge installation. Try installing the '$i' package individually by executing this in the command line: 'sudo apt-get install $i"
|
||||
echo "ERROR: '$i' package did not install properly. Please check the terminal output above for any errors related to the pacakge installation. Try installing the '$i' package individually by executing this in the command line: 'sudo apt-get install $i"
|
||||
fi
|
||||
packagefail="true"
|
||||
#echo $packagefail
|
||||
@@ -86,4 +87,4 @@ fi
|
||||
|
||||
exit 0
|
||||
|
||||
#Notes: The <20>-y<> after each install means that the user doesn<73>t need to press <20>y<EFBFBD> in between each package download. The install script is based on this page: https://docs.docker.com/engine/installation/linux/docker-ce/debian/
|
||||
#Notes: The <20>-y<> after each install means that the user doesn<73>t need to press <20>y<EFBFBD> in between each package download. The install script is based on this page: https://docs.docker.com/engine/installation/linux/docker-ce/debian/
|
||||
|
||||
@@ -4,7 +4,7 @@ class labtainers::config{
|
||||
$secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file)
|
||||
$lab = $secgen_parameters['lab'][0]
|
||||
|
||||
exec { 'install script':
|
||||
exec { 'start lab':
|
||||
command => "/opt/labtainers/labtainer-student/labtainer $lab",
|
||||
provider => shell,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class hackerbot::install{
|
||||
class labtainers::install{
|
||||
# $json_inputs = base64('decode', $::base64_inputs)
|
||||
# $secgen_parameters = parsejson($json_inputs)
|
||||
# $server_ip = $secgen_parameters['server_ip'][0]
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
config/config.inc.php
|
||||
Dockerfile
|
||||
Dockerfile
|
||||
|
||||
# Vim swap files
|
||||
.*swp
|
||||
|
||||
@@ -12,7 +12,7 @@ Damn Vulnerable Web Application is damn vulnerable! **Do not upload it to your h
|
||||
|
||||
### Disclaimer
|
||||
|
||||
We do not take responsibility for the way in which any one uses this application (DVWA). We have made the purposes of the application clear and it should not be used maliciously. We have given warnings and taken measures to prevent users from installing DVWA on to live web servers. If your web server is compromised via an installation of DVWA it is not our responsibility it is the responsibility of the person/s who uploaded and installed it.
|
||||
We do not take responsibility for the way in which any one uses this application (DVWA). We have made the purposes of the application clear and it should not be used maliciously. We have given warnings and taken measures to prevent users from installing DVWA on to live web servers. If your web server is compromised via an installation of DVWA, it is not our responsibility, it is the responsibility of the person/s who uploaded and installed it.
|
||||
|
||||
- - -
|
||||
|
||||
@@ -37,8 +37,8 @@ along with Damn Vulnerable Web Application (DVWA). If not, see http://www.gnu.o
|
||||
## Download and install as a docker container
|
||||
- [dockerhub page](https://hub.docker.com/r/vulnerables/web-dvwa/)
|
||||
`docker run --rm -it -p 80:80 vulnerables/web-dvwa`
|
||||
|
||||
Please ensure you are using aufs due to previous MySQL issues. Run `docker info` to check your storage driver. If it isn't aufs, please change it as such. There are guides for each operating system on how to do that, but they're quite different so we won't cover that here.
|
||||
|
||||
Please ensure you are using aufs due to previous MySQL issues. Run `docker info` to check your storage driver. If it isn't aufs, please change it as such. There are guides for each operating system on how to do that, but they're quite different so we won't cover that here.
|
||||
|
||||
## Download
|
||||
|
||||
@@ -74,7 +74,7 @@ Simply unzip dvwa.zip, place the unzipped files in your public html folder, then
|
||||
|
||||
If you are using a Debian based Linux distribution, you will need to install the following packages _(or their equivalent)_:
|
||||
|
||||
`apt-get -y install apache2 mysql-server php php-mysqli php-gd libapache2-mod-php`
|
||||
`apt-get -y install apache2 mysql-server php php-mysqli php-gd libapache2-mod-php`
|
||||
|
||||
### Database Setup
|
||||
|
||||
@@ -84,30 +84,36 @@ If you receive an error while trying to create your database, make sure your dat
|
||||
|
||||
The variables are set to the following by default:
|
||||
|
||||
```php
|
||||
```php
|
||||
$_DVWA[ 'db_user' ] = 'root';
|
||||
$_DVWA[ 'db_password' ] = 'p@ssw0rd';
|
||||
$_DVWA[ 'db_database' ] = 'dvwa';
|
||||
```
|
||||
|
||||
Note, if you are using MariaDB rather than MySQL (MariaDB is default in Kali), then you can't use the database root user, you must create a new database user. To do this, connect to the database as the root user then use the following commands:
|
||||
|
||||
```mysql
|
||||
mysql> create database dvwa;
|
||||
Query OK, 1 row affected (0.00 sec)
|
||||
|
||||
mysql> grant all on dvwa.* to dvwa@localhost identified by 'xxx';
|
||||
Query OK, 0 rows affected, 1 warning (0.01 sec)
|
||||
|
||||
mysql> flush privileges;
|
||||
Query OK, 0 rows affected (0.00 sec)
|
||||
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
Note, if you are using MariaDB rather than MySQL (MariaDB is default in Kali), then you can't use the database root user, you must create a new database user. To do this, connect to the database as the root user then use the following commands:
|
||||
|
||||
```mysql
|
||||
mysql> create database dvwa;
|
||||
Query OK, 1 row affected (0.00 sec)
|
||||
|
||||
mysql> grant all on dvwa.* to dvwa@localhost identified by 'SuperSecretPassword99';
|
||||
Query OK, 0 rows affected, 1 warning (0.01 sec)
|
||||
|
||||
mysql> flush privileges;
|
||||
Query OK, 0 rows affected (0.00 sec)
|
||||
```
|
||||
|
||||
You will then need to update the config file, the new entries will look like this:
|
||||
|
||||
```php
|
||||
$_DVWA[ 'db_user' ] = 'dvwa';
|
||||
$_DVWA[ 'db_password' ] = 'SuperSecretPassword99';
|
||||
$_DVWA[ 'db_database' ] = 'dvwa';
|
||||
```
|
||||
|
||||
### Other Configuration
|
||||
|
||||
Depending on your Operating System as well as version of PHP, you may wish to alter the default configuration. The location of the files will be different on a per-machine basis.
|
||||
Depending on your Operating System, as well as version of PHP, you may wish to alter the default configuration. The location of the files will be different on a per-machine basis.
|
||||
|
||||
**Folder Permissions**:
|
||||
|
||||
@@ -143,7 +149,7 @@ https://github.com/ethicalhack3r/DVWA/issues
|
||||
|
||||
+Q. SQL Injection won't work on PHP v5.2.6.
|
||||
|
||||
-A.If you are using PHP v5.2.6 or above you will need to do the following in order for SQL injection and other vulnerabilities to work.
|
||||
-A.If you are using PHP v5.2.6 or above, you will need to do the following in order for SQL injection and other vulnerabilities to work.
|
||||
|
||||
In `.htaccess`:
|
||||
|
||||
@@ -171,6 +177,12 @@ With:
|
||||
|
||||
-A. Apache may not have high enough privileges to run commands on the web server. If you are running DVWA under Linux make sure you are logged in as root. Under Windows log in as Administrator.
|
||||
|
||||
+Q. Why can't the database connect on CentOS?
|
||||
|
||||
-A. You may be running into problems with SELinux. Either disable SELinux or run this command to allow the webserver to talk to the database:
|
||||
```
|
||||
setsebool -P httpd_can_network_connect_db 1
|
||||
```
|
||||
|
||||
- - -
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ $_DVWA[ 'db_port '] = '5432';
|
||||
|
||||
# ReCAPTCHA settings
|
||||
# Used for the 'Insecure CAPTCHA' module
|
||||
# You'll need to generate your own keys at: https://www.google.com/recaptcha/admin/create
|
||||
# You'll need to generate your own keys at: https://www.google.com/recaptcha/admin
|
||||
$_DVWA[ 'recaptcha_public_key' ] = '';
|
||||
$_DVWA[ 'recaptcha_private_key' ] = '';
|
||||
|
||||
|
||||
@@ -47,17 +47,14 @@ dvwaMessagePush( "'users' table was created." );
|
||||
|
||||
|
||||
// Insert some data into users
|
||||
// Get the base directory for the avatar media...
|
||||
$baseUrl = 'http://' . $_SERVER[ 'SERVER_NAME' ] . $_SERVER[ 'PHP_SELF' ];
|
||||
$stripPos = strpos( $baseUrl, 'setup.php' );
|
||||
$baseUrl = substr( $baseUrl, 0, $stripPos ) . 'hackable/users/';
|
||||
$avatarUrl = '/hackable/users/';
|
||||
|
||||
$insert = "INSERT INTO users VALUES
|
||||
('1','admin','admin','admin',MD5('password'),'{$baseUrl}admin.jpg', NOW(), '0'),
|
||||
('2','Gordon','Brown','gordonb',MD5('abc123'),'{$baseUrl}gordonb.jpg', NOW(), '0'),
|
||||
('3','Hack','Me','1337',MD5('charley'),'{$baseUrl}1337.jpg', NOW(), '0'),
|
||||
('4','Pablo','Picasso','pablo',MD5('letmein'),'{$baseUrl}pablo.jpg', NOW(), '0'),
|
||||
('5','Bob','Smith','smithy',MD5('password'),'{$baseUrl}smithy.jpg', NOW(), '0');";
|
||||
('1','admin','admin','admin',MD5('password'),'{$avatarUrl}admin.jpg', NOW(), '0'),
|
||||
('2','Gordon','Brown','gordonb',MD5('abc123'),'{$avatarUrl}gordonb.jpg', NOW(), '0'),
|
||||
('3','Hack','Me','1337',MD5('charley'),'{$avatarUrl}1337.jpg', NOW(), '0'),
|
||||
('4','Pablo','Picasso','pablo',MD5('letmein'),'{$avatarUrl}pablo.jpg', NOW(), '0'),
|
||||
('5','Bob','Smith','smithy',MD5('password'),'{$avatarUrl}smithy.jpg', NOW(), '0');";
|
||||
if( !mysqli_query($GLOBALS["___mysqli_ston"], $insert ) ) {
|
||||
dvwaMessagePush( "Data could not be inserted into 'users' table<br />SQL: " . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) );
|
||||
dvwaPageReload();
|
||||
|
||||
@@ -208,6 +208,8 @@ function dvwaHtmlEcho( $pPage ) {
|
||||
$menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'xss_d', 'name' => 'XSS (DOM)', 'url' => 'vulnerabilities/xss_d/' );
|
||||
$menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'xss_r', 'name' => 'XSS (Reflected)', 'url' => 'vulnerabilities/xss_r/' );
|
||||
$menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'xss_s', 'name' => 'XSS (Stored)', 'url' => 'vulnerabilities/xss_s/' );
|
||||
$menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'csp', 'name' => 'CSP Bypass', 'url' => 'vulnerabilities/csp/' );
|
||||
$menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'javascript', 'name' => 'JavaScript', 'url' => 'vulnerabilities/javascript/' );
|
||||
}
|
||||
|
||||
$menuBlocks[ 'meta' ] = array();
|
||||
@@ -229,7 +231,7 @@ function dvwaHtmlEcho( $pPage ) {
|
||||
foreach( $menuBlock as $menuItem ) {
|
||||
$selectedClass = ( $menuItem[ 'id' ] == $pPage[ 'page_id' ] ) ? 'selected' : '';
|
||||
$fixedUrl = DVWA_WEB_PAGE_TO_ROOT.$menuItem[ 'url' ];
|
||||
$menuBlockHtml .= "<li onclick=\"window.location='{$fixedUrl}'\" class=\"{$selectedClass}\"><a href=\"{$fixedUrl}\">{$menuItem[ 'name' ]}</a></li>\n";
|
||||
$menuBlockHtml .= "<li class=\"{$selectedClass}\"><a href=\"{$fixedUrl}\">{$menuItem[ 'name' ]}</a></li>\n";
|
||||
}
|
||||
$menuHtml .= "<ul class=\"menuBlocks\">{$menuBlockHtml}</ul>";
|
||||
}
|
||||
@@ -328,6 +330,7 @@ function dvwaHtmlEcho( $pPage ) {
|
||||
<div id=\"footer\">
|
||||
|
||||
<p>Damn Vulnerable Web Application (DVWA) v" . dvwaVersionGet() . "</p>
|
||||
<script src='" . DVWA_WEB_PAGE_TO_ROOT . "/dvwa/js/add_event_listeners.js'></script>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -425,13 +428,13 @@ function dvwaExternalLinkUrlGet( $pLink,$text=null ) {
|
||||
|
||||
function dvwaButtonHelpHtmlGet( $pId ) {
|
||||
$security = dvwaSecurityLevelGet();
|
||||
return "<input type=\"button\" value=\"View Help\" class=\"popup_button\" onclick=\"javascript:popUp( '" . DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/view_help.php?id={$pId}&security={$security}' )\">";
|
||||
return "<input type=\"button\" value=\"View Help\" class=\"popup_button\" id='help_button' data-help-url='" . DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/view_help.php?id={$pId}&security={$security}' )\">";
|
||||
}
|
||||
|
||||
|
||||
function dvwaButtonSourceHtmlGet( $pId ) {
|
||||
$security = dvwaSecurityLevelGet();
|
||||
return "<input type=\"button\" value=\"View Source\" class=\"popup_button\" onclick=\"javascript:popUp( '" . DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/view_source.php?id={$pId}&security={$security}' )\">";
|
||||
return "<input type=\"button\" value=\"View Source\" class=\"popup_button\" id='source_button' data-source-url='" . DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/view_source.php?id={$pId}&security={$security}' )\">";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// These functions need to be called after the content they reference
|
||||
// has been added to the page otherwise they will fail.
|
||||
|
||||
function addEventListeners() {
|
||||
var source_button = document.getElementById ("source_button");
|
||||
|
||||
if (source_button) {
|
||||
source_button.addEventListener("click", function() {
|
||||
var url=source_button.dataset.sourceUrl;
|
||||
popUp (url);
|
||||
});
|
||||
}
|
||||
|
||||
var help_button = document.getElementById ("help_button");
|
||||
|
||||
if (help_button) {
|
||||
help_button.addEventListener("click", function() {
|
||||
var url=help_button.dataset.helpUrl;
|
||||
popUp (url);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
addEventListeners();
|
||||
@@ -3,7 +3,8 @@
|
||||
function popUp(URL) {
|
||||
day = new Date();
|
||||
id = day.getTime();
|
||||
eval("page" + id + " = window.open(URL, '" + id + "', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=1,width=500,height=300,left = 540,top = 250');");
|
||||
window.open(URL, '" + id + "', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=1,width=800,height=300,left=540,top=250');
|
||||
//eval("page" + id + " = window.open(URL, '" + id + "', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=1,width=800,height=300,left=540,top=250');");
|
||||
}
|
||||
|
||||
/* Form validation */
|
||||
|
||||
290
modules/vulnerabilities/unix/web_training/dvwa/files/DVWA-master/external/recaptcha/recaptchalib.php
vendored
Executable file → Normal file
290
modules/vulnerabilities/unix/web_training/dvwa/files/DVWA-master/external/recaptcha/recaptchalib.php
vendored
Executable file → Normal file
@@ -1,279 +1,45 @@
|
||||
<?php
|
||||
/*
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
* - Documentation and latest version
|
||||
* http://recaptcha.net/plugins/php/
|
||||
* - Get a reCAPTCHA API Key
|
||||
* https://www.google.com/recaptcha/admin/create
|
||||
* - Discussion group
|
||||
* http://groups.google.com/group/recaptcha
|
||||
*
|
||||
* Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
|
||||
* AUTHORS:
|
||||
* Mike Crawford
|
||||
* Ben Maurer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The reCAPTCHA server URL's
|
||||
*/
|
||||
define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
|
||||
define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
|
||||
define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
|
||||
// new php7 captcha v2 implementation.
|
||||
|
||||
/**
|
||||
* Encodes the given data into a query string format
|
||||
* @param $data - array of string elements to be encoded
|
||||
* @return string - encoded request
|
||||
*/
|
||||
function _recaptcha_qsencode ($data) {
|
||||
$req = "";
|
||||
foreach ( $data as $key => $value )
|
||||
$req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
|
||||
|
||||
// Cut the last '&'
|
||||
$req=substr($req,0,strlen($req)-1);
|
||||
return $req;
|
||||
function recaptcha_check_answer($key, $response){
|
||||
return CheckCaptcha($key, $response);
|
||||
}
|
||||
|
||||
function CheckCaptcha($key, $response) {
|
||||
|
||||
try {
|
||||
$url = 'https://www.google.com/recaptcha/api/siteverify';
|
||||
$dat = array(
|
||||
'secret' => $key,
|
||||
'response' => urlencode($response),
|
||||
'remoteip' => urlencode($_SERVER['REMOTE_ADDR'])
|
||||
);
|
||||
|
||||
/**
|
||||
* Submits an HTTP POST to a reCAPTCHA server
|
||||
* @param string $host
|
||||
* @param string $path
|
||||
* @param array $data
|
||||
* @param int port
|
||||
* @return array response
|
||||
*/
|
||||
function _recaptcha_http_post($host, $path, $data, $port = 80) {
|
||||
$opt = array(
|
||||
'http' => array(
|
||||
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
|
||||
'method' => 'POST',
|
||||
'content' => http_build_query($dat)
|
||||
)
|
||||
);
|
||||
|
||||
$req = _recaptcha_qsencode ($data);
|
||||
$context = stream_context_create($opt);
|
||||
$result = file_get_contents($url, false, $context);
|
||||
|
||||
$http_request = "POST $path HTTP/1.0\r\n";
|
||||
$http_request .= "Host: $host\r\n";
|
||||
$http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
|
||||
$http_request .= "Content-Length: " . strlen($req) . "\r\n";
|
||||
$http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
|
||||
$http_request .= "\r\n";
|
||||
$http_request .= $req;
|
||||
return json_decode($result)->success;
|
||||
|
||||
$response = '';
|
||||
if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
|
||||
die ('Could not open socket');
|
||||
}
|
||||
|
||||
fwrite($fs, $http_request);
|
||||
|
||||
while ( !feof($fs) )
|
||||
$response .= fgets($fs, 1160); // One TCP-IP packet
|
||||
fclose($fs);
|
||||
$response = explode("\r\n\r\n", $response, 2);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the challenge HTML (javascript and non-javascript version).
|
||||
* This is called from the browser, and the resulting reCAPTCHA HTML widget
|
||||
* is embedded within the HTML form it was called from.
|
||||
* @param string $pubkey A public key for reCAPTCHA
|
||||
* @param string $error The error given by reCAPTCHA (optional, default is null)
|
||||
* @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
|
||||
|
||||
* @return string - The HTML to be embedded in the user's form.
|
||||
*/
|
||||
function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
|
||||
{
|
||||
|
||||
# commented out to deal with error in DVWA - ethicalhack3r
|
||||
#if ($pubkey == null || $pubkey == '') {
|
||||
# die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create' target='_blank'>https://www.google.com/recaptcha/admin/create</a>");
|
||||
#}
|
||||
|
||||
if ($use_ssl) {
|
||||
$server = RECAPTCHA_API_SECURE_SERVER;
|
||||
} else {
|
||||
$server = RECAPTCHA_API_SERVER;
|
||||
}
|
||||
|
||||
$errorpart = "";
|
||||
if ($error) {
|
||||
$errorpart = "&error=" . $error;
|
||||
}
|
||||
return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script>
|
||||
|
||||
<noscript>
|
||||
<iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
|
||||
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
|
||||
<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
|
||||
</noscript>';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A ReCaptchaResponse is returned from recaptcha_check_answer()
|
||||
*/
|
||||
class ReCaptchaResponse {
|
||||
var $is_valid;
|
||||
var $error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls an HTTP POST function to verify if the user's guess was correct
|
||||
* @param string $privkey
|
||||
* @param string $remoteip
|
||||
* @param string $challenge
|
||||
* @param string $response
|
||||
* @param array $extra_params an array of extra variables to post to the server
|
||||
* @return ReCaptchaResponse
|
||||
*/
|
||||
function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array())
|
||||
{
|
||||
if ($privkey == null || $privkey == '') {
|
||||
die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create' target='_blank'>https://www.google.com/recaptcha/admin/create</a>");
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($remoteip == null || $remoteip == '') {
|
||||
die ("For security reasons, you must pass the remote ip to reCAPTCHA");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//discard spam submissions
|
||||
if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
|
||||
$recaptcha_response = new ReCaptchaResponse();
|
||||
$recaptcha_response->is_valid = false;
|
||||
$recaptcha_response->error = 'incorrect-captcha-sol';
|
||||
return $recaptcha_response;
|
||||
}
|
||||
|
||||
$response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
|
||||
array (
|
||||
'privatekey' => $privkey,
|
||||
'remoteip' => $remoteip,
|
||||
'challenge' => $challenge,
|
||||
'response' => $response
|
||||
) + $extra_params
|
||||
);
|
||||
|
||||
$answers = explode ("\n", $response [1]);
|
||||
$recaptcha_response = new ReCaptchaResponse();
|
||||
|
||||
if (trim ($answers [0]) == 'true') {
|
||||
$recaptcha_response->is_valid = true;
|
||||
}
|
||||
else {
|
||||
$recaptcha_response->is_valid = false;
|
||||
$recaptcha_response->error = $answers [1];
|
||||
}
|
||||
return $recaptcha_response;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a URL where the user can sign up for reCAPTCHA. If your application
|
||||
* has a configuration page where you enter a key, you should provide a link
|
||||
* using this function.
|
||||
* @param string $domain The domain where the page is hosted
|
||||
* @param string $appname The name of your application
|
||||
*/
|
||||
function recaptcha_get_signup_url ($domain = null, $appname = null) {
|
||||
return "https://www.google.com/recaptcha/admin/create?" . _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname));
|
||||
function recaptcha_get_html($pubKey){
|
||||
return "
|
||||
<script src='https://www.google.com/recaptcha/api.js'></script>
|
||||
<br /> <div class='g-recaptcha' data-theme='dark' data-sitekey='" . $pubKey . "'></div>
|
||||
";
|
||||
}
|
||||
|
||||
function _recaptcha_aes_pad($val) {
|
||||
$block_size = 16;
|
||||
$numpad = $block_size - (strlen ($val) % $block_size);
|
||||
return str_pad($val, strlen ($val) + $numpad, chr($numpad));
|
||||
}
|
||||
|
||||
/* Mailhide related code */
|
||||
|
||||
function _recaptcha_aes_encrypt($val,$ky) {
|
||||
if (! function_exists ("mcrypt_encrypt")) {
|
||||
die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
|
||||
}
|
||||
$mode=MCRYPT_MODE_CBC;
|
||||
$enc=MCRYPT_RIJNDAEL_128;
|
||||
$val=_recaptcha_aes_pad($val);
|
||||
return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
|
||||
}
|
||||
|
||||
|
||||
function _recaptcha_mailhide_urlbase64 ($x) {
|
||||
return strtr(base64_encode ($x), '+/', '-_');
|
||||
}
|
||||
|
||||
/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
|
||||
function recaptcha_mailhide_url($pubkey, $privkey, $email) {
|
||||
if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
|
||||
die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
|
||||
"you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey' target='_blank'>http://www.google.com/recaptcha/mailhide/apikey</a>");
|
||||
}
|
||||
|
||||
|
||||
$ky = pack('H*', $privkey);
|
||||
$cryptmail = _recaptcha_aes_encrypt ($email, $ky);
|
||||
|
||||
return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the parts of the email to expose to the user.
|
||||
* eg, given johndoe@example,com return ["john", "example.com"].
|
||||
* the email is then displayed as john...@example.com
|
||||
*/
|
||||
function _recaptcha_mailhide_email_parts ($email) {
|
||||
$arr = preg_split("/@/", $email );
|
||||
|
||||
if (strlen ($arr[0]) <= 4) {
|
||||
$arr[0] = substr ($arr[0], 0, 1);
|
||||
} else if (strlen ($arr[0]) <= 6) {
|
||||
$arr[0] = substr ($arr[0], 0, 3);
|
||||
} else {
|
||||
$arr[0] = substr ($arr[0], 0, 4);
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets html to display an email address given a public an private key.
|
||||
* to get a key, go to:
|
||||
*
|
||||
* http://www.google.com/recaptcha/mailhide/apikey
|
||||
*/
|
||||
function recaptcha_mailhide_html($pubkey, $privkey, $email) {
|
||||
$emailparts = _recaptcha_mailhide_email_parts ($email);
|
||||
$url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
|
||||
|
||||
return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
|
||||
"' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
This level also extends on the medium level, by waiting when there is a failed login but this time it is a random amount of time between two and four seconds.
|
||||
The idea of this is to try and confuse any timing predictions.</p>
|
||||
|
||||
<p>Using a <?php echo dvwaExternalLinkUrlGet( 'http://www.captcha.net/', 'CAPTCHA' ); ?> form could have a similar effect as a CSRF token.</p>
|
||||
<p>Using a <?php echo dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/CAPTCHA', 'CAPTCHA' ); ?> form could have a similar effect as a CSRF token.</p>
|
||||
|
||||
<br />
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
if( isset( $_POST[ 'Login' ] ) ) {
|
||||
if( isset( $_POST[ 'Login' ] ) && isset ($_POST['username']) && isset ($_POST['password']) ) {
|
||||
// Check Anti-CSRF token
|
||||
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<tr>
|
||||
<td><div id="code">
|
||||
<h3>About</h3>
|
||||
<p>A <?php echo dvwaExternalLinkUrlGet( 'http://www.captcha.net/', 'CAPTCHA' ); ?> is a program that can tell whether its user is a human or a computer. You've probably seen
|
||||
<p>A <?php echo dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/CAPTCHA', 'CAPTCHA' ); ?> is a program that can tell whether its user is a human or a computer. You've probably seen
|
||||
them - colourful images with distorted text at the bottom of Web registration forms. CAPTCHAs are used by many websites to prevent abuse from
|
||||
"bots", or automated programs usually written to generate spam. No computer program can read distorted text as well as humans can, so bots
|
||||
cannot navigate sites protected by CAPTCHAs.</p>
|
||||
@@ -58,5 +58,5 @@
|
||||
|
||||
<br />
|
||||
|
||||
<p>Reference: <?php echo dvwaExternalLinkUrlGet( 'http://www.captcha.net/' ); ?></p>
|
||||
<p>Reference: <?php echo dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/CAPTCHA' ); ?></p>
|
||||
</div>
|
||||
|
||||
@@ -87,7 +87,7 @@ $page[ 'body' ] .= "
|
||||
|
||||
<h2>More Information</h2>
|
||||
<ul>
|
||||
<li>" . dvwaExternalLinkUrlGet( 'http://www.captcha.net/' ) . "</li>
|
||||
<li>" . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/CAPTCHA' ) . "</li>
|
||||
<li>" . dvwaExternalLinkUrlGet( 'https://www.google.com/recaptcha/' ) . "</li>
|
||||
<li>" . dvwaExternalLinkUrlGet( 'https://www.owasp.org/index.php/Testing_for_Captcha_(OWASP-AT-012)' ) . "</li>
|
||||
</ul>
|
||||
|
||||
@@ -9,21 +9,20 @@ if( isset( $_POST[ 'Change' ] ) ) {
|
||||
$pass_conf = $_POST[ 'password_conf' ];
|
||||
|
||||
// Check CAPTCHA from 3rd party
|
||||
$resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ],
|
||||
$_SERVER[ 'REMOTE_ADDR' ],
|
||||
$_POST[ 'recaptcha_challenge_field' ],
|
||||
$_POST[ 'recaptcha_response_field' ] );
|
||||
$resp = recaptcha_check_answer(
|
||||
$_DVWA[ 'recaptcha_private_key' ],
|
||||
$_POST['g-recaptcha-response']
|
||||
);
|
||||
|
||||
// Did the CAPTCHA fail?
|
||||
if( !$resp->is_valid && ( $_POST[ 'recaptcha_response_field' ] != 'hidd3n_valu3' || $_SERVER[ 'HTTP_USER_AGENT' ] != 'reCAPTCHA' ) ) {
|
||||
// What happens when the CAPTCHA was entered incorrectly
|
||||
$html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
|
||||
$hide_form = false;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (
|
||||
$resp ||
|
||||
(
|
||||
$_POST[ 'g-recaptcha-response' ] == 'hidd3n_valu3'
|
||||
&& $_SERVER[ 'HTTP_USER_AGENT' ] == 'reCAPTCHA'
|
||||
)
|
||||
){
|
||||
// CAPTCHA was correct. Do both new passwords match?
|
||||
if( $pass_new == $pass_conf ) {
|
||||
if ($pass_new == $pass_conf) {
|
||||
$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
|
||||
$pass_new = md5( $pass_new );
|
||||
|
||||
@@ -33,12 +32,18 @@ if( isset( $_POST[ 'Change' ] ) ) {
|
||||
|
||||
// Feedback for user
|
||||
$html .= "<pre>Password Changed.</pre>";
|
||||
}
|
||||
else {
|
||||
|
||||
} else {
|
||||
// Ops. Password mismatch
|
||||
$html .= "<pre>Both passwords must match.</pre>";
|
||||
$hide_form = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
// What happens when the CAPTCHA was entered incorrectly
|
||||
$html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
|
||||
$hide_form = false;
|
||||
return;
|
||||
}
|
||||
|
||||
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
|
||||
|
||||
@@ -24,13 +24,13 @@ if( isset( $_POST[ 'Change' ] ) ) {
|
||||
$pass_curr = md5( $pass_curr );
|
||||
|
||||
// Check CAPTCHA from 3rd party
|
||||
$resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ],
|
||||
$_SERVER[ 'REMOTE_ADDR' ],
|
||||
$_POST[ 'recaptcha_challenge_field' ],
|
||||
$_POST[ 'recaptcha_response_field' ] );
|
||||
$resp = recaptcha_check_answer(
|
||||
$_DVWA[ 'recaptcha_private_key' ],
|
||||
$_POST['g-recaptcha-response']
|
||||
);
|
||||
|
||||
// Did the CAPTCHA fail?
|
||||
if( !$resp->is_valid ) {
|
||||
if( !$resp ) {
|
||||
// What happens when the CAPTCHA was entered incorrectly
|
||||
$html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
|
||||
$hide_form = false;
|
||||
|
||||
@@ -9,13 +9,13 @@ if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {
|
||||
$pass_conf = $_POST[ 'password_conf' ];
|
||||
|
||||
// Check CAPTCHA from 3rd party
|
||||
$resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ],
|
||||
$_SERVER[ 'REMOTE_ADDR' ],
|
||||
$_POST[ 'recaptcha_challenge_field' ],
|
||||
$_POST[ 'recaptcha_response_field' ] );
|
||||
$resp = recaptcha_check_answer(
|
||||
$_DVWA[ 'recaptcha_private_key'],
|
||||
$_POST['g-recaptcha-response']
|
||||
);
|
||||
|
||||
// Did the CAPTCHA fail?
|
||||
if( !$resp->is_valid ) {
|
||||
if( !$resp ) {
|
||||
// What happens when the CAPTCHA was entered incorrectly
|
||||
$html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
|
||||
$hide_form = false;
|
||||
|
||||
@@ -9,13 +9,13 @@ if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {
|
||||
$pass_conf = $_POST[ 'password_conf' ];
|
||||
|
||||
// Check CAPTCHA from 3rd party
|
||||
$resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ],
|
||||
$_SERVER[ 'REMOTE_ADDR' ],
|
||||
$_POST[ 'recaptcha_challenge_field' ],
|
||||
$_POST[ 'recaptcha_response_field' ] );
|
||||
$resp = recaptcha_check_answer(
|
||||
$_DVWA[ 'recaptcha_private_key' ],
|
||||
$_POST['g-recaptcha-response']
|
||||
);
|
||||
|
||||
// Did the CAPTCHA fail?
|
||||
if( !$resp->is_valid ) {
|
||||
if( !$resp ) {
|
||||
// What happens when the CAPTCHA was entered incorrectly
|
||||
$html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
|
||||
$hide_form = false;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<div class="body_padded">
|
||||
<h1>Help - Content Security Policy (CSP) Bypass</h1>
|
||||
|
||||
<div id="code">
|
||||
<table width='100%' bgcolor='white' style="border:2px #C0C0C0 solid">
|
||||
<tr>
|
||||
<td><div id="code">
|
||||
<h3>About</h3>
|
||||
<p>Content Security Policy (CSP) is used to define where scripts and other resources can be loaded or executed from. This module will walk you through ways to bypass the policy based on common mistakes made by developers.</p>
|
||||
<p>None of the vulnerabilities are actual vulnerabilities in CSP, they are vulnerabilities in the way it has been implemented.</p>
|
||||
|
||||
<br /><hr /><br />
|
||||
|
||||
<h3>Objective</h3>
|
||||
<p>Bypass Content Security Policy (CSP) and execute JavaScript in the page.</p>
|
||||
|
||||
<br /><hr /><br />
|
||||
|
||||
<h3>Low Level</h3>
|
||||
<p>Examine the policy to find all the sources that can be used to host external script files.</p>
|
||||
<pre>Spoiler: <span class="spoiler">Scripts can be included from Pastebin, try storing some JavaScript on there and then loading it in.</span></pre>
|
||||
|
||||
<br />
|
||||
|
||||
<h3>Medium Level</h3>
|
||||
<p>The CSP policy tries to use a nonce to prevent inline scripts from being added by attackers.</p>
|
||||
<pre>Spoiler: <span class="spoiler">Examine the nonce and see how it varies (or doesn't).</span></pre>
|
||||
|
||||
<br />
|
||||
|
||||
<h3>High Level</h3>
|
||||
<p>The page makes a JSONP call to source/jsonp.php passing the name of the function to callback to, you need to modify the jsonp.php script to change the callback function.</p>
|
||||
<pre>Spoiler: <span class="spoiler">The JavaScript on the page will execute whatever is returned by the page, changing this to your own code will execute that instead</span></pre>
|
||||
|
||||
<br />
|
||||
|
||||
<h3>Impossible Level</h3>
|
||||
<p>
|
||||
This level is an update of the high level where the JSONP call has its callback function hardcoded and the CSP policy is locked down to only allow external scripts.
|
||||
</p>
|
||||
</div></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<p>Reference: <?php echo dvwaExternalLinkUrlGet( 'https://content-security-policy.com/', "Content Security Policy Reference" ); ?></p>
|
||||
<p>Reference: <?php echo dvwaExternalLinkUrlGet( 'https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP', "Mozilla Developer Network - CSP: script-src"); ?></p>
|
||||
<p>Reference: <?php echo dvwaExternalLinkUrlGet( 'https://blog.mozilla.org/security/2014/10/04/csp-for-the-web-we-have/', "Mozilla Security Blog - CSP for the web we have" ); ?></p>
|
||||
</div>
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
define( 'DVWA_WEB_PAGE_TO_ROOT', '../../' );
|
||||
require_once DVWA_WEB_PAGE_TO_ROOT . 'dvwa/includes/dvwaPage.inc.php';
|
||||
|
||||
dvwaPageStartup( array( 'authenticated', 'phpids' ) );
|
||||
|
||||
$page = dvwaPageNewGrab();
|
||||
$page[ 'title' ] = 'Vulnerability: Content Security Policy (CSP) Bypass' . $page[ 'title_separator' ].$page[ 'title' ];
|
||||
$page[ 'page_id' ] = 'csp';
|
||||
$page[ 'help_button' ] = 'csp';
|
||||
$page[ 'source_button' ] = 'csp';
|
||||
|
||||
dvwaDatabaseConnect();
|
||||
|
||||
$vulnerabilityFile = '';
|
||||
switch( $_COOKIE[ 'security' ] ) {
|
||||
case 'low':
|
||||
$vulnerabilityFile = 'low.php';
|
||||
break;
|
||||
case 'medium':
|
||||
$vulnerabilityFile = 'medium.php';
|
||||
break;
|
||||
case 'high':
|
||||
$vulnerabilityFile = 'high.php';
|
||||
break;
|
||||
default:
|
||||
$vulnerabilityFile = 'impossible.php';
|
||||
break;
|
||||
}
|
||||
|
||||
$page[ 'body' ] = <<<EOF
|
||||
<div class="body_padded">
|
||||
<h1>Vulnerability: Content Security Policy (CSP) Bypass</h1>
|
||||
|
||||
<div class="vulnerable_code_area">
|
||||
EOF;
|
||||
|
||||
require_once DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/csp/source/{$vulnerabilityFile}";
|
||||
|
||||
$page[ 'body' ] .= <<<EOF
|
||||
</div>
|
||||
EOF;
|
||||
|
||||
$page[ 'body' ] .= "
|
||||
<h2>More Information</h2>
|
||||
<ul>
|
||||
<li>" . dvwaExternalLinkUrlGet( 'https://content-security-policy.com/', "Content Security Policy Reference" ) . "</li>
|
||||
<li>" . dvwaExternalLinkUrlGet( 'https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP', "Mozilla Developer Network - CSP: script-src") . "</li>
|
||||
<li>" . dvwaExternalLinkUrlGet( 'https://blog.mozilla.org/security/2014/10/04/csp-for-the-web-we-have/', "Mozilla Security Blog - CSP for the web we have" ) . "</li>
|
||||
</ul>
|
||||
<p><i>Module developed by <a href='https://twitter.com/digininja'>Digininja</a>.</i></p>
|
||||
</div>\n";
|
||||
|
||||
dvwaHtmlEcho( $page );
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,19 @@
|
||||
function clickButton() {
|
||||
var s = document.createElement("script");
|
||||
s.src = "source/jsonp.php?callback=solveSum";
|
||||
document.body.appendChild(s);
|
||||
}
|
||||
|
||||
function solveSum(obj) {
|
||||
if ("answer" in obj) {
|
||||
document.getElementById("answer").innerHTML = obj['answer'];
|
||||
}
|
||||
}
|
||||
|
||||
var solve_button = document.getElementById ("solve");
|
||||
|
||||
if (solve_button) {
|
||||
solve_button.addEventListener("click", function() {
|
||||
clickButton();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
$headerCSP = "Content-Security-Policy: script-src 'self';";
|
||||
|
||||
header($headerCSP);
|
||||
|
||||
?>
|
||||
<?php
|
||||
if (isset ($_POST['include'])) {
|
||||
$page[ 'body' ] .= "
|
||||
" . $_POST['include'] . "
|
||||
";
|
||||
}
|
||||
$page[ 'body' ] .= '
|
||||
<form name="csp" method="POST">
|
||||
<p>The page makes a call to ' . DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.</p>
|
||||
<p>1+2+3+4+5=<span id="answer"></span></p>
|
||||
<input type="button" id="solve" value="Solve the sum" />
|
||||
</form>
|
||||
|
||||
<script src="source/high.js"></script>
|
||||
';
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
function clickButton() {
|
||||
var s = document.createElement("script");
|
||||
s.src = "source/jsonp_impossible.php";
|
||||
document.body.appendChild(s);
|
||||
}
|
||||
|
||||
function solveSum(obj) {
|
||||
if ("answer" in obj) {
|
||||
document.getElementById("answer").innerHTML = obj['answer'];
|
||||
}
|
||||
}
|
||||
|
||||
var solve_button = document.getElementById ("solve");
|
||||
|
||||
if (solve_button) {
|
||||
solve_button.addEventListener("click", function() {
|
||||
clickButton();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
$headerCSP = "Content-Security-Policy: script-src 'self';";
|
||||
|
||||
header($headerCSP);
|
||||
|
||||
?>
|
||||
<?php
|
||||
if (isset ($_POST['include'])) {
|
||||
$page[ 'body' ] .= "
|
||||
" . $_POST['include'] . "
|
||||
";
|
||||
}
|
||||
$page[ 'body' ] .= '
|
||||
<form name="csp" method="POST">
|
||||
<p>Unlike the high level, this does a JSONP call but does not use a callback, instead it hardcodes the function to call.</p><p>The CSP settings only allow external JavaScript on the local server and no inline code.</p>
|
||||
<p>1+2+3+4+5=<span id="answer"></span></p>
|
||||
<input type="button" id="solve" value="Solve the sum" />
|
||||
</form>
|
||||
|
||||
<script src="source/impossible.js"></script>
|
||||
';
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
header("Content-Type: application/json; charset=UTF-8");
|
||||
|
||||
if (array_key_exists ("callback", $_GET)) {
|
||||
$callback = $_GET['callback'];
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
$outp = array ("answer" => "15");
|
||||
|
||||
echo $callback . "(".json_encode($outp).")";
|
||||
?>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
header("Content-Type: application/json; charset=UTF-8");
|
||||
|
||||
$outp = array ("answer" => "15");
|
||||
|
||||
echo "solveSum (".json_encode($outp).")";
|
||||
?>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;"; // allows js from self, pastebin.com, jquery and google analytics.
|
||||
|
||||
header($headerCSP);
|
||||
|
||||
# https://pastebin.com/raw/R570EE00
|
||||
|
||||
?>
|
||||
<?php
|
||||
if (isset ($_POST['include'])) {
|
||||
$page[ 'body' ] .= "
|
||||
<script src='" . $_POST['include'] . "'></script>
|
||||
";
|
||||
}
|
||||
$page[ 'body' ] .= '
|
||||
<form name="csp" method="POST">
|
||||
<p>You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:</p>
|
||||
<input size="50" type="text" name="include" value="" id="include" />
|
||||
<input type="submit" value="Include" />
|
||||
</form>
|
||||
';
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
$headerCSP = "Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';";
|
||||
|
||||
header($headerCSP);
|
||||
|
||||
// Disable XSS protections so that inline alert boxes will work
|
||||
header ("X-XSS-Protection: 0");
|
||||
|
||||
# <script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>
|
||||
|
||||
?>
|
||||
<?php
|
||||
if (isset ($_POST['include'])) {
|
||||
$page[ 'body' ] .= "
|
||||
" . $_POST['include'] . "
|
||||
";
|
||||
}
|
||||
$page[ 'body' ] .= '
|
||||
<form name="csp" method="POST">
|
||||
<p>Whatever you enter here gets dropped directly into the page, see if you can get an alert box to pop up.</p>
|
||||
<input size="50" type="text" name="include" value="" id="include" />
|
||||
<input type="submit" value="Include" />
|
||||
</form>
|
||||
';
|
||||
@@ -0,0 +1,52 @@
|
||||
<div class="body_padded">
|
||||
<h1>Help - Client Side JavaScript</h1>
|
||||
|
||||
<div id="code" style="padding: 3px; border: 2px #C0C0C0 solid;>">
|
||||
<h3>About</h3>
|
||||
<p>The attacks in this section are designed to help you learn about how JavaScript is used in the browser and how it can be manipulated. The attacks could be carried out by just analysing network traffic, but that isn't the point and it would also probably be a lot harder.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>Objective</h3>
|
||||
<p>Simply submit the phrase "success" to win the level. Obviously, it isn't quite that easy, each level implements different protection mechanisms, the JavaScript included in the pages has to be analysed and then manipulated to bypass the protections.</p>
|
||||
|
||||
<hr />
|
||||
<h3>Low Level</h3>
|
||||
<p>All the JavaScript is included in the page. Read the source and work out what function is being used to generate the token required to match with the phrase and then call the function manually.</p>
|
||||
<pre>Spoiler: <span class="spoiler">Change the phrase to success and then use the function generate_token() to update the token.</span></pre>
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
<h3>Medium Level</h3>
|
||||
<p>
|
||||
The JavaScript has been broken out into its own file and then minimized. You need to view the source for the included file and then work out what it is doing. Both Firefox and Chrome have a Pretty Print feature which attempts to reverse the compression and display code in a readable way.
|
||||
</p>
|
||||
<pre>Spoiler: <span class="spoiler">The file uses the setTimeout function to run the do_elsesomething function which generates the token.</span></pre>
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
<h3>High Level</h3>
|
||||
<p>
|
||||
The JavaScript has been obfuscated by at least one engine. You are going to need to step through the code to work out what is useful, what is garbage and what is needed to complete the mission.
|
||||
</p>
|
||||
<pre>Spoiler: <span class="spoiler">If it helps, two packers have been used, the first is from <a href="https://www.danstools.com/javascript-obfuscate/index.php">Dan's Tools</a> and the second is the <a href="https://javascriptobfuscator.herokuapp.com/">JavaScript Obfuscator Tool</a>.</span></pre>
|
||||
<pre>Spoiler 2: <span class="spoiler">This deobfuscation tool seems to work the best on this code <a href="http://deobfuscatejavascript.com/">deobfuscate javascript</a>.</span></pre>
|
||||
<pre>Spoiler 3: <span class="spoiler">This is one way to do it... run the obfuscated JS through a deobfuscation app, intercept the response for the obfuscated JS and swap in the readable version. Work out the flow and you will see three functions that need to be called in order. Call the functions at the right time with the right parameters.</pre>
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
<h3>Impossible Level</h3>
|
||||
<p>You can never trust the user and have to assume that any code sent to the user can be manipulated or bypassed and so there is no impossible level.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<p>Reference:</p>
|
||||
<ul>
|
||||
<li><?php echo dvwaExternalLinkUrlGet( 'https://www.youtube.com/watch?v=8UqHCrGdxOM' )?></li>
|
||||
<li><?php echo dvwaExternalLinkUrlGet( 'https://www.w3schools.com/js/' )?></li>
|
||||
<li><?php echo dvwaExternalLinkUrlGet( 'https://www.youtube.com/watch?v=cs7EQdWO5o0&index=17&list=WL' )?></li>
|
||||
<li><?php echo dvwaExternalLinkUrlGet( 'https://www.youtube.com/playlist?list=PLC9K7uaDMdAUNktlDTxsmj6rJBf4Q9TR5' )?></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
define( 'DVWA_WEB_PAGE_TO_ROOT', '../../' );
|
||||
require_once DVWA_WEB_PAGE_TO_ROOT . 'dvwa/includes/dvwaPage.inc.php';
|
||||
|
||||
dvwaPageStartup( array( 'authenticated', 'phpids' ) );
|
||||
|
||||
$page = dvwaPageNewGrab();
|
||||
$page[ 'title' ] = 'Vulnerability: JavaScript Attacks' . $page[ 'title_separator' ].$page[ 'title' ];
|
||||
$page[ 'page_id' ] = 'javascript';
|
||||
$page[ 'help_button' ] = 'javascript';
|
||||
$page[ 'source_button' ] = 'javascript';
|
||||
|
||||
dvwaDatabaseConnect();
|
||||
|
||||
$vulnerabilityFile = '';
|
||||
switch( $_COOKIE[ 'security' ] ) {
|
||||
case 'low':
|
||||
$vulnerabilityFile = 'low.php';
|
||||
break;
|
||||
case 'medium':
|
||||
$vulnerabilityFile = 'medium.php';
|
||||
break;
|
||||
case 'high':
|
||||
$vulnerabilityFile = 'high.php';
|
||||
break;
|
||||
default:
|
||||
$vulnerabilityFile = 'impossible.php';
|
||||
break;
|
||||
}
|
||||
|
||||
$message = "";
|
||||
// Check whwat was sent in to see if it was what was expected
|
||||
if ($_SERVER['REQUEST_METHOD'] == "POST") {
|
||||
if (array_key_exists ("phrase", $_POST) && array_key_exists ("token", $_POST)) {
|
||||
|
||||
$phrase = $_POST['phrase'];
|
||||
$token = $_POST['token'];
|
||||
|
||||
if ($phrase == "success") {
|
||||
switch( $_COOKIE[ 'security' ] ) {
|
||||
case 'low':
|
||||
if ($token == md5(str_rot13("success"))) {
|
||||
$message = "<p style='color:red'>Well done!</p>";
|
||||
} else {
|
||||
$message = "<p>Invalid token.</p>";
|
||||
}
|
||||
break;
|
||||
case 'medium':
|
||||
if ($token == strrev("XXsuccessXX")) {
|
||||
$message = "<p style='color:red'>Well done!</p>";
|
||||
} else {
|
||||
$message = "<p>Invalid token.</p>";
|
||||
}
|
||||
break;
|
||||
case 'high':
|
||||
if ($token == hash("sha256", hash("sha256", "XX" . strrev("success")) . "ZZ")) {
|
||||
$message = "<p style='color:red'>Well done!</p>";
|
||||
} else {
|
||||
$message = "<p>Invalid token.</p>";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$vulnerabilityFile = 'impossible.php';
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$message = "<p>You got the phrase wrong.</p>";
|
||||
}
|
||||
} else {
|
||||
$message = "<p>Missing phrase or token.</p>";
|
||||
}
|
||||
}
|
||||
|
||||
if ( $_COOKIE[ 'security' ] == "impossible" ) {
|
||||
$page[ 'body' ] = <<<EOF
|
||||
<div class="body_padded">
|
||||
<h1>Vulnerability: JavaScript Attacks</h1>
|
||||
|
||||
<div class="vulnerable_code_area">
|
||||
<p>
|
||||
You can never trust anything that comes from the user or prevent them from messing with it and so there is no impossible level.
|
||||
</p>
|
||||
EOF;
|
||||
} else {
|
||||
$page[ 'body' ] = <<<EOF
|
||||
<div class="body_padded">
|
||||
<h1>Vulnerability: JavaScript Attacks</h1>
|
||||
|
||||
<div class="vulnerable_code_area">
|
||||
<p>
|
||||
Submit the word "success" to win.
|
||||
</p>
|
||||
|
||||
$message
|
||||
|
||||
<form name="low_js" method="post">
|
||||
<input type="hidden" name="token" value="" id="token" />
|
||||
<label for="phrase">Phrase</label> <input type="text" name="phrase" value="ChangeMe" id="phrase" />
|
||||
<input type="submit" id="send" name="send" value="Submit" />
|
||||
</form>
|
||||
EOF;
|
||||
}
|
||||
|
||||
require_once DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/javascript/source/{$vulnerabilityFile}";
|
||||
|
||||
$page[ 'body' ] .= <<<EOF
|
||||
</div>
|
||||
EOF;
|
||||
|
||||
$page[ 'body' ] .= "
|
||||
<h2>More Information</h2>
|
||||
<ul>
|
||||
<li>" . dvwaExternalLinkUrlGet( 'https://www.w3schools.com/js/' ) . "</li>
|
||||
<li>" . dvwaExternalLinkUrlGet( 'https://www.youtube.com/watch?v=cs7EQdWO5o0&index=17&list=WL' ) . "</li>
|
||||
<li>" . dvwaExternalLinkUrlGet( 'https://ponyfoo.com/articles/es6-proxies-in-depth' ) . "</li>
|
||||
</ul>
|
||||
<p><i>Module developed by <a href='https://twitter.com/digininja'>Digininja</a>.</i></p>
|
||||
</div>\n";
|
||||
|
||||
dvwaHtmlEcho( $page );
|
||||
|
||||
?>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
$page[ 'body' ] .= <<<EOF
|
||||
<script src="/vulnerabilities/javascript/source/high.js"></script>
|
||||
EOF;
|
||||
?>
|
||||
@@ -0,0 +1,540 @@
|
||||
/**
|
||||
* [js-sha256]{@link https://github.com/emn178/js-sha256}
|
||||
*
|
||||
* @version 0.9.0
|
||||
* @author Chen, Yi-Cyuan [emn178@gmail.com]
|
||||
* @copyright Chen, Yi-Cyuan 2014-2017
|
||||
* @license MIT
|
||||
*/
|
||||
/*jslint bitwise: true */
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var ERROR = 'input is invalid type';
|
||||
var WINDOW = typeof window === 'object';
|
||||
var root = WINDOW ? window : {};
|
||||
if (root.JS_SHA256_NO_WINDOW) {
|
||||
WINDOW = false;
|
||||
}
|
||||
var WEB_WORKER = !WINDOW && typeof self === 'object';
|
||||
var NODE_JS = !root.JS_SHA256_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
|
||||
if (NODE_JS) {
|
||||
root = global;
|
||||
} else if (WEB_WORKER) {
|
||||
root = self;
|
||||
}
|
||||
var COMMON_JS = !root.JS_SHA256_NO_COMMON_JS && typeof module === 'object' && module.exports;
|
||||
var AMD = typeof define === 'function' && define.amd;
|
||||
var ARRAY_BUFFER = !root.JS_SHA256_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
|
||||
var HEX_CHARS = '0123456789abcdef'.split('');
|
||||
var EXTRA = [-2147483648, 8388608, 32768, 128];
|
||||
var SHIFT = [24, 16, 8, 0];
|
||||
var K = [
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
];
|
||||
var OUTPUT_TYPES = ['hex', 'array', 'digest', 'arrayBuffer'];
|
||||
|
||||
var blocks = [];
|
||||
|
||||
if (root.JS_SHA256_NO_NODE_JS || !Array.isArray) {
|
||||
Array.isArray = function (obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object Array]';
|
||||
};
|
||||
}
|
||||
|
||||
if (ARRAY_BUFFER && (root.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {
|
||||
ArrayBuffer.isView = function (obj) {
|
||||
return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
|
||||
};
|
||||
}
|
||||
|
||||
var createOutputMethod = function (outputType, is224) {
|
||||
return function (message) {
|
||||
return new Sha256(is224, true).update(message)[outputType]();
|
||||
};
|
||||
};
|
||||
|
||||
var createMethod = function (is224) {
|
||||
var method = createOutputMethod('hex', is224);
|
||||
if (NODE_JS) {
|
||||
method = nodeWrap(method, is224);
|
||||
}
|
||||
method.create = function () {
|
||||
return new Sha256(is224);
|
||||
};
|
||||
method.update = function (message) {
|
||||
return method.create().update(message);
|
||||
};
|
||||
for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
|
||||
var type = OUTPUT_TYPES[i];
|
||||
method[type] = createOutputMethod(type, is224);
|
||||
}
|
||||
return method;
|
||||
};
|
||||
|
||||
var nodeWrap = function (method, is224) {
|
||||
var crypto = eval("require('crypto')");
|
||||
var Buffer = eval("require('buffer').Buffer");
|
||||
var algorithm = is224 ? 'sha224' : 'sha256';
|
||||
var nodeMethod = function (message) {
|
||||
if (typeof message === 'string') {
|
||||
return crypto.createHash(algorithm).update(message, 'utf8').digest('hex');
|
||||
} else {
|
||||
if (message === null || message === undefined) {
|
||||
throw new Error(ERROR);
|
||||
} else if (message.constructor === ArrayBuffer) {
|
||||
message = new Uint8Array(message);
|
||||
}
|
||||
}
|
||||
if (Array.isArray(message) || ArrayBuffer.isView(message) ||
|
||||
message.constructor === Buffer) {
|
||||
return crypto.createHash(algorithm).update(new Buffer(message)).digest('hex');
|
||||
} else {
|
||||
return method(message);
|
||||
}
|
||||
};
|
||||
return nodeMethod;
|
||||
};
|
||||
|
||||
var createHmacOutputMethod = function (outputType, is224) {
|
||||
return function (key, message) {
|
||||
return new HmacSha256(key, is224, true).update(message)[outputType]();
|
||||
};
|
||||
};
|
||||
|
||||
var createHmacMethod = function (is224) {
|
||||
var method = createHmacOutputMethod('hex', is224);
|
||||
method.create = function (key) {
|
||||
return new HmacSha256(key, is224);
|
||||
};
|
||||
method.update = function (key, message) {
|
||||
return method.create(key).update(message);
|
||||
};
|
||||
for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
|
||||
var type = OUTPUT_TYPES[i];
|
||||
method[type] = createHmacOutputMethod(type, is224);
|
||||
}
|
||||
return method;
|
||||
};
|
||||
|
||||
function Sha256(is224, sharedMemory) {
|
||||
if (sharedMemory) {
|
||||
blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =
|
||||
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
|
||||
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
|
||||
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
|
||||
this.blocks = blocks;
|
||||
} else {
|
||||
this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
}
|
||||
|
||||
if (is224) {
|
||||
this.h0 = 0xc1059ed8;
|
||||
this.h1 = 0x367cd507;
|
||||
this.h2 = 0x3070dd17;
|
||||
this.h3 = 0xf70e5939;
|
||||
this.h4 = 0xffc00b31;
|
||||
this.h5 = 0x68581511;
|
||||
this.h6 = 0x64f98fa7;
|
||||
this.h7 = 0xbefa4fa4;
|
||||
} else { // 256
|
||||
this.h0 = 0x6a09e667;
|
||||
this.h1 = 0xbb67ae85;
|
||||
this.h2 = 0x3c6ef372;
|
||||
this.h3 = 0xa54ff53a;
|
||||
this.h4 = 0x510e527f;
|
||||
this.h5 = 0x9b05688c;
|
||||
this.h6 = 0x1f83d9ab;
|
||||
this.h7 = 0x5be0cd19;
|
||||
}
|
||||
|
||||
this.block = this.start = this.bytes = this.hBytes = 0;
|
||||
this.finalized = this.hashed = false;
|
||||
this.first = true;
|
||||
this.is224 = is224;
|
||||
}
|
||||
|
||||
Sha256.prototype.update = function (message) {
|
||||
if (this.finalized) {
|
||||
return;
|
||||
}
|
||||
var notString, type = typeof message;
|
||||
if (type !== 'string') {
|
||||
if (type === 'object') {
|
||||
if (message === null) {
|
||||
throw new Error(ERROR);
|
||||
} else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
|
||||
message = new Uint8Array(message);
|
||||
} else if (!Array.isArray(message)) {
|
||||
if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {
|
||||
throw new Error(ERROR);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Error(ERROR);
|
||||
}
|
||||
notString = true;
|
||||
}
|
||||
var code, index = 0, i, length = message.length, blocks = this.blocks;
|
||||
|
||||
while (index < length) {
|
||||
if (this.hashed) {
|
||||
this.hashed = false;
|
||||
blocks[0] = this.block;
|
||||
blocks[16] = blocks[1] = blocks[2] = blocks[3] =
|
||||
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
|
||||
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
|
||||
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
|
||||
}
|
||||
|
||||
if (notString) {
|
||||
for (i = this.start; index < length && i < 64; ++index) {
|
||||
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
|
||||
}
|
||||
} else {
|
||||
for (i = this.start; index < length && i < 64; ++index) {
|
||||
code = message.charCodeAt(index);
|
||||
if (code < 0x80) {
|
||||
blocks[i >> 2] |= code << SHIFT[i++ & 3];
|
||||
} else if (code < 0x800) {
|
||||
blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
||||
} else if (code < 0xd800 || code >= 0xe000) {
|
||||
blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
||||
} else {
|
||||
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
|
||||
blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.lastByteIndex = i;
|
||||
this.bytes += i - this.start;
|
||||
if (i >= 64) {
|
||||
this.block = blocks[16];
|
||||
this.start = i - 64;
|
||||
this.hash();
|
||||
this.hashed = true;
|
||||
} else {
|
||||
this.start = i;
|
||||
}
|
||||
}
|
||||
if (this.bytes > 4294967295) {
|
||||
this.hBytes += this.bytes / 4294967296 << 0;
|
||||
this.bytes = this.bytes % 4294967296;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Sha256.prototype.finalize = function () {
|
||||
if (this.finalized) {
|
||||
return;
|
||||
}
|
||||
this.finalized = true;
|
||||
var blocks = this.blocks, i = this.lastByteIndex;
|
||||
blocks[16] = this.block;
|
||||
blocks[i >> 2] |= EXTRA[i & 3];
|
||||
this.block = blocks[16];
|
||||
if (i >= 56) {
|
||||
if (!this.hashed) {
|
||||
this.hash();
|
||||
}
|
||||
blocks[0] = this.block;
|
||||
blocks[16] = blocks[1] = blocks[2] = blocks[3] =
|
||||
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
|
||||
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
|
||||
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
|
||||
}
|
||||
blocks[14] = this.hBytes << 3 | this.bytes >>> 29;
|
||||
blocks[15] = this.bytes << 3;
|
||||
this.hash();
|
||||
};
|
||||
|
||||
Sha256.prototype.hash = function () {
|
||||
var a = this.h0, b = this.h1, c = this.h2, d = this.h3, e = this.h4, f = this.h5, g = this.h6,
|
||||
h = this.h7, blocks = this.blocks, j, s0, s1, maj, t1, t2, ch, ab, da, cd, bc;
|
||||
|
||||
for (j = 16; j < 64; ++j) {
|
||||
// rightrotate
|
||||
t1 = blocks[j - 15];
|
||||
s0 = ((t1 >>> 7) | (t1 << 25)) ^ ((t1 >>> 18) | (t1 << 14)) ^ (t1 >>> 3);
|
||||
t1 = blocks[j - 2];
|
||||
s1 = ((t1 >>> 17) | (t1 << 15)) ^ ((t1 >>> 19) | (t1 << 13)) ^ (t1 >>> 10);
|
||||
blocks[j] = blocks[j - 16] + s0 + blocks[j - 7] + s1 << 0;
|
||||
}
|
||||
|
||||
bc = b & c;
|
||||
for (j = 0; j < 64; j += 4) {
|
||||
if (this.first) {
|
||||
if (this.is224) {
|
||||
ab = 300032;
|
||||
t1 = blocks[0] - 1413257819;
|
||||
h = t1 - 150054599 << 0;
|
||||
d = t1 + 24177077 << 0;
|
||||
} else {
|
||||
ab = 704751109;
|
||||
t1 = blocks[0] - 210244248;
|
||||
h = t1 - 1521486534 << 0;
|
||||
d = t1 + 143694565 << 0;
|
||||
}
|
||||
this.first = false;
|
||||
} else {
|
||||
s0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));
|
||||
s1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));
|
||||
ab = a & b;
|
||||
maj = ab ^ (a & c) ^ bc;
|
||||
ch = (e & f) ^ (~e & g);
|
||||
t1 = h + s1 + ch + K[j] + blocks[j];
|
||||
t2 = s0 + maj;
|
||||
h = d + t1 << 0;
|
||||
d = t1 + t2 << 0;
|
||||
}
|
||||
s0 = ((d >>> 2) | (d << 30)) ^ ((d >>> 13) | (d << 19)) ^ ((d >>> 22) | (d << 10));
|
||||
s1 = ((h >>> 6) | (h << 26)) ^ ((h >>> 11) | (h << 21)) ^ ((h >>> 25) | (h << 7));
|
||||
da = d & a;
|
||||
maj = da ^ (d & b) ^ ab;
|
||||
ch = (h & e) ^ (~h & f);
|
||||
t1 = g + s1 + ch + K[j + 1] + blocks[j + 1];
|
||||
t2 = s0 + maj;
|
||||
g = c + t1 << 0;
|
||||
c = t1 + t2 << 0;
|
||||
s0 = ((c >>> 2) | (c << 30)) ^ ((c >>> 13) | (c << 19)) ^ ((c >>> 22) | (c << 10));
|
||||
s1 = ((g >>> 6) | (g << 26)) ^ ((g >>> 11) | (g << 21)) ^ ((g >>> 25) | (g << 7));
|
||||
cd = c & d;
|
||||
maj = cd ^ (c & a) ^ da;
|
||||
ch = (g & h) ^ (~g & e);
|
||||
t1 = f + s1 + ch + K[j + 2] + blocks[j + 2];
|
||||
t2 = s0 + maj;
|
||||
f = b + t1 << 0;
|
||||
b = t1 + t2 << 0;
|
||||
s0 = ((b >>> 2) | (b << 30)) ^ ((b >>> 13) | (b << 19)) ^ ((b >>> 22) | (b << 10));
|
||||
s1 = ((f >>> 6) | (f << 26)) ^ ((f >>> 11) | (f << 21)) ^ ((f >>> 25) | (f << 7));
|
||||
bc = b & c;
|
||||
maj = bc ^ (b & d) ^ cd;
|
||||
ch = (f & g) ^ (~f & h);
|
||||
t1 = e + s1 + ch + K[j + 3] + blocks[j + 3];
|
||||
t2 = s0 + maj;
|
||||
e = a + t1 << 0;
|
||||
a = t1 + t2 << 0;
|
||||
}
|
||||
|
||||
this.h0 = this.h0 + a << 0;
|
||||
this.h1 = this.h1 + b << 0;
|
||||
this.h2 = this.h2 + c << 0;
|
||||
this.h3 = this.h3 + d << 0;
|
||||
this.h4 = this.h4 + e << 0;
|
||||
this.h5 = this.h5 + f << 0;
|
||||
this.h6 = this.h6 + g << 0;
|
||||
this.h7 = this.h7 + h << 0;
|
||||
};
|
||||
|
||||
Sha256.prototype.hex = function () {
|
||||
this.finalize();
|
||||
|
||||
var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5,
|
||||
h6 = this.h6, h7 = this.h7;
|
||||
|
||||
var hex = HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +
|
||||
HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +
|
||||
HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +
|
||||
HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +
|
||||
HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +
|
||||
HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +
|
||||
HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +
|
||||
HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +
|
||||
HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +
|
||||
HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +
|
||||
HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +
|
||||
HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +
|
||||
HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F] +
|
||||
HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +
|
||||
HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +
|
||||
HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +
|
||||
HEX_CHARS[(h4 >> 28) & 0x0F] + HEX_CHARS[(h4 >> 24) & 0x0F] +
|
||||
HEX_CHARS[(h4 >> 20) & 0x0F] + HEX_CHARS[(h4 >> 16) & 0x0F] +
|
||||
HEX_CHARS[(h4 >> 12) & 0x0F] + HEX_CHARS[(h4 >> 8) & 0x0F] +
|
||||
HEX_CHARS[(h4 >> 4) & 0x0F] + HEX_CHARS[h4 & 0x0F] +
|
||||
HEX_CHARS[(h5 >> 28) & 0x0F] + HEX_CHARS[(h5 >> 24) & 0x0F] +
|
||||
HEX_CHARS[(h5 >> 20) & 0x0F] + HEX_CHARS[(h5 >> 16) & 0x0F] +
|
||||
HEX_CHARS[(h5 >> 12) & 0x0F] + HEX_CHARS[(h5 >> 8) & 0x0F] +
|
||||
HEX_CHARS[(h5 >> 4) & 0x0F] + HEX_CHARS[h5 & 0x0F] +
|
||||
HEX_CHARS[(h6 >> 28) & 0x0F] + HEX_CHARS[(h6 >> 24) & 0x0F] +
|
||||
HEX_CHARS[(h6 >> 20) & 0x0F] + HEX_CHARS[(h6 >> 16) & 0x0F] +
|
||||
HEX_CHARS[(h6 >> 12) & 0x0F] + HEX_CHARS[(h6 >> 8) & 0x0F] +
|
||||
HEX_CHARS[(h6 >> 4) & 0x0F] + HEX_CHARS[h6 & 0x0F];
|
||||
if (!this.is224) {
|
||||
hex += HEX_CHARS[(h7 >> 28) & 0x0F] + HEX_CHARS[(h7 >> 24) & 0x0F] +
|
||||
HEX_CHARS[(h7 >> 20) & 0x0F] + HEX_CHARS[(h7 >> 16) & 0x0F] +
|
||||
HEX_CHARS[(h7 >> 12) & 0x0F] + HEX_CHARS[(h7 >> 8) & 0x0F] +
|
||||
HEX_CHARS[(h7 >> 4) & 0x0F] + HEX_CHARS[h7 & 0x0F];
|
||||
}
|
||||
return hex;
|
||||
};
|
||||
|
||||
Sha256.prototype.toString = Sha256.prototype.hex;
|
||||
|
||||
Sha256.prototype.digest = function () {
|
||||
this.finalize();
|
||||
|
||||
var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5,
|
||||
h6 = this.h6, h7 = this.h7;
|
||||
|
||||
var arr = [
|
||||
(h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, h0 & 0xFF,
|
||||
(h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, h1 & 0xFF,
|
||||
(h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, h2 & 0xFF,
|
||||
(h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, h3 & 0xFF,
|
||||
(h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, h4 & 0xFF,
|
||||
(h5 >> 24) & 0xFF, (h5 >> 16) & 0xFF, (h5 >> 8) & 0xFF, h5 & 0xFF,
|
||||
(h6 >> 24) & 0xFF, (h6 >> 16) & 0xFF, (h6 >> 8) & 0xFF, h6 & 0xFF
|
||||
];
|
||||
if (!this.is224) {
|
||||
arr.push((h7 >> 24) & 0xFF, (h7 >> 16) & 0xFF, (h7 >> 8) & 0xFF, h7 & 0xFF);
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
Sha256.prototype.array = Sha256.prototype.digest;
|
||||
|
||||
Sha256.prototype.arrayBuffer = function () {
|
||||
this.finalize();
|
||||
|
||||
var buffer = new ArrayBuffer(this.is224 ? 28 : 32);
|
||||
var dataView = new DataView(buffer);
|
||||
dataView.setUint32(0, this.h0);
|
||||
dataView.setUint32(4, this.h1);
|
||||
dataView.setUint32(8, this.h2);
|
||||
dataView.setUint32(12, this.h3);
|
||||
dataView.setUint32(16, this.h4);
|
||||
dataView.setUint32(20, this.h5);
|
||||
dataView.setUint32(24, this.h6);
|
||||
if (!this.is224) {
|
||||
dataView.setUint32(28, this.h7);
|
||||
}
|
||||
return buffer;
|
||||
};
|
||||
|
||||
function HmacSha256(key, is224, sharedMemory) {
|
||||
var i, type = typeof key;
|
||||
if (type === 'string') {
|
||||
var bytes = [], length = key.length, index = 0, code;
|
||||
for (i = 0; i < length; ++i) {
|
||||
code = key.charCodeAt(i);
|
||||
if (code < 0x80) {
|
||||
bytes[index++] = code;
|
||||
} else if (code < 0x800) {
|
||||
bytes[index++] = (0xc0 | (code >> 6));
|
||||
bytes[index++] = (0x80 | (code & 0x3f));
|
||||
} else if (code < 0xd800 || code >= 0xe000) {
|
||||
bytes[index++] = (0xe0 | (code >> 12));
|
||||
bytes[index++] = (0x80 | ((code >> 6) & 0x3f));
|
||||
bytes[index++] = (0x80 | (code & 0x3f));
|
||||
} else {
|
||||
code = 0x10000 + (((code & 0x3ff) << 10) | (key.charCodeAt(++i) & 0x3ff));
|
||||
bytes[index++] = (0xf0 | (code >> 18));
|
||||
bytes[index++] = (0x80 | ((code >> 12) & 0x3f));
|
||||
bytes[index++] = (0x80 | ((code >> 6) & 0x3f));
|
||||
bytes[index++] = (0x80 | (code & 0x3f));
|
||||
}
|
||||
}
|
||||
key = bytes;
|
||||
} else {
|
||||
if (type === 'object') {
|
||||
if (key === null) {
|
||||
throw new Error(ERROR);
|
||||
} else if (ARRAY_BUFFER && key.constructor === ArrayBuffer) {
|
||||
key = new Uint8Array(key);
|
||||
} else if (!Array.isArray(key)) {
|
||||
if (!ARRAY_BUFFER || !ArrayBuffer.isView(key)) {
|
||||
throw new Error(ERROR);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Error(ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (key.length > 64) {
|
||||
key = (new Sha256(is224, true)).update(key).array();
|
||||
}
|
||||
|
||||
var oKeyPad = [], iKeyPad = [];
|
||||
for (i = 0; i < 64; ++i) {
|
||||
var b = key[i] || 0;
|
||||
oKeyPad[i] = 0x5c ^ b;
|
||||
iKeyPad[i] = 0x36 ^ b;
|
||||
}
|
||||
|
||||
Sha256.call(this, is224, sharedMemory);
|
||||
|
||||
this.update(iKeyPad);
|
||||
this.oKeyPad = oKeyPad;
|
||||
this.inner = true;
|
||||
this.sharedMemory = sharedMemory;
|
||||
}
|
||||
HmacSha256.prototype = new Sha256();
|
||||
|
||||
HmacSha256.prototype.finalize = function () {
|
||||
Sha256.prototype.finalize.call(this);
|
||||
if (this.inner) {
|
||||
this.inner = false;
|
||||
var innerHash = this.array();
|
||||
Sha256.call(this, this.is224, this.sharedMemory);
|
||||
this.update(this.oKeyPad);
|
||||
this.update(innerHash);
|
||||
Sha256.prototype.finalize.call(this);
|
||||
}
|
||||
};
|
||||
|
||||
var exports = createMethod();
|
||||
exports.sha256 = exports;
|
||||
exports.sha224 = createMethod(true);
|
||||
exports.sha256.hmac = createHmacMethod();
|
||||
exports.sha224.hmac = createHmacMethod(true);
|
||||
|
||||
if (COMMON_JS) {
|
||||
module.exports = exports;
|
||||
} else {
|
||||
root.sha256 = exports.sha256;
|
||||
root.sha224 = exports.sha224;
|
||||
if (AMD) {
|
||||
define(function () {
|
||||
return exports;
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
function do_something(e){for(var t="",n=e.length-1;n>=0;n--)t+=e[n];return t}
|
||||
|
||||
function token_part_3(t, y="ZZ") {
|
||||
document.getElementById("token").value=sha256(document.getElementById("token").value+y)
|
||||
}
|
||||
|
||||
function token_part_2(e="YY") {
|
||||
document.getElementById("token").value=sha256(e+document.getElementById("token").value)
|
||||
}
|
||||
|
||||
function token_part_1(a,b) {
|
||||
document.getElementById("token").value=do_something(document.getElementById("phrase").value)
|
||||
}
|
||||
|
||||
document.getElementById("phrase").value="";
|
||||
|
||||
setTimeout(function(){token_part_2("XX")},300);
|
||||
|
||||
document.getElementById("send").addEventListener("click", token_part_3);
|
||||
|
||||
token_part_1("ABCD", 44);
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
$page[ 'body' ] .= <<<EOF
|
||||
<script>
|
||||
|
||||
/*
|
||||
MD5 code from here
|
||||
https://github.com/blueimp/JavaScript-MD5
|
||||
*/
|
||||
|
||||
!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function r(n,t){return n<<t|n>>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<<r%32,n[14+(r+64>>>9<<4)]=r;var e,i,a,d,h,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e<n.length;e+=16)i=l,a=g,d=v,h=m,g=f(g=f(g=f(g=f(g=c(g=c(g=c(g=c(g=u(g=u(g=u(g=u(g=o(g=o(g=o(g=o(g,v=o(v,m=o(m,l=o(l,g,v,m,n[e],7,-680876936),g,v,n[e+1],12,-389564586),l,g,n[e+2],17,606105819),m,l,n[e+3],22,-1044525330),v=o(v,m=o(m,l=o(l,g,v,m,n[e+4],7,-176418897),g,v,n[e+5],12,1200080426),l,g,n[e+6],17,-1473231341),m,l,n[e+7],22,-45705983),v=o(v,m=o(m,l=o(l,g,v,m,n[e+8],7,1770035416),g,v,n[e+9],12,-1958414417),l,g,n[e+10],17,-42063),m,l,n[e+11],22,-1990404162),v=o(v,m=o(m,l=o(l,g,v,m,n[e+12],7,1804603682),g,v,n[e+13],12,-40341101),l,g,n[e+14],17,-1502002290),m,l,n[e+15],22,1236535329),v=u(v,m=u(m,l=u(l,g,v,m,n[e+1],5,-165796510),g,v,n[e+6],9,-1069501632),l,g,n[e+11],14,643717713),m,l,n[e],20,-373897302),v=u(v,m=u(m,l=u(l,g,v,m,n[e+5],5,-701558691),g,v,n[e+10],9,38016083),l,g,n[e+15],14,-660478335),m,l,n[e+4],20,-405537848),v=u(v,m=u(m,l=u(l,g,v,m,n[e+9],5,568446438),g,v,n[e+14],9,-1019803690),l,g,n[e+3],14,-187363961),m,l,n[e+8],20,1163531501),v=u(v,m=u(m,l=u(l,g,v,m,n[e+13],5,-1444681467),g,v,n[e+2],9,-51403784),l,g,n[e+7],14,1735328473),m,l,n[e+12],20,-1926607734),v=c(v,m=c(m,l=c(l,g,v,m,n[e+5],4,-378558),g,v,n[e+8],11,-2022574463),l,g,n[e+11],16,1839030562),m,l,n[e+14],23,-35309556),v=c(v,m=c(m,l=c(l,g,v,m,n[e+1],4,-1530992060),g,v,n[e+4],11,1272893353),l,g,n[e+7],16,-155497632),m,l,n[e+10],23,-1094730640),v=c(v,m=c(m,l=c(l,g,v,m,n[e+13],4,681279174),g,v,n[e],11,-358537222),l,g,n[e+3],16,-722521979),m,l,n[e+6],23,76029189),v=c(v,m=c(m,l=c(l,g,v,m,n[e+9],4,-640364487),g,v,n[e+12],11,-421815835),l,g,n[e+15],16,530742520),m,l,n[e+2],23,-995338651),v=f(v,m=f(m,l=f(l,g,v,m,n[e],6,-198630844),g,v,n[e+7],10,1126891415),l,g,n[e+14],15,-1416354905),m,l,n[e+5],21,-57434055),v=f(v,m=f(m,l=f(l,g,v,m,n[e+12],6,1700485571),g,v,n[e+3],10,-1894986606),l,g,n[e+10],15,-1051523),m,l,n[e+1],21,-2054922799),v=f(v,m=f(m,l=f(l,g,v,m,n[e+8],6,1873313359),g,v,n[e+15],10,-30611744),l,g,n[e+6],15,-1560198380),m,l,n[e+13],21,1309151649),v=f(v,m=f(m,l=f(l,g,v,m,n[e+4],6,-145523070),g,v,n[e+11],10,-1120210379),l,g,n[e+2],15,718787259),m,l,n[e+9],21,-343485551),l=t(l,i),g=t(g,a),v=t(v,d),m=t(m,h);return[l,g,v,m]}function a(n){var t,r="",e=32*n.length;for(t=0;t<e;t+=8)r+=String.fromCharCode(n[t>>5]>>>t%32&255);return r}function d(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t<r.length;t+=1)r[t]=0;var e=8*n.length;for(t=0;t<e;t+=8)r[t>>5]|=(255&n.charCodeAt(t/8))<<t%32;return r}function h(n){return a(i(d(n),8*n.length))}function l(n,t){var r,e,o=d(n),u=[],c=[];for(u[15]=c[15]=void 0,o.length>16&&(o=i(o,8*n.length)),r=0;r<16;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(d(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="";for(r=0;r<n.length;r+=1)t=n.charCodeAt(r),e+="0123456789abcdef".charAt(t>>>4&15)+"0123456789abcdef".charAt(15&t);return e}function v(n){return unescape(encodeURIComponent(n))}function m(n){return h(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this);
|
||||
|
||||
function rot13(inp) {
|
||||
return inp.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});
|
||||
}
|
||||
|
||||
function generate_token() {
|
||||
var phrase = document.getElementById("phrase").value;
|
||||
document.getElementById("token").value = md5(rot13(phrase));
|
||||
}
|
||||
|
||||
generate_token();
|
||||
</script>
|
||||
EOF;
|
||||
?>
|
||||
@@ -0,0 +1 @@
|
||||
function do_something(e){for(var t="",n=e.length-1;n>=0;n--)t+=e[n];return t}setTimeout(function(){do_elsesomething("XX")},300);function do_elsesomething(e){document.getElementById("token").value=do_something(e+document.getElementById("phrase").value+"XX")}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
$page[ 'body' ] .= <<<EOF
|
||||
<script src="/vulnerabilities/javascript/source/medium.js"></script>
|
||||
EOF;
|
||||
?>
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
<h3>High Level</h3>
|
||||
<p>Once the file has been received from the client, the server will try to resize any image that was included in the request.</p>
|
||||
<pre>Spoiler: <span class="spoiler">need to link in another vulnerability, such as file includion</span>.</pre>
|
||||
<pre>Spoiler: <span class="spoiler">need to link in another vulnerability, such as file inclusion</span>.</pre>
|
||||
|
||||
<br />
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@ switch ($id) {
|
||||
case "weak_id" :
|
||||
$vuln = 'Weak Session IDs';
|
||||
break;
|
||||
case "javascript" :
|
||||
$vuln = 'JavaScript';
|
||||
break;
|
||||
default:
|
||||
$vuln = "Unknown Vulnerability";
|
||||
}
|
||||
@@ -50,10 +53,26 @@ switch ($id) {
|
||||
$source = @file_get_contents( DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/{$id}/source/{$security}.php" );
|
||||
$source = str_replace( array( '$html .=' ), array( 'echo' ), $source );
|
||||
|
||||
$js_html = "";
|
||||
if (file_exists (DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/{$id}/source/{$security}.js")) {
|
||||
$js_source = @file_get_contents( DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/{$id}/source/{$security}.js" );
|
||||
$js_html = "
|
||||
<h2>vulnerabilities/{$id}/source/{$security}.js</h2>
|
||||
<div id=\"code\">
|
||||
<table width='100%' bgcolor='white' style=\"border:2px #C0C0C0 solid\">
|
||||
<tr>
|
||||
<td><div id=\"code\">" . highlight_string( $js_source, true ) . "</div></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
";
|
||||
}
|
||||
|
||||
$page[ 'body' ] .= "
|
||||
<div class=\"body_padded\">
|
||||
<h1>{$vuln} Source</h1>
|
||||
|
||||
<h2>vulnerabilities/{$id}/source/{$security}.php</h2>
|
||||
<div id=\"code\">
|
||||
<table width='100%' bgcolor='white' style=\"border:2px #C0C0C0 solid\">
|
||||
<tr>
|
||||
@@ -61,6 +80,7 @@ $page[ 'body' ] .= "
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{$js_html}
|
||||
<br /> <br />
|
||||
|
||||
<form>
|
||||
|
||||
@@ -27,6 +27,9 @@ $impsrc = str_replace( array( '$html .=' ), array( 'echo' ), $impsrc);
|
||||
$impsrc = highlight_string( $impsrc, true );
|
||||
|
||||
switch ($id) {
|
||||
case "javascript" :
|
||||
$vuln = 'JavaScript';
|
||||
break;
|
||||
case "fi" :
|
||||
$vuln = 'File Inclusion';
|
||||
break;
|
||||
|
||||
@@ -4,33 +4,52 @@ class dvwa::apache {
|
||||
$db_password = $secgen_parameters['db_password'][0]
|
||||
$docroot = '/var/www/dvwa'
|
||||
|
||||
package { ['php5', 'php5-gd', 'php5-mysql']:
|
||||
if ($operatingsystem == 'Debian') {
|
||||
package { 'mysql-server':
|
||||
ensure => installed,
|
||||
}
|
||||
case $operatingsystemrelease {
|
||||
/^9.*/: { # do 9.x stretch stuff
|
||||
$php_version = "php7.0"
|
||||
}
|
||||
/^7.*/: { #do 7.x wheezy stuff
|
||||
$php_version = "php"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# kali
|
||||
$php_version = "php7.3"
|
||||
}
|
||||
|
||||
package { ['php', 'php-mysqli', 'php-gd', 'libapache2-mod-php']:
|
||||
ensure => installed,
|
||||
}
|
||||
|
||||
class { '::apache':
|
||||
default_vhost => false,
|
||||
default_mods => 'php',
|
||||
default_mods => $php_version,
|
||||
overwrite_ports => false,
|
||||
mpm_module => 'prefork',
|
||||
}
|
||||
|
||||
::apache::vhost { 'dvwa':
|
||||
port => $port,
|
||||
docroot => $docroot,
|
||||
|
||||
}
|
||||
|
||||
mysql::db { 'dvwa_database':
|
||||
user => 'dvwa_user',
|
||||
password => $db_password,
|
||||
host => 'localhost',
|
||||
grant => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP'],
|
||||
}
|
||||
|
||||
# mysql::db { 'dvwa_database':
|
||||
# user => 'dvwa_user',
|
||||
# password => $db_password,
|
||||
# host => 'localhost',
|
||||
# grant => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP'],
|
||||
# }
|
||||
|
||||
mysql_user{ 'dvwa_user@localhost':
|
||||
ensure => present,
|
||||
password_hash => mysql_password($db_password)
|
||||
}
|
||||
|
||||
|
||||
mysql_grant{'dvwa_user@localhost/dvwa_database.*':
|
||||
user => 'dvwa_user@localhost',
|
||||
table => 'dvwa_database.*',
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
|
||||
<read_fact>port</read_fact>
|
||||
<read_fact>db_password</read_fact>
|
||||
|
||||
|
||||
<default_input into="port">
|
||||
<value>80</value>
|
||||
</default_input>
|
||||
|
||||
|
||||
<default_input into="db_password">
|
||||
<generator type="strong_password_generator"/>
|
||||
</default_input>
|
||||
@@ -30,12 +30,12 @@
|
||||
<software_license>GPLv3</software_license>
|
||||
|
||||
<!-- TODO: Make stretch compatible, php5 packages are not available... -->
|
||||
<conflict>
|
||||
<!-- <conflict>
|
||||
<name>Stretch</name>
|
||||
</conflict>
|
||||
<conflict>
|
||||
<name>Kali</name>
|
||||
</conflict>
|
||||
</conflict> -->
|
||||
<!-- <conflict>
|
||||
<distro>Kali</distro>
|
||||
</conflict> -->
|
||||
|
||||
<requires>
|
||||
<module_path>.*/apache.*</module_path>
|
||||
|
||||
@@ -5,12 +5,29 @@
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/scenario">
|
||||
|
||||
<system>
|
||||
<system_name>dvwa</system_name>
|
||||
<base platform="linux" type="server"/>
|
||||
<system_name>dvwa_stretch</system_name>
|
||||
<base distro="Debian 9" type="desktop" name="KDE"/>
|
||||
|
||||
<vulnerability module_path=".*dvwa" />
|
||||
|
||||
<network type="private_network" range="dhcp"/>
|
||||
</system>
|
||||
|
||||
<system>
|
||||
<system_name>dvwa_wheezy</system_name>
|
||||
<base distro="Debian 7" type="desktop" name="KDE"/>
|
||||
|
||||
<vulnerability module_path=".*dvwa" />
|
||||
|
||||
<network type="private_network" range="dhcp"/>
|
||||
</system>
|
||||
|
||||
<system>
|
||||
<system_name>dvwa_kali</system_name>
|
||||
<base distro="Kali" name="MSF"/>
|
||||
|
||||
<vulnerability module_path=".*dvwa" />
|
||||
|
||||
<network type="private_network" range="dhcp"/>
|
||||
</system>
|
||||
</scenario>
|
||||
|
||||
@@ -18,9 +18,14 @@
|
||||
<base distro="Debian 9" type="desktop" name="KDE"/>
|
||||
|
||||
<input into_datastore="IP_addresses">
|
||||
<!-- 0 desktop -->
|
||||
<value>172.16.0.2</value>
|
||||
<!-- 1 server -->
|
||||
<value>172.16.0.3</value>
|
||||
<!-- 2 hackerbot_server -->
|
||||
<value>172.16.0.4</value>
|
||||
<!-- 3 kali_cracker -->
|
||||
<value>172.16.0.5</value>
|
||||
</input>
|
||||
|
||||
<!-- generate some usernames to use -->
|
||||
@@ -82,7 +87,7 @@
|
||||
<datastore access="next">usernames</datastore>
|
||||
</input>
|
||||
<input into="password">
|
||||
<datastore access="next">weak_passwords</datastore>
|
||||
<datastore access="0">weak_passwords</datastore>
|
||||
</input>
|
||||
</generator>
|
||||
<generator type="account">
|
||||
@@ -144,16 +149,16 @@
|
||||
<value>true</value>
|
||||
</input>
|
||||
<input into="start_page">
|
||||
<datastore access="1">IP_addresses</datastore>
|
||||
<datastore access="2">IP_addresses</datastore>
|
||||
</input>
|
||||
</utility>
|
||||
|
||||
<utility module_path=".*pidgin">
|
||||
<input into="server_ip">
|
||||
<datastore access="1">IP_addresses</datastore>
|
||||
<datastore access="2">IP_addresses</datastore>
|
||||
</input>
|
||||
<input into="accounts">
|
||||
<datastore access="0">accounts</datastore>
|
||||
<datastore access="0">user_accounts_desktop</datastore>
|
||||
</input>
|
||||
</utility>
|
||||
|
||||
@@ -194,7 +199,7 @@
|
||||
<datastore access="next">usernames</datastore>
|
||||
</input>
|
||||
<input into="password">
|
||||
<datastore access="next">weak_passwords</datastore>
|
||||
<datastore access="0">weak_passwords</datastore>
|
||||
</input>
|
||||
<input into="leaked_filenames">
|
||||
<value>flag</value>
|
||||
@@ -283,13 +288,16 @@
|
||||
|
||||
<utility module_path=".*hackerbot">
|
||||
<input into="hackerbot_configs">
|
||||
<generator module_path=".*authentication">
|
||||
<generator module_path=".*hbauthentication">
|
||||
<input into="accounts">
|
||||
<datastore>user_accounts_server</datastore>
|
||||
<datastore>user_accounts_desktop</datastore>
|
||||
</input>
|
||||
<input into="root_password">
|
||||
<datastore>desktop_root_password</datastore>
|
||||
</input>
|
||||
<input into="server_ip">
|
||||
<datastore access="1">IP_addresses</datastore>
|
||||
</input>
|
||||
</generator>
|
||||
</input>
|
||||
</utility>
|
||||
@@ -307,4 +315,36 @@
|
||||
</build>
|
||||
</system>
|
||||
|
||||
<system>
|
||||
<system_name>kali_cracker</system_name>
|
||||
<base distro="Kali" name="MSF"/>
|
||||
|
||||
<input into_datastore="kali_root_account">
|
||||
<value>{"username":"root","password":"toor","super_user":"","strings_to_leak":[],"leaked_filenames":[]}</value>
|
||||
</input>
|
||||
|
||||
<utility module_path=".*kali_pwtools"/>
|
||||
<utility module_path=".*metasploit_framework"/>
|
||||
<utility module_path=".*handy_cli_tools"/>
|
||||
<utility module_path=".*nmap"/>
|
||||
|
||||
<utility module_path=".*iceweasel">
|
||||
<input into="accounts">
|
||||
<datastore>kali_root_account</datastore>
|
||||
</input>
|
||||
<input into="autostart">
|
||||
<value>true</value>
|
||||
</input>
|
||||
<input into="start_page">
|
||||
<datastore access="2">IP_addresses</datastore>
|
||||
</input>
|
||||
</utility>
|
||||
|
||||
<network type="private_network" >
|
||||
<input into="IP_address">
|
||||
<datastore access="3">IP_addresses</datastore>
|
||||
</input>
|
||||
</network>
|
||||
</system>
|
||||
|
||||
</scenario>
|
||||
|
||||
53
scenarios/labs/websec_lab_env.xml
Normal file
53
scenarios/labs/websec_lab_env.xml
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<scenario xmlns="http://www.github/cliffe/SecGen/scenario"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/scenario">
|
||||
|
||||
<name>Web security lab environment</name>
|
||||
<author>Z. Cliffe Schreuders</author>
|
||||
<description>An environment for web security labs. Debian Stretch desktop with Damn Vulnerable Web App server, and Kali Linux. </description>
|
||||
|
||||
<type>lab-environment</type>
|
||||
|
||||
<system>
|
||||
<system_name>kali</system_name>
|
||||
<base distro="Kali" name="MSF"/>
|
||||
|
||||
<input into_datastore="IP_addresses">
|
||||
<value>172.16.0.2</value>
|
||||
<value>172.16.0.3</value>
|
||||
<value>172.16.0.4</value>
|
||||
</input>
|
||||
|
||||
<input into_datastore="kali_root_account">
|
||||
<value>{"username":"root","password":"toor","super_user":"","strings_to_leak":[],"leaked_filenames":[]}</value>
|
||||
</input>
|
||||
|
||||
<utility module_path=".*kali_web"/>
|
||||
<utility module_path=".*metasploit_framework"/>
|
||||
<utility module_path=".*handy_cli_tools"/>
|
||||
<utility module_path=".*nmap"/>
|
||||
|
||||
<utility module_path=".*iceweasel">
|
||||
<input into="accounts">
|
||||
<datastore>kali_root_account</datastore>
|
||||
</input>
|
||||
<input into="autostart">
|
||||
<value>true</value>
|
||||
</input>
|
||||
<input into="start_page">
|
||||
<datastore access="0">IP_addresses</datastore>
|
||||
</input>
|
||||
</utility>
|
||||
|
||||
<vulnerability module_path=".*dvwa" />
|
||||
|
||||
<network type="private_network" >
|
||||
<input into="IP_address">
|
||||
<datastore access="1">IP_addresses</datastore>
|
||||
</input>
|
||||
</network>
|
||||
</system>
|
||||
|
||||
</scenario>
|
||||
Reference in New Issue
Block a user