Отправка SQL-запроса в URL с помощью NSURLRequest в ObjC - PullRequest
1 голос
/ 09 февраля 2012

У меня очень странная проблема при попытке передать запрос SQL с использованием класса NSURLRequest в задаче C. Я могу отправить простой запрос, который работает и возвращает правильное содержимое (в формате JSON). Вот мой код:

NSString *URLWithSQLQuery = [NSString stringWithString:@"http://localhost/querydatabase.php?query=INSERT+INTO+Table+(ID,Column1,Column2,Column3,Column4,Column5,Column6,Column7,Column8)+VALUES+(NULL,'a','b','','c','d','','1','2')"];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:URLWithSQLQuery]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *data = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSLog(@"%@", data);

Это не добавляет фиктивные значения в таблицу. Следующий код возвращает правильное содержание:

NSString *URLWithSQLQuery = [NSString stringWithString:@"http://localhost/querydatabase.php?query=SELECT+*+FROM+Table"];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:URLWithSQLQuery]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *data = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSLog(@"%@", data);

И когда я вставляю URL http://localhost/querydatabase.php?query=INSERT+INTO+Table+(ID,Column1,Column2,Column3,Column4,Column5,Column6,Column7,Column8)+VALUES+(NULL,'a','b','','c','d','','1','2') в свой браузер, запрос выполняется правильно. Так что я действительно не знаю, откуда возникла проблема, поскольку она не исходит из сценария PHP или URLWithSQLQuery, а также из моего кода Objective C.

Любая идея будет принята с благодарностью. Спасибо всем за помощь.

Scott

1 Ответ

13 голосов
/ 09 февраля 2012

На этот вопрос дан ответ, но я думаю, что стоит кое-что указать любому, кто сталкивается с этим вопросом в будущем, а также его автора:

НИКОГДА не отправляйте реальный SQL черезВаши URL

Это гигантский недостаток безопасности.Без совершенно нелепой дезинфекции и проверки этот код, когда он будет выпущен в дикую природу, оставит ваш сервер и базу данных широко открытыми для использования.

Я собираюсь сделать предположение, что вы толкаете строку запроса вmysql_query() или что-то подобное, например:

$query = mysql_query($_GET['query']);

Любому, кто найдет ваш API, даже не нужно его взламывать, потому что вы сделали всю тяжелую работу для него.Это как строить Форт Нокс, но оставить входную дверь открытой.Здание может противостоять атаке, но любой, кто знает, может просто войти.

Им просто нужно изменить URL на любой запрос, который им нравится:

// Delete one of your databases
http://your-server.com/querydatabase.php?query=DROP+DATABASE+DBNAME

// Create a new user account to log in directly
http://your-server.com/querydatabase.php?query=GRANT+ALL+PRIVILEGES+ON+*.*+TO+'bobby'%40%25+IDENTIFIED+BY+'password'

Ваш код PHP должен принятьряд отдельных параметров для данных, которые вы хотите сохранить, и вы должны убедиться, что они нормальны и действительны, прежде чем вставлять их в предварительно созданный SQL-запрос.Это серьезно ограничивает (но не мешает всем) возможности, доступные недобросовестному человеку делать что-то плохое с вашим сервером.

В качестве очень простого примера (в стиле того, что у вас уже есть):

// get records from the database
http://your-server.com/querydatabase.php?query=list

if ($_GET['query'] == 'list') {
    mysql_query("SELECT * FROM TABLE");
}

// you would actually make a POST request to do this
http://your-server.com/querydatabase.php?query=save&column1=value1&column2=value2...

if ($_GET['query'] == 'save') {
    $column1 = mysql_real_escape_string($_GET['column1']);
    $column2 = mysql_real_escape_string($_GET['column2']);

   // only want column 1 to be an integer?
   if (!ctype_digit($column1)) die("Column 1 is not a number");

   mysql_query("INSERT INTO TABLE (column1, column2) VALUES ($column1, $column2)");
}

Предпочтительным и немного более продвинутым методом является отбрасывание mysql_* и использование mysqli или PDO (или ORM, который обрабатывает все это за вас), поэтому вы можете использовать prepared statements вместо.

Это может показаться неважным, особенно если вы запускаете его на локальном хосте, но в вопросе показано, что опасно .

...