View | Details | Raw Unified | Return to bug 37508
Collapse All | Expand All

(-)a/Koha/Report.pm (+42 lines)
Lines 28-33 use base qw(Koha::Object); Link Here
28
# Only 1 error is returned
28
# Only 1 error is returned
29
# TODO Koha::Report->store should check this before saving
29
# TODO Koha::Report->store should check this before saving
30
30
31
use constant FORBIDDEN_COLUMN_MATCHES => qw(password token uuid secret);
32
use constant WHITELISTED_COLUMN_NAMES =>
33
    qw(password_expiration_date password_expiry_days reset_password change_password min_password_length require_strong_password password_expiration_date);
34
31
=head1 NAME
35
=head1 NAME
32
36
33
Koha::Report - Koha Report Object class
37
Koha::Report - Koha Report Object class
Lines 58-68 sub is_sql_valid { Link Here
58
        push @errors, { sqlerr => $1 };
62
        push @errors, { sqlerr => $1 };
59
    } elsif ($sql !~ /^\s*SELECT\b\s*/i) {
63
    } elsif ($sql !~ /^\s*SELECT\b\s*/i) {
60
        push @errors, { queryerr => 'Missing SELECT' };
64
        push @errors, { queryerr => 'Missing SELECT' };
65
    } else {
66
        push @errors, { passworderr => "Illegal column in results" }
67
            if $self->check_columns($sql);
61
    }
68
    }
62
69
63
    return ( @errors ? 0 : 1, \@errors );
70
    return ( @errors ? 0 : 1, \@errors );
64
}
71
}
65
72
73
=head3 check_columns
74
75
    $self->check_columns('SELECT password from borrowers');
76
    $self->check_columns( undef, [qw(password token)] );
77
78
    Check if passed sql statement or column_names arrayref contains
79
    forbidden column names (credentials etc.).
80
    Returns all bad column names or empty list.
81
82
=cut
83
84
sub check_columns {
85
    my ( $self, $sql, $column_names ) = @_;
86
87
    # TODO When passing sql, we actually go thru the whole statement, not just columns
88
89
    my $regex;
90
    push my @columns, @{ $column_names // [] };
91
    if ($sql) {
92
93
        # Now find all matches for e.g. password but also modulepassword or password_hash
94
        # Note that \w includes underscore, not hyphen
95
        $regex   = '(\w*(?:' . ( join '|', FORBIDDEN_COLUMN_MATCHES ) . ')\w*)';
96
        @columns = ( $sql =~ /$regex/ig );
97
    } else {
98
        $regex   = '(' . ( join '|', FORBIDDEN_COLUMN_MATCHES ) . ')';
99
        @columns = grep { /$regex/i } @columns;
100
    }
101
102
    # Check for whitelisted variants
103
    $regex   = '(^' . ( join '|', WHITELISTED_COLUMN_NAMES ) . ')$';    # should be full match
104
    @columns = grep { !/$regex/i } @columns;
105
    return @columns;
106
}
107
66
=head3 get_search_info
108
=head3 get_search_info
67
109
68
Return search info
110
Return search info
(-)a/t/db_dependent/Koha/Reports.t (-5 / +25 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 6;
20
use Test::More tests => 7;
21
21
22
use Koha::Report;
22
use Koha::Report;
23
use Koha::Reports;
23
use Koha::Reports;
Lines 76-83 subtest 'prep_report' => sub { Link Here
76
    is_deeply( $headers, { 'itemnumber for batch' => 'itemnumber' } );
76
    is_deeply( $headers, { 'itemnumber for batch' => 'itemnumber' } );
77
};
77
};
78
78
79
$schema->storage->txn_rollback;
80
81
subtest 'is_sql_valid' => sub {
79
subtest 'is_sql_valid' => sub {
82
    plan tests => 3 + 6 * 2;
80
    plan tests => 3 + 6 * 2;
83
    my @badwords = ( 'UPDATE', 'DELETE', 'DROP', 'INSERT', 'SHOW', 'CREATE' );
81
    my @badwords = ( 'UPDATE', 'DELETE', 'DROP', 'INSERT', 'SHOW', 'CREATE' );
Lines 115-118 subtest 'is_sql_valid' => sub { Link Here
115
            $word . ' qux'
113
            $word . ' qux'
116
        );
114
        );
117
    }
115
    }
118
  }
116
};
117
118
subtest 'check_columns' => sub {
119
    plan tests => 3;
120
121
    my $report = Koha::Report->new;
122
    is_deeply( [ $report->check_columns('SELECT passWorD from borrowers') ], ['passWorD'], 'Bad column found in SQL' );
123
    is( scalar $report->check_columns('SELECT reset_passWorD from borrowers'), 0, 'No bad column found in SQL' );
124
125
    is_deeply(
126
        [
127
            $report->check_columns(
128
                undef,
129
                [
130
                    qw(change_password hash secret test place mytoken hersecret password_expiry_days password_expiry_days2)
131
                ]
132
            )
133
        ],
134
        [qw(secret mytoken hersecret password_expiry_days2)],
135
        'Check column_names parameter'
136
    );
137
};
138
139
$schema->storage->txn_rollback;
119
- 

Return to bug 37508