• No results found

Practical Tips for Better PostgreSQL Applications

N/A
N/A
Protected

Academic year: 2021

Share "Practical Tips for Better PostgreSQL Applications"

Copied!
97
0
0

Loading.... (view fulltext now)

Full text

(1)

PostgreSQL Applications

Marc Balmer<[email protected]> pgconf.de 2013

(2)

Topics

1 Introduction

2 User Experience

3 Security

4 Colophon

(3)

1 Introduction

2 User Experience

3 Security

(4)

About this presentation

• Aimed at application developers. . .

• . . . who do client programming using libpq (or a wrapper around libpq for a language other than C)

• . . . who know a little about PL/pgSQL • . . . who want to use PostgreSQL features

• demo code will be presented in the Lua language

(5)

About this presentation

• Aimed at application developers. . .

• . . . who do client programming using libpq (or a wrapper

around libpq for a language other than C)

• . . . who know a little about PL/pgSQL • . . . who want to use PostgreSQL features

(6)

About this presentation

• Aimed at application developers. . .

• . . . who do client programming using libpq (or a wrapper around libpq for a language other than C)

• . . . who know a little about PL/pgSQL

• . . . who want to use PostgreSQL features

• demo code will be presented in the Lua language

(7)

About this presentation

• Aimed at application developers. . .

• . . . who do client programming using libpq (or a wrapper around libpq for a language other than C)

• . . . who know a little about PL/pgSQL

• . . . who want to use PostgreSQL features

(8)

About this presentation

• Aimed at application developers. . .

• . . . who do client programming using libpq (or a wrapper around libpq for a language other than C)

• . . . who know a little about PL/pgSQL • . . . who want to use PostgreSQL features

• demo code will be presented in the Lua language

(9)

What makes an application ,,Better”?

• Smaller code: Easier to maintain

• More robust: Immune to runtime problems (Network, etc.) • More secure: Immune to SQL-Injection

• More responsive: Better user experience • . . .

(10)

What makes an application ,,Better”?

• Smaller code: Easier to maintain

• More robust: Immune to runtime problems (Network, etc.)

• More secure: Immune to SQL-Injection • More responsive: Better user experience • . . .

(11)

What makes an application ,,Better”?

• Smaller code: Easier to maintain

• More robust: Immune to runtime problems (Network, etc.)

• More secure: Immune to SQL-Injection

• More responsive: Better user experience • . . .

(12)

What makes an application ,,Better”?

• Smaller code: Easier to maintain

• More robust: Immune to runtime problems (Network, etc.) • More secure: Immune to SQL-Injection

• More responsive: Better user experience

• . . .

(13)

What makes an application ,,Better”?

• Smaller code: Easier to maintain

• More robust: Immune to runtime problems (Network, etc.) • More secure: Immune to SQL-Injection

• More responsive: Better user experience • . . .

(14)

The room capacity monitoring example

• The ,,capacity” table in the ,,pgconf” database:

Column Type

room character varying(32) max persons integer

persons integer

• When there are more than max persons in a room, the room is over capacity. In the demo, max persons of the ,,red” room is 30.

,→ Room capacity monitoring

,→ Room capacity monitoring with many clients

(15)

The room capacity monitoring example

• The ,,capacity” table in the ,,pgconf” database:

Column Type

room character varying(32)

max persons integer

persons integer

• When there are more than max persons in a room, the room is over capacity. In the demo, max persons of the ,,red” room is 30.

,→ Room capacity monitoring

(16)

The room capacity monitoring example

• The ,,capacity” table in the ,,pgconf” database:

Column Type

room character varying(32) max persons integer

persons integer

• When there are more than max persons in a room, the room

is over capacity. In the demo, max persons of the ,,red” room is 30.

,→ Room capacity monitoring

,→ Room capacity monitoring with many clients

(17)

The room capacity monitoring example

• The ,,capacity” table in the ,,pgconf” database:

Column Type

room character varying(32) max persons integer

persons integer

• When there are more than max persons in a room, the room is over capacity. In the demo, max persons of the ,,red” room is 30.

,→ Room capacity monitoring

(18)

The room capacity monitoring example

• The ,,capacity” table in the ,,pgconf” database:

Column Type

room character varying(32) max persons integer

persons integer

• When there are more than max persons in a room, the room is over capacity. In the demo, max persons of the ,,red” room is 30.

,→ Room capacity monitoring

,→ Room capacity monitoring with many clients

(19)

1 Introduction

2 User Experience

3 Security

(20)

Asynchronous notifications: A PostgreSQL Feature

• Clients register for an event using LISTEN name

• Any client or the server can fire an event using NOTIFY

name

• At any time a client can stop listening usingUNLISTEN

name

(21)

Asynchronous notifications: A PostgreSQL Feature

• Clients register for an event using LISTEN name

• Any client or the server can fire an event using NOTIFY

name

• At any time a client can stop listening usingUNLISTEN

(22)

Asynchronous notifications: A PostgreSQL Feature

• Clients register for an event using LISTEN name

• Any client or the server can fire an event using NOTIFY name

• At any time a client can stop listening usingUNLISTEN

name

(23)

Asynchronous notifications to de-couple applications

• Trigger procedures can issue NOTIFY

• Use triggers e.g. on INSERT,UPDATE,DELETE, TRUNCATE

(24)

Asynchronous notifications to de-couple applications

• Trigger procedures can issue NOTIFY

• Use triggers e.g. on INSERT,UPDATE,DELETE,

TRUNCATE

• Client executesUPDATE, server creates the notification

(25)

Asynchronous notifications to de-couple applications

• Trigger procedures can issue NOTIFY

• Use triggers e.g. on INSERT,UPDATE,DELETE, TRUNCATE

(26)

Process notifies after an SQL statement

conn :exec( ’ l i s t e n c a p a c i t y c h a n g e d ’ . . room )

(27)

Process notifies after an SQL statement, cont’d.

conn :exec( ” u p d a t e c a p a c i t y s e t p e r s o n s = ” . . ” p e r s o n s + 1 w h e r e room = ’ ” . . room . . ” ’ ” ) l o c a l nam = ’ c a p a c i t y c h a n g e d ’ . . room l o c a l n = conn :n o t i f i e s( ) w h i l e ( n ˜= n i l) do

i f n :relname( ) == nam then

r e s = conn :exec( ” s e l e c t p e r s o n s f r o m ” . . ” c a p a c i t y w h e r e room = ’ ” . . room . . ” ’ ” ) t e x t F i e l d : S e t S t r i n g ( r e s : g e t v a l u e ( 1 , 1 ) ) end n = conn :n o t i f i e s( ) end

(28)

Real-time behaviour

• Server sends notifies immediately on the socket

• ,,Watch” the connection socket: select(), XtAddInput(), GTK Input, etc.

• Process notifies when there is activity on the socket

(29)

Real-time behaviour

• Server sends notifies immediately on the socket

• ,,Watch” the connection socket: select(), XtAddInput(), GTK

Input, etc.

(30)

Real-time behaviour

• Server sends notifies immediately on the socket

• ,,Watch” the connection socket: select(), XtAddInput(), GTK Input, etc.

• Process notifies when there is activity on the socket

(31)

Using XtAddInput

conn :exec( ” l i s t e n c a p a c i t y c h a n g e d ” . . room ) i n p u t I d = app :AddInput( conn :s o c k e t( ) ,

p r o c e s s N o t i f i e s )

(32)

Showing the connected clients

• The view pg stat activity shows connected clients

• We look at columns usename, client addr, application name • We connect the usual way to the database:

conn = pgsql.connectdb([[user=pgconf dbname=pgconf host=localhost]])

,→ Show connected clients

(33)

Showing the connected clients

• The view pg stat activity shows connected clients

• We look at columns usename, client addr, application name

• We connect the usual way to the database:

conn = pgsql.connectdb([[user=pgconf dbname=pgconf host=localhost]])

(34)

Showing the connected clients

• The view pg stat activity shows connected clients

• We look at columns usename, client addr, application name

• We connect the usual way to the database:

conn = pgsql.connectdb([[user=pgconf dbname=pgconf host=localhost]])

,→ Show connected clients

(35)

Showing the connected clients

• The view pg stat activity shows connected clients

• We look at columns usename, client addr, application name • We connect the usual way to the database:

conn = pgsql.connectdb([[user=pgconf dbname=pgconf host=localhost]])

(36)

Showing the connected clients

• The view pg stat activity shows connected clients

• We look at columns usename, client addr, application name • We connect the usual way to the database:

conn = pgsql.connectdb([[user=pgconf dbname=pgconf host=localhost]])

,→ Show connected clients

(37)

A better way to connect

An application name can be set when connecting:

conn = pgsql.connectdb([[user=pgconf dbname=pgconf

host=localhost application_name=control(room_red)]]) application name=control(room red)

(38)

A better way to connect

An application name can be set when connecting:

conn = pgsql.connectdb([[user=pgconf dbname=pgconf

host=localhost application_name=control(room_red)]]) application name=control(room red)

,→ Clients that set their names

(39)

A better way to connect

An application name can be set when connecting:

conn = pgsql.connectdb([[user=pgconf dbname=pgconf

host=localhost application_name=control(room_red)]]) application name=control(room red)

(40)

A better way to connect

An application name can be set when connecting:

conn = pgsql.connectdb([[user=pgconf dbname=pgconf

host=localhost application_name=control(room_red)]]) application name=control(room red)

,→ Clients that set their names

(41)

Unexpected behaviour

We still use the room capacity monitoring example

(42)

Unexpected behaviour

We still use the room capacity monitoring example

,→ Capacity monitoring

(43)

A server restart caused the application to misbehave

Connection setup:

conn = p g s q l .connectdb( . . . )

i f conn :s t a t u s( ) ˜= p g s q l .CONNECTION OK then

p r i n t ( ’ F a i l e d t o c o n n e c t t o d a t a b a s e ’ ) o s . e x i t ( 1 )

e l s e

updateRoom ( )

conn :exec( ’ l i s t e n c a p a c i t y c h a n g e d ’ ) i n p u t I d = app :AddInput( conn :s o c k e t( ) ,

p r o c e s s N o t i f i e s )

end

(44)

A closer look at the problem

• The application uses the X11 event loop

• It adds an X11 XtInput to the raw socket of the database connection to catch asynchronous notifications

• When the remote end closes the socket, this causes an endless loop

• A server restart causes the socket to be closed

(45)

A closer look at the problem

• The application uses the X11 event loop

• It adds an X11 XtInput to the raw socket of the database

connection to catch asynchronous notifications

• When the remote end closes the socket, this causes an endless loop

(46)

A closer look at the problem

• The application uses the X11 event loop

• It adds an X11 XtInput to the raw socket of the database connection to catch asynchronous notifications

• When the remote end closes the socket, this causes an endless

loop

• A server restart causes the socket to be closed

(47)

A closer look at the problem

• The application uses the X11 event loop

• It adds an X11 XtInput to the raw socket of the database connection to catch asynchronous notifications

• When the remote end closes the socket, this causes an endless loop

(48)

Connection setup, again

conn = p g s q l .connectdb( . . . )

i f conn :s t a t u s( ) ˜= p g s q l .CONNECTION OK then

p r i n t ( ’ F a i l e d t o c o n n e c t t o d a t a b a s e ’ ) o s . e x i t ( 1 )

e l s e

updateRoom ( )

conn :exec( ’ l i s t e n c a p a c i t y c h a n g e d ’ ) i n p u t I d = app :AddInput( conn :s o c k e t( ) ,

p r o c e s s N o t i f i e s )

end

app :MainLoop( )

(49)

processNotifies()

f u n c t i o n p r o c e s s N o t i f i e s ( ) conn :consumeInput( ) l o c a l n = conn :n o t i f i e s( ) w h i l e ( n ˜= n i l) do i f n :relname( ) == ’ c a p a c i t y c h a n g e d ’ then updateRoom ( ) end n = conn :n o t i f i e s( ) end end
(50)

The solution: Manage the connection

• Watch the connection status

• reset() the connection when needed

,→ Server restart, no harm done

(51)

The solution: Manage the connection

• Watch the connection status

• reset() the connection when needed

(52)

The solution: Manage the connection

• Watch the connection status • reset() the connection when needed

,→ Server restart, no harm done

(53)

Making the connection

conn = p g s q l .connectdb( . . . )

i f conn :s t a t u s( ) ˜= p g s q l .CONNECTION OK then

t e x t F i e l d : S e t S t r i n g ( ’ ( C o n n e c t i n g t o d a t a b a s e ) ’ ) app :AddTimeOut( 1 0 0 0 , t r y R e c o n n e c t D a t a b a s e )

e l s e

updateRoom ( )

conn :exec( ’ l i s t e n c a p a c i t y c h a n g e d ’ ) i n p u t I d = app :AddInput( conn :s o c k e t( ) ,

p r o c e s s N o t i f i e s )

end

(54)

tryReconnectDatabase()

f u n c t i o n t r y R e c o n n e c t D a t a b a s e ( ) conn : r e s e t ( )

i f conn :s t a t u s( ) == p g s q l .CONNECTION BAD then

app :AddTimeOut( 1 0 0 0 , t r y R e c o n n e c t D a t a b a s e )

r e t u r n end

updateRoom ( )

i n p u t I d = app :AddInput( conn :s o c k e t( ) , p r o c e s s N o t i f i e s )

conn :exec( ’ l i s t e n c a p a c i t y c h a n g e d ’ )

end

(55)

processNotifies(), new version

f u n c t i o n p r o c e s s N o t i f i e s ( ) conn :consumeInput( )

i f conn :s t a t u s( ) == p g s q l .CONNECTION BAD then

r e c o n n e c t D a t a b a s e ( ) r e t u r n end l o c a l n = conn :n o t i f i e s( ) w h i l e ( n ˜= n i l) do i f n :relname( ) == ’ c a p a c i t y c h a n g e d ’ then updateRoom ( ) end n = conn :n o t i f i e s( ) end end

(56)

1 Introduction

2 User Experience

3 Security

4 Colophon

(57)

Security at the right layer

• Many applications handle security at the application layer, use

only one database login

• Surprise! Software can have bugs. What if the application gets compromised?

(58)

Security at the right layer

• Many applications handle security at the application layer, use only one database login

• Surprise! Software can have bugs. What if the application gets compromised?

• Full access to the application database by the intruder!

(59)

Security at the right layer

• Many applications handle security at the application layer, use only one database login

• Surprise! Software can have bugs. What if the application gets compromised?

(60)

Security at the database layer

• PostgreSQL has a fine grained security system

• Define security at the database layer

• Let the application ,,mirror” the security settings

• Define ,,model” roles with security privileges for distinct areas of an application

• GRANT the ,,model role” to the real users • Don’t let a database administrator account log in

,→ Webapplication security measures

(61)

Security at the database layer

• PostgreSQL has a fine grained security system

• Define security at the database layer

• Let the application ,,mirror” the security settings

• Define ,,model” roles with security privileges for distinct areas of an application

• GRANT the ,,model role” to the real users • Don’t let a database administrator account log in

(62)

Security at the database layer

• PostgreSQL has a fine grained security system • Define security at the database layer

• Let the application ,,mirror” the security settings

• Define ,,model” roles with security privileges for distinct areas of an application

• GRANT the ,,model role” to the real users • Don’t let a database administrator account log in

,→ Webapplication security measures

(63)

Security at the database layer

• PostgreSQL has a fine grained security system • Define security at the database layer

• Let the application ,,mirror” the security settings

• Define ,,model” roles with security privileges for distinct areas of an application

• GRANT the ,,model role” to the real users • Don’t let a database administrator account log in

(64)

Security at the database layer

• PostgreSQL has a fine grained security system • Define security at the database layer

• Let the application ,,mirror” the security settings

• Define ,,model” roles with security privileges for distinct areas of an application

• GRANT the ,,model role” to the real users

• Don’t let a database administrator account log in

,→ Webapplication security measures

(65)

Security at the database layer

• PostgreSQL has a fine grained security system • Define security at the database layer

• Let the application ,,mirror” the security settings

• Define ,,model” roles with security privileges for distinct areas of an application

• GRANT the ,,model role” to the real users

• Don’t let a database administrator account log in

(66)

Security at the database layer

• PostgreSQL has a fine grained security system • Define security at the database layer

• Let the application ,,mirror” the security settings

• Define ,,model” roles with security privileges for distinct areas of an application

• GRANT the ,,model role” to the real users • Don’t let a database administrator account log in

,→ Webapplication security measures

(67)

Deny database administrator login

conn = p g s q l .connectdb( . . . ) r e s conn :exec( ’ s e l e c t r o l s u p e r f r o m p g r o l e s ’ . . ’ w h e r e r o l n a m e = c u r r e n t u s e r ’ ) i f r e s : n t u p l e s ( ) != 1 then −− No r e s u l t , f a i l l o g i n o s . e x i t ( 1 ) end i f r e s : g e t v a l u e ( 1 , 1 ) == ’ t ’ then −− db s u p e r u s e r , f a i l l o g i n o s . e x i t ( 2 ) end
(68)

Mirror user privileges in the application

r e s = conn :exec( [ [

SELECT groname FROM p g g r o u p WHERE ( SELECT u s e s y s i d FROM p g u s e r WHERE usename = c u r r e n t u s e r ) = ANY ( g r o l i s t ) ] ] f o r n = 1 , r e s : n t u p l e s ( ) do −− u s e r o l e m e m b e r s h i p t o a d j u s t UI −− h a s r o l e ( r e s : g e t v a l u e ( n , 1 ) ) end

(69)

User input

An all time classic...

(70)

User input

An all time classic...

,→ Data entry application

(71)

The code

f u n c t i o n i n s e r t D a t a ( )

conn :exec( s t r i n g . f o r m a t ( [ [

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’%s ’ , ’%s ’ , ’%s ’ ) ] ] , g u i . e n t r y . f i r s t n a m e :G e t S t r i n g( ) , g u i . e n t r y . l a s t n a m e :G e t S t r i n g( ) , g u i . e n t r y . town :G e t S t r i n g( ) ) ) end

(72)

Good SQL

l o c a l a = ’ Marc ’

l o c a l b = ’ B a l m e r ’

l o c a l c = ’ B a s e l ’

conn :exec( s t r i n g . f o r m a t ( [ [

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’%s ’ , ’%s ’ , ’%s ’ )

a , b , c )

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’ Marc ’ , ’ B a l m e r ’ , ’ B a s e l ’ )

(73)

Good SQL

l o c a l a = ’ Marc ’ l o c a l b = ’ B a l m e r ’ l o c a l c = ’ B a s e l ’

conn :exec( s t r i n g . f o r m a t ( [ [

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’%s ’ , ’%s ’ , ’%s ’ )

a , b , c )

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’ Marc ’ , ’ B a l m e r ’ , ’ B a s e l ’ )

(74)

Malicious Input

’); truncate person;

(75)

Malicious SQL

l o c a l a = ’ S t e v e ’

l o c a l b = ’B . ’

l o c a l c = ” ’ ) ; t r u n c a t e p e r s o n ; −−” conn :exec( s t r i n g . f o r m a t ( [ [

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’%s ’ , ’%s ’ , ’%s ’ )

a , b , c )

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’ S t e v e ’ , ’B . ’ , ’ ’ ) ; t r u n c a t e p e r s o n ; −−’ )

(76)

Malicious SQL

l o c a l a = ’ S t e v e ’ l o c a l b = ’B . ’

l o c a l c = ” ’ ) ; t r u n c a t e p e r s o n ; −−” conn :exec( s t r i n g . f o r m a t ( [ [

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’%s ’ , ’%s ’ , ’%s ’ )

a , b , c )

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’ S t e v e ’ , ’B . ’ , ’ ’ ) ; t r u n c a t e p e r s o n ; −−’ )

(77)

Solution 1/2: Escaping input

The same application, but this time the input is escaped

(78)

Solution 1/2: Escaping input

The same application, but this time the input is escaped

,→ Data entry application, with input escaping

(79)

Inserting data with escaping

f u n c t i o n i n s e r t D a t a ( )

conn :exec( s t r i n g . f o r m a t ( [ [

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’%s ’ , ’%s ’ , ’%s ’ )

] ] ,

conn :escape( g u i . e n t r y . f i r s t n a m e :G e t S t r i n g( ) ) , conn :escape( g u i . e n t r y . l a s t n a m e :G e t S t r i n g( ) ) , conn :escape( g u i . e n t r y . town :G e t S t r i n g( ) ) ) )

(80)

Nice try, but...

l o c a l a = ’ S t e v e ’

l o c a l b = ’B . ’

l o c a l c = ” ’ ) ; t r u n c a t e p e r s o n ; −−” conn :exec( s t r i n g . f o r m a t ( [ [

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’%s ’ , ’%s ’ , ’%s ’ )

conn :escape( a ) , conn :escape( b ) , conn :escape( c ) )

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’ S t e v e ’ , ’B . ’ , ’ ’ ’ ) ; t r u n c a t e p e r s o n ; −−’ )

(81)

Nice try, but...

l o c a l a = ’ S t e v e ’ l o c a l b = ’B . ’

l o c a l c = ” ’ ) ; t r u n c a t e p e r s o n ; −−” conn :exec( s t r i n g . f o r m a t ( [ [

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’%s ’ , ’%s ’ , ’%s ’ )

conn :escape( a ) , conn :escape( b ) , conn :escape( c ) )

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( ’ S t e v e ’ , ’B . ’ , ’ ’ ’ ) ; t r u n c a t e p e r s o n ; −−’ )

(82)

Solution 2/2: Using prepared statements

The same application, but a prepared statement is used

,→ Data entry application, with prepared statements

(83)

Solution 2/2: Using prepared statements

The same application, but a prepared statement is used

(84)

Inserting data with prepared statements, preparation step

f u n c t i o n p r e p a r e C o n n e c t i o n ( ) conn :p r e p a r e( ’ s a f e e n t r y ’ , [ [

INSERT INTO p e r s o n ( f i r s t n a m e , l a s t n a m e , town ) VALUES ( $1 , $2 , $3 )

] ] , ’ ’ , ’ ’ , ’ ’ )

end

(85)

Inserting data with prepared statements, execution step

f u n c t i o n i n s e r t D a t a ( ) conn :execPrepared( ’ s a f e e n t r y ’ , g u i . e n t r y . f i r s t n a m e :G e t S t r i n g( ) , g u i . e n t r y . l a s t n a m e :G e t S t r i n g( ) , g u i . e n t r y . town :G e t S t r i n g( ) ) end
(86)

More advantages of prepared statements

• The statement is parsed only in the preparation step

• The query plan and optimizations are done in the preparation step

→There is no setup time in the execution step

(87)

More advantages of prepared statements

• The statement is parsed only in the preparation step

• The query plan and optimizations are done in the preparation

step

(88)

More advantages of prepared statements

• The statement is parsed only in the preparation step

• The query plan and optimizations are done in the preparation step

→There is no setup time in the execution step

(89)
(90)

SQL must be composed carefully

• Whenever SQL is composed, extra care is needed

• *ALL* input must be sanitized

• Even when coming from sources we assume safe (Scanners etc.)

• Ever! • Ever!

(91)

SQL must be composed carefully

• Whenever SQL is composed, extra care is needed

• *ALL* input must be sanitized

• Even when coming from sources we assume safe (Scanners etc.)

• Ever! • Ever!

(92)

SQL must be composed carefully

• Whenever SQL is composed, extra care is needed • *ALL* input must be sanitized

• Even when coming from sources we assume safe (Scanners

etc.)

• Ever! • Ever!

(93)

SQL must be composed carefully

• Whenever SQL is composed, extra care is needed • *ALL* input must be sanitized

• Even when coming from sources we assume safe (Scanners etc.)

• Ever!

(94)

SQL must be composed carefully

• Whenever SQL is composed, extra care is needed • *ALL* input must be sanitized

• Even when coming from sources we assume safe (Scanners etc.)

• Ever!

• Ever!

(95)

1 Introduction

2 User Experience

3 Security

(96)

Questions?

(97)

Source code & Contact

The Lua interface to PostgreSQL

https://github.com/mbalmer/luapgsql/

Contact

Email: [email protected], [email protected], [email protected] Twitter: @mbalmer

IRC: mbalmer on freenode.net, #postgresql, #postgresql-de

,→ ,→ ,→ ,→ ,→ ,→ ,→ ,→ ,→ ,→ ,→ ,→ https://github.com/mbalmer/luapgsql/ http://www.vnode.ch/

References

Related documents

In addition, instead of returning events, a filter can trigger execution of specific actions in the simulation modules, e.g., to apply some forces in the physics module or

It shows anti-intellectual elements in the language of, in turn: Sylvester Graham, an influen- tial lecturer during the 1830s; the Natural Food Company, maker of Shredded Wheat and

Professor Christine Harland, Director of the Centre for Research in Strategic Purchasing and Supply (CRiSPS) and Professor Paul Maropoulos of Mechanical Engineering are leading

The sections of the standard deviation of θ, S and O 2 relative to the time averages yield a comprehensive view of the temporal variability of the water mass properties (Figs. To

In our high-resolution neutral gas mode EI-MS experiments on two prototypic ammonium salts, we observed complex mass spectra resulting from a mixture of sublimation,

These are many multiples of per capita income for the developing countries, and considerably higher than the incomes being earned in the home country by return migrants

While the reforms resulted in higher producer prices and an increase in output, lack of consensus on the specifics of the reforms and associated non-price support arrangements

(may) or integrated development land use management (must) or recognise any planning and spatial schemes) recognise any body of persons planning in province, body of established