-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathksql.xml
186 lines (185 loc) · 9.36 KB
/
ksql.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
<!DOCTYPE html>
<html lang="en" prefix="og: http://ogp.me/ns#">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>BCHS//ksql: split-process SQLite</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Alegreya+Sans:400,400italic,500" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<link rel="stylesheet" href="highlight.css" />
<link rel="stylesheet" href="ksql.css" />
<link rel="shortcut icon" type="image/png" href="/favicon-196x196.png" />
<link rel="shortcut icon" sizes="196x196" href="/favicon-196x196.png" />
<link rel="apple-touch-icon" href="/favicon-196x196.png" />
<meta property="og:title" content="BCHS and ksql: split-process SQLite" />
<meta property="og:image" content="https://learnbchs.org/logo-blue.png" />
<meta property="og:url" content="https://learnbchs.org/ksql.html" />
<meta property="og:type" content="website" />
<meta property="og:description" content="Sequestering database operations in a protected process." />
<meta name="description" content="Sequestering database operations in a protected process." />
</head>
<body>
<section itemscope="itemscope" itemtype="http://schema.org/WebPage">
<header>
<img itemprop="image" src="logo-blue.png" alt="BCHS Logo" />
<h1>
<a href="index.html" itemprop="name">BCHS</a>
</h1>
<nav>
<a href="tools.html"><span>tools</span></a>
<a href="easy.html"><span>example</span></a>
<a href="https://github.com/kristapsdz/bchs"><i class="fa fa-github"></i></a>
</nav>
</header>
<article>
<p class="tldr">
<b>tl;dr</b>: the new split-process mode of <a href="https://kristaps.bsd.lv/ksql">ksql</a>
constrains SQLite database operations to a child process, allowing the caller to <a
href="https://man.openbsd.org/pledge.2">pledge(2)</a> better.
</p>
<p>
I use <a href="https://sqlite.org">SQLite</a> a lot because managing a <q>big</q> database is a pain in
the ass and my database needs are few. Most of these uses are within small to medium-size web
applications, so security (see <q>web</q>) is very important.
</p>
<p>
One thing that bothers me security-wise about using SQLite is that it opens files during run-time.
The main database might be opened immediately, but auxiliary files (<a
href="https://sqlite.org/tempfiles.html">WAL, journal, etc.</a>) might be opened at any time.
And according to the documentation, even the names and locations of these files aren't fixed
(although <a href="https://github.com/bapt">bapt</a> has implemented a
<a href="https://github.com/freebsd/pkg/blob/master/libpkg/pkgdb.c">clever solution</a> for keeping
files under the same root).
Take a <a href="https://sqlite.org/wal.html">WAL mode</a> example…
</p>
<pre>% ls -l /var/www/data/
total 604
-rw-rw-rw- 1 root daemon 220160 Dec 12 2016 cgi.db
-rw-rw-rw- 1 www daemon 32768 Dec 12 2016 cgi.db-shm
-rw-rw-rw- 1 www daemon 30424 May 3 2016 cgi.db-wal</pre>
<p>
One database, one shared-memory file, one WAL file.
The database is created beforehand; the latter two are created on demand.
(<b>Note</b>: <code>/dev/null</code> may also be required…)
So what's the problem?
The run-time files prevent me from using <a href="pledge.html">pledge</a> intelligently within my
applications, as I must accommodate for opening (and processing) new files.
In most web applications, <code>stdio</code> is the only promise that's required by the CGI bits.
(CGI and FastCGI communicate over pre-opened descriptors.)
But because of SQLite, I need to let in a whole lot more.
</p>
<article data-sblg-article="1" data-sblg-permlink="0"></article>
<p>
Not good!
It's true that new processes can't be launched, nor can sockets be opened, but the database (and all
other databases in the web server's root) are open for exploitation.
Surely we can do better?
</p>
<p>
A few years ago, I wrote <a href="https://kristaps.bsd.lv/ksql">ksql</a> to mandate that database access
errors should cause program termination, and program termination should safely close the database.
One too many times, a database error had been ignored from sloppy programming and had caused mysterious
failures—<q>fool me once</q>…
It occurred to me that I could extend the system to use the same model as in <a
href="https://kristaps.bsd.lv/kcgi">kcgi</a>: constraining the vulnerable database access in
a child process.
Something like…
</p>
<article data-sblg-article="1" data-sblg-permlink="0"></article>
<p>
This way, a constrained child process would manage the database.
The master process, enacting my web application's <q>business logic</q>, would be completely sandboxed
and unable to access the database except over a communication socket.
</p>
<p>
Since ksql wraps a small subset over the <a href="https://sqlite.org/capi3ref.html">SQLite C API</a>,
it's manageable to enable each function individually.
Only about 30 functions need to be fitted with split-process bits.
</p>
<figure>
<img src="ksql-fig3.svg" alt="Interprocess communication" />
<figcaption>
The database is securely managed by a child process and communicates with the main web
application process over sockets.
</figcaption>
</figure>
<p>
For the time being, the protocol is an overly simple (read: slow and inefficient) one: open a
non-blocking socket pair, fork, pass the pair to the child and parent.
The child then opens and works with the database with a <a
href="https://man.openbsd.org/pledge.2">pledge(2)</a> set for file access.
(In the event that the original single-process model is used, none of this overhead is invoked.)
</p>
<p>
Following invocation, the parent caller usually will pledge for <code>stdio</code> and whatever else is
required by the application.
</p>
<p>
All in all, this roughly doubled the code-base size.
See it for yourself in <a href="https://github.com/kristapsdz/ksql/blob/VERSION_0_1_0/ksql.c">ksql.c</a>
(available as of the <b>0.1.0</b> release).
The only bits needed to enable split-process mode are calling <a
href="https://kristaps.bsd.lv/ksql/ksql_alloc_child.3.html">ksql_alloc_child(3)</a> instead of
<a href="https://kristaps.bsd.lv/ksql/ksql_alloc.3.html">ksql_alloc(3)</a> on initialisation.
</p>
<p>
For example, the following simple application opens the database, then sandboxes itself.
Note that the ksql functions aren't checked for errors since the default behaviour is to exit on
database errors.
(Technically the calls to <a href="https://kristaps.bsd.lv/ksql/ksql_close.3.html">ksql_close(3)</a> and
<a href="https://kristaps.bsd.lv/ksql/ksql_free.3.html">ksql_free(3)</a> are superfluous, but let's be
tidy.)
</p>
<article data-sblg-article="1" data-sblg-permlink="0"></article>
<p>
A much more reasonable sandbox.
</p>
<p>
In a web application that combines <a href="https://kristaps.bsd.lv/kcgi">kcgi</a> and <a
href="https://kristaps.bsd.lv/ksql">ksql</a>, both the parsing of validation of data
<i>and</i> database import and export are all performed separately from the main CGI script.
So all <q>vulnerable</q> operations (touching network, touching files—the attack surface being
<span style="color: red;">coloured in red</span>) of such applications are now limited to sandboxed child processes.
</p>
<figure>
<img src="ksql-fig6.svg" alt="Interprocess communication" />
<figcaption>
All parts being compartmentalised.
</figcaption>
</figure>
<p>
Not only does this protect your application from bad input, it also protects your database from you!
</p>
<p>
I've already added the functionality to <a href="https://kristaps.bsd.lv/openradtool">openradtool</a>
(this system was discussed <a href="kwebapp.html">here</a>) as of <b>0.2.8</b> to make this even easier
to use. Assuming we've generated a database API exporting the usual <code>db_open</code>
function…
</p>
<article data-sblg-article="1" data-sblg-permlink="0"></article>
<p>
What can be improved in ksql's split-process model?
A lot.
</p>
<p>
For starters, the protocol can be significantly (make that <q><i>significantly</i></q>) improved.
Right now, it has a lot of reads and writes that can be consolidated into one: a header frame with most
data, followed by additional data in the event of strings.
In fact, any request can be limited to two transmissions: a header frame and a data frame.
Most requests will only have the header.
(Those with string or blob values will need the extra frame.)
</p>
<p>
It's also rather easy to add other sandboxes.
But since I generally only use <a href="https://www.openbsd.org">OpenBSD</a>, I'm not there yet!
</p>
</article>
<footer>
<div>
<a href="https://creativecommons.org/licenses/by/4.0/"><i class="fa fa-creative-commons"></i></a>
<a rel="author" href="https://kristaps.bsd.lv">Kristaps Dzonsons</a>
</div>
</footer>
</section>
</body>
</html>