Skip to content

Commit

Permalink
Add failing test for SQL injection via route parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
hansott committed Apr 22, 2024
1 parent e8a03fe commit 14f0a5d
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 4 deletions.
22 changes: 18 additions & 4 deletions end2end/tests/express-mysql2.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,20 @@ t.test("it blocks in blocking mode", (t) => {
signal: AbortSignal.timeout(5000),
}
),
fetch(
`http://localhost:4000/cats/${encodeURIComponent("Njuska'; DELETE FROM cats;-- H")}`,
{
signal: AbortSignal.timeout(5000),
}
),
fetch("http://localhost:4000/?petname=Njuska", {
signal: AbortSignal.timeout(5000),
}),
]);
})
.then(([noSQLInjection, normalSearch]) => {
t.equal(noSQLInjection.status, 500);
.then(([sqlInjection, sqlInjection2, normalSearch]) => {
t.equal(sqlInjection.status, 500);
t.equal(sqlInjection2.status, 500);
t.equal(normalSearch.status, 200);
t.match(stdout, /Starting agent/);
t.match(stderr, /Aikido runtime has blocked a SQL injection/);
Expand Down Expand Up @@ -90,13 +97,20 @@ t.test("it does not block in dry mode", (t) => {
signal: AbortSignal.timeout(5000),
}
),
fetch(
`http://localhost:4001/cats/${encodeURIComponent("Njuska'; DELETE FROM cats;-- H")}`,
{
signal: AbortSignal.timeout(5000),
}
),
fetch("http://localhost:4001/?petname=Njuska", {
signal: AbortSignal.timeout(5000),
}),
])
)
.then(([noSQLInjection, normalSearch]) => {
t.equal(noSQLInjection.status, 200);
.then(([sqlInjection, sqlInjection2, normalSearch]) => {
t.equal(sqlInjection.status, 200);
t.equal(sqlInjection2.status, 200);
t.equal(normalSearch.status, 200);
t.match(stdout, /Starting agent/);
t.notMatch(stderr, /Aikido runtime has blocked a SQL injection/);
Expand Down
9 changes: 9 additions & 0 deletions sample-apps/express-mysql2/Cats.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ class Cats {
await this.db.query(`INSERT INTO cats(petname) VALUES ('${name}');`);
}

async byName(name) {
// This is unsafe! This is for demo purposes only, you should use parameterized queries.
const [cats] = await this.db.query(
`SELECT petname FROM cats WHERE petname = '${name}'`
);

return cats.map((row) => row.petname);
}

async getAll() {
const [cats] = await this.db.execute("SELECT petname FROM `cats`;");

Expand Down
21 changes: 21 additions & 0 deletions sample-apps/express-mysql2/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,27 @@ async function main(port) {
})
);

app.get(
"/cats/:name",
asyncHandler(async (req, res) => {
const found = await cats.byName(req.params.name);

if (found.length === 0) {
return res.status(404).send("Cat not found");
}

const cat = found[0];

res.send(`
<html lang="en">
<body>
<h1>${escape(cat)}</h1>
</body>
</html>
`);
})
);

return new Promise((resolve, reject) => {
try {
app.listen(port, () => {
Expand Down

0 comments on commit 14f0a5d

Please sign in to comment.