\n\n\n\n\nThe web keeps getting flashier with AJAX toys, but the old tricks still work. The nasty ones do not care if you are running a tiny blog or a busy shop.
Code injection attacks are the cheap lock pick that still opens too many doors.\n\n\n\nWe keep seeing forum scripts and blog engines patched after being poked the same way. The
MySpace worm reminded everyone that
cross site scripting is not academic. The price of speed is often skipping the boring parts like input checks.\n\n\n\nSo what are we really talking about?\n\n\n\n
Code injection is when user input gets treated as code. That code runs inside a database query, a browser, a shell, a template, or even inside your email headers. You thought it was data, the parser thought it was instructions.\n\n\n\nWhere does this show up most?\n\n\n\nTop of the list is
SQL injection. Right next to it lives
XSS which runs script in the browser of your users. Then you have
command injection through shell calls. And there is template injection when you pass raw stuff into the view layer.\n\n\n\nSQL injection in the wild\n\n\n\nHere is the classic pattern. A login form takes a name and password. The code stitches them into a query string and fires it at the database. The attacker adds a tiny twist and the query now has a new branch that always returns true.\n\n\n\n
// Vulnerable PHP\n$user = $_GET['user'];\n$pass = $_GET['pass'];\n\n$sql = "SELECT id FROM users WHERE user='$user' AND pass='$pass'";\n$result = mysql_query($sql);\n\n// Attack input for user: ' OR '1'='1\n// Everyone gets in
\n\n\n\nThe fix is not a giant firewall. The fix is to stop mixing code and data. Use
parameterized queries so the driver knows what is code and what is a value.\n\n\n\n
// Safe PHP with PDO\n$pdo = new PDO('mysql:host=localhost;dbname=app', 'user', 'secret');\n$stmt = $pdo->prepare("SELECT id FROM users WHERE user = ? AND pass = ?");\n$stmt->execute([$user, $pass]);
\n\n\n\nWhat if you are on .NET or Java?\n\n\n\n
// C# with parameters\nvar cmd = new SqlCommand("SELECT id FROM users WHERE user=@u AND pass=@p", conn);\ncmd.Parameters.AddWithValue("@u", user);\ncmd.Parameters.AddWithValue("@p", pass);\nvar reader = cmd.ExecuteReader();
\n\n\n\n
// Java PreparedStatement\nPreparedStatement ps = conn.prepareStatement(\n "SELECT id FROM users WHERE user=? AND pass=?");\nps.setString(1, user);\nps.setString(2, pass);\nResultSet rs = ps.executeQuery();
\n\n\n\nDo stored procedures save you by default?\n\n\n\nNo. If you build a query string inside the proc with user input you are back where you started.
Prepared statements with real bound parameters are the key. Also give your app user
least privilege. Your web account does not need DROP TABLE rights.\n\n\n\nCross site scripting that bites your users\n\n\n\nXSS is when you echo user input back into a page without escaping. The browser takes it as markup or script. A simple comment box can become a session thief.\n\n\n\n
// Vulnerable PHP output\necho "<div class='comment'>" . $_GET['comment'] . "</div>";\n\n// Attacker supplies: <script>document.location='/steal?c='+document.cookie</script>
\n\n\n\nThe fix is
output encoding based on context. For HTML text use htmlspecialchars with quotes and the right charset.\n\n\n\n
// Safer HTML context\necho "<div class='comment'>" .\n htmlspecialchars($_GET['comment'], ENT_QUOTES, 'UTF-8') .\n "</div>";
\n\n\n\nWhat about attributes and URLs?\n\n\n\n
// Attribute context needs quotes and escaping\n$title = htmlspecialchars($title, ENT_QUOTES, 'UTF-8');\necho "<a title='$title' href='/user?name=" . rawurlencode($name) . "'>Profile</a>";
\n\n\n\nCookies? Set
HttpOnly so simple script cannot read them. It is not a silver bullet but it cuts many cheap steals.\n\n\n\n
// PHP HttpOnly flag\nsetcookie("sid", $sid, 0, "/", "", false, true);
\n\n\n\nCommand injection through shell calls\n\n\n\nAny time you pass input to the shell you are on thin ice. Even a ping tool can become a remote control if you glue strings and hope for the best.\n\n\n\n
// Dangerous\n$ip = $_GET['ip'];\n$output = shell_exec("ping -c 1 " . $ip);\n\n// Attacker: 8.8.8.8; cat /etc/passwd
\n\n\n\nIf you must call the shell,
escape arguments and prefer a safe API. Better yet, use a library call that does not spawn a shell at all.\n\n\n\n
// Safer\n$ip = escapeshellarg($ip);\n$output = shell_exec("ping -c 1 " . $ip);
\n\n\n\nValidation that actually helps\n\n\n\nValidation is not only about keeping weird symbols out. It is about
defining what good looks like. If a username is letters numbers and underscore, reject anything else up front.\n\n\n\n
// Allow list validation\nif (!preg_match('/^[a-zA-Z0-9_]{3,16}$/', $username)) {\n die('Bad username');\n}
\n\n\n\nWhy not just strip quotes or rely on magic quotes?\n\n\n\nBecause it breaks input and still misses many paths.
magic_quotes_gpc is messy and gives a fake sense of safety. Use
prepared statements for queries and
context aware encoding for output. Validation is the bonus, not the main lock.\n\n\n\nTemplates and output layers\n\n\n\nTemplate engines like Smarty and friends make it easy to separate concerns. They also make it easy to echo raw input if you are in a rush. Turn on
auto escape or apply escape filters on every variable that hits HTML.\n\n\n\n
{* Smarty *}\n{$title|escape:'htmlall'}\n{$name|escape:'url'}
\n\n\n\nAre frameworks a free pass?\n\n\n\nRails, Django, and new PHP frameworks push better defaults. They help, but a single raw print or a manual SQL string brings the old ghosts back. Know your tools and keep the rules in your head.\n\n\n\nExtra guardrails that matter\n\n\n\n- Give the database user only what it needs. Read and write to the right tables and nothing more. \n- Turn off verbose errors so stack traces do not leak secrets. \n- Keep logs and watch for odd spikes and strange input.\n\n\n\nDo scanners help?\n\n\n\nYes. Run
sqlmap on a staging copy to catch blind SQL bugs. Use
Burp or
WebScarab to fuzz forms. Nikto will nag you about open doors. None of these replace solid code but they spot low hanging fruit fast.\n\n\n\nSmall myths that refuse to die\n\n\n\n- We use stored procedures so we are safe. Not true if you build strings inside them. \n- We escape single quotes so we are safe. What about comments, unions, encodings, or different drivers. \n- We filtered input so we are safe. You also need
prepared queries and
output encoding.\n\n\n\nEmail features can be a door as well. Header injection through newlines can turn a contact form into a spam cannon. Clean those fields and use the native mail APIs the right way.\n\n\n\nQuick reference code bits\n\n\n\n
// PHP MySQLi prepared\n$stmt = $mysqli->prepare("INSERT INTO posts(title, body) VALUES(?, ?)");\n$stmt->bind_param("ss", $title, $body);\n$stmt->execute();
\n\n\n\n
// PHP filter API\n$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);\n$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT);
\n\n\n\n
// MySQL least privilege example\nCREATE USER 'app'@'localhost' IDENTIFIED BY 'strongpass';\nGRANT SELECT, INSERT, UPDATE, DELETE ON app.* TO 'app'@'localhost';
\n\n\n\nWhy does this keep happening if the fixes are known?\n\n\n\nBecause pressure wins over discipline when deadlines loom. Because simple samples on the web still show string building. And because attackers only need one door that you forgot.\n\n\n\nWhat should you do this week?\n\n\n\nPick one app and trace one flow of input to output. Search for raw echo, string stitched SQL, and shell calls. Replace with
prepared statements,
encoding, and
safe APIs. Then set the database rights tight and flip on HttpOnly.\n\n\n\nWhat should you do next month?\n\n\n\nAdopt a baseline. New code uses parameters and escapes by default. Add a pre commit checklist. Add a staging scan with
sqlmap and
Burp. Write down a tiny playbook for incidents so on a bad day you do not freeze.\n\n\n\nWrap up\n\n\n\n
Code injection attacks are not fancy. They are simple tricks that turn your own tools against you. The fix is also simple when you make it a habit.\n\n\n\nTreat input as guilty until proven clean. Bind variables in queries. Encode before output. Avoid shell calls. Keep rights small. These
timeless lessons make apps harder to break and easier to trust.\n\n\n\nYou do not need a giant budget to get this right. You need a steady hand and a few rules you always follow. Start with one route, fix it well, and keep going until every door is locked.\n\n\n\nKeywords for today:
code injection,
SQL injection,
cross site scripting XSS,
command injection,
input validation,
output encoding,
prepared statements,
parameterized queries,
web security.\n