Skip to content

Commit ad1a235

Browse files
committed
clickhouse escape strings
1 parent 41187c8 commit ad1a235

File tree

4 files changed

+17
-21
lines changed

4 files changed

+17
-21
lines changed

find/handler.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package find
33
import (
44
"fmt"
55
"net/http"
6-
"strings"
76

87
"github.com/lomik/graphite-clickhouse/config"
98
"github.com/lomik/graphite-clickhouse/helper/clickhouse"
@@ -22,11 +21,6 @@ func NewHandler(config *config.Config) *Handler {
2221
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
2322
query := r.URL.Query().Get("query")
2423

25-
if strings.IndexByte(query, '\'') > -1 { // sql injection dumb fix
26-
http.Error(w, "Bad request", http.StatusBadRequest)
27-
return
28-
}
29-
3024
var prefix string
3125
var err error
3226

find/where.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"fmt"
55
"regexp"
66
"strings"
7+
8+
"github.com/lomik/graphite-clickhouse/helper/clickhouse"
79
)
810

911
func HasWildcard(target string) bool {
@@ -31,15 +33,15 @@ func MakeWhere(target string, withLevel bool) (where string) {
3133

3234
// simple metric
3335
if !HasWildcard(target) {
34-
AND(fmt.Sprintf("Path = '%s'", target))
36+
AND(fmt.Sprintf("Path = '%s'", clickhouse.Escape(target)))
3537
return
3638
}
3739

3840
// before any wildcard symbol
3941
simplePrefix := target[:strings.IndexAny(target, "[]{}*")]
4042

4143
if len(simplePrefix) > 0 {
42-
AND(fmt.Sprintf("Path LIKE '%s%%'", simplePrefix))
44+
AND(fmt.Sprintf("Path LIKE '%s%%'", clickhouse.Escape(simplePrefix)))
4345
}
4446

4547
// prefix search like "metric.name.xx*"
@@ -48,7 +50,7 @@ func MakeWhere(target string, withLevel bool) (where string) {
4850
}
4951

5052
pattern := GlobToRegexp(target)
51-
AND(fmt.Sprintf("match(Path, '%s')", pattern))
53+
AND(fmt.Sprintf("match(Path, '%s')", clickhouse.Escape(pattern)))
5254

5355
return
5456
}

helper/clickhouse/clickhouse.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ func formatSQL(q string) string {
2323
return strings.Join(s, " ")
2424
}
2525

26+
func Escape(s string) string {
27+
s = strings.Replace(s, `\`, `\\`, -1)
28+
s = strings.Replace(s, `'`, `\'`, -1)
29+
return s
30+
}
31+
2632
func Query(ctx context.Context, dsn string, query string, timeout time.Duration) (body []byte, err error) {
2733
start := time.Now()
2834

render/handler.go

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"net/http"
88
"sort"
99
"strconv"
10-
"strings"
1110
"time"
1211

1312
"github.com/gogo/protobuf/proto"
@@ -36,11 +35,6 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
3635
logger := log.FromContext(r.Context())
3736
target := r.URL.Query().Get("target")
3837

39-
if strings.IndexByte(target, '\'') > -1 { // sql injection dumb fix
40-
http.Error(w, "Bad request", http.StatusBadRequest)
41-
return
42-
}
43-
4438
var prefix string
4539
var err error
4640

@@ -94,11 +88,11 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
9488

9589
listBuf := bytes.NewBuffer(nil)
9690
first := true
97-
for _, p := range strings.Split(string(treeData), "\n") {
98-
if p == "" {
91+
for _, p := range bytes.Split(treeData, []byte{'\n'}) {
92+
if len(p) == 0 {
9993
continue
10094
}
101-
step := h.config.Rollup.Step(p, int32(fromTimestamp))
95+
step := h.config.Rollup.Step(unsafeString(p), int32(fromTimestamp))
10296
if step > maxStep {
10397
maxStep = step
10498
}
@@ -108,7 +102,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
108102
}
109103
first = false
110104

111-
listBuf.WriteString("'" + p + "'") // SQL-Injection
105+
listBuf.WriteString("'" + clickhouse.Escape(unsafeString(p)) + "'")
112106
}
113107

114108
if listBuf.Len() == 0 {
@@ -127,11 +121,11 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
127121
// )
128122
// pathWhere = makeWhere(target, false)
129123
} else {
130-
pathWhere = fmt.Sprintf("Path = '%s'", target)
124+
pathWhere = fmt.Sprintf("Path = '%s'", clickhouse.Escape(target))
131125
maxStep = h.config.Rollup.Step(target, int32(fromTimestamp))
132126
}
133127

134-
until := untilTimestamp - untilTimestamp % int64(maxStep) + int64(maxStep) - 1
128+
until := untilTimestamp - untilTimestamp%int64(maxStep) + int64(maxStep) - 1
135129
dateWhere := fmt.Sprintf(
136130
"(Date >='%s' AND Date <= '%s' AND Time >= %d AND Time <= %d)",
137131
time.Unix(fromTimestamp, 0).Format("2006-01-02"),

0 commit comments

Comments
 (0)