Merge pull request #2 from connortechnology/fix_sql_injection
Sanitize input parameters
This commit is contained in:
commit
5804cd2462
154
web/ajax/log.php
154
web/ajax/log.php
|
@ -1,5 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
# Moved up here because it is used in several spots.
|
||||||
|
# These are the valid columns that you can filter on.
|
||||||
|
$filterFields = array( 'Component', 'ServerId', 'Pid', 'Level', 'File', 'Line' );
|
||||||
|
|
||||||
switch ( $_REQUEST['task'] )
|
switch ( $_REQUEST['task'] )
|
||||||
{
|
{
|
||||||
case 'create' :
|
case 'create' :
|
||||||
|
@ -31,68 +35,85 @@ switch ( $_REQUEST['task'] )
|
||||||
if ( !canView( 'System' ) )
|
if ( !canView( 'System' ) )
|
||||||
ajaxError( 'Insufficient permissions to view log entries' );
|
ajaxError( 'Insufficient permissions to view log entries' );
|
||||||
|
|
||||||
$servers = Server::find_all();
|
$servers = Server::find_all();
|
||||||
$servers_by_Id = array();
|
$servers_by_Id = array();
|
||||||
# There is probably a better way to do this.
|
# There is probably a better way to do this.
|
||||||
foreach ( $servers as $server ) {
|
foreach ( $servers as $server ) {
|
||||||
$servers_by_Id[$server->Id()] = $server;
|
$servers_by_Id[$server->Id()] = $server;
|
||||||
}
|
}
|
||||||
|
|
||||||
$minTime = isset($_POST['minTime'])?$_POST['minTime']:NULL;
|
$minTime = isset($_POST['minTime'])?$_POST['minTime']:NULL;
|
||||||
$maxTime = isset($_POST['maxTime'])?$_POST['maxTime']:NULL;
|
$maxTime = isset($_POST['maxTime'])?$_POST['maxTime']:NULL;
|
||||||
$limit = isset($_POST['limit'])?$_POST['limit']:100;
|
$limit = 100;
|
||||||
$filter = isset($_POST['filter'])?$_POST['filter']:array();
|
if ( isset($_POST['limit']) ) {
|
||||||
$sortField = isset($_POST['sortField'])?$_POST['sortField']:'TimeKey';
|
if ( ( !is_integer( $_POST['limit'] ) and !ctype_digit($_POST['limit']) ) ) {
|
||||||
|
Error("Invalid value for limit " . $_POST['limit'] );
|
||||||
|
} else {
|
||||||
|
$limit = $_POST['limit'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sortField = 'TimeKey';
|
||||||
|
if ( isset($_POST['sortField']) ) {
|
||||||
|
if ( ! in_array( $_POST['sortField'], $filterFields ) and ( $_POST['sortField'] != 'TimeKey' ) ) {
|
||||||
|
Error("Invalid sort field " . $_POST['sortField'] );
|
||||||
|
} else {
|
||||||
|
$sortField = $_POST['sortField'];
|
||||||
|
}
|
||||||
|
}
|
||||||
$sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc';
|
$sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc';
|
||||||
|
$filter = isset($_POST['filter'])?$_POST['filter']:array();
|
||||||
|
|
||||||
$filterFields = array( 'Component', 'ServerId', 'Pid', 'Level', 'File', 'Line' );
|
$total = dbFetchOne( 'SELECT count(*) AS Total FROM Logs', 'Total' );
|
||||||
|
|
||||||
$total = dbFetchOne( "SELECT count(*) AS Total FROM Logs", 'Total' );
|
|
||||||
$sql = 'SELECT * FROM Logs';
|
$sql = 'SELECT * FROM Logs';
|
||||||
$where = array();
|
$where = array();
|
||||||
$values = array();
|
$values = array();
|
||||||
if ( $minTime ) {
|
if ( $minTime ) {
|
||||||
$where[] = "TimeKey > ?";
|
$where[] = "TimeKey > ?";
|
||||||
$values[] = $minTime;
|
$values[] = $minTime;
|
||||||
} elseif ( $maxTime ) {
|
} elseif ( $maxTime ) {
|
||||||
$where[] = "TimeKey < ?";
|
$where[] = "TimeKey < ?";
|
||||||
$values[] = $maxTime;
|
$values[] = $maxTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ( $filter as $field=>$value ) {
|
foreach ( $filter as $field=>$value ) {
|
||||||
if ( $field == 'Level' ){
|
if ( ! in_array( $field, $filterFields ) ) {
|
||||||
$where[] = $field." <= ?";
|
Error("$field is not in valid filter fields");
|
||||||
$values[] = $value;
|
continue;
|
||||||
} else {
|
}
|
||||||
$where[] = $field." = ?";
|
if ( $field == 'Level' ){
|
||||||
$values[] = $value;
|
$where[] = $field." <= ?";
|
||||||
}
|
$values[] = $value;
|
||||||
}
|
} else {
|
||||||
|
$where[] = $field." = ?";
|
||||||
|
$values[] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
if ( count($where) )
|
if ( count($where) )
|
||||||
$sql.= ' WHERE '.join( ' AND ', $where );
|
$sql.= ' WHERE '.join( ' AND ', $where );
|
||||||
$sql .= " order by ".$sortField." ".$sortOrder." limit ".$limit;
|
$sql .= " order by ".$sortField." ".$sortOrder." limit ".$limit;
|
||||||
$logs = array();
|
$logs = array();
|
||||||
foreach ( dbFetchAll( $sql, NULL, $values ) as $log ) {
|
foreach ( dbFetchAll( $sql, NULL, $values ) as $log ) {
|
||||||
$log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] );
|
$log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] );
|
||||||
$log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : '';
|
$log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : '';
|
||||||
$logs[] = $log;
|
$logs[] = $log;
|
||||||
}
|
}
|
||||||
$options = array();
|
$options = array();
|
||||||
$where = array();
|
$where = array();
|
||||||
$values = array();
|
$values = array();
|
||||||
foreach( $filter as $field=>$value ) {
|
foreach( $filter as $field=>$value ) {
|
||||||
if ( $field == 'Level' ) {
|
if ( $field == 'Level' ) {
|
||||||
$where[$field] = $field." <= ?";
|
$where[$field] = $field." <= ?";
|
||||||
$values[$field] = $value;
|
$values[$field] = $value;
|
||||||
} else {
|
} else {
|
||||||
$where[$field] = $field." = ?";
|
$where[$field] = $field." = ?";
|
||||||
$values[$field] = $value;
|
$values[$field] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach( $filterFields as $field )
|
foreach( $filterFields as $field )
|
||||||
{
|
{
|
||||||
$sql = "SELECT DISTINCT $field FROM Logs WHERE NOT isnull($field)";
|
$sql = "SELECT DISTINCT $field FROM Logs WHERE NOT isnull($field)";
|
||||||
$fieldWhere = array_diff_key( $where, array( $field=>true ) );
|
$fieldWhere = array_diff_key( $where, array( $field=>true ) );
|
||||||
$fieldValues = array_diff_key( $values, array( $field=>true ) );
|
$fieldValues = array_diff_key( $values, array( $field=>true ) );
|
||||||
if ( count($fieldWhere) )
|
if ( count($fieldWhere) )
|
||||||
$sql.= " AND ".join( ' AND ', $fieldWhere );
|
$sql.= " AND ".join( ' AND ', $fieldWhere );
|
||||||
$sql.= " ORDER BY $field ASC";
|
$sql.= " ORDER BY $field ASC";
|
||||||
|
@ -108,7 +129,7 @@ switch ( $_REQUEST['task'] )
|
||||||
{
|
{
|
||||||
foreach( dbFetchAll( $sql, $field, array_values($fieldValues) ) as $value )
|
foreach( dbFetchAll( $sql, $field, array_values($fieldValues) ) as $value )
|
||||||
$options['ServerId'][$value] = ( $value and isset($servers_by_Id[$value]) ) ? $servers_by_Id[$value]->Name() : '';
|
$options['ServerId'][$value] = ( $value and isset($servers_by_Id[$value]) ) ? $servers_by_Id[$value]->Name() : '';
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -147,44 +168,51 @@ switch ( $_REQUEST['task'] )
|
||||||
}
|
}
|
||||||
//$limit = isset($_POST['limit'])?$_POST['limit']:1000;
|
//$limit = isset($_POST['limit'])?$_POST['limit']:1000;
|
||||||
$filter = isset($_POST['filter'])?$_POST['filter']:array();
|
$filter = isset($_POST['filter'])?$_POST['filter']:array();
|
||||||
$sortField = isset($_POST['sortField'])?$_POST['sortField']:'TimeKey';
|
$sortField = 'TimeKey';
|
||||||
$sortOrder = isset($_POST['sortOrder'])?$_POST['sortOrder']:'asc';
|
if ( isset($_POST['sortField']) ) {
|
||||||
|
if ( ! in_array( $_POST['sortField'], $filterFields ) and ( $_POST['sortField'] != 'TimeKey' ) ) {
|
||||||
|
Error("Invalid sort field " . $_POST['sortField'] );
|
||||||
|
} else {
|
||||||
|
$sortField = $_POST['sortField'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc';
|
||||||
|
|
||||||
$servers = Server::find_all();
|
$servers = Server::find_all();
|
||||||
$servers_by_Id = array();
|
$servers_by_Id = array();
|
||||||
# There is probably a better way to do this.
|
# There is probably a better way to do this.
|
||||||
foreach ( $servers as $server ) {
|
foreach ( $servers as $server ) {
|
||||||
$servers_by_Id[$server->Id()] = $server;
|
$servers_by_Id[$server->Id()] = $server;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql = "select * from Logs";
|
$sql = "select * from Logs";
|
||||||
$where = array();
|
$where = array();
|
||||||
$values = array();
|
$values = array();
|
||||||
if ( $minTime )
|
if ( $minTime )
|
||||||
{
|
{
|
||||||
preg_match( '/(.+)(\.\d+)/', $minTime, $matches );
|
preg_match( '/(.+)(\.\d+)/', $minTime, $matches );
|
||||||
$minTime = strtotime($matches[1]).$matches[2];
|
$minTime = strtotime($matches[1]).$matches[2];
|
||||||
$where[] = "TimeKey >= ?";
|
$where[] = "TimeKey >= ?";
|
||||||
$values[] = $minTime;
|
$values[] = $minTime;
|
||||||
}
|
}
|
||||||
if ( $maxTime )
|
if ( $maxTime )
|
||||||
{
|
{
|
||||||
preg_match( '/(.+)(\.\d+)/', $maxTime, $matches );
|
preg_match( '/(.+)(\.\d+)/', $maxTime, $matches );
|
||||||
$maxTime = strtotime($matches[1]).$matches[2];
|
$maxTime = strtotime($matches[1]).$matches[2];
|
||||||
$where[] = "TimeKey <= ?";
|
$where[] = "TimeKey <= ?";
|
||||||
$values[] = $maxTime;
|
$values[] = $maxTime;
|
||||||
}
|
}
|
||||||
foreach ( $filter as $field=>$value ) {
|
foreach ( $filter as $field=>$value ) {
|
||||||
if ( $value != '' ) {
|
if ( $value != '' ) {
|
||||||
if ( $field == 'Level' ) {
|
if ( $field == 'Level' ) {
|
||||||
$where[] = $field." <= ?";
|
$where[] = $field." <= ?";
|
||||||
$values[] = $value;
|
$values[] = $value;
|
||||||
} else {
|
} else {
|
||||||
$where[] = $field." = ?'";
|
$where[] = $field." = ?'";
|
||||||
$values[] = $value;
|
$values[] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( count($where) )
|
if ( count($where) )
|
||||||
$sql.= " where ".join( " and ", $where );
|
$sql.= " where ".join( " and ", $where );
|
||||||
$sql .= " order by ".$sortField." ".$sortOrder;
|
$sql .= " order by ".$sortField." ".$sortOrder;
|
||||||
|
@ -216,7 +244,7 @@ switch ( $_REQUEST['task'] )
|
||||||
foreach ( dbFetchAll( $sql, NULL, $values ) as $log )
|
foreach ( dbFetchAll( $sql, NULL, $values ) as $log )
|
||||||
{
|
{
|
||||||
$log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] );
|
$log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] );
|
||||||
$log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : '';
|
$log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : '';
|
||||||
$logs[] = $log;
|
$logs[] = $log;
|
||||||
}
|
}
|
||||||
switch( $format )
|
switch( $format )
|
||||||
|
@ -234,20 +262,20 @@ switch ( $_REQUEST['task'] )
|
||||||
}
|
}
|
||||||
case 'tsv' :
|
case 'tsv' :
|
||||||
{
|
{
|
||||||
# This line doesn't need fprintf, it could use fwrite
|
# This line doesn't need fprintf, it could use fwrite
|
||||||
fprintf( $exportFP, join( "\t",
|
fprintf( $exportFP, join( "\t",
|
||||||
translate('DateTime'),
|
translate('DateTime'),
|
||||||
translate('Component'),
|
translate('Component'),
|
||||||
translate('Server'),
|
translate('Server'),
|
||||||
translate('Pid'),
|
translate('Pid'),
|
||||||
translate('Level'),
|
translate('Level'),
|
||||||
translate('Message'),
|
translate('Message'),
|
||||||
translate('File'),
|
translate('File'),
|
||||||
translate('Line')
|
translate('Line')
|
||||||
)."\n" );
|
)."\n" );
|
||||||
foreach ( $logs as $log )
|
foreach ( $logs as $log )
|
||||||
{
|
{
|
||||||
fprintf( $exportFP, "%s\t%s\t%s\t%d\t%s\t%s\t%s\t%s\n", $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] );
|
fprintf( $exportFP, "%s\t%s\t%s\t%d\t%s\t%s\t%s\t%s\n", $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ class Frame {
|
||||||
public function __construct( $IdOrRow ) {
|
public function __construct( $IdOrRow ) {
|
||||||
$row = NULL;
|
$row = NULL;
|
||||||
if ( $IdOrRow ) {
|
if ( $IdOrRow ) {
|
||||||
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
|
if ( is_integer( $IdOrRow ) or ctype_digit($IdOrRow) ) {
|
||||||
$row = dbFetchOne( 'SELECT * FROM Frames WHERE Id=?', NULL, array( $IdOrRow ) );
|
$row = dbFetchOne( 'SELECT * FROM Frames WHERE Id=?', NULL, array( $IdOrRow ) );
|
||||||
if ( ! $row ) {
|
if ( ! $row ) {
|
||||||
Error("Unable to load Frame record for Id=" . $IdOrRow );
|
Error("Unable to load Frame record for Id=" . $IdOrRow );
|
||||||
|
@ -84,7 +84,15 @@ class Frame {
|
||||||
$values = array_values( $parameters );
|
$values = array_values( $parameters );
|
||||||
}
|
}
|
||||||
if ( $limit ) {
|
if ( $limit ) {
|
||||||
$sql .= ' LIMIT ' . $limit;
|
if ( is_integer( $limit ) or ctype_digit( $limit ) ) {
|
||||||
|
$sql .= ' LIMIT ' . $limit;
|
||||||
|
} else {
|
||||||
|
$backTrace = debug_backtrace();
|
||||||
|
$file = $backTrace[1]['file'];
|
||||||
|
$line = $backTrace[1]['line'];
|
||||||
|
Error("Invalid value for limit($limit) passed to Frame::find from $file:$line");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$results = dbFetchAll( $sql, NULL, $values );
|
$results = dbFetchAll( $sql, NULL, $values );
|
||||||
if ( $results ) {
|
if ( $results ) {
|
||||||
|
|
|
@ -5,7 +5,7 @@ class Server {
|
||||||
public function __construct( $IdOrRow = NULL ) {
|
public function __construct( $IdOrRow = NULL ) {
|
||||||
$row = NULL;
|
$row = NULL;
|
||||||
if ( $IdOrRow ) {
|
if ( $IdOrRow ) {
|
||||||
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
|
if ( is_integer( $IdOrRow ) or ctype_digit( $IdOrRow ) ) {
|
||||||
$row = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array( $IdOrRow ) );
|
$row = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array( $IdOrRow ) );
|
||||||
if ( ! $row ) {
|
if ( ! $row ) {
|
||||||
Error("Unable to load Server record for Id=" . $IdOrRow );
|
Error("Unable to load Server record for Id=" . $IdOrRow );
|
||||||
|
@ -63,9 +63,15 @@ class Server {
|
||||||
) );
|
) );
|
||||||
$values = array_values( $parameters );
|
$values = array_values( $parameters );
|
||||||
}
|
}
|
||||||
if ( $limit ) {
|
if ( is_integer( $limit ) or ctype_digit( $limit ) ) {
|
||||||
$sql .= ' LIMIT ' . $limit;
|
$sql .= ' LIMIT ' . $limit;
|
||||||
}
|
} else {
|
||||||
|
$backTrace = debug_backtrace();
|
||||||
|
$file = $backTrace[1]['file'];
|
||||||
|
$line = $backTrace[1]['line'];
|
||||||
|
Error("Invalid value for limit($limit) passed to Server::find from $file:$line");
|
||||||
|
return;
|
||||||
|
}
|
||||||
$results = dbFetchAll( $sql, NULL, $values );
|
$results = dbFetchAll( $sql, NULL, $values );
|
||||||
if ( $results ) {
|
if ( $results ) {
|
||||||
return array_map( function($id){ return new Server($id); }, $results );
|
return array_map( function($id){ return new Server($id); }, $results );
|
||||||
|
|
Loading…
Reference in New Issue