我使用的是一个perl脚本,它打开一个文本文件,并允许我在文本区域字段中编辑它。以下是摘录:
# Database Definition
# --------------------------------------------------------
# Definition of your database. Format is
# field_name => ['position', 'field_type', 'form-length', 'maxlength', 'not_null', 'default', 'valid_expr']
%def = (
'RecordID' => [ 0, 'numer', -1, 255, 1, '', ''],
'Userid' => [ 1, 'alpha', -1, 255, 1, '', ''],
'Title' => [ 2, 'alpha', 20, 255, 1, '', ''],
'Category' => [ 3, 'alpha', 20, 255, 1, '', ''],
'Type' => [ 4, 'alpha', 20, 255, 1, 'D2015', ''],
'Client' => [ 5, 'alpha', 20, 255, 0, '', ''],
'Client_database' => [ 6, 'alpha', 20, 255, 0, '', ''],
'Installed' => [ 7, 'alpha', 20, 255, 0, 'xxxxx', ''],
'Description' => [ 8, 'alpha', 0, 1500, 1, '', ''],
'Called_by' => [ 9, 'alpha', 20, 255, 0, '', ''],
'Updated' => [10, 'timestamp', -1, 25, 0, &get_timestamp(), ''],
'Display' => [11, 'alpha', -1, 4, 0, 'No', ''],
'Files' => [12,'alpha',20,255,0,'',''],
'Followup' => [13, 'alpha', -1, 4, 0, 'No', ''],
'Status_public' => [14, 'alpha', 20, 255, 0, '', ''],
'Status_private' => [15, 'alpha', 20, 255, 0, '', ''],
'Reserved' => [16, 'alpha', -1, 5, 0, 'zzzzz', '']
);
# Select fields. Field name => 'comma seperated list of drop down options'.
%select_fields = (
);
# client is both radio and checkbox so checkbox can be used on search form
# Radio fields. Field name => comma seperated list of radio buttons.
%radio_fields = (
'Type' => 'DBMan,Delicia,Client,D2015',
'Display' => 'Yes,No,Deleted',
'Followup' => 'Yes,No',
'Client' => 'delicia,dreydev,ohs1968,bhccwga,interiorsolutions,danaespa,knue,langford,kudzu,suwaneeday',
'Status_public' => 'n/a,Planning,Coding,Alpha,Beta,Complete',
'Status_private' => 'n/a,Planning,Coding,Alpha,Beta,Complete'
);
# Checkbox fields. Field name => Checkbox value.
%checkbox_fields = (
'Category' => 'Configuration,Variable,Flag,Subroutine,Field,FieldType,Problem,TroubleTip,File,Hack,ChangeLog,Other',
'Client' => 'delicia,dreydev,ohs1968,bhccwga,knue',
'Installed' => 'delicia,dreydev,ohs1968,bhccwga,knue'
);
#
# delicia added from autogenerate enhancement
# Textarea fields. Field name => '[columns]x[rows]'.
%textarea_fields = (
Description => '60x10'
);
我的问题是,当我保存编辑后的文件时,百分号会转换为不可打印的字符。我需要他们保持原样。例如:我可能想添加或删除单选字段列表中的项目。我的页眉包含以下内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
以下是编辑后的文件的示例:
#
# Database Definition
# --------------------------------------------------------
# Definition of your database. Format is
# field_name => ['position', 'field_type', 'form-length', 'maxlength', 'not_null', 'default', 'valid_expr']
Þf = (
'RecordID' => [ 0, 'numer', -1, 255, 1, '', ''],
'Userid' => [ 1, 'alpha', -1, 255, 1, '', ''],
'Title' => [ 2, 'alpha', 20, 255, 1, '', ''],
%def已更改为无法识别的内容,因此脚本无法运行。
编辑:这是读取文件的代码:
open (FILEEDIT, $edit_file_data) or &cgierr ("unable to open: $edit_file_data.nReason: $!");
if ($db_use_flock) {
flock(FILEEDIT, 1) or &cgierr("unable to get exclusive lock on $edit_file_data.nReason: $!");
}
$out = join ("", <FILEEDIT>);
close (FILEEDIT);
... I'M OMITTING THE OTHER PARTS OF HTML PAGE
print qq|
<TEXTAREA NAME="file_data" COLS="66" ROWS="20" wrap=virtual>$out</TEXTAREA></td></tr>
<td class="text-center"><input type=submit value="$submit_button" class="btn btn-primary"></td></tr>
</table></form>
|;
现在是编写文件的代码:
my ($out, $write_file_data);
$write_file_data = $in{'write_file_data'};
$out = $in{'file_data'};
$out =~ s/r//g;
open (FILEDATA, ">$write_file_data") or &cgierr("unable to open: $write_file_data.nReason: $!");
if ($db_use_flock) {
flock(FILEDATA, 2) or &cgierr("unable to get exclusive lock on $write_file_data.nReason: $!");
}
print FILEDATA $out; # write file.
close FILEDATA;
编辑:我认为问题在这里,但我不知道是什么
sub parse_form {
# --------------------------------------------------------
my (%in);
my ($buffer, $pair, $name, $value,$s);
PAIR: foreach $name ($query->param()) {
@value = $query->param("$name");
$value = join '~~', @value;
$name =~ tr/+/ /;
$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
if ($value eq "---") { next PAIR; }
if ($value eq "http://") { next PAIR; } # Removes default beginning of URLs
unless ($value) { next PAIR; }
unless ( length ($value) ) { next PAIR; }
unless ($value =~ /S+/) { next PAIR; } # 01/29/2017
$in{$name} = $value;
}
return %in;
}
我从几年前在网上发现的一个修改中得到了这个代码;它应该处理上传文件并允许多个选择项目;如果我使用原始脚本,我对%没有问题,但我需要这些技巧这是打开表单的标签:
<FORM ENCTYPE="multipart/form-data" action="$db_script_url" method="POST">
问题:
您的脚本对表单字段进行双重解码,不必要地导致数据损坏。
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
CCD_ 1是CCD_ 2的URL编码。
对已解码的表单数据调用pack
会损坏它。
解决方案:
不要双重解码。
你说这是有充分理由的。如果是这样的话,一个最小的变通方法可能是只在那些真正需要它的字段上进行
my %is_double_decode_field = map { $_=>1 } qw(
name_of_field_containing_url
name_of_another_field_containing_url
...
);
sub parse_form {
my (%in);
my ($buffer, $pair, $name, $value, $s);
PAIR: foreach $name ($query->param()) {
@value = $query->param("$name");
$value = join '~~', @value;
if ( $is_double_decode_field{ $name } ) {
$name =~ tr/+/ /;
$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
}
if ($value eq "---") { next PAIR; }
if ($value eq "http://") { next PAIR; } # Removes default beginning of URLs
unless ($value) { next PAIR; }
unless ( length ($value) ) { next PAIR; }
unless ($value =~ /S+/) { next PAIR; } # 01/29/2017
$in{$name} = $value;
}
return %in;
}
安全问题:
考虑:
$out = join ("", <FILEEDIT>);
# ...
print qq|
<TEXTAREA NAME="file_data" ...>$out</TEXTAREA>...
|;
您显示的从文件加载的代码在注入到html表单之前并没有对其进行消毒,也没有显示的将其写回的代码似乎这样做
如果您在某个地方用&
提交后加载网页,文本区域是包含&
还是仅包含&
?
如果附加:
</textarea><textarea name="file2_data">hello!
下次加载时是否会显示额外的表单字段?
检索表单数据的代码看起来也不安全。在列表上下文中使用param()
是一个漏洞。建议使用multi_param()
。请参阅CGI
文档。
我预计还有更多的问题在潜伏。