Implemented SQL injection attackable service

This commit is contained in:
2023-04-20 23:17:34 +02:00
parent c234ec6806
commit aa8d4f4036
10 changed files with 213 additions and 2 deletions

View File

@@ -6,3 +6,10 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web="4.3.1"
actix-files="0.6.2"
actix-web-validator = "5.0.1"
serde = { veresion = "1.0.160", features = ["derive"] }
serde_json = "1.0.96"
handlebars = { version="4.3.6", features = ["dir_source"] }
rusqlite = "0.29.0"

23
Readme.md Normal file
View File

@@ -0,0 +1,23 @@
# Sql-Injection-Test
> Version: 1.0.23110.1 \
> Created by: Jali<jali@orca-central.de>
> Last Modified by: Jali<jali@orca-central.de>
## About
This project implements a very simple web-service, that is vulnerable to an SQL
injection attack. In this case a simple web-page is protected by a user name and
password, and the password is checked by requesting the user name and password
from the database, and check if they exist. If they do, users are granted access
to the web-page, if not they are thrown back to the login page.
The SQL queries, however, are vulnerable to SQL injection. So a user can gain
access by simply putting a statement such as
```wurst' OR '1'='1```
into the password field. The where clause '1'='1' will always be true, and
therefore the statement always returns a list of all possible users.
The example creates an in memory database with users Alice and Bob.

View File

@@ -1,3 +1,122 @@
fn main() {
println!("Hello, world!");
use actix_files::Files;
use actix_web::{web, App, HttpResponse, HttpServer};
use handlebars::Handlebars;
use serde::Deserialize;
use serde_json::json;
#[derive(Deserialize)]
struct Credentials {
username: String,
password: String,
}
fn init_sql() -> rusqlite::Connection {
let connection = rusqlite::Connection::open_in_memory().unwrap();
connection
.execute(
"CREATE TABLE IF NOT EXISTS users (username TEXT, password TEXT, UNIQUE(username));",
(),
)
.unwrap();
connection
.execute("INSERT OR IGNORE INTO users VALUES ('Alice', 'test');", ())
.unwrap();
connection
.execute(
"INSERT OR IGNORE INTO users VALUES ('Bob', 'lovesApples');",
(),
)
.unwrap();
connection
}
async fn index(hb: web::Data<Handlebars<'_>>) -> HttpResponse {
let data = json!({
"project_name": "Book Store Login",
});
let body = hb.render("index", &data).unwrap();
HttpResponse::Ok().body(body)
}
async fn validate_login(
hb: web::Data<Handlebars<'_>>,
cred: web::Form<Credentials>,
) -> HttpResponse {
let connection = init_sql();
let query = format!(
"SELECT * FROM users WHERE username = '{}' AND password = '{}';",
cred.username, cred.password
);
println!("{}", query);
let mut stmt = connection.prepare(query.as_str()).unwrap();
let users = stmt
.query_map([], |row| {
Ok(Credentials {
username: row.get(0)?,
password: row.get(1)?,
})
})
.unwrap();
if users.count() > 0 {
println!("Match!");
return storepage(hb).await;
}
println!("No Match!");
index(hb).await
}
async fn storepage(hb: web::Data<Handlebars<'_>>) -> HttpResponse {
let data = json!({
"project_name": "Book Store",
"books":[
{
"name":"Harry Potter",
"author":"J K Rowlings",
"image_path":"/static/images/download.jpeg"
},
{
"name":"Lord of the ring",
"author":"Tolken",
"image_path": "/static/images/lord_of.jpeg"
},
{
"name":"Americanah",
"author":"Chimamada Adichie",
"image_path":"/static/images/americanah.jpeg"
},
{
"name":"Elon Musk",
"author":"#####",
"image_path":"/static/images/elon.jpeg"
},
]
});
let body = hb.render("store", &data).unwrap();
HttpResponse::Ok().body(body)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let mut handlebars = Handlebars::new();
handlebars
.register_templates_directory(".html", "./static/")
.unwrap();
let handlebars_ref = web::Data::new(handlebars);
println!("listening on port 8080");
HttpServer::new(move || {
App::new()
.app_data(handlebars_ref.clone())
.service(Files::new("/static", "static").show_files_listing())
//.service(web::resource("/login").route(web::post().to(validate_login)))
.route("/", web::post().to(validate_login))
.route("/", web::get().to(index))
})
.bind("0.0.0.0:8080")?
.run()
.await
}

16
static/css/index.css Normal file
View File

@@ -0,0 +1,16 @@
.cats {
display: flex;
}
.books {
border: 1px solid grey;
min-width: 200px;
min-height: 350px;
margin: 5px;
padding: 5px;
text-align: center;
}
.book > img {
width: 190px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
static/images/download.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
static/images/elon.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
static/images/lord_of.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

23
static/index.html Normal file
View File

@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{{project_name}}</title>
<link rel="stylesheet" href="static/css/index.css" type="text/css">
</head>
<body>
<h1>{{project_name}}</h1>
<form method="post" a>
<label for="username">Username: </label>
<input type="text" name="username" required>
<br>
<label for="password">Password: </label>
<input type="text" name="password" required>
<br>
<input type="submit" value="login">
</form>
</body>
</html>

23
static/store.html Normal file
View File

@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{{project_name}}</title>
<link rel="stylesheet" href="static/css/index.css" type="text/css">
</head>
<body>
<h1>{{project_name}}</h1>
<section class="cats">
{{#each books}}
<article class="cat">
<h3>{{this.name}}</h3>
<img src="{{this.image_path}}" />
<h4>Author: {{this.author}}</h4>
</article>
{{/each}}
</section>
</body>
</html>