Compare commits
10 Commits
b3f7f42ab0
...
sheet05-su
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58553b688a | ||
|
|
b118e163b2 | ||
|
|
266df5d32c | ||
|
|
a2d5d23307 | ||
|
|
e40906a933 | ||
|
|
f29fbed900 | ||
|
|
ea32ada42d | ||
|
|
6676f07705 | ||
|
|
62fb088403 | ||
|
|
64ae54469d |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,3 +1,6 @@
|
||||
*.pdf
|
||||
sheet01/a2/Hash.java
|
||||
*.class
|
||||
*.class
|
||||
passwd
|
||||
sheet04/AuthWithTOTP.java
|
||||
sheet04/key-exchange.pcap
|
||||
6
sheet04/a1/c.txt
Normal file
6
sheet04/a1/c.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Let's Encrypt:
|
||||
Let's Encrypt is a Certificate Authority that provides free TLS certificates, making it easy for websites to enable HTTPS encryption and create a more secure Internet for everyone. Let's Encrypt is a project of the nonprofit Internet Security Research Group
|
||||
|
||||
|
||||
Internet Security Research Group:
|
||||
The Internet Security Research Group (ISRG) is a public-benefit non-profit corporation based in California which focuses on Internet security.
|
||||
149
sheet04/a2/AuthWithTOTP.java
Normal file
149
sheet04/a2/AuthWithTOTP.java
Normal file
@@ -0,0 +1,149 @@
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
import java.time.Instant;
|
||||
import java.util.HexFormat;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class AuthWithTOTP {
|
||||
|
||||
private static final byte[] INVALID_HASH =
|
||||
"----------------------------------------------------------------".getBytes();
|
||||
|
||||
// hex-encoded: 3c2bc45f2de6568bb285aa1c6fcac1b6965cc770
|
||||
// base32-encoded: HQV4IXZN4ZLIXMUFVIOG7SWBW2LFZR3Q
|
||||
private static final byte[] K = new byte[] {
|
||||
60,
|
||||
43,
|
||||
-60,
|
||||
95,
|
||||
45,
|
||||
-26,
|
||||
86,
|
||||
-117,
|
||||
-78,
|
||||
-123,
|
||||
-86,
|
||||
28,
|
||||
111,
|
||||
-54,
|
||||
-63,
|
||||
-74,
|
||||
-106,
|
||||
92,
|
||||
-57,
|
||||
112,
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
// I changed it to a scanner cause my terminal had issues with the other thingy
|
||||
try (Scanner sc = new Scanner(System.in)) {
|
||||
Map<String, byte[]> passwd = Files.readAllLines(Path.of("passwd"))
|
||||
.stream()
|
||||
.filter(line -> line.indexOf(":") > 1 && line.length() > 3)
|
||||
.collect(
|
||||
Collectors.toMap(
|
||||
line -> line.substring(0, line.indexOf(':')),
|
||||
line ->
|
||||
HexFormat.of().parseHex(
|
||||
line.substring(line.indexOf(':') + 1)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
System.out.println(
|
||||
"Chocolate Factory SCADA Command Line Interface v2.2.144"
|
||||
);
|
||||
System.out.println();
|
||||
System.out.println(
|
||||
"Please, enter your authentication credentials."
|
||||
);
|
||||
System.out.println();
|
||||
|
||||
String username;
|
||||
String password;
|
||||
String totpCode;
|
||||
|
||||
long timeout = 500;
|
||||
while (true) {
|
||||
System.out.print("> Username: ");
|
||||
username = sc.nextLine();
|
||||
System.out.print("> Password: ");
|
||||
password = sc.nextLine();
|
||||
System.out.print("> TOTP Code: ");
|
||||
totpCode = sc.nextLine();
|
||||
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] encodedHash = digest.digest(password.getBytes());
|
||||
|
||||
// constant time comparison to prevent timing attacks
|
||||
if (
|
||||
MessageDigest.isEqual(
|
||||
passwd.getOrDefault(username, INVALID_HASH),
|
||||
encodedHash
|
||||
)
|
||||
) {
|
||||
// Get the counter from the unix seconds
|
||||
final var counter = (int) Math.floor(
|
||||
Instant.now().getEpochSecond() / 30.0
|
||||
);
|
||||
|
||||
// Compute the hmac
|
||||
final var mac = Mac.getInstance("HmacSHA1");
|
||||
mac.init(new SecretKeySpec(K, "HmacSHA1"));
|
||||
mac.update(ByteBuffer.allocate(8).putLong(counter).array());
|
||||
final var hmacResult = mac.doFinal();
|
||||
|
||||
// Do the truncating + modulo
|
||||
int offset = hmacResult[19] & 0x0f;
|
||||
int binaryCode =
|
||||
((hmacResult[offset] & 0x7f) << 24) |
|
||||
((hmacResult[offset + 1] & 0xff) << 16) |
|
||||
((hmacResult[offset + 2] & 0xff) << 8) |
|
||||
(hmacResult[offset + 3] & 0xff);
|
||||
binaryCode = binaryCode % 1000000;
|
||||
|
||||
// Validate the code + padding
|
||||
final var code = String.format("%06d", binaryCode);
|
||||
if (!code.equals(totpCode)) {
|
||||
System.out.println(
|
||||
"Invalid username, password and/or TOTP code."
|
||||
);
|
||||
Thread.sleep(timeout);
|
||||
timeout *= 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
System.out.printf("Welcome %s!%n", username);
|
||||
Thread.sleep(150);
|
||||
break;
|
||||
} else {
|
||||
// exponential timeout to prevent brute force attacks
|
||||
System.out.println(
|
||||
"Invalid username, password and/or TOTP code."
|
||||
);
|
||||
Thread.sleep(timeout);
|
||||
timeout *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
printSystemStatus();
|
||||
printSecretRecipe();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void printSystemStatus() throws Exception {
|
||||
// SECRET
|
||||
}
|
||||
|
||||
private static void printSecretRecipe() throws Exception {
|
||||
// SECRET
|
||||
}
|
||||
}
|
||||
5
sheet04/a2/c.txt
Normal file
5
sheet04/a2/c.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Without the time interval entering the codes would be really difficult. Imagine having only one second to enter the code + the request having to travel to some server for it to verify (can take up to 200ms around the world) + the server having to process the request and verify the code.
|
||||
|
||||
There could be measures to make sure the code is still valid even when entering a little old code, but then you're really just introducing an interval. So why not do it from the start?
|
||||
|
||||
That's why you need a 30s interval. For user experience, to make sure the system can actually work even when grandma has to type it in and reopen the authenticator 10x because she forgot the code or typed something wrong.
|
||||
3
sheet05/a1/archive.sh
Normal file
3
sheet05/a1/archive.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
# $1 = directory path
|
||||
chmod -R a-w "$1"
|
||||
3
sheet05/a1/create_user.sh
Normal file
3
sheet05/a1/create_user.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
# $1 = username, $2 = comma-separated groups
|
||||
useradd -G "$2" "$1" || usermod -aG "$2" "$1"
|
||||
6
sheet05/a1/explanation.txt
Normal file
6
sheet05/a1/explanation.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
UNIX permissions only support one Owner, one Group, and Other (UGO).
|
||||
The 'Group' slot is already taken by the specific lecture group to give students write access.
|
||||
If we use 'Other' to give the supervisor read access, every user on the system could read it, which would violate the requirements.
|
||||
If we add the supervisor to the lecture group, they get write access, which also violates the requirements.
|
||||
|
||||
Because a file cannot have multiple groups or user-specific overrides under standard UNIX permissions, this cannot be solved.
|
||||
3
sheet05/a1/supervisor.sh
Normal file
3
sheet05/a1/supervisor.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
# $1 = supervisor username
|
||||
echo "not possible with the standard UNIX permissions. See explanation.txt."
|
||||
3
sheet05/a2/archive.sh
Normal file
3
sheet05/a2/archive.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
TARGET_DIR=$1
|
||||
chmod -R a-w "$TARGET_DIR"
|
||||
4
sheet05/a2/create_user.sh
Normal file
4
sheet05/a2/create_user.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
USERNAME=$1
|
||||
GROUPS=$2
|
||||
useradd -G "$GROUPS" "$USERNAME" || usermod -aG "$GROUPS" "$USERNAME"
|
||||
3
sheet05/a2/explanation.txt
Normal file
3
sheet05/a2/explanation.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
The supervisor's read access would fail with UNIX permissions, since they are limited to one owner, one group, and "others".
|
||||
Access Control Lists (ACLs) resolve this problem by allowing permissions beyond the standard three.
|
||||
Using `setfacl`, we can append specific read and execute rights (r-x) for individual users (the supervisors) directly to the files and directories.
|
||||
6
sheet05/a2/supervisor.sh
Normal file
6
sheet05/a2/supervisor.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
SUPERVISOR=$1
|
||||
# Grant read and execute permissions to the supervisor user recursively
|
||||
setfacl -R -m u:"$SUPERVISOR":r-x .
|
||||
# Set the default ACL
|
||||
setfacl -R -d -m u:"$SUPERVISOR":r-x .
|
||||
4
sheet05/a3/a.txt
Normal file
4
sheet05/a3/a.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Passwords are stored in the /etc/shadow file, which is restricted to the root user.
|
||||
A standard user cannot write to it directly. However, the passwd executable is owned by root and has the SUID permission set.
|
||||
When a standard user runs passwd, the SUID bit tells the system to execute the program with the privileges of root,
|
||||
giving the program the temporary permissions to update /etc/shadow
|
||||
5
sheet05/a3/b.txt
Normal file
5
sheet05/a3/b.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
The script runs with root privileges because the setuid bit is set.
|
||||
Since it just asks for a username and saves the new hash to /etc/shadow,
|
||||
and there is no validation checking if the user running the program is actually changing their own password,
|
||||
someone could simply run the program, type root as the username, and set a new password for the root user.
|
||||
The script would then overwrite the actual root password in /etc/shadow.
|
||||
Reference in New Issue
Block a user