Skip to content

Commit e861284

Browse files
committed
fix(dhcp, hostapd): validate interface names and sanitize shell commands
1 parent 7883514 commit e861284

File tree

3 files changed

+26
-9
lines changed

3 files changed

+26
-9
lines changed

includes/configure_client.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function DisplayWPAConfig()
4141

4242
if (preg_match('/delete(\d+)/', $post, $post_match)) {
4343
$network = $tmp_networks[$_POST['ssid' . $post_match[1]]];
44-
$netid = $network['index'];
44+
$netid = intval($network['index']);
4545
exec('sudo wpa_cli -i ' . $iface . ' disconnect ' . $netid);
4646
exec('sudo wpa_cli -i ' . $iface . ' remove_network ' . $netid);
4747
unset($tmp_networks[$_POST['ssid' . $post_match[1]]]);

includes/dhcp.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ function DisplayDHCPConfig()
8787
function saveDHCPConfig($status)
8888
{
8989
$iface = $_POST['interface'];
90+
if (!validateInterface($iface)) {
91+
$status->addMessage('Invalid interface name provided.', 'danger');
92+
return false;
93+
}
9094
$return = 1;
9195

9296
// handle disable dhcp option
@@ -140,7 +144,7 @@ function validateDHCPInput()
140144
$errors = [];
141145
define('IFNAMSIZ', 16);
142146
$iface = $_POST['interface'];
143-
if (!preg_match('/^[^\s\/\\0]+$/', $iface)
147+
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $iface)
144148
|| strlen($iface) >= IFNAMSIZ
145149
) {
146150
$errors[] = _('Invalid interface name.');
@@ -273,7 +277,9 @@ function updateDnsmasqConfig($iface,$status)
273277
}
274278
file_put_contents("/tmp/dnsmasqdata", $config);
275279
$msg = file_exists(RASPI_DNSMASQ_PREFIX.$iface.'.conf') ? 'updated' : 'added';
276-
system('sudo cp /tmp/dnsmasqdata '.RASPI_DNSMASQ_PREFIX.$iface.'.conf', $result);
280+
$destination = RASPI_DNSMASQ_PREFIX . escapeshellarg($iface . '.conf');
281+
$command = sprintf('sudo cp /tmp/dnsmasqdata %s', $destination);
282+
system($command, $result);
277283
if ($result == 0) {
278284
$status->addMessage('Dnsmasq configuration for '.$iface.' '.$msg.'.', 'success');
279285
}
@@ -291,7 +297,9 @@ function updateDnsmasqConfig($iface,$status)
291297
}
292298
$config .= PHP_EOL;
293299
file_put_contents("/tmp/dnsmasqdata", $config);
294-
system('sudo cp /tmp/dnsmasqdata '.RASPI_DNSMASQ_PREFIX.'raspap.conf', $result);
300+
$destination = escapeshellarg(RASPI_DNSMASQ_PREFIX . 'raspap.conf');
301+
$command = sprintf('sudo cp /tmp/dnsmasqdata %s', $destination);
302+
system($command, $result);
295303

296304
return $result;
297305
}
@@ -340,7 +348,9 @@ function updateDHCPConfig($iface,$status)
340348
$status->addMessage('DHCP configuration for '.$iface.' updated.', 'success');
341349
}
342350
file_put_contents("/tmp/dhcpddata", $dhcp_cfg);
343-
system('sudo cp /tmp/dhcpddata '.RASPI_DHCPCD_CONFIG, $result);
351+
$destination = escapeshellarg(RASPI_DHCPCD_CONFIG);
352+
$command = sprintf('sudo cp /tmp/dhcpddata %s', $destination);
353+
system($command, $result);
344354

345355
return $result;
346356
}

includes/hostapd.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $reg_dom
310310
$status->addMessage('Unknown interface '.htmlspecialchars($_POST['interface'], ENT_QUOTES), 'danger');
311311
$good_input = false;
312312
}
313-
if (strlen($_POST['country_code']) !== 0 && strlen($_POST['country_code']) != 2) {
313+
if (strlen($_POST['country_code']) !== 0 && !preg_match('/^[A-Z]{2}$/', $_POST['country_code'])) {
314314
$status->addMessage('Country code must be blank or two characters', 'danger');
315315
$good_input = false;
316316
} else {
@@ -330,6 +330,7 @@ function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $reg_dom
330330
$_POST['max_num_sta'] = $_POST['max_num_sta'] < 1 ? null : $_POST['max_num_sta'];
331331

332332
if ($good_input) {
333+
$interface = escapeshellarg($_POST['interface']);
333334
$return = updateHostapdConfig($ignore_broadcast_ssid,$wifiAPEnable,$bridgedEnable);
334335

335336
if (trim($country_code) != trim($reg_domain)) {
@@ -357,7 +358,9 @@ function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $reg_dom
357358
scanConfigDir('/etc/dnsmasq.d/','uap0',$status);
358359
$config = join(PHP_EOL, $config);
359360
file_put_contents("/tmp/dnsmasqdata", $config);
360-
system('sudo cp /tmp/dnsmasqdata '.RASPI_DNSMASQ_PREFIX.$ap_iface.'.conf', $return);
361+
$destination = RASPI_DNSMASQ_PREFIX . escapeshellarg($ap_iface . '.conf');
362+
$command = sprintf('sudo cp /tmp/dnsmasqdata %s', $destination);
363+
system($command, $return);
361364
} elseif ($bridgedEnable !==1) {
362365
$dhcp_range = ($syscfg['dhcp-range'] =='') ? getDefaultNetValue('dnsmasq',$ap_iface,'dhcp-range') : $syscfg['dhcp-range'];
363366
$config = [ '# RaspAP '.$_POST['interface'].' configuration' ];
@@ -370,7 +373,9 @@ function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $reg_dom
370373
$config[] = PHP_EOL;
371374
$config = join(PHP_EOL, $config);
372375
file_put_contents("/tmp/dnsmasqdata", $config);
373-
system('sudo cp /tmp/dnsmasqdata '.RASPI_DNSMASQ_PREFIX.$ap_iface.'.conf', $return);
376+
$destination = RASPI_DNSMASQ_PREFIX . escapeshellarg($ap_iface . '.conf');
377+
$command = sprintf('sudo cp /tmp/dnsmasqdata %s', $destination);
378+
system($command, $return);
374379
}
375380

376381
// Set dhcp values from system config, fallback to default if undefined
@@ -524,7 +529,9 @@ function updateHostapdConfig($ignore_broadcast_ssid,$wifiAPEnable,$bridgedEnable
524529
$config.= parseUserHostapdCfg();
525530

526531
file_put_contents("/tmp/hostapddata", $config);
527-
system("sudo cp /tmp/hostapddata " . RASPI_HOSTAPD_CONFIG, $result);
532+
$destination = escapeshellarg(RASPI_HOSTAPD_CONFIG);
533+
$command = sprintf("sudo cp /tmp/hostapddata %s", $destination);
534+
system($command, $result);
528535
return $result;
529536
}
530537

0 commit comments

Comments
 (0)