diff --git a/README.md b/README.md index 6c25ee7..66affb3 100644 --- a/README.md +++ b/README.md @@ -384,5 +384,6 @@ MySQL localhost:3306 ssl SQL> select * from store_test; C:\> "C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqldump.exe" -u root -p nusbank > d:/nusbank.sql ``` - -[Next](./server-side.md) \ No newline at end of file +## Others +* [Server Side](./server-side.md) +* [Security & API](./security-api.md) \ No newline at end of file diff --git a/files/homework1/backend_database_homework1.docx b/files/homework1/backend_database_homework1.docx index 9546f10..7e43244 100644 Binary files a/files/homework1/backend_database_homework1.docx and b/files/homework1/backend_database_homework1.docx differ diff --git a/files/homework1/nusbank.png b/files/homework1/nusbank.png new file mode 100644 index 0000000..ea9b172 Binary files /dev/null and b/files/homework1/nusbank.png differ diff --git a/security-api.md b/security-api.md new file mode 100644 index 0000000..0a97d98 --- /dev/null +++ b/security-api.md @@ -0,0 +1,256 @@ +# Security and API + +* Defense on depth +* Best Practices for web servers + + switch off unnecessary funtionality + + limit secure remote access + + use accounts with limited privileges + + segregate development, testing and live environment + + segregate data + + secrity patches + + monitor and audit servers and logs + + use security tools +* Top 10 Application security risks + + Injection - + + Broken authentication - compromised passwords + + sensitive data exposure + + xxe + + broken acess control + + security misconfiguration + +[Equifax case study](https://www.csoonline.com/article/3444488/equifax-data-breach-faq-what-happened-who-was-affected-what-was-the-impact.html) +* security patches +* broken authentication +* broken access control +* security misconfiguration +* single point of failure +* lack of management commitment + +## Security od Data in motion +* HTTPS / FTPS +* Type of SSL Certificates + + Signed by a Cerficate Authority (CA) + + Self-signed certificates (less trusted. For testing) + + + self sigend + ``` + $ openssl genrsa -out key.pem + $ openssl req -new -key key.pem -out csr.pem + $ openssl x509 -req -days 9999 -in csr.pem -signkey key.pem -out cert.pem + $ rm csr.pem + ``` + + ```Javascript + + ``` +* role based access control + + ## Security date at rest + * encrypt + + sensitive files + + storage drive + + password +* security of username and password + +## Regulation and Standards +* [international](https://www.pcisecuritystandards.org/) +* [Singapore](https://www.mas.gov.sg/regulation/guidelines/technology-risk-management-guidelines) +* [Personal Data Protection Act](https://www.pdpc.gov.sg/Overview-of-PDPA/The-Legislation/Personal-Data-Protection-Act) +* [FintTech Service](https://singaporefintech.org/sfa-launches-digital-self-assessment-framework-to-fast-track-fintech-firms-partnerships-with-financial-institutions/) + +## API Security +* Basic Authentication +* API key +* Bearer token +* JSON Web Token (JWT) + +## SQL Injection attack + +* sending body `{ id = "5 or 1=1" }`, will return all records. Thus, data leak +* need strong validation of inputs + +```javascript +// GET route for /user/id query +// with body = { "id": 2 } +app.get("/user/id", (request, response) => { + console.log(request.body); + // !!! validation example !!! + if (request.body.id === null + || Number.isNaN(request.body.id) + || !Number.isInteger(request.body.id)) { + response.send("Some id error occur"); + return; + } + // + connection.query(`SELECT * FROM users WHERE user_id = ${request.body.id}`, + (err, result) => { + if (err) { + response.send("Some id error occur"); + } + else { + response.send(result); + } + }); +}); + +``` + +## Code organisation & management +* folder tree + + \server.js + + \database.js + + \routes => store all routes + + \routes\customer.js + + \routes\seller.js + +* modularise into individual module file + + server.js : setup server listen and route linkage + ```javascript + const express = require("express"); + const bodyParser = require("body-parser"); + + const CustomerRouter = require("./routes/customer"); + const SellerRouter = require("./routes/seller"); + + let app = express(); //uri mapper + app.use(bodyParser.json()); + + app.use("/customer", CustomerRouter); + app.use("/seller", SellerRouter); + + app.listen(3000); + ``` + + database.js : database connection + ```javascript + const mysql = require("mysql"); + + let params = { + host: "localhost", + user: "root", + password: "root", + database: "sales", + }; + + mysqlConnection = mysql.createConnection(params); + + mysqlConnection.connect((err) => { + if (err) { + console.log("Failed to Connect"); + } else { + console.log("Connection successful"); + } + }); + + module.exports = mysqlConnection; + ``` + + customer.js : customer apis + ```javascript + const express = require("express"); + const connection = require("../database"); // import database connection + + CustomerRouter = express.Router(); + + // localhost:3000/customer/ + CustomerRouter.get("/", (req, res) => { + connection.query("select * from customer", (err, rows) => { + if (err) { + console.log(err); + res.send("Some error occurred"); + } else { + res.send(rows); + } + }); + }); + + // localhost:3000/customer/name/Zixuan + CustomerRouter.get("/name/:value", (req, res) => { + connection.query( + `select * from customer where customer_name = '${req.params.value}'`, + (err, rows) => { + if (err) { + console.log(err); + res.send("Some error occurred"); + } else { + res.send(rows); + } + } + ); + }); + + // localhost:3000/customer/id/10 + CustomerRouter.delete("/id/:value", (req, res) => { + connection.query( + `delete from customer where customer_id = ${req.params.value}`, + (err, rows) => { + if (err) { + console.log(err); + res.send("Some error occurred"); + } else { + res.send("Deleted Successfully"); + } + } + ); + }); + + module.exports = CustomerRouter; + ``` + + seller.js : seller apis + ```javascript + const express = require("express"); + const connection = require("../database"); + + SellerRouter = express.Router(); + + // localhost:3000/seller/ + SellerRouter.post("/", (req, res) => { + connection.query( + `insert into seller (seller_name, seller_wallet) values ('${req.body. name}',${req.body.wallet})`, + (err, rows) => { + if (err) { + console.log(err); + res.send("Some error occurred."); + } else { + res.send("Saved Successfully."); + } + } + ); + }); + + module.exports = SellerRouter; + ``` +* sample client fetch +```javascript +const fetch = require("node-fetch"); + +fetch("http://localhost:3000/customer/name/Zixuan", { + method: "get", + // body: JSON.stringify( + // (body = { + // name: "dixant", + // email: "mittal", + // }) + // ), + headers: { "Content-Type": "application/json" }, +}) + .then((res) => res.json()) + .then((json) => console.log(json)); +``` + +* API key + +```javascript + +connection.query( + `SELECT * FROM client WHERE client_id = ${request.body.client_id} AND client_key = '${request.body.client_key}'`, + (err, result) => { + if (ok) + serve the request... + ... + } +) +``` + +* Backend server + + formatting conflicting + + flexibility with separation + + separation on client-ui and backend \ No newline at end of file