Błąd przy zapisie treści ze znakiem ' do bazy PostgreSQL

0

Hej, mam pewną apkę, która została napisana dla mnie przez znajomego. Niestety ten znajomy obecnie jest zajęty czymś innym i nie chcę mu zawracać głowy. Apka zapisuje do postgresowej bazy (9.3) tweety. Problem jest z tweetami zawierającymi ' (np. I'm) apka się wywala. Może ktoś mi jest w stanie doradzić, co należy zmienić w kodzie?

function saveTweetToDB(tweet) {

    try {
        var values = [
            tweet.created_at,
            tweet.text,
            tweet.user.screen_name,
            tweet.geo ? tweet.geo.coordinates[0] : 0,
            tweet.geo ? tweet.geo.coordinates[1] : 0
        ].map(function (val) {
                return "'" + val + "'";
            }).join(",");
    } catch (e) {
        console.log("error in parsing", e.message);
        console.log(tweet);
    }

    pgClient.query("insert into tweets (data, text, user_name, lat, lng, tweet) values (" + values + ", $1)",
           [JSON.stringify(tweet)], function (err, result) {
        if (err) {
            console.log("error in pg", err);
           console.log("values", values);
        }
    });
}

przy zapisie do bazy dostaję taki bład:

error in pg { [error: błąd składni w lub blisko "s"]
  name: 'error',
  length: 109,
  severity: 'BŁĄD',
  code: '42601',
  detail: undefined,
  hint: undefined,
  position: '197',
  internalPosition: undefined,
  internalQuery: undefined,
  where: undefined,
  file: 'src\\backend\\parser\\scan.l',
  line: '1002',
  routine: 'scanner_yyerror' }

Natomiast tabela w bazie wygląda tak:

CREATE TABLE tweets
(
  id serial NOT NULL,
  data timestamp without time zone,
  text text,
  user_name text,
  lat numeric,
  lng numeric,
  tweet json
)

Jak pisałem całość śmiga na Postgresql 9.3, natomiast aplikacja na nodejs. Będę wdzięczny za pomoc.

dodanie znacznika <code class="javascript"> - fp

0

Proponuje pochwalić kolegę za wspaniale zaimplementowane SQL injection. Książkowy przykład. I to jeszcze w aplikacji do której dane ciągniesz od użytkowników :D
Wiesz co by się stało jakbyś miał tweeta z jakimś:

'; drop database

?
Bo zauważ co sie dzieje jak sklejasz tak na pałe zapytanie w postaci stringa...

Rozwiazanie: Użyć jakiegoś PreparedStatement który pozwala na placeholdery na parametry, a nie sklejać stringa

http://pl.wikipedia.org/wiki/SQL_injection

0

A pewny jesteś? Bo na moje oko to query wcale nie jest poprawnie zrobione. Zauważ że OPRÓCZ $1 czyli placeholdera masz też "na pałe" doklejone wartości do stringa z zapytaniem. Gdybyś miał tam tylko $1 to byłoby w porządku. Ale teraz jeśli w tym stringu "values" będziesz miał jakiegoś kwiatka to do pola "data" można zrobić sql injection.
Więc: nodejs oczywiście pozwala uniknąć sql injection, ale tylko jak sie go umie używać.

0

Ja jak pisałem, nie znam się na programowaniu, ale łatwo się przekonać, napisz takie Tweeta po prostu :)

0

Ale tu nie ma co sprawdzać bo to widać w tym kodzie ;)

pgClient.query("insert into tweets (data, text, user_name, lat, lng, tweet) values (" + values + ", $1)", [JSON.stringify(tweet)], function (err, result)

Widzisz tutaj fragment:

 values (" + values + ", $1)

Zauważ więc że oprócz $1 który sql injection nie łyknie jest też doklejenie na pałe stringa values. A co on zawiera? Sklejone wszystkie dane dotyczące danego tweeta. Czyli jest podatny na injection. Zresztą z tego też wynika błąd od którego zacząłeś ten temat -> miałeś znak ' i stąd sie wysypało

0

A wiesz jak to poprawić?

Z ciekawości aż sprawdziłem, baza ma się dobrze, natomiast bład jak jest, tak był:

error in pg { [error: błąd składni w lub blisko ";"]
  name: 'error',
  length: 109,
  severity: 'BŁĄD',
  code: '42601',
  detail: undefined,
  hint: undefined,
  position: '487',
  internalPosition: undefined,
  internalQuery: undefined,
  where: undefined,
  file: 'src\\backend\\parser\\scan.l',
  line: '1002',
  routine: 'scanner_yyerror' }
values 'Thu Dec 12 23:50:56 +0000 2013','\'; drop database aaa','luc4s', 'city','Kraków','PL','Polska'
0

Nie znam nodejs ale zgaduje ze np. tak:

pgClient.query("insert into tweets (data, text, user_name, lat, lng, tweet) values ($1, $2)", [values, JSON.stringify(tweet)]

1 użytkowników online, w tym zalogowanych: 0, gości: 1