搭建 PHP 开发环境并配置权限

以下是创建 PHP 开发环境、配置 MySQL 和 phpMyAdmin 权限、以及创建 index.php 文件的详细步骤。

### 步骤 1: 创建目录并进入项目目录

在终端中执行以下命令:

mkdir php-dev && cd php-dev


### 步骤 2: 创建 docker-compose.yml 文件

php-dev 目录下创建一个 docker-compose.yml 文件,内容如下:

version: '3.7'

services:
  # 构建 MySQL 服务
  mysql:
    image: mysql:8.0 # 使用官方 MySQL 镜像
    container_name: php_mysql
    environment:
      MYSQL_ROOT_PASSWORD: password # 设置 MySQL root 密码
      MYSQL_DATABASE: pikachu # 设置初始化数据库
      MYSQL_USER: user # 创建用户
      MYSQL_PASSWORD: password # 设置用户密码
      # MYSQL_ALLOW_EMPTY_PASSWORD: "yes" # 允许空密码
    command:
      - mysqld
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_bin
      - --lower_case_table_names=1
    ports:
      - "3306:3306" # 映射端口
    volumes:
      - mysql_data:/var/lib/mysql # 数据持久化

  # 构建 PHP+Apache 服务
  web:
    image: php:8.2-apache # 使用 PHP + Apache 官方镜像
    container_name: php-apache
    depends_on:
      - mysql # 确保 MySQL 在此服务之前启动
    volumes:
      - ./html:/var/www/html # 将主机目录挂载到容器工作目录
    ports:
      - "8080:80" # 映射端口

  # 构建 phpMyAdmin 服务
  phpmyadmin:
    image: phpmyadmin/phpmyadmin # 使用官方 phpMyAdmin 镜像
    container_name: phpmyadmin
    environment:
      PMA_HOST: php_mysql # 设置连接的 MySQL 容器名称
      PMA_USER: user      # 设置 phpMyAdmin 使用的数据库用户名
      PMA_PASSWORD: password # 设置 phpMyAdmin 使用的密码
    depends_on:
      - mysql # 确保 MySQL 启动后才启动 phpMyAdmin
    ports:
      - "8081:80" # 映射端口

# 定义持久化存储
volumes:
  mysql_data:


### 步骤 3: 启动 Docker 服务

php-dev 目录下执行以下命令启动服务:

docker-compose up -d


这将会启动 MySQL、PHP+Apache 和 phpMyAdmin 服务。

### 步骤 4: 授权普通用户创建数据库和管理权限

MySQL 容器启动后,执行以下命令为普通用户 user 授予创建、删除、修改数据库的权限。

首先,进入 MySQL 容器:

docker exec -it php_mysql mysql -u root -p


输入 root 密码后,执行以下 SQL 语句:

GRANT CREATE, DROP, ALTER, INDEX ON *.* TO 'user'@'%';
FLUSH PRIVILEGES;


这将授予 user 用户在所有数据库上的创建、删除、修改和索引权限,并刷新权限表。

### 步骤 5: 创建 index.php 文件

php-dev 目录下创建 html 文件夹,并在其中创建 index.php 文件:

echo "<?php phpinfo(); ?>" > html/index.php


### 步骤 6: 访问 PHP 开发环境

1. **访问 PHP 页面**:在浏览器中访问 `http://localhost:8080/`,你将看到 PHP 配置信息页面。

2. 访问 phpMyAdmin:在浏览器中访问 `http://localhost:8081/`,使用以下凭据登录:

- **用户名**:`user`
- **密码**:`password`

登录后,你可以使用 phpMyAdmin 来管理 MySQL 数据库和执行其他操作。

### 总结

通过以上步骤,你成功搭建了一个包含 MySQL、PHP+Apache 和 phpMyAdmin 的开发环境,并授予了普通用户创建数据库的权限。同时,你也创建了一个简单的 PHP 文件来展示 PHP 配置信息。

#docker #php #mysql #phpmyadmin #开发环境 #权限控制
1. **最小化修改**:修复未授权访问漏洞
时,避免重构现有的系统架构,重点加强身份验证和权限控制。
2. **身份验证和权限管理**:实施严格的用户身份验证机制,并通过会话或JWT等方式验证每个请求的合法性。
3. **细粒度的权限控制**:基于角色、ACL等方式实现细粒度的权限管理,确保用户只能执行授权操作。
4. **避免敏感信息泄露**:避免通过URL等方式传递敏感信息,增强系统的安全性。

通过这些修复方法,可以有效防止未授权访问漏洞,提升系统的安全性。  
#未授权访问 #Web安全 #身份验证 #权限控制 #安全修复


### 频率限制

#### 漏洞点

频率限制漏洞发生在没有对用户操作进行适当的限制时,特别是在关键业务操作中,如用户登录、账户注册、敏感操作等。攻击者可以利用频繁的请求,例如密码爆破、垃圾信息填充等,造成系统资源消耗或绕过正常的业务限制,从而进行攻击。

#### 漏洞代码

在没有频率限制的情况下,攻击者可以不断尝试密码或进行其他重复性请求:

```php
<?php
// 用户登录
if (isset($_POST['username']) && iss
et($_POST['password'])) {
$username = $_POST['username'];
$password = $_POST['password'];

/
/ 进行用户身份验证
$query = "SELECT * FROM users WHERE username
= '$username' AND password = '$password'";
    $result = mysqli_query($conn, $query);
    if (mysqli_num_rows($result) > 0) {
        echo "Login successful!";
    } else {
        echo "Invali
d credentials!";
}
}
?>
```

#### 漏洞产生的危害

- **密码爆破**:攻击者可以通过多次尝试登录,利用暴力破解等方式获取用户密码。
- **垃圾信息填充**:例如频繁发起订单、发表评论等,可能导致系统资源浪费、性能下降,影响正常用户使用。
- **拒绝服务攻击**:频繁请求可以占用服务器资源,导致合法用户无法使用服务,形成拒绝服务(DoS)攻击。
- **验证码绕过**:攻击者可以通过绕过验证码或多次尝试来提高成功率,从而进行暴力破解。

#### 漏洞产生的原因

- **缺乏请求频率限制**:关键操作缺乏限制,未对用户的请求频率进行有效控制。
- **没有使用有效的缓存机制**:没有使用缓存机制(如Memcached、Redis)来存储请求次数,从而缺乏对频繁操作的跟踪。
- **未设置多次失败后锁定机制**:没有在失败尝试超过一定次数后锁定用户或请求。

#### 修复思路

1. **最小化修改**:修复时,主要增强现有的频率限制,避免大规模改动现有代码。
2. **引入请求频率限制**:在每个关键操作前加入对IP、用户名、设备等的频率限制。例如,限制每分钟的登录尝试次数。
3. **增加锁定机制**:当尝试次数超过阈值时,暂时锁定账户,并显示适当的错误信息。
4. **引入验证码**:在多次失败后,强制显示验证码,防止暴力破解。
5. **使用缓存存储尝试次数**:使用Redis、Memcached等缓存系统来存储用户尝试次数,限制频率。

#### 漏洞修复

##### 1. **频率限制和锁定机制

利用缓存机制(如Redis)存储用户的尝试次数,达到阈值后限制登录:

<?php
session_start();
$redis = new Redis();
$redis->connect('localhost', 6379);

$username = $_POST['username'];
$attempts = $redis->get('login_attempts_' . $username);

// 如果尝试次数超过5次,锁定账户5分钟
if ($attempts >= 5) {
die('Too many login attempts. Please try again later.');
}

// 进行密码验证
$password = $_POST['password'];
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $query);
if (mysqli_num_rows($result) > 0) {
echo "Login successful!";
$redis->del('login_attempts_' . $username); // 登录成功后清除尝试次数
} else {
$redis->incr('login_attempts_' . $username); // 增加尝试次数
$redis->expire('login_attempts_' . $username, 600); // 设置过期时间为10分钟
echo "Invalid credentials!";
}
?>

解释**:

- 每次登录时,首先检查用户的登录尝试次数。
- 如果超过设定阈值(如5次),则锁定账户并提示用户稍后再试。
- 使用Redis存储登录尝试
次数,过期时间设置为10分钟,防止频繁的暴力破解。

##### 2. **验证码引入


- **缺乏有效的访问控制**:未对每个请求和用户身份进行严格的访问控制,导致权限判断不到位。
- **信任用户输入**:直接使用用户输入的数据(如 URL 参数、表单数据等)进行权限验证,而没有对其进行适当的验证和限制。
- **不完善的权限检查**:在后台未对每个操作进行权限校验,只依
赖前端的展示权限,造成攻击者绕过前端控制。
- **未分配适当的用户角色**:用户角色和权限设置不当,导致某些用户能够执行本不该有的操作。

#### 修复思路

1. **最小化修改**:在修复越权漏洞时,应专注于添加或修改访问控制逻辑,避免大规模修改业务逻辑,确保兼容性。
2. **实施严格的访问控制**:根据每个用户的角色和权限对敏感资源进行细粒度的控制,避免任意用户访问他人数据。
3. **身份验证和权限校验**:对每个敏感操作都进行权限检查,确保用户只有在有权限时才能进行操作。
4. **输入验证和过滤**:不要信任用户输入,所有用户提供的数据必须经过验证和过滤,避免参数伪造和越权访问。

#### 漏洞修复

##### 1. **加强权限控制

修复方法:使用权限校验来确保用户只能访问自己的数据。例如,在数据库查询时,不允许直接使用来自客户端的 `user_id`,而应根据当前登录用户的身份来查询数据。

<?php
// 当前用户的ID
$current_user_id = $_SESSION['user_id']; // 通过会话获取当前登录用户的ID

// 用户只能访问自己的数据
$query = "SELECT * FROM users WHERE id = $current_user_id";
$result = mysqli_query($conn, $query);

// 显示用户信息
$row = mysqli_fetch_assoc($result);
echo "Hello, ".$row['name']."!";
?>

解释**:

- 当前用户的ID应该通过会话、Token等安全方式获取,而不是直接从用户输入中获取,防止攻击者篡改 `user_id`。

##### 2. **权限校验函数

修复方法:通过权限校验函数,确保每个请求的操作仅限于特定权限的用户执行。

<?php
// 权限检查函数
function check_permission($user_id, $action) {
// 检查用户是否有权限执行某个操作
if ($action == 'edit' && $_SESSION['role'] == 'admin') {
return true;
} elseif ($action == 'view' && $_SESSION['user_id'] == $user_id) {
return true;
}
return false;
}

// 用户输入的数据
$user_id = $_GET['user_id'];
$action = $_GET['action']; // 操作类型

// 检查是否有权限
if (check_permission($user_id, $action)) {
// 执行操作
echo "用户有权限执行此操作";
} else {
die('无权限访问');
}
?>

解释**:

- `check_permission()` 函数用来判断当前用户是否有权限执行某个特定操作。确保不同权限的用户只能执行被允许的操作。

##### 3. **禁止直接通过URL访问敏感资源

修复方法:避免通过URL直接访问敏感资源,改为使用会话或权限校验来访问。例如,通过检查登录状态或角色来限制访问。

<?php
// 通过会话验证用户身份
session_start();
if (!isset($_SESSION['user_id'])) {
die('请先登录');
}

// 如果用户尝试访问不属于他们的数据,进行检查
if ($_SESSION['user_id'] != $_GET['user_id']) {
die('无权限访问该用户数据');
}
?>

解释**:

- 使用 `session` 变量确保只有登录用户可以访问其自身数据,防止通过 URL 直接访问其他用户的数据。

#### 总结

1. **最小化修改**:修复越权漏洞时,尽量避免大规模的业务逻辑改动,专注于添加或修改访问控制逻辑,以确保现有系统互操作性。
2. **身份验证和权限校验*
*:在每个关键操作之前,必须严格校验用户的身份和权限,确保用户只能访问和操作自己有权访问的数据。
3. **严格的输入验证和过滤**:避免直接信任用户输入,确保所有敏感操作都经过严格的验证。
4. **会话和角色控制**:通过会话和角色控制访问权限,确保只有授权用户可以执行特定的操作。

通过这些措施,可以有效防止越权漏洞,提升系统的安全性。  
#越权漏洞 #Web安全 #权限控制 #安全修复

### 未授权访问/无鉴权/鉴权绕过

#### 漏洞点

未授权访问(或无鉴权/鉴权绕过)漏洞是指用户在没有适当身份验证和权限控制的情况下,访问本不应公开的资源或执行本不应允许的操作。这种漏洞通常是由于应用程序未正确实施身份验证机制或绕过了
权限验证,攻击者可通过直接访问未授权的 URL、篡改请求参数或使用其他手段绕过安全机制。

#### 漏洞代码

在以下示例中,应用程序直接根据传递的用户ID
返回数据,没有进行有效的权限验证,导致未授权的访问。
 
 
Back to Top