Skip to content

Commit 76db54e

Browse files
author
micha-p
committed
Protection against sql injection doesnt work with ? for table. Using HTMLEscapeString instead
1 parent e951aa2 commit 76db54e

File tree

5 files changed

+47
-39
lines changed

5 files changed

+47
-39
lines changed

Diff for: README.md

+9-8
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ Use your fantasy for best UX and choose high levels of abstraction and imaginati
77

88
## prepare
99

10-
sudo mysqladmin --defaults-file=/etc/mysql/debian.cnf create gotestdb
11-
sudo mysql --defaults-file=/etc/mysql/debian.cnf -e "GRANT ALL PRIVILEGES ON gotestdb.* TO 'go_user'@'localhost' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;"
12-
mysql -p"mypassword" -u go_user gotestdb -e 'create table posts (title varchar(64) default null, start date default null);'
13-
mysql -p"mypassword" -u go_user gotestdb -e 'insert into posts values("hello","2015-01-01");'
14-
mysql -p"mypassword" -u go_user gotestdb -e 'insert into posts values("more","2015-01-03");'
15-
mysql -p"mypassword" -u go_user gotestdb -e 'insert into posts values("end","2015-01-23");'
16-
mysql -p"mypassword" -u go_user gotestdb -B -e 'select * from posts;'
10+
sudo mysqladmin --defaults-file=/etc/mysql/debian.cnf create galadb
11+
sudo mysql --defaults-file=/etc/mysql/debian.cnf -e "GRANT ALL PRIVILEGES ON galadb.* TO 'galagopher'@'localhost' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;"
12+
mysql -p"mypassword" -u galagopher galadb -e 'create table posts (title varchar(64) default null, start date default null);'
13+
mysql -p"mypassword" -u galagopher galadb -e 'insert into posts values("hello","2015-01-01");'
14+
mysql -p"mypassword" -u galagopher galadb -e 'insert into posts values("more","2015-01-03");'
15+
mysql -p"mypassword" -u galagopher galadb -e 'insert into posts values("end","2015-01-23");'
16+
mysql -p"mypassword" -u galagopher galadb -B -e 'select * from posts;'
1717

1818
## install
1919

@@ -38,7 +38,8 @@ Use your fantasy for best UX and choose high levels of abstraction and imaginati
3838

3939
## perspectives
4040

41-
. output in tables
41+
- output in tables
42+
- menu line
4243
- choice for different database drivers
4344
- insert and edit records
4445

Diff for: auth.go

+20-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* no Credentials management needed
1+
/* no session management needed
22
* Credentials are stored at user side using secure cookies
33
*
44
* credits:
@@ -16,25 +16,29 @@ var cookieHandler = securecookie.New(
1616
securecookie.GenerateRandomKey(64),
1717
securecookie.GenerateRandomKey(32))
1818

19-
func getCredentials(request *http.Request) (userName string, password string) {
20-
if cookie, err := request.Cookie("Credentials"); err == nil {
19+
func getCredentials(request *http.Request) (userName string, password string, host string, port string) {
20+
if cookie, err := request.Cookie("Datasource"); err == nil {
2121
cookieValue := make(map[string]string)
22-
if err = cookieHandler.Decode("Credentials", cookie.Value, &cookieValue); err == nil {
22+
if err = cookieHandler.Decode("Datasource", cookie.Value, &cookieValue); err == nil {
2323
userName = cookieValue["user"]
2424
password = cookieValue["passwd"]
25+
host = cookieValue["host"]
26+
port = cookieValue["port"]
2527
}
2628
}
27-
return userName, password
29+
return userName, password, host, port
2830
}
2931

30-
func setCredentials(userName string, pw string, w http.ResponseWriter) {
32+
func setCredentials( w http.ResponseWriter, userName string, pw string, host string, port string) {
3133
value := map[string]string{
3234
"user": userName,
3335
"passwd": pw,
36+
"host": host,
37+
"port": port,
3438
}
35-
if encoded, err := cookieHandler.Encode("Credentials", value); err == nil {
39+
if encoded, err := cookieHandler.Encode("Datasource", value); err == nil {
3640
cookie := &http.Cookie{
37-
Name: "Credentials",
41+
Name: "Datasource",
3842
Value: encoded,
3943
Path: "/",
4044
}
@@ -44,7 +48,7 @@ func setCredentials(userName string, pw string, w http.ResponseWriter) {
4448

4549
func clearCredentials(w http.ResponseWriter) {
4650
cookie := &http.Cookie{
47-
Name: "Credentials",
51+
Name: "Datasource",
4852
Value: "",
4953
Path: "/",
5054
MaxAge: -1,
@@ -55,8 +59,10 @@ func clearCredentials(w http.ResponseWriter) {
5559
func loginHandler(w http.ResponseWriter, request *http.Request) {
5660
user := request.FormValue("user")
5761
pass := request.FormValue("password")
62+
host := request.FormValue("host")
63+
port := request.FormValue("port")
5864
if user != "" && pass != "" {
59-
setCredentials(user, pass, w)
65+
setCredentials(w, user, pass, host, port)
6066
}
6167
http.Redirect(w, request, "/", 302)
6268
}
@@ -69,8 +75,10 @@ func logoutHandler(w http.ResponseWriter, request *http.Request) {
6975
const loginPage = `
7076
<h1>Login</h1>
7177
<form method="post" action="/login">
72-
<label for="user">User name</label><input type="text" id="user" name="user">
73-
<label for="password">Password</label><input type="password" id="password" name="password">
78+
<label for="user">User name</label><input type="text" id="user" name="user"><br>
79+
<label for="password">Password</label><input type="password" id="password" name="password"><br>
80+
<label for="host">Host</label><input type="text" id="host" name="host" value="localhost"><br>
81+
<label for="port">Port</label><input type="text" id="port" name="port" value="3306"><br>
7482
<button type="submit">Login</button>
7583
</form>
7684
`

Diff for: aux.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func linkDeeper(cwd string, link string, name string) string {
2121
}
2222

2323
// Compose dataSourceName from components and globals
24-
func dsn(user string, pw string, db string) string {
24+
func dsn(user string, pw string, host string, port string, db string) string {
2525
return user + ":" + pw + "@tcp(" + host + ":" + port + ")/" + db
2626
}
2727

Diff for: dump.go

+14-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package main
22

33
/* TODO
4-
* turn into generic functions
4+
* turn into more generic functions for printing into tables
55
*/
66

77
import (
@@ -11,13 +11,14 @@ import (
1111
"net/http"
1212
"strconv"
1313
"strings"
14+
"text/template"
1415
)
1516

1617
// Shows selection of databases at top level
1718
func home(w http.ResponseWriter, r *http.Request) {
1819

19-
user, pw := getCredentials(r)
20-
conn, err := sql.Open("mysql", dsn(user, pw, database))
20+
user, pw, h , p := getCredentials(r)
21+
conn, err := sql.Open("mysql", dsn(user, pw, h, p, database))
2122
checkY(err)
2223
defer conn.Close()
2324

@@ -41,9 +42,9 @@ func home(w http.ResponseWriter, r *http.Request) {
4142
// Dump all tables of a database
4243
func dumpdb(w http.ResponseWriter, r *http.Request, parray []string) {
4344

44-
user, pw := getCredentials(r)
45+
user, pw, h, p := getCredentials(r)
4546
database := parray[0]
46-
conn, err := sql.Open("mysql", dsn(user, pw, database))
47+
conn, err := sql.Open("mysql", dsn(user, pw, h, p, database))
4748
checkY(err)
4849
defer conn.Close()
4950

@@ -67,18 +68,18 @@ func dumpdb(w http.ResponseWriter, r *http.Request, parray []string) {
6768
// Dump all records of a table, one per line
6869
func dumptable(w http.ResponseWriter, r *http.Request, parray []string) {
6970

70-
user, pw := getCredentials(r)
71+
user, pw, h, p := getCredentials(r)
7172
database := parray[0]
7273
table := parray[1]
7374

74-
conn, err := sql.Open("mysql", dsn(user, pw, database))
75+
conn, err := sql.Open("mysql", dsn(user, pw, h, p, database))
7576
checkY(err)
7677
defer conn.Close()
7778

78-
statement, err := conn.Prepare("select * from ?")
79+
statement, err := conn.Prepare("select * from " + template.HTMLEscapeString(table))
7980
checkY(err)
8081

81-
rows, err := statement.Query(table)
82+
rows, err := statement.Query()
8283
checkY(err)
8384
defer rows.Close()
8485

@@ -123,15 +124,15 @@ func dumprecord(w http.ResponseWriter, r *http.Request, parray []string) {
123124
rec, err := strconv.Atoi(parray[2])
124125
checkY(err)
125126

126-
user, pw := getCredentials(r)
127-
conn, err := sql.Open("mysql", dsn(user, pw, database))
127+
user, pw, h, p := getCredentials(r)
128+
conn, err := sql.Open("mysql", dsn(user, pw, h, p, database))
128129
checkY(err)
129130
defer conn.Close()
130131

131-
statement, err := conn.Prepare("select * from ?")
132+
statement, err := conn.Prepare("select * from " + template.HTMLEscapeString(table))
132133
checkY(err)
133134

134-
rows, err := statement.Query(table)
135+
rows, err := statement.Query()
135136
checkY(err)
136137
defer rows.Close()
137138

Diff for: sqldump.go

+3-5
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import (
77
)
88

99
var base_url = "http://localhost"
10-
var host = "localhost"
11-
var port = "3306"
1210
var database = "information_schema"
1311

1412
func faviconHandler(w http.ResponseWriter, r *http.Request) {
@@ -38,10 +36,10 @@ func pathHandler(w http.ResponseWriter, r *http.Request) {
3836
}
3937

4038
func indexHandler(w http.ResponseWriter, r *http.Request) {
41-
u, _ := getCredentials(r)
39+
user , _ , host , port := getCredentials(r)
4240

43-
if u != "" {
44-
fmt.Fprintln(w, "<h1>", u, "</h1>")
41+
if user != "" {
42+
fmt.Fprintln(w, "<p>", user + "@" + host + ":" + port, "</p>")
4543
pathHandler(w, r)
4644
} else {
4745
loginPageHandler(w, r)

0 commit comments

Comments
 (0)