Summary
Multiple Stored XSS vulnerabilities in php/apsearch.php
and php/alsearch.php
allow authenticated remote attackers to inject arbitrary JavaScript or HTML via airport and airline attributes.
Details
Airport and airline attributes received from users are saved in the database without proper validation:
|
$name = $_POST["name"]; |
|
$alias = $_POST["alias"]; |
|
$mode = $_POST["mode"]; |
|
if (!$mode || $mode == 'F') { |
|
$iata = $_POST["iata"]; |
|
$icao = $_POST["icao"]; |
|
$callsign = $_POST["callsign"]; |
|
$mode = "F"; |
|
} else { |
|
$iata = ""; |
|
$icao = ""; |
|
$callsign = ""; |
|
} |
|
$country = $_POST["country"]; |
|
$offset = $_POST["offset"]; |
|
$active = $_POST["active"]; |
|
$iatafilter = $_POST["iatafilter"]; |
|
$action = $_POST["action"]; |
|
$alid = $_POST["alid"]; |
|
if (!$alid || $alid == "") { |
|
// Adding new airline |
|
$sql = <<<SQL |
|
INSERT INTO airlines(name, alias, country, iata, icao, callsign, mode, active, uid) |
|
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?) |
|
SQL; |
|
$params = [ |
|
$name, |
|
$alias, |
|
$country, |
|
$iata == "" ? null : $iata, |
|
$icao == "" ? null : $icao, |
|
$callsign, |
|
$mode, |
|
$active, |
|
$uid |
|
]; |
|
} else { |
|
// Editing an existing airline |
|
$sql = <<<SQL |
|
UPDATE airlines |
|
SET name = ?, alias = ?, country = ?, iata = ?, icao = ?, callsign = ?, mode = ?, active = ? |
|
WHERE alid = ? AND (uid = ? OR ? IN (?)) |
|
SQL; |
|
$params = [ |
|
$name, |
|
$alias, |
|
$country, |
|
$iata == "" ? null : $iata, |
|
$icao == "" ? null : $icao, |
|
$callsign, |
|
$mode, |
|
$active, |
|
$alid, |
|
$uid, |
|
$uid, |
|
implode(', ', (array)$OF_ADMIN_UID) |
|
]; |
|
} |
|
|
|
$sth = $dbh->prepare($sql); |
|
if (!$sth->execute($params)) { |
|
die('0;' . sprintf(_('Adding new %s failed.'), MODES_OPERATOR[$mode])); |
|
} |
|
$airport = $_POST["name"]; |
|
$iata = $_POST["iata"]; |
|
$icao = $_POST["icao"]; |
|
$city = $_POST["city"]; |
|
$country = $_POST["country"]; |
|
$code = $_POST["code"]; |
|
$myX = $_POST["x"]; |
|
$myY = $_POST["y"]; |
|
$elevation = $_POST["elevation"]; |
|
$tz = $_POST["timezone"]; |
|
$dst = $_POST["dst"]; |
|
$tableName = $_POST["db"]; |
|
$iatafilter = $_POST["iatafilter"]; |
|
$offset = intval($_POST["offset"]); |
|
$action = $_POST["action"]; |
|
$apid = $_POST["apid"]; |
|
if (empty($duplicates)) { |
|
// If no duplicates, attempt to insert/update as appropriate |
|
if ($addAirport) { |
|
$sql = <<<SQL |
|
INSERT INTO airports(name, city, country, iata, icao, x, y, elevation, timezone, dst, uid) |
|
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) |
|
SQL; |
|
$params = [ |
|
$airport, |
|
$city, |
|
$country, |
|
$iata == "" ? null : $iata, |
|
$icao == "" ? null : $icao, |
|
$myX, |
|
$myY, |
|
$elevation, |
|
$tz, |
|
$dst, |
|
$uid |
|
]; |
|
} else { |
|
// Editing an existing airport |
|
$sql = <<<SQL |
|
UPDATE airports |
|
SET name = ?, city = ?, country = ?, iata = ?, icao = ?, x = ?, y = ?, elevation = ?, timezone = ?, dst = ? |
|
WHERE apid = ? |
|
SQL; |
|
$params = [ |
|
$airport, |
|
$city, |
|
$country, |
|
$iata == "" ? null : $iata, |
|
$icao == "" ? null : $icao, |
|
$myX, |
|
$myY, |
|
$elevation, |
|
$tz, |
|
$dst, |
|
$apid |
|
]; |
|
} |
|
|
|
$sth = $dbh->prepare($sql); |
|
$res = $sth->execute($params); |
Then these attributes are displayed without proper sanitization in multiple places: (I'm not sure if the following list is complete)
|
$row["al_name"] = format_airline($row); |
|
print "\n" . json_encode($row); |
|
$row["ap_name"] = format_airport($row); |
|
unset($row["uid"]); |
|
$response['airports'][] = $row; |
|
} |
|
print json_encode($response); |
|
$results[] = ['value' => format_apdata($row), 'label' => format_airport($row)]; |
|
$results[] = ['label' => format_airline($row), 'value' => (int)$row['alid']]; |
|
printf( |
|
"%s;%s;%s (<b>%s</b>)<br><small>%s, %s<br>%s routes</small>\n", |
|
$apid, |
|
$row["count"], |
|
$row["name"], |
|
format_apcode($row), |
|
$row["city"], |
|
$row["country"], |
|
$row["count"] |
|
); |
|
if ($row["count"] == 0) { |
|
// No routes, print this airport and abort |
|
printf( |
|
"\n%s;%s;%s;%s;0;%s;N\n", |
|
format_apdata($row), |
|
$row["name"], |
|
$row["city"], |
|
$row["country"], |
|
format_airport($row) |
|
); |
|
printf( |
|
"%s;%s;%s (<b>%s</b>)<br><small>%s</small><br>%s routes\n", |
|
"L" . $apid, |
|
$row["count"], |
|
$row["name"], |
|
$row["iata"], |
|
$row["country"], |
|
$row["count"] |
|
); |
|
$rows[] = sprintf( |
|
"%s;%s;%s;%s;%s;%s;%s;%s;%s;%s", |
|
$row[0], |
|
$row[1], |
|
$row[2], |
|
$row[3], |
|
$row[4], |
|
$row[5], |
|
$row[6], |
|
$row[7], |
|
$row[8], |
|
$row[9] |
|
); |
|
foreach ($sth as $row) { |
|
$rows[] = sprintf( |
|
"%s;%s;%s;%s;%s;%s;%s", |
|
format_apdata($row), |
|
$row["name"], |
|
$row["city"], |
|
$row["country"], |
|
$row["visits"], |
|
format_airport($row), |
|
$row["future"] |
|
); |
|
} |
|
foreach ($sth as $row) { |
|
$rows[] = sprintf("%s;%s", $row["alid"], $row["name"]); |
|
} |
|
$map .= implode("\t", $rows); |
|
} |
|
|
|
// And years also null |
|
print $map . "\n\n"; |
PoC
Malicious airline: post action=RECORD&name=%3Cimg+src+onerror%3D%22alert%28%27xss%27%29%22%3E&icao=X2S
to https://openflights.org/php/alsearch.php
.
Malicious airport: post action=RECORD&name=XSS+Test&country=%3Cimg+src+onerror%3D%22alert%28%27xss%27%29%22%3E&iata=XSS&x=1&y=1
to https://openflights.org/php/apsearch.php
.
Then search for them in al/apsearch.
Impact
Authenticated attackers can inject arbitrary JavaScript into the website by storing malicious airlines or airports in the database, and then fool the victims into searching for them or wait for the victim to accidentally search for them.
Summary
Multiple Stored XSS vulnerabilities in
php/apsearch.php
andphp/alsearch.php
allow authenticated remote attackers to inject arbitrary JavaScript or HTML via airport and airline attributes.Details
Airport and airline attributes received from users are saved in the database without proper validation:
openflights/php/alsearch.php
Lines 8 to 26 in f53e452
openflights/php/alsearch.php
Lines 130 to 173 in f53e452
openflights/php/apsearch.php
Lines 12 to 27 in f53e452
openflights/php/apsearch.php
Lines 69 to 112 in f53e452
Then these attributes are displayed without proper sanitization in multiple places: (I'm not sure if the following list is complete)
openflights/php/alsearch.php
Lines 260 to 261 in f53e452
openflights/php/apsearch.php
Lines 465 to 469 in f53e452
openflights/php/autocomplete.php
Line 107 in f53e452
openflights/php/autocomplete.php
Line 176 in f53e452
openflights/php/routes.php
Lines 96 to 115 in f53e452
openflights/php/routes.php
Lines 137 to 145 in f53e452
openflights/php/routes.php
Lines 171 to 183 in f53e452
openflights/php/routes.php
Lines 207 to 218 in f53e452
openflights/php/routes.php
Lines 238 to 245 in f53e452
PoC
Malicious airline: post
action=RECORD&name=%3Cimg+src+onerror%3D%22alert%28%27xss%27%29%22%3E&icao=X2S
tohttps://openflights.org/php/alsearch.php
.Malicious airport: post
action=RECORD&name=XSS+Test&country=%3Cimg+src+onerror%3D%22alert%28%27xss%27%29%22%3E&iata=XSS&x=1&y=1
tohttps://openflights.org/php/apsearch.php
.Then search for them in al/apsearch.
Impact
Authenticated attackers can inject arbitrary JavaScript into the website by storing malicious airlines or airports in the database, and then fool the victims into searching for them or wait for the victim to accidentally search for them.