侧边栏壁纸

基于AI大模型的Web攻击检测系统(源码分析)

2024年11月10日 904阅读 2评论 1点赞

本系统由作者自己个人独立完成,作为了自己的课题研究(未经作者允许,禁止转载!!!)

代码分析


require('mail/autoload.php');
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require('vendor/autoload.php');
use WebSocket\Client;

上诉代码分别引用了PHPmailer和科大讯飞第三库


function fetchAndClearLog($url) {
    // 使用file_get_contents()函数读取远程文件内容
    $content = file_get_contents($url);
    file_put_contents('log1.log', $content, FILE_APPEND);//网络日志处理后的保存位置和名称,要和原日志名称区分
    $lines = explode("
", $content);

    // 遍历每一行并处理日志信息
    if (is_array($lines) && count($lines) > 0) {
        foreach ($lines as $line) {
            $parts = preg_split('/\s+/', $line);
            if (count($parts) >= 10) {
                $ip = $parts[0];
                $date = str_replace('[', '', $parts[3]);
                $request = str_replace('"', '', $parts[5]);
                $status = $parts[6];
                $size = str_replace('"', '', $parts[7]);
                $referer = $parts[8];
                $userAgent = $parts[9];
                $zt = 1;
$logUrl = './log.log'; // 替换为实际的网络日志URL
fetchAndClearLog($logUrl);

上诉代码初步实现对宝塔面板日志进行分割,分为了ip,请求时间,请求方式,访问URL等等


                // 检查是否存在XSS、SQL注入、Sanitization攻击和PHP代码注入
                if (preg_match('/^([\/\w \.-]*)*\/?$/', $status)) {
                    $result1 = "正常请求";
                    $zt = 0;
                } elseif (preg_match('/]*>(.*?)<\/script>/is', $status)) {
                    $result1= 'XSS攻击';
                } elseif (preg_match('/(\bSELECT\b|\bINSERT\b|\bUPDATE\b|\bDELETE\b|\bDROP\b|\bALTER\b|\bCREATE\b)/i', $status)) {
                    $result1 = 'SQL注入';
                } elseif (preg_match('/(\bhtmlspecialchars\b|\bstrip_tags\b|\baddslashes\b)/i', $status)) {
                    $result1= 'Sanitization攻击';
                } elseif (preg_match('/(\beval\b|\bassert\b|\bsystem\b|\bpopen\b)/i', $status)) {
                    $result1= 'PHP代码注入';
                } else {
                    $testClass = new Test();
                    $result1 = $testClass->xfyun($status);
                    if (strpos($result1, '攻击类型:') !== false) {
                        $result1 = str_replace('攻击方式:', '', $result1);
                        $zt = 2;
                    } else {
                        $result1= '异常';
                        $zt = 3;
                    }
                }

实现对访问URL进行判断


                //IP定位
                $dwkey = "******"; // 替换为你的高德地图API密钥
                $dw = "https://restapi.amap.com/v3/ip?ip={$ip}&output=json&key={$dwkey}";
                
                // 发送HTTP GET请求
                $responsedw = file_get_contents($dw);
                
                // 解析JSON数据
                $datadw = json_decode($responsedw, true);
                if (isset($datadw['status']) && $datadw['status'] == '1') {
                    $province = $datadw['province'];
                }

实现对ip进行定位(只限于国内)


                include './connect.php';
                $sql = "INSERT INTO soul_waf (ip, province, date, request, status, size, referer, useragent, result, zt) VALUES ('$ip', '$province' ,'$date', '$request', '$status', '$size', '$referer', '$userAgent', '$result1', '$zt')";
                
                if ($conn->query($sql) === TRUE) {
                }
                // 关闭连接
                $conn->close();

引用connect.php(连接数据库),将数据保存到数据库中


// 连接到数据库
$servername = "***";//自己的服务器IP
$username = "***";//数据库名
$password = "***";//用户名
$dbname = "***";//密码

// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);

// 检查连接
if ($conn->connect_error) {
    die("连接失败: " . $conn->connect_error);
} 

上诉为connect.php为实现连接数据库


if ($zt != 0) {
                    // 将内容写入到blacklist.conf文件中
                    file_put_contents('blacklist.conf', 'deny ' . $ip . ';', FILE_APPEND);
                    session_start();
    
                    $mail = new PHPMailer(true);
                    try {
                    
                        $mail->isSMTP();
                        $mail->Host = '***'; // SMTP服务器地址(列:smtp.qq.com)
                        $mail->SMTPAuth = true;
                        $mail->Username = '***'; // 发件人邮箱地址
                        $mail->Password = '***'; // 发件人POP3
                        $mail->SMTPSecure = 'ssl';
                        $mail->Port = ***;//端口号
                        
                        $mail->setFrom('***', 'Soul'); // 发件人邮箱和名称地址
                        $mail->addAddress('***'); // 收件人邮箱地址
                        
                        $mail->isHTML(true);
                        $mail->Subject = 'Soul攻击检测系统';
                        $mail->Body    = "时间:{$date},攻击IP:{$ip},请求URL:{$status},攻击类型:{$result1}";
                    
                        $mail->send();
                    } catch (Exception $e) {
                    }
                }

上诉代码构建了一个blacklist.conf(用来储存攻击者ip),然后通过邮箱告知管理者攻击者的有关信息


class Test{
    function xfyun($status){
            $addr = "wss://spark-api.xf-yun.com/v3.1/chat";
            //密钥信息,在开放平台-控制台中获取:https://console.xfyun.cn/services/cbm
            $Appid = "***";
            $Apikey = "***";
            // $XCurTime =time();
            $ApiSecret ="***";
            // $XCheckSum ="";
            
            // $data = $this->getBody("你是谁?");
            $authUrl = $this->assembleAuthUrl("GET",$addr,$Apikey,$ApiSecret);
            //创建ws连接对象
            $client = new Client($authUrl);

            // 连接到 WebSocket 服务器
            if ($client) {
                $st = $status;
                // 发送数据到 WebSocket 服务器
                $data = $this->getBody($Appid,$st);
                $client->send($data);

                // 从 WebSocket 服务器接收数据
                $answer = "";
                while(true){
                    $response = $client->receive();
                    $resp = json_decode($response,true);
                    $code = $resp["header"]["code"];
                    if(0 == $code){
                        $status = $resp["header"]["status"];
                        if($status != 2){
                            $content = $resp['payload']['choices']['text'][0]['content'];
                            $answer .= $content;
                        }else{
                            $content = $resp['payload']['choices']['text'][0]['content'];
                            $answer .= $content;
                            $total_tokens = $resp['payload']['usage']['text']['total_tokens'];
                            break;
                        }
                    }else{
                        echo "服务返回报错".$response;
                        break;
                    }
                }

                $result1 = $answer;
                return $result1;
            } else {
                echo "无法连接到 WebSocket 服务器";
            }



        }

        /**
         * 发送post请求
         * @param string $url 请求地址
         * @param array $post_data post键值对数据
         * @return string
         */
        function http_request($url, $post_data, $headers) {         
          $postdata = http_build_query($post_data);
          $options = array(
            'http' => array(
              'method' => 'POST',
              'header' => $headers,
              'content' => $postdata,
              'timeout' => 15 * 60 // 超时时间(单位:s)
            )
          );
          $context = stream_context_create($options);
          $result = file_get_contents($url, false, $context);
 
          echo $result; 
            
          return "success";
        }

        //构造参数体
        function getBody($appid,$question){
            $header = array(
                "app_id" => $appid,
                "uid" => "12345"
            );
            
            $parameter = array(
                "chat" => array(
                    "domain" => "general",//根据使用的版本要修改
                    "temperature" => 0.5,
                    "max_tokens" => 1024
                )
            );
            
            $payload = array(
                "message" => array(
                    "text" => array(
                        array("role" => "system", "content" => "请根据我给出的请求url,仅回答攻击方式"),
                        // 需要联系上下文时,要按照下面的方式上传历史对话
                        // array("role" => "user", "content" => "你是谁"),
                        // array("role" => "assistant", "content" => "....."),
                        // ...省略的历史对话
                        array("role" => "user", "content" => $question)
                    )
                )
            );
            
            $json_string = json_encode(array(
                "header" => $header,
                "parameter" => $parameter,
                "payload" => $payload
            ));

            return $json_string;

        }
        //鉴权方法
        function assembleAuthUrl($method, $addr, $apiKey, $apiSecret) {
            if ($apiKey == "" && $apiSecret == "") { // 不鉴权
                return $addr;
            }
            
            $ul = parse_url($addr); // 解析地址
            if ($ul === false) { // 地址不对,也不鉴权
                return $addr;
            }
            
            // // $date = date(DATE_RFC1123); // 获取当前时间并格式化为RFC1123格式的字符串
            $timestamp = time();
            $rfc1123_format = gmdate("D, d M Y H:i:s \G\M\T", $timestamp);
            // $rfc1123_format = "Mon, 31 Jul 2023 08:24:03 GMT";

            
            // 参与签名的字段 host, date, request-line
            $signString = array("host: " . $ul["host"], "date: " . $rfc1123_format, $method . " " . $ul["path"] . " HTTP/1.1");
            
            // 对签名字符串进行排序,确保顺序一致
            // ksort($signString);
            
            // 将签名字符串拼接成一个字符串
            $sgin = implode("\n", $signString);
            
            // 对签名字符串进行HMAC-SHA256加密,得到签名结果
            $sha = hash_hmac('sha256', $sgin, $apiSecret,true);
            $signature_sha_base64 = base64_encode($sha);
            
            // 将API密钥、算法、头部信息和签名结果拼接成一个授权URL
            $authUrl = "api_key=\"$apiKey\", algorithm=\"hmac-sha256\", headers=\"host date request-line\", signature=\"$signature_sha_base64\"";
            
            // 对授权URL进行Base64编码,并添加到原始地址后面作为查询参数
            $authAddr = $addr . '?' . http_build_query(array(
                'host' => $ul['host'],
                'date' => $rfc1123_format,
                'authorization' => base64_encode($authUrl),
            ));
            
            return $authAddr;
        }
}

上诉为科大讯飞(作者改编过部分)实际用起来还需根据其不同版本才能使用


成果使用


构建的数据库
m3b2h5bq.png
构建的IP黑名单(blacklist.conf)
m3b2jqa4.png
更改nginx配置文件,引入blacklist.conf
m3b2q39t.png

while true; do php index.php; sleep 5; done

构建一个run.sh文件(实现业务逻辑自动化运行),引用index.php(上诉由PHP语言写的业务逻辑)
然后在宝塔面板中安装软件进程守护管理器,然后添加进程
m3b2vg60.png
对blacklist.conf中的IP禁止访问
m3b2zn8q.png
邮箱告知
m3b30tpw.png


数据可视化

将数据库中的数据可视化
m3b34t8d.png

点击查看


本系统为1.0版本,2.0版本正在开发( 点击查看

1
打赏

—— 评论区 ——

请登录后发表评论
立即登录 用户注册
LOGIN
  1. 头像
    回复

    你的才华让人惊叹,你是我的榜样。 http://www.55baobei.com/0C3zLqSY2r.html

  2. 头像
    RDFYjolf
    回复

    555

人生倒计时
舔狗日记