Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

<ul>

<li> test1 (1-2) - (fieldName3-1) </li>

<li> test2 (2-2) - (fieldName3-2) </li>

<li> test3 (3-2) - (fieldName3-3) </li>

<li> test4 (4-2) - (fieldName3-4) </li>

<li> test5 (5-2) - (fieldName3-5) </li>

</ul>

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

<ul>

<li> test1 (1-2) - (fieldName3-1) </li>

<li> test2 (2-2) - (fieldName3-2) </li>

<li> test3 (3-2) - (fieldName3-3) </li>

<li> test4 (4-2) - (fieldName3-4) </li>

<li> test5 (5-2) - (fieldName3-5) </li>

</ul>

23 changes: 22 additions & 1 deletion endPoint/h2HttpHostEndPoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,14 @@ export default class H2HttpHostEndPoint extends SecureHttpHostEndPoint {
this.#options.minVersion = "TLSv1.2";
this.#options.allowHTTP1 = true;
}

_sqlInjectionMiddleware = (stream, headers) => {
const reqUrl = headers[http2.constants.HTTP2_HEADER_PATH] || '';
const host = headers[http2.constants.HTTP2_HEADER_AUTHORITY] || 'localhost';
const url = new URL(reqUrl, `https://${host}`);
const queryString = this._decodeURIComponentSafe(url.search);
const sqlInjectionPattern = /(?:\b(SELECT|INSERT|DELETE|UPDATE|WHERE|DROP|EXEC|UNION|--|\*|#)\b.*?[=;]|\b(OR|AND)\b\s*?['"\d])/i;
return sqlInjectionPattern.test(queryString);
};
/**
* @param {string} urlStr
* @param {string} method
Expand Down Expand Up @@ -79,6 +86,20 @@ export default class H2HttpHostEndPoint extends SecureHttpHostEndPoint {
.createSecureServer(this.#options)
.on("stream", async (stream, headers) => {
this._checkCacheAsync(stream, headers, async () => {
if (this._sqlInjectionMiddleware(stream, headers)) {
stream.respond({ ':status': 400, 'content-type': 'text/plain' });
return stream.end('Bad Request: Potential SQL injection detected.');
}
const ip = stream.session.socket.remoteAddress;
try{
await this.rateLimiter.consume(ip)
}catch(err){
stream.respond({
':status': 429,
'retry-after': 60,
});
stream.end("Too many requests - try again later");
}
/** @type {Request} */
let cms = null;
/** @type {BinaryContent[]} */
Expand Down
25 changes: 25 additions & 0 deletions endPoint/httpHostEndPoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import CacheConnectionBase from "../models/CacheCommands/CacheConnection/CacheCo
import { HostEndPointOptions } from "../models/model.js";
import SqliteCacheConnection from "../models/CacheCommands/CacheConnection/SqliteCacheConnection.js";
import CacheSettings from "../models/options/CacheSettings.js";
import {RateLimiterMemory} from "rate-limiter-flexible"

let requestId = 0;
class HttpHostEndPoint extends HostEndPoint {
Expand All @@ -27,6 +28,8 @@ class HttpHostEndPoint extends HostEndPoint {
_cacheConnection;
/** @type {http.Server} */
_server;
/** @type {RateLimiterMemory} */
rateLimiter;
/**
*
* @param {string} ip
Expand All @@ -38,6 +41,10 @@ class HttpHostEndPoint extends HostEndPoint {
super(ip, port);
this._service = service;
this._cacheOptions = cacheOptions;
this.rateLimiter =new RateLimiterMemory({
points: 10,
duration: 60,
});
if (cacheOptions && cacheOptions.connectionType) {
switch (cacheOptions.connectionType) {
case "sqlite": {
Expand Down Expand Up @@ -353,5 +360,23 @@ class HttpHostEndPoint extends HostEndPoint {
this._server.close();
console.log(`server ip ${this._ip} and port ${this._port} killed`);
}
_decodeURIComponentSafe = (s) => {
try {
return decodeURIComponent(s);
} catch {
return s; // Return as-is if decoding fails
}
};
_sqlInjectionMiddleware = (req, res, next) => {
const url = new URL(req.url, `https://${req.headers.host}`);
const queryString = url.search;
const sqlInjectionPattern = /[\s'";()&|]|(SELECT|select|INSERT|insert|DELETE|delete|UPDATE|update|WHERE|where|DROP|drop|EXEC|exec|UNION|union|--|\*|#|\/\*|\/\*.*?\*\/)/;
if (sqlInjectionPattern.test(queryString)) {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('Bad Request: Potential SQL injection detected.');
} else {
next();
}
};
}
export default HttpHostEndPoint;
129 changes: 69 additions & 60 deletions endPoint/nonSecureHttpHostEndPoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import { StatusCodes } from "http-status-codes";
import HttpHostEndPoint from "./HttpHostEndPoint.js";
import { HostService } from "../services/hostServices.js";
import LightgDebugStep from "../renderEngine/Models/LightgDebugStep.js";
import StringResult from "../renderEngine/Models/StringResult.js";
import fs from "fs";

export default class NonSecureHttpHostEndPoint extends HttpHostEndPoint {
/**
Expand All @@ -17,71 +15,82 @@ export default class NonSecureHttpHostEndPoint extends HttpHostEndPoint {
constructor(ip, port, service, cacheOptions) {
super(ip, port, service, cacheOptions);
}

_createServer() {
this._server = http.createServer(async (req, res) => {
try {
this._securityHeadersMiddleware(req, res, async () => {
this._handleContentTypes(req, res, async () => {
this._checkCacheAsync(req, res, false, async () => {
const createCmsAndCreateResponseAsync = async () => {
const queryObj = url.parse(req.url, true).query;
let debugCondition =
queryObj.debug == "true" ||
queryObj.debug == "1" ||
queryObj.debug == "2";
let routingDataStep = debugCondition
? new LightgDebugStep(null, "Get Routing Data")
: null;
let rawRequest = debugCondition
? this.joinHeaders(req.rawHeaders)
: null;
/** @type {Request} */
let cms = await this._createCmsObjectAsync(
req.url,
req.method,
req.headers,
req.formFields,
req.jsonHeaders ? req.jsonHeaders : {},
req.socket,
req.bodyStr,
false
);
let result = await this._service.processAsync(
cms,
req.fileContents
);
let cachecms;
if (result.result) {

cachecms = result.responseCms;
result = result.result;
}
routingDataStep?.complete();
const [code, headers, body] = await result.getResultAsync(
routingDataStep,
rawRequest,
debugCondition ? cms.dict : undefined
);
const statuscode = Number(
result._request.webserver.headercode.split(" ")[0]
);
if (statuscode != 301 && statuscode != 302) {
this.addCacheContentAsync(
`http://${req.headers.host}${req.url}`,
body,
headers,
const ip = req.socket.remoteAddress;
try{
await this.rateLimiter.consume(ip)
}catch(err){
res.writeHead(429, {
'Content-Type': 'text/plain',
'Retry-After': 60,
});
return res.end("Too many requests - try again later");
}
this._sqlInjectionMiddleware(req, res, async () => {
this._securityHeadersMiddleware(req, res, async () => {
this._handleContentTypes(req, res, async () => {
this._checkCacheAsync(req, res, false, async () => {
const createCmsAndCreateResponseAsync = async () => {
const queryObj = url.parse(req.url, true).query;
let debugCondition =
queryObj.debug == "true" ||
queryObj.debug == "1" ||
queryObj.debug == "2";
let routingDataStep = debugCondition
? new LightgDebugStep(null, "Get Routing Data")
: null;
let rawRequest = debugCondition
? this.joinHeaders(req.rawHeaders)
: null;
/** @type {Request} */
let cms = await this._createCmsObjectAsync(
req.url,
req.method,
cachecms
req.headers,
req.formFields,
req.jsonHeaders ? req.jsonHeaders : {},
req.socket,
req.bodyStr,
false
);
let result = await this._service.processAsync(
cms,
req.fileContents
);
let cachecms;
if (result.result) {

cachecms = result.responseCms;
result = result.result;
}
routingDataStep?.complete();
const [code, headers, body] = await result.getResultAsync(
routingDataStep,
rawRequest,
debugCondition ? cms.dict : undefined
);
const statuscode = Number(
result._request.webserver.headercode.split(" ")[0]
);
}
res.writeHead(code, headers);
res.end(body);
};
await createCmsAndCreateResponseAsync();
if (statuscode != 301 && statuscode != 302) {
this.addCacheContentAsync(
`http://${req.headers.host}${req.url}`,
body,
headers,
req.method,
cachecms
);
}
res.writeHead(code, headers);
res.end(body);
};
await createCmsAndCreateResponseAsync();
});
});
});
});
})
} catch (ex) {
console.error(ex);
res.writeHead(StatusCodes.INTERNAL_SERVER_ERROR);
Expand Down
Loading