课程: Secure Coding in Go

SQL injection

- [Instructor] Injection is a valued member of the OWASP top 10 for many years. I find it sad since it's very easy to prevent such issues. First, let's take a look at the issue and then how to solve it. Assume we have a database for logs. So we have the schema for the database and an insertSQL. The createTable function will create the table and the insertLog is going to get the time and the message is going to format the time and generate the SQL to execute using fmt.Sprintf, which is the security issue. And now we're going to call db.Exec. If you look at the schema, it's pretty simple. We create a table called logs with a time and a message columns. And in the insert.sql does INSERT INTO logs time and message and has %s for placeholders to the values we're going to insert. And finally in the main, we read the data from the standard input, and then open connection to the database, create the tables and finally, insert the log. Let's first run the database. To do that, you need to have Docker installed. And then you can run run-database, which will run a Docker container for Postgres. And now we can run our code. So we can do go run dot and we say we want to enter log1.txt. And the command finished successfully. Let's connect to the database and see what's in there. So \d shows the tables and we can run SELECT * FROM logs, and see that the first message is inside the table. Let's quit and run our code again, this time with the second log. And the code finished successfully. Let's connect again and have a look, and we can't find our table anymore. Let's have a look at log2. So log2 has this piece of code terminating the previous SQL with a semicolon and then adding a DROP TABLE for the logs. And this is the SQL injection. To prevent SQL injection, database drivers allows you to pass parameters to SQL query and they will populate the query, taking care to escape issues. So let's fix this. So I'm going to copy the files from the fix directory to the current directory and let's have a look at what we have now. Now when we look at the db, we are doing Exec and passing the time and the message to the Exec function. And when we look at the insert, we see that we put in the values, $1 and $2, which are placeholders for SQL. And this means that the SQL driver will do the right escaping. Now let's run the code again. So go run dot slash log1.txt. And let's run the second one as well. And connect to the database. We see that the table is there. And when we do SELECT * FROM logs, we see both messages now in the database.

内容