Mer

Unngå SQL-injeksjon når du oppdaterer tabeller via CartoDB API


Jeg prøver å skrive en rutine som synkroniserer data i databasen vår med CartoDB-databasen, slik at vi kan vise dem på et kart. Det er enkle ting som navn og kontaktdetaljer, som brukerne våre har muligheten til å endre online. Det er usannsynlig å være et problem, men likevel er det klokt å bekymre seg for SQL-injeksjon.

Er det en anbefalt måte å gjøre dette gjennom SQL API? Jeg skriver spørsmål som:

https://ouraccount.cartodb.com/api/v2/sql?q=update our_table set surname = 'Smith' where cartodb_id = 5 & api_key = 123456789

Jeg vil heller ikke prøve å rense Smith-delen selv, og jeg finner ingen dokumentasjon som sier at API-et støtter parameterisering. Hva gjør folk her?


REDIGERE: Mitt gamle svar gjaldt bare den vanlige CartoDB API, som bare tillater lesetilgang.

Du spesifiserte ikke i spørsmålet ditt, men det virker som om du prøver å få klienten til å skyve oppdateringsforespørselen direkte til API-et. Dette er ingen god idé. Når API-nøkkelen din er utgitt for publikum, kan alle gjøre forespørsler ved hjelp av den. Den skal forbli på serveren din. Klienter kan samhandle med den ved hjelp av OAuth i kombinasjon med nøkkelen. Så for å oppsummere:

IKKE generer skriv SQL (INSERT, UPDATE, DELETE) på klientsiden. Alt som krever en API-nøkkel, bør gjøres på serveren din gjennom OAuth-interaktivitet. Alt lesetilgang uten nøkkel er greit.

Formålet med SQL API med nøkkel er å tillate serverapplikasjonen, ikke klienten, for å kjøre oppdateringsspørsmål på CartoDB. Det har noen grunnleggende kontroller for å validere om du sender god SQL eller ikke, men det vil ikke parameterisere spørsmålene dine for deg.

Jeg vil helst ikke prøve å rense Smith-delen selv

Dessverre må du. Den delen av SQL API som oppdaterer tabeller ser for tiden etter noen grunnleggende ugyldige spørsmål, men er ikke designet for at klienten direkte skal samhandle med den. Det du trenger å gjøre er å samle spørsmålsparametrene fra brukeren din, unnslippe deretter, og la appgrensesnittet ditt med selve API-et.

Er det en anbefalt måte å gjøre dette gjennom SQL API? Jeg skriver spørsmål som:

I denne lenken skisserer CartoDB en metode som ennå ikke skal utvikles for å bygge "Named Queries" for å samhandle med API-en. Selv om bruken ikke er implementert i APIen på tidspunktet for dette innlegget, gir det god innsikt i hvordan du kan bygge opp et parameterisert skrivespørsmål på serveren din:

Spørringsmaler refererer til parametere ved hjelp av skilletegnene <% = og%>. Det vil være systemparametere (levert av serveren, som klient-IP eller lignende) og brukerparametere (levert av brukeren ved innkallingstidspunktet).

For å unngå SQL-injeksjon, vil hver parameter være av en gitt "type", som bestemmer den nødvendige rømningen for den. Støttede typer er:

sql_literal (interne enkle anførselstegn vil være sql-rømt) sql_ident (interne dobbelt anførselstegn vil være sql-rømmet) nummer (kan bare inneholde numerisk representasjon) ... (legg til mer etter behov) Gyldige brukerparameternavn starter med en bokstav og kan inneholder bare bokstaver, tall eller understrekninger. Systemparameternavn er prefikset med sys :: for å unngå sammenstøt med brukerparametere.

Brukerparametere må defineres eksplisitt når NamedQuery opprettes, med standardinnstillingene (for å sjekke SQL-gyldighet).

// namedquery.json {versjon: '0.0.1', // det kan maksimalt være 1 mal med samme navn for enhver bruker // gyldige navn starter med en bokstav og inneholder bare bokstav, tall // eller understreker navn: 'query_name', // innebygd autorisasjonssertifikat auth: {// Se https://github.com/CartoDB/Windshaft-cartodb/wiki/Signed-maps method: 'token', // eller "open" valid_tokens: [' auth_token1 ',' auth_token2 '] // bare for' token '-metoden}, // variabler som ikke er oppført her erstattes ikke // variabel ikke oppgitt ved øyeblikkelig tidspunkt utløser en feil // Det kreves en standard for valgfrie variabler // typespesifikasjon brukes til å sitere, for å unngå injeksjoner plassholdere: {x: {type: 'nummer', standard: 0}, y: {type: 'nummer', standard: 0}, z: {type: 'nummer', standard: 0}, iso2: {type: 'sql_literal', standard: 'ES'}}, sql: "select CDB_TorqueTile (" + "$$ SELECT * FROM land WHERE iso2 = '<% = iso2%>' $$," + "<% = z%>, <% = x%>, <% = y%>)", påvirket_tabeller: 'land' // valgfritt}

For videre lesing, se også dette spørsmålet.


Det kan være en bedre ressurs enn dette CartoDB-blogginnlegget, men du kan nå lage sql / plpgsql-funksjoner som har svært begrensede bruksområder som du deretter kan eksponere offentlig, for eksempel:

OPPRETT ELLER ERSTAT FUNKSJON name_change (_surname TEXT, _id INT) RETURNS integer AS $$ BEGIN EXECUTE 'UPDATE ourtable SET efternamn = $ 1 WHERE cartodb_id = $ 2' USING (_sname, _id); RETUR 1; SLUTT; $$ SPRÅK plpgsql SIKKERHETSDEFINERER; - Gi tilgang til den offentlige brukeren GRANT EXECUTE ON FUNCTION name_change (text, int) TO publicuser;

Og få tilgang til det med noe sånt som:

https://ouraccount.cartodb.com/api/v2/sql?q=SELECT name_change ('Smith', 5)


Se videoen: CartoDB tutorial (September 2021).