我已经对此进行了一段时间的黑客攻击,但我找不到以下行为的充分理由:
我有一个 Android 应用程序,我从中发送一个 multipart/form-data http 帖子。该请求具有以下形式:
private final String delimiter = "--";
private final String boundary = "SwA"
+ Long.toString(System.currentTimeMillis()) + "SwA";
private final String charset = "UTF-8";
private final String lineSpace = "\r\n";
private final String domain = (domain);
private HttpURLConnection configureConnectionForMultipart(String url)
throws MalformedURLException, IOException {
HttpURLConnection con = (HttpURLConnection) (new URL(url))
.openConnection();
con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(true);
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Content-Type", "multipart/form-data;boundary="
+ boundary);
return con;
}
private void addFormPart(String paramName, String value, DataOutputStream os)
throws IOException {
os.writeBytes(lineSpace + delimiter + boundary + lineSpace);
os.writeBytes("Content-Disposition: form-data; name=\"" + paramName
+ "\"" + lineSpace);
os.writeBytes("Content-Type: text/plain; charset=" + charset + lineSpace);
os.writeBytes(lineSpace + value + lineSpace);
os.flush();
}
private void addFilePart(String paramName, File data, DataOutputStream os)
throws IOException {
os.writeBytes(lineSpace + delimiter + boundary + lineSpace);
os.writeBytes("Content-Disposition: form-data; name=\"" + paramName
+ "\"" + lineSpace);
os.writeBytes("Content-Type: application/octet-stream\r\n");
os.writeBytes("Content-Transfer-Encoding: binary" + lineSpace);
os.writeBytes(lineSpace);
os.flush();
FileInputStream fis = new FileInputStream(data);
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = fis.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.writeBytes(lineSpace);
os.flush();
fis.close();
}
private void finishMultipart(DataOutputStream os) throws IOException {
os.writeBytes(lineSpace);
os.flush();
os.writeBytes(delimiter + boundary + delimiter + lineSpace);
os.close();
}
private String getResponse(HttpURLConnection con) throws IOException {
String response = "";
int status = con.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
response += line;
}
reader.close();
} else {
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getErrorStream()));
String line = "";
while ((line = reader.readLine()) != null) {
response += line;
}
reader.close();
throw new IOException("Server returned non-OK status: " + status+", "+response);
}
return response;
}
public SearchQueryRunnable initSearchQueryRunnable(String query) {
return new SearchQueryRunnable(query);
}
private class SearchQueryRunnable implements Runnable {
private final String _query;
private final String _url = domain + "search_query.php";
public SearchQueryRunnable(String query) {
_query = query;
}
@Override
public void run() {
try {
HttpURLConnection con = configureConnectionForMultipart(_url);
DataOutputStream os = new DataOutputStream(
con.getOutputStream());
addFormPart("tag", _query, os);
finishMultipart(os);
String result = getResponse(con);
Log.i("SearchQuery", result);
con.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
在 search_query.php 中,我有以下内容:
include 'hashtags_table_api.php';
$tag = $_POST["tag"];
$res = queryHashTagsTable($tag);
在hashtags_table_api.php中,有:
include 'connect.php';
function queryHashTagsTable($hashtag) {
global $pdo;
$sql = "SELECT * FROM `tbl_hashtags` WHERE hashtag = :hashtag";
$stmt = $pdo->prepare ( $sql );
echo $hashtag;
$stmt->bindValue(':hashtag', $hashtag);
if ($stmt->execute()) {
$result = $stmt->fetchAll();
echo count($result);
}
}
connect.php 是(省略重要变量):
try {
$pdo = new PDO ( "mysql:host=$host;dbname=$dbname;charset=utf8", $username, $password );
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo 'Connected to database';
} catch(PDOException $e) {
echo $e->getMessage();
}
当我运行此代码并将值“hash”传递给 initSearchQueryRunnable 时,我得到的结果为 0,即使我在列主题标签中有一行包含值“hash”。奇怪的是,当我在 search_query.php 中硬编码以下内容时:
include 'hashtags_table_api.php';
$tag = 'hash';
$res = queryHashTagsTable($tag);
我从查询中得到了所需的结果 1。我仔细检查了一下,$_POST["tag"] 正在将值“hash”传递到我的服务器,但由于某种原因,我的 SQL 查询不会将其识别为等于我数据库中的值,即使完全相同的硬编码值被认为是相等的。
知道我还需要做什么才能将动态传递的参数识别为与 MySQL 数据相等的值吗?
编辑
经过一些测试,我意识到 $_POST["tag"] 带有引号,因此 strlen[$tag] = 6。我认为这可能是 SQL 与查询不匹配的原因与数据库中的内容串起来。果然 strlen['hash'] = 4,SQL 成功与我的查询匹配。如何有效地从 $tag 的值中删除引号,以便我的查询有效?仅供引用,我的服务器正在运行 PHP 5.4.24(如果相关的话)。
最佳答案
我在这里解决了我自己的问题。事实证明,通过我的 http 帖子发送的文本有两个额外的不可见空格,我只能通过使用 strlen 的一些测试来检测它们,并使用 for 语句来查看空格附加的位置。我的解决方案是使用 trim() 函数( http://php.net/manual/en/function.trim.php ),并在运行 queryHashTagsTable($tag) 之前简单地将 $tag = trim($tag) 添加到 search_query.php 中。我希望这可以帮助其他人,他们没有意识到他们的 http post 请求是用额外的不可见字符发送的,并且需要 SQL 查询的确切字符串。
关于java - 在 MySQL SELECT 查询中无法正确识别从 Android POST 请求传递到服务器中 PHP 的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26572622/