Git
During the Web enumeration, a Git directory was found within the hidden /dev/
directory
i will be using the git-dumper tool to download the Git directory to Kali
┌──(kali㉿kali)-[~/archive/htb/labs/updown]
└─$ mkdir git ; git-dumper http://$IP/dev/.git/ ./GIT
[-] testing http://10.10.11.177/dev/.git/HEAD [200]
[-] testing http://10.10.11.177/dev/.git/ [200]
[-] Fetching .git recursively
[-] fetching http://10.10.11.177/dev/.git/ [200]
[-] fetching http://10.10.11.177/dev/.gitignore [404]
[-] http://10.10.11.177/dev/.gitignore responded with status code 404
[-] fetching http://10.10.11.177/dev/.git/objects/ [200]
[-] fetching http://10.10.11.177/dev/.git/HEAD [200]
[-] fetching http://10.10.11.177/dev/.git/branches/ [200]
[-] fetching http://10.10.11.177/dev/.git/description [200]
[-] fetching http://10.10.11.177/dev/.git/config [200]
[-] fetching http://10.10.11.177/dev/.git/info/ [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/ [200]
[-] fetching http://10.10.11.177/dev/.git/index [200]
[-] fetching http://10.10.11.177/dev/.git/logs/ [200]
[-] fetching http://10.10.11.177/dev/.git/refs/ [200]
[-] fetching http://10.10.11.177/dev/.git/objects/info/ [200]
[-] fetching http://10.10.11.177/dev/.git/info/exclude [200]
[-] fetching http://10.10.11.177/dev/.git/objects/pack/ [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/applypatch-msg.sample [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/commit-msg.sample [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/pre-applypatch.sample [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/fsmonitor-watchman.sample [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/post-update.sample [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/pre-commit.sample [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/pre-merge-commit.sample [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/pre-push.sample [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/pre-rebase.sample [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/prepare-commit-msg.sample [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/pre-receive.sample [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/push-to-checkout.sample [200]
[-] fetching http://10.10.11.177/dev/.git/hooks/update.sample [200]
[-] fetching http://10.10.11.177/dev/.git/logs/HEAD [200]
[-] fetching http://10.10.11.177/dev/.git/refs/heads/ [200]
[-] fetching http://10.10.11.177/dev/.git/logs/refs/ [200]
[-] fetching http://10.10.11.177/dev/.git/refs/remotes/ [200]
[-] fetching http://10.10.11.177/dev/.git/refs/tags/ [200]
[-] fetching http://10.10.11.177/dev/.git/objects/pack/pack-30e4e40cb7b0c696d1ce3a83a6725267d45715da.idx [200]
[-] fetching http://10.10.11.177/dev/.git/objects/pack/pack-30e4e40cb7b0c696d1ce3a83a6725267d45715da.pack [200]
[-] fetching http://10.10.11.177/dev/.git/logs/refs/heads/ [200]
[-] fetching http://10.10.11.177/dev/.git/refs/heads/main [200]
[-] fetching http://10.10.11.177/dev/.git/logs/refs/remotes/ [200]
[-] fetching http://10.10.11.177/dev/.git/refs/remotes/origin/ [200]
[-] fetching http://10.10.11.177/dev/.git/logs/refs/heads/main [200]
[-] fetching http://10.10.11.177/dev/.git/packed-refs [200]
[-] fetching http://10.10.11.177/dev/.git/logs/refs/remotes/origin/ [200]
[-] fetching http://10.10.11.177/dev/.git/refs/remotes/origin/HEAD [200]
[-] fetching http://10.10.11.177/dev/.git/logs/refs/remotes/origin/HEAD [200]
[-] Running git checkout .
Updated 6 paths from the index
Checking out
┌──(kali㉿kali)-[~/…/htb/labs/updown/GIT]
└─$ git log
commit 010dcc30cc1e89344e2bdbd3064f61c772d89a34 (HEAD -> main, origin/main, origin/HEAD)
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 19:38:51 2021 +0200
Delete index.php
commit c8fcc4032487eaf637d41486eb150b7182ecd1f1
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 19:38:08 2021 +0200
Update checker.php
commit f67efd00c10784ae75bd251add3d52af50d7addd
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 18:33:11 2021 +0200
Create checker.php
commit ab9bc164b4103de3c12ac97152e6d63040d5c4c6
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 18:30:58 2021 +0200
Update changelog.txt
commit 60d2b3280d5356fe0698561e8ef8991825fec6cb
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 18:30:39 2021 +0200
Create admin.php
commit c1998f8fbe683dd0bee8d94167bb896bd926c4c7
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 18:29:45 2021 +0200
Add admin panel.
commit 35a380176ff228067def9c2ecc52ccfe705de640
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 17:40:49 2021 +0200
Update changelog.txt
commit 57af03ba60cdcfe443e92c33c188c6cecb70eb10
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 17:29:42 2021 +0200
Create index.php
commit 354fe069f6205af09f26c99cfe2457dea3eb6a6c
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 17:28:48 2021 +0200
Delete .htpasswd
commit 8812785e31c879261050e72e20f298ae8c43b565
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 16:38:54 2021 +0200
New technique in header to protect our dev vhost.
commit bc4ba79e596e9fd98f1b2837b9bd3548d04fe7ab
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 16:37:20 2021 +0200
Update .htaccess
New technique in header to protect our dev vhost.
commit 61e5cc0550d44c08b6c316d4f04d3fcc7783ae71
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 15:45:48 2021 +0200
Update index.php
commit 3d66cd48933b35f4012066bcc7ee8d60f0069926
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 15:45:18 2021 +0200
Create changelog.txt
commit 4fb192727c29c158a659911aadcdcc23e4decec5
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 15:28:26 2021 +0200
Create stylesheet.css
commit 6f89af70fd23819664dd28d764f13efc02ecfd88
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 15:05:40 2021 +0200
Create index.php
commit 8d1beb1cf5a1327c4cdb271b8efb1599b1b1c87f
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 15:05:08 2021 +0200
Create .htpasswd
commit 6ddcc7a8ac393edb7764788c0cbc13a7a521d372
author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
date: Wed Oct 20 15:04:38 2021 +0200
Create .htaccess
There appears to be a total of 17 commits
┌──(kali㉿kali)-[~/archive/htb/labs/updown]
└─$ cd GIT ; ll
total 40K
4.0k drwxr-xr-x 3 kali kali 4.0k dec 4 14:31 .
4.0k -rw-r--r-- 1 kali kali 59 dec 4 14:31 admin.php
4.0k -rw-r--r-- 1 kali kali 147 dec 4 14:31 changelog.txt
4.0k -rw-r--r-- 1 kali kali 3.1k dec 4 14:31 checker.php
4.0k drwxr-xr-x 7 kali kali 4.0k dec 4 14:31 .git
4.0k -rw-r--r-- 1 kali kali 117 dec 4 14:31 .htaccess
4.0k -rw-r--r-- 1 kali kali 273 dec 4 14:31 index.php
8.0k -rw-r--r-- 1 kali kali 5.5k dec 4 14:31 stylesheet.css
4.0k drwxr-xr-x 3 kali kali 4.0k dec 4 14:31 ..
This appears to be relevant to the target web application, there are more files than what’s known up until this point from the enumeration
I’ll check the changelog.txt
file first and go over the rest
changelog.txt
┌──(kali㉿kali)-[~/…/htb/labs/updown/GIT]
└─$ cat changelog.txt
Beta version
1- Check a bunch of websites.
-- ToDo:
1- Multithreading for a faster version :D.
2- Remove the upload option.
3- New admin panel.
Based on the Todo list, it would appears that the target web app contained an uploading option, and it may still be present Additionally, there is a mention of an “admin panel” being updated
┌──(kali㉿kali)-[~/…/htb/labs/updown/GIT]
└─$ git show 8812785e31c879261050e72e20f298ae8c43b565
commit 8812785e31c879261050e72e20f298ae8c43b565
Author: Abdou.Y <84577967+ab2pentest@users.noreply.github.com>
Date: Wed Oct 20 16:38:54 2021 +0200
New technique in header to protect our dev vhost.
diff --git a/.htaccess b/.htaccess
index 44ff240..b317ab5 100644
--- a/.htaccess
+++ b/.htaccess
@@ -2,3 +2,4 @@ SetEnvIfNoCase Special-Dev "only4dev" Required-Header
Order Deny,Allow
Deny from All
Allow from env=Required-Header
+
The 8812785e31c879261050e72e20f298ae8c43b565
commit in particular goes over that said “admin panel”
It’s defined in the .htaccess
file
admin.php
┌──(kali㉿kali)-[~/…/htb/labs/updown/GIT]
└─$ cat admin.php
<?php
if(DIRECTACCESS){
die("Access Denied");
}
#ToDo
?>
The admin.php
file seems to deny direct access by default
index.php
┌──(kali㉿kali)-[~/…/htb/labs/updown/GIT]
└─$ cat index.php
<b>This is only for developers</b>
<br>
<a href="?page=admin">Admin Panel</a>
<?php
define("DIRECTACCESS",false);
$page=$_GET['page'];
if($page && !preg_match("/bin|usr|home|var|etc/i",$page)){
include($_GET['page'] . ".php");
}else{
include("checker.php");
}
?>
While the index.php
file appears to be the landing page, it also denies direct access and includes the checker.php
file
Additionally, there is a potentially vulnerable parameter, page
, with the PHP include
Due to the blacklist containing the key words (bin, usr, home, var, etc), LFI approach might be limited
checker.php
┌──(kali㉿kali)-[~/…/htb/labs/updown/GIT]
└─$ cat checker.php
<?php
if(DIRECTACCESS){
die("Access Denied");
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<link rel="stylesheet" type="text/css" media="screen" href="stylesheet.css">
<title>Is my Website up ? (beta version)</title>
</head>
<body>
<div id="header_wrap" class="outer">
<header class="inner">
<h1 id="project_title">Welcome,<br> Is My Website UP ?</h1>
<h2 id="project_tagline">In this version you are able to scan a list of websites !</h2>
</header>
</div>
<div id="main_content_wrap" class="outer">
<section id="main_content" class="inner">
<form method="post" enctype="multipart/form-data">
<label>list of websites to check:</label><br><br>
<input type="file" name="file" size="50">
<input name="check" type="submit" value="Check">
</form>
<?php
function isitup($url){
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, trim($url));
curl_setopt($ch, CURLOPT_USERAGENT, "siteisup.htb beta");
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$f = curl_exec($ch);
$header = curl_getinfo($ch);
if($f AND $header['http_code'] == 200){
return array(true,$f);
}else{
return false;
}
curl_close($ch);
}
if($_POST['check']){
# File size must be less than 10kb.
if ($_FILES['file']['size'] > 10000) {
die("File too large!");
}
$file = $_FILES['file']['name'];
# Check if extension is allowed.
$ext = getExtension($file);
if(preg_match("/php|php[0-9]|html|py|pl|phtml|zip|rar|gz|gzip|tar/i",$ext)){
die("Extension not allowed!");
}
# Create directory to upload our file.
$dir = "uploads/".md5(time())."/";
if(!is_dir($dir)){
mkdir($dir, 0770, true);
}
# Upload the file.
$final_path = $dir.$file;
move_uploaded_file($_FILES['file']['tmp_name'], "{$final_path}");
# Read the uploaded file.
$websites = explode("\n",file_get_contents($final_path));
foreach($websites as $site){
$site=trim($site);
if(!preg_match("#file://#i",$site) && !preg_match("#data://#i",$site) && !preg_match("#ftp://#i",$site)){
$check=isitup($site);
if($check){
echo "<center>{$site}<br><font color='green'>is up ^_^</font></center>";
}else{
echo "<center>{$site}<br><font color='red'>seems to be down :(</font></center>";
}
}else{
echo "<center><font color='red'>Hacking attempt was detected !</font></center>";
}
}
# Delete the uploaded file.
@unlink($final_path);
}
function getExtension($file) {
$extension = strrpos($file,".");
return ($extension===false) ? "" : substr($file,$extension+1);
}
?>
</section>
</div>
<div id="footer_wrap" class="outer">
<footer class="inner">
<p class="copyright">siteisup.htb (beta)</p><br>
<a class="changelog" href="changelog.txt">changelog.txt</a><br>
</footer>
</div>
</body>
</html>
The file contains what appears to be the uploading option, mentioned in the changelog.txt
file above
While the checker.php
file also denies direct access by default, it supports and handles POST request to scan a list of websites
- file upload and validation:
- upon form submission (
$_post['check']
), the script performs checks on the uploaded file:- It verifies that the file size is less than 10KB, and if not, it terminates with “File too large!”
- It checks the file extension to ensure it’s not one of the disallowed extensions (
php
,html
,py
,pl
,phtml
,zip
,rar
,gz
,gzip
,tar
).- There is no PHAR
- PHP code execution could be achievable with the
.phar
extension! It may be further leveraged
- PHP code execution could be achievable with the
- If it matches, the script terminates with “Extension not allowed!”
- There is no PHAR
- it creates a directory (
uploads/<md5_hash_of_current_timestamp>/
) with the php md5 and time to store the uploaded file if the directory doesn’t exist.- It uploads the file to the created directory.
- upon form submission (
- website status check:
- The script reads the uploaded file, which contains a list of websites.
$websites = explode("\n",file_get_contents($final_path))
- for each website in the list:
- It checks if the URL is valid and not attempting hacking based on specific patterns.
- the preg_match function is used to check if the
$site
variable contains certain patterns in the URL.- it checks that the url does not start with
file://
,data://
, orftp://
.
- it checks that the url does not start with
- It uses cURL to make an HTTP request to each website and checks if the HTTP response code is 200 (OK).
- If the site is up, it prints a message indicating that the site is up; otherwise, it prints a message indicating that the site seems to be down.
- The script reads the uploaded file, which contains a list of websites.
- cleanup:
- after checking the status of all websites, the script deletes the uploaded file using the php unlink
- Due to the deletion, PHP code execution will likely be timely-limited
- after checking the status of all websites, the script deletes the uploaded file using the php unlink
.htaccess
┌──(kali㉿kali)-[~/…/htb/labs/updown/GIT]
└─$ cat .htaccess
SetEnvIfNoCase Special-Dev "only4dev" Required-Header
Order Deny,Allow
Deny from All
Allow from env=Required-Header
The .htaccess
file configures the server to deny access by default but allow access if the request contains a privileged header, Special-Dev: only4dev
.
This explains the “deny by default” rule set to the all the PHP files above
SetEnvIfNoCase Special-Dev "only4dev" Required-Header
:- This line sets an environment variable (
Required-Header
) only if the request header namedSpecial-Dev
contains the case-insensitive string,only4dev
- This line sets an environment variable (
Order Deny,Allow
:- This line specifies the order in which the
Deny
andAllow
directives should be evaluated. In this case, it first denies by default, and then allows based on the condition specified in the next line
- This line specifies the order in which the
Deny from All
:- This line denies access to all requests by default
Allow from env=Required-Header
:- This line allows access only if the environment variable
Required-Header
is set. This variable is set in the previous line based on the condition in the request headerSpecial-Dev
- This line allows access only if the environment variable
The information gained may be further leveraged