0%

网站的简单搭建

前言:

虽然之前就已经搭建过一次简单的登录注册网站了,但是随着一年web的学习对于php、html和js的理解才懂得之前的那些代码的含义。借为24级新生出题需要搭建一个登录网站的机会,此时再次搭建一个网站巩固对于语言的学习。

目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
web - admin
|
|--------files
|--------flag.sh
|--------run.sh
|--------TGlu.sql
|--------src
|--------404.html
|--------admin.php
|--------db.php
|--------index.php
|--------login.php
|--------register.php
|--------user.php
|--------docker-compose.yml
|--------Dockerfile

一、登录界面和注册界面

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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
//login.php
<?php
// 开始会话
session_start();
// 清除所有会话数据
session_unset();

// 连接数据库
include 'db.php';

// 处理用户登录
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = $_POST['username'];
$password = $_POST['password'];

// 使用预准备语句和参数化查询
$stmt = $conn->prepare("SELECT * FROM User WHERE username=? AND password=?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
$result = $stmt->get_result();

// 查询用户信息
// $sql = "SELECT * FROM User WHERE username='$username' AND password='$password'";
// $result = $conn->query($sql);

if ($result->num_rows == 1) {
$user = $result->fetch_assoc();
// 假设验证成功,将用户名存储在 session 中
$_SESSION['username'] = $username;
if ($user['username'] == 'admin') {
// 如果是admin用户,重定向到 admin.php
header("Location: admin.php");
exit();
} else {
// 如果不是admin用户,重定向到 user.php
header("Location: user.php");
exit();
}
} else {
$loginMessage = '用户名或密码错误!';
}
}

// 关闭数据库连接
$conn->close();
?>
<style>
* {
font-family: "Poppins", sans-serif;
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: #282a37;
background-size: cover;
background-position: center;
}

.wrapper {
position: relative;
width: 400px;
height: 450px;
background: #3e404d;
border: 2px solid rgba(255, 255, 255, 0.5);
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(15px);
}

.wrapper:hover {
box-shadow: 0 0 40px rgba(255,255,255,0.5);
background: #46474e;
}

.wrapper h1 {
font-size: 2em;
color: #fff;
text-align: center;
}

.wrapper .input-box {
position: relative;
width: 310px;
margin: 30px 0;
border-bottom: 2px solid #fff;
}

.wrapper .input-box input {
width: 100%;
height: 50px;
background: transparent;
outline: none;
border: none;
font-size: 1em;
color: #fff;
padding: 0 40px 0 5px;
}

.wrapper .input-box label {
position: absolute;
top: 50%;
left: 5px;
transform: translateY(-50%);
font-size: 1em;
color: #fff;
pointer-events: none;
transition: 0.5s;
}

.wrapper .input-box input:focus ~ label,
.wrapper .input-box input:valid ~ label {
top: -5px;
}

.wrapper .input-box .icon {
position: absolute;
right: 8px;
color: #fff;
font-size: 1.2em;
line-height: 57px;
}

.wrapper .row {
margin: -15px 0 15px;
font-size: 0.9em;
color: #fff;
display: flex;
justify-content: space-between;
}

.wrapper .row label {
display: flex;
align-items: center;
gap: 5px;
}

.wrapper .row a {
color: #fff;
text-decoration: none;
}

.wrapper .options a:hover {
text-decoration: underline;
}

.wrapper .btn {
width: 100%;
height: 40px;
background: #fff;
outline: none;
border: none;
border-radius: 40px;
cursor: pointer;
font-size: 1em;
font-weight: 500;
color: #000;
margin-top: 10px;
}

.btn:hover {
background: #ffffea;
}

.wrapper .signup-link {
font-size: 0.9em;
color: #fff;
text-align: center;
margin: 25px 0 10px;
}

.wrapper .signup-link a {
color: #fff;
text-decoration: none;
font-weight: 600;
}

.wrapper .signup-link a:hover {
text-decoration: underline;
}

@media (max-width: 360px) {
.wrapper {
width: 100%;
height: 100vh;
border: none;
border-radius: 0px;
}

.wrapper .input-box {
width: 290px;
}
#img {
z-index: -90;
}
}


</style>

<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
/>

<!--css file-->
<link rel="stylesheet" href="styles.css" />
<head>
<title>登录</title>
</head>
<body>

<div class="wrapper">
<form action="login.php" method="POST">
<h1>Login</h1>
<div class="input-box">
<input type="text" name="username" id="usernameInput" required />
<label>Username</label>
</div>
<div class="input-box">
<input type="password" name="password" id="passwordInput" required />
<label>Password</label>
</div>
<button type="submit" class="btn">Login</button>
<div class="signup-link">
<p>Don't have an account? <a href="register.php">Create one</a></p>
</div>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
var loginMessage = "<?php echo isset($loginMessage) ? $loginMessage : ''; ?>";
if (loginMessage !== '') {
alert(loginMessage);
}
});
</script>
</body>
</html>
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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
//register.php
<?php

include 'db.php';

// 处理用户注册
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = $_POST['username'];
$password = $_POST['password'];

// 检查数据库中是否已经存在相同用户名的用户
$check_sql = "SELECT * FROM User WHERE username=?";
$stmt = $conn->prepare($check_sql);
$stmt->bind_param("s", $username);
$stmt->execute();
$check_result = $stmt->get_result();

if ($check_result->num_rows > 0) {
$registerMessage = '用户名已存在,请选择其他用户名!';
} else {
// 插入用户信息到数据库
// 使用准备语句插入用户信息到数据库
$sql = "INSERT INTO User (username, password) VALUES (?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $username, $password);

if ($stmt->execute()) {
header("Location: login.php");
exit();
} else {
$registerMessage = '注册失败!';
}
}
}

// 关闭数据库连接
$conn->close();
?>
<style>
* {
font-family: "Poppins", sans-serif;
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: #282a37;
background-size: cover;
background-position: center;
}

.wrapper {
position: relative;
width: 400px;
height: 450px;
background: #3e404d;
border: 2px solid rgba(255, 255, 255, 0.5);
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(15px);
}

.wrapper:hover {
box-shadow: 0 0 40px rgba(255,255,255,0.5);
background: #46474e;
}

.wrapper h1 {
font-size: 2em;
color: #fff;
text-align: center;
}

.wrapper .input-box {
position: relative;
width: 310px;
margin: 30px 0;
border-bottom: 2px solid #fff;
}

.wrapper .input-box input {
width: 100%;
height: 50px;
background: transparent;
outline: none;
border: none;
font-size: 1em;
color: #fff;
padding: 0 40px 0 5px;
}

.wrapper .input-box label {
position: absolute;
top: 50%;
left: 5px;
transform: translateY(-50%);
font-size: 1em;
color: #fff;
pointer-events: none;
transition: 0.5s;
}

.wrapper .input-box input:focus ~ label,
.wrapper .input-box input:valid ~ label {
top: -5px;
}

.wrapper .input-box .icon {
position: absolute;
right: 8px;
color: #fff;
font-size: 1.2em;
line-height: 57px;
}

.wrapper .row {
margin: -15px 0 15px;
font-size: 0.9em;
color: #fff;
display: flex;
justify-content: space-between;
}

.wrapper .row label {
display: flex;
align-items: center;
gap: 5px;
}

.wrapper .row a {
color: #fff;
text-decoration: none;
}

.wrapper .options a:hover {
text-decoration: underline;
}

.wrapper .btn {
width: 100%;
height: 40px;
background: #fff;
outline: none;
border: none;
border-radius: 40px;
cursor: pointer;
font-size: 1em;
font-weight: 500;
color: #000;
margin-top: 10px;
}

.btn:hover {
background: #ffffea;
}

.wrapper .signup-link {
font-size: 0.9em;
color: #fff;
text-align: center;
margin: 25px 0 10px;
}

.wrapper .signup-link a {
color: #fff;
text-decoration: none;
font-weight: 600;
}

.wrapper .signup-link a:hover {
text-decoration: underline;
}

@media (max-width: 360px) {
.wrapper {
width: 100%;
height: 100vh;
border: none;
border-radius: 0px;
}

.wrapper .input-box {
width: 290px;
}
#img {
z-index: -90;
}
}
</style>

<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
/>

<!--css file-->
<link rel="stylesheet" href="styles.css" />
<head>
<title>注册</title>
<script>
// JavaScript代码,根据注册消息显示弹窗
window.onload = function() {
var registerMessage = "<?php echo $registerMessage; ?>";
if (registerMessage !== '') {
alert(registerMessage);
}
};
</script>
</head>
<body>

<div class="wrapper">
<form action="#" method="POST">
<h1>Register</h1>
<div class="input-box">
<!--<i class="fas fa-envelope icon"></i>-->
<input type="text" name="username" id="usernameInput" required />
<label>Username</label>
</div>
<div class="input-box">
<!--<i class="fas fa-lock icon"></i>-->
<input type="password" name="password" id="passwordInput" required />
<label>Password</label>
</div>


<button type="submit" class="btn">Register</button>

</form>
</div>
</body>
</html>

二、数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//db.php
<?php
$servername = "localhost";
$username = "root";
$password = "root";
$dbname = "TGlu";

$conn = new mysqli($servername, $username, $password, $dbname);

// 检查数据库连接
if ($conn->connect_error) {
die("数据库连接失败: " . $conn->connect_error);
}
?>
1
2
3
4
5
6
7
//run.sh
#!/bin/sh

mysqld_safe --skip-grant-tables&
sleep 20

mysql -uroot -proot < /TGlu.sql

sql文件直接从phpmyadmin导出,然后需要添加以下代码

1
2
3
4
5
6
7
--
-- 数据库: `TGlu`
--

drop database if exists `TGlu`;
create database `TGlu` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
use TGlu;

三、设置后台界面

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
//user.php
<?php
session_start();

// 检查用户是否登录,如果未登录则重定向到登录页面
if (!isset($_SESSION['username'])) {
header("Location: login.php"); // 重定向到登录页面
exit();
}

$username = $_SESSION['username'];

// 连接数据库
include 'db.php';

if (isset($_GET['id'])) {
$id = $_GET['id']; // 直接使用用户输入,允许 SQL 注入

// 构建 SQL 查询,允许联合注入
$sql = "SELECT flag FROM flag WHERE id = '$id' LIMIT 0,1";
$result = $conn->query($sql);
$error = $conn->error;

// 获取查询结果
if ($result->num_rows > 0) {
$data = $result->fetch_assoc();
echo $data['flag'];
} else {
echo "$error";
}

// 关闭数据库连接
$conn->close();
exit(); // 确保在返回 flag 值后停止脚本执行
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>主页</title>
<style>
.center-block {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
.center-block h1 {
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="center-block">
<h1>Welcome, <?php echo htmlspecialchars($username); ?>!</h1>
<button id="idButton">点击得到flag</button>
<script>
document.getElementById('idButton').addEventListener('click', function() {
// 构建请求 URL
const url = 'user.php?id=1';

// 发送 GET 请求
fetch(url)
.then(response => response.text())
.then(data => {
// 处理响应数据并显示弹窗
alert(data);
// 改变地址栏 URL
history.pushState(null, '', 'user.php?id=1');
})
.catch(error => {
console.error('Error:', error);
});
});
</script>
</div>
</body>
</html>
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
//admin.php
<?php
session_start();

// 检查用户是否登录,如果未登录则重定向到登录页面
if(!isset($_SESSION['username'])) {
header("Location: login.php"); // 重定向到登录页面
exit();
}

$username = $_SESSION['username'];

// 检查用户是否是 admin
if ($username !== 'admin') {
header("Location: 404.html"); // 重定向到访问被拒绝页面
exit();
}

$flag = "Yunxi{123}";

?>


<!DOCTYPE html>
<html lang="en">
<head>
<title>主页</title>
<style>
.center-block {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
.center-block h1 {
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="center-block">
<h1>Welcome, <?php echo $username; ?>!</h1>
<p>This is the real flag <?php echo $flag; ?></p>
</div>
</body>
</html>

四、设置主页和重定向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//index.php
<!DOCTYPE html>
<html>
<head>
<title>Redirect Example</title>
<script>
window.onload = function() {
if (window.location.pathname === '/' || window.location.pathname === '/index.php') {
window.location.href = '/login.php';
}
};
</script>
</head>
<body>

</body>
</html>

五、Dockerfile和docker-compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Dockerfile
FROM ctftraining/base_image_nginx_mysql_php_73

COPY files /tmp/files/

COPY src /var/www/html/

COPY /files/flag.sh /flag.sh
RUN chmod +x /flag.sh

RUN chown -R root:root /var/www/html/ && \
chmod -R 755 /var/www/html && \
mv /tmp/files/run.sh /run.sh && \
mv /tmp/files/TGlu.sql /TGlu.sql && \
chmod +x /run.sh && \
rm -rf /tmp/files/

RUN /run.sh

EXPOSE 80
1
2
3
4
5
6
7
8
9
10
11
12
//docker-compose.yml
version: "2"

services:

web:
build: .
restart: always
ports:
- "0.0.0.0:8087:80"
environment:
- FLAG=Yunxi{TGlu}

六、制作动态flag

1
2
3
4
5
6
7
8
9
10
11
//flag.sh
#!/bin/sh

sed -i "s/Yunxi{123}/$FLAG/g" /var/www/html/admin.php

# 覆盖掉环境变量,防止非预期
export FLAG=nonono
FLAG=nonono

# 删除自身
rm -f /flag.sh

注:

如果使用的是Windows 编辑器,请确保保存文件时使用 Unix 风格的换行符(LF),而不是 Windows 风格的换行符(CRLF)。