• 當前位置:首頁 > IT技術 > Web編程 > 正文

    nodejs入門(0)
    2022-04-29 13:55:45

    簡介

    一些回顧

    在開始之前,我們先簡單回顧一下目前為止已經接觸過的web服務端:

    PHP:安裝后自動運行,搭配apache2食用,/etc/init.d/apache2 (restart)(start)(stop)調整apache2狀態;php腳本放在/var/www/html中;直接localhost(或云服務器公網IP)+http默認端口 訪問。

    python_socket服務端:直接python運行寫好的腳本就行了;運輸層內容,運行在某個套接字上;如果連接公網的話,IP需要填0.0.0.0。默認不支持http協議,與其交互需要使用nc或python_socket客戶端。實現功能的方面和PHP差異很大。

    python模板(以flask為例):直接python運行寫好的腳本就行了;運行在某個套接字上,支持http協議,實現功能的能力和PHP不相上下。

    nodejs簡介

    簡單的說, Node.js 就是運行在服務端的 JavaScript。

    從部署操作上來講,nodejs和PHP不同,而和python模板相似。安裝好nodejsnpm后,在nodejs服務端項目目錄下直接運行相關程序就可開啟服務:

    //server.js
    var http = require('http');
    
    http.createServer(function (request, response) {
    
        // 發送 HTTP 頭部 
        // HTTP 狀態值: 200 : OK
        // 內容類型: text/plain
        response.writeHead(200, {'Content-Type': 'text/plain'});
        
        // 發送響應數據 "Hello World"
        response.end('Hello World
    ');
    
    }).listen(8888);
    
    // 終端打印如下信息
    console.log('Server running at http://127.0.0.1:8888/');
    

    從理論上來講,nodejs和PHP就更不同了:

    #引自菜鳥教程#
    如果我們使用 PHP 來編寫后端的代碼時,需要 Apache 或者 Nginx 的 HTTP 服務器,并配上 mod_php5 模塊和 php-cgi。
    
    從這個角度看,整個"接收 HTTP 請求并提供 Web 頁面"的需求就不需要 PHP 來處理。
    
    不過對 Node.js 來說,概念完全不一樣了。使用 Node.js 時,我們不僅僅 在實現一個應用,同時還實現了整個 HTTP 服務器。事實上,我們的 Web 應用以及對應的 Web 服務器基本上是一樣的。
    

    nodejs簡單使用

    讓我們先了解下 Node.js 應用是由哪幾部分組成的:

    1. 引入 required 模塊:我們可以使用 require 指令來載入 Node.js 模塊。
    2. 創建服務器:服務器可以監聽客戶端的請求,類似于 Apache 、Nginx 等 HTTP 服務器。
    3. 接收請求與響應請求 服務器很容易創建,客戶端可以使用瀏覽器或終端發送 HTTP 請求,服務器接收請求后返回響應數據。

    Express框架

    熟悉了nodejs的基本使用方式,我們就直接開始看框架。

    安裝與鏈接

    有兩種安裝方式:本地安裝;預先全局安裝后鏈接到本地。(均需root)

    本地安裝

    直接在nodejs項目下npm install express即可。

    全局鏈接

    先全局安裝:npm install express -g

    再進入項目,進行鏈接:npm link express

    基礎知識

    基本部署/做題識別

    var express = require('express');
    var app = express();
    

    創建服務器

    var server = app.listen(8081, function () {   
        var host = server.address().address  
    	var port = server.address().port   
        console.log(" http://%s:%s", host, port)  
    })
    

    路由、請求和相應

    app.get('/', function (req, res) {
       // --
    })
    

    感覺很類似python里的裝飾器@app.route。

    app.get()就是路由,決定了誰去響應。這里的get指的是響應get請求。app.post()也很易于理解。

    還有一個app.use(),感覺用途就比較廣了,這里先附一個用例,以后碰到躲不過的再詳細學。

    路由規則是app.use(path,router)定義的,router代表一個由express.Router()創建的對象,在路由對象中可定義多個路由規則??墒侨绻覀兊穆酚芍挥幸粭l規則時,可直接接一個回調作為簡寫,也可直接使用app.getapp.post方法。即當一個路徑有多個匹配規則時,使用app.use()

    代碼可以提供public目錄下的圖片、css文件和js文件:
    app.use(express.static('public'));

    req是Request對象,表示 HTTP 請求,包含了請求查詢字符串,參數,內容,HTTP 頭部等屬性。

    res是Response對象,表示 HTTP 響應,即在接收到請求時向客戶端發送的 HTTP 響應數據。

    app與express.route()

    上述的app(用express()生成的對象)可以看做一個Express應用程序,它的作用是做全局的處理。而在稍微復雜一些的服務端邏輯中,我們還會看到express.route(),它被稱為迷你應用程序,用于將邏輯移動到單獨的文件中/"局部處理"。

    具體的,可以在nodejs工程的根目錄下創建app.js寫app相關的東西用于統籌,并創建routes文件夾用express.route寫細分邏輯。

    我們很快就可以在例題中見到類似的邏輯。

    例題1

    題目

    一個計算器。

    const express = require("express");
    const path = require("path");
    const vm2 = require("vm2");
    
    const app = express();
    app.use(express.urlencoded({ extended: true }));
    app.use(express.json());
    
    app.use(express.static("static"));
    
    const vm = new vm2.NodeVM();
    
    app.use("/eval", (req, res) => {
      const e = req.body.e;
      if (!e) {
        res.send("wrong?");
        return;
      }
      try {
        res.send(vm.run("module.exports="+e)?.toString() ?? "no");
      } catch (e) {
        console.log(e)
        res.send("wrong?");
      }
    });
    
    app.use("/flag", (req, res) => {
      if(Object.keys(Object.prototype).length > 0) {
        Object.keys(Object.prototype).forEach(k => delete Object.prototype[k]);
        res.send(process.env.FLAG);
      } else {
        res.send(Object.keys(Object.prototype));
      }
    })
    
    app.use("/source", (req, res) => {
      let p = req.query.path || "/src/index.js";
      p = path.join(path.resolve("."), path.resolve(p));
      console.log(p);
      res.sendFile(p);
    });
    
    app.use((err, req, res, next) => {
      console.log(err)
      res.redirect("index.html");
    });
    
    app.listen(process.env.PORT || 8888);
    

    考察一個很新的洞CVE-2022-21824.

    Due to the formatting logic of the "console.table()" function it was not safe to allow user controlled input to be passed to the "properties" parameter while simultaneously passing a plain object with at least one property as the first parameter, which could be "__proto__". The prototype pollution has very limited control, in that it only allows an empty string to be assigned to numerical keys of the object prototype.Node.js >= 12.22.9, >= 14.18.3, >= 16.13.2, and >= 17.3.1 use a null protoype for the object these properties are being assigned to.
    

    payload:console.table([{x:1}], ["__proto__"]);

    注意,這個payload要放到它的計算器里去,在本地的console里是沒用的!

    本地的console是客戶端瀏覽器自帶的JS,服務端的后端才是nodejs;新手(當時的我)真的會犯這種低級失誤的。

    復現

    如果我沒理解錯的話,那個洞的描述應該說得是它在>= 12.22.9, >= 14.18.3, >= 16.13.2, and >= 17.3.1這幾個版本修掉了。我不會下12、14、16中舊的版本,8大版本下連table都沒有、10.22版本下直接報語法錯,所以就復現失敗了。

    挖個版本小坑:https://github.com/nodesource/distributions/issues/33#issuecomment-169345680

    復現效果:

    搬運網圖:

    補充一些命令

    apt-cache madison <<package name>>查詢可以拿apt-get直接安裝的該軟件版本。

    apt-get install <<package name>>=<<version>>安裝指定版本;版本號從上面的回顯里復制完整的。

    從官方源安裝對應大版本:

    curl -sL https://deb.nodesource.com/setup_【大版本號】.x | sudo -E bash -
    sudo apt-get install -y nodejs

    本文摘自 :https://www.cnblogs.com/

    開通會員,享受整站包年服務
    国产呦精品一区二区三区网站|久久www免费人咸|精品无码人妻一区二区|久99久热只有精品国产15|中文字幕亚洲无线码