Re: Is it possible to modify __DATA__ via the DATA file handle or otherwise?
by Arunbear (Prior) on Feb 09, 2018 at 17:48 UTC
|
| [reply] |
Re: Is it possible to modify __DATA__ via the DATA file handle or otherwise?
by ikegami (Patriarch) on Feb 09, 2018 at 18:55 UTC
|
DATA is a plain, ordinary file handle to the source file, but it's open for reading (not writing). I don't know how to convert a handle opened for reading into a handle opened for writing (if it's even possible), but you can open a new handle to the current file, and use tell(DATA) to find the location of the start of the data.
die("Not safe for setuid") if ${^TAINT};
open(my $fh, ">>", __FILE__)
or die("open: $!\n");
( my $data_pos = tell(DATA) ) >= 0
or die("tell: $!\n");
truncate($fh, $data_pos)
or die("truncate: $!\n");
say($fh "bar")
or die("say: $!\n");
__DATA__
foo
| [reply] [d/l] [select] |
|
Pretty much what I had in mind, but to avoid race conditions due to parallel starts, I'd rather write to a temporary file and rename it at the end.
| [reply] |
|
use warnings;
use strict;
use File::Replace 'replace2';
my ($infh,$outfh) = replace2(__FILE__);
while (<$infh>) {
last if /^__DATA__$/;
print $outfh $_;
}
print $outfh "__DATA__\n";
print $outfh "New stuff! ".gmtime." UTC\n";
close $infh;
close $outfh;
| [reply] [d/l] |
|
|
|
| [reply] [d/l] |
|
| [reply] [d/l] |
|
setuid allows a user to execute a script as the script's owner.
I believe it can be attacked as follows:
- Create a symbolic link to the setuid script.
- Execute the setuid script via that symbolic link.
- Immediately replace the symbolic link with a file.
- If you get the timing right, the setuid script will read and write the data from your file instead of from the script file. The script trusts the data since it expects to be the only one able to change it, but you actually have full access to the data.
As a variation of the above, the attack could also replace the volume on which the script resides by unmounting it and mounting a new one.
| [reply] |
Re: Is it possible to modify __DATA__ via the DATA file handle or otherwise?
by BrowserUk (Patriarch) on Feb 09, 2018 at 17:58 UTC
|
| [reply] |
Re: Is it possible to modify __DATA__ via the DATA file handle or otherwise?
by Laurent_R (Canon) on Feb 09, 2018 at 22:29 UTC
|
Frankly, I wouldn't do that. It's too easy to make a mistake and clobber your entire program. Use a separate file (simple config file, DBM, tied hash or array, whatever is convenient), but don't take the risk of overwriting your program.
You can shoot yourself in the foot, if you like. I also can (at least in theory), but I just wouldn't.
| [reply] |
Re: Is it possible to modify __DATA__ via the DATA file handle or otherwise?
by karlgoethebier (Abbot) on Feb 10, 2018 at 09:49 UTC
|
"...otherwise?"
If I were in your shoes i would use another file for this task. Please see JSON::Tiny and Path::Tiny for a convenient way how to accomplish this.
Best regards, Karl
«The Crux of the Biscuit is the Apostrophe»
perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help
| [reply] [d/l] |
Re: Is it possible to modify __DATA__ via the DATA file handle or otherwise?
by LanX (Saint) on Feb 10, 2018 at 12:27 UTC
|
It's definitely possible, I would have shown you Ikegami's approach.
But I have trouble imagining a use case where the benefits of this approach outweigh the drawbacks.
The only thing I could come up with was self reproducing code like a virus.
(But then you would alter a copy ...)
| [reply] |
|
package Acme::Bleach;
our $VERSION = '1.150';
my $tie = " \t"x8;
sub whiten { local $_ = unpack "b*", pop; tr/01/ \t/; s/(.{9})/$1\n/g;
+ $tie.$_ }
sub brighten { local $_ = pop; s/^$tie|[^ \t]//g; tr/ \t/01/; pack "b*
+", $_ }
sub dirty { $_[0] =~ /\S/ }
sub dress { $_[0] =~ /^$tie/ }
open 0 or print "Can't rebleach '$0'\n" and exit;
(my $shirt = join "", <0>) =~ s/(.*)^\s*use\s+Acme::Bleach\s*;\n//sm;
my $coat = $1;
my $pressed = '#line ' . ("$coat\n" =~ tr/\n/\n/) . ' ' . (caller)[1]
+. "\n";
local $SIG{__WARN__} = \&dirty;
do {eval $coat . brighten $shirt; print STDERR $@ if $@; exit}
unless dirty $shirt && not dress $shirt;
open 0, ">$0" or print "Cannot bleach '$0'\n" and exit;
print {0} "${coat}use Acme::Bleach;\n", whiten $pressed.$shirt and exi
+t;
__END__
| [reply] [d/l] [select] |
Re: Is it possible to modify __DATA__ via the DATA file handle or otherwise?
by dsheroh (Monsignor) on Feb 10, 2018 at 09:57 UTC
|
This strikes me as a rather bad idea. If you do use version control, you're generating needless churn in the source repository whenever you change something in __DATA__. If you don't, you're taking an unnecessary risk of losing some or all of your program if a file offset is miscalculated or there's a problem while rewriting the file.
Too much risk, too little benefit, if you ask me. | [reply] [d/l] |
Re: Is it possible to modify __DATA__ via the DATA file handle or otherwise?
by clueless newbie (Curate) on Feb 09, 2018 at 19:30 UTC
|
#!/usr/bin/env perl
# Just because you can be a SOB doesn't mean you should
# or among the things you probably shouldn't do is this:
# modify (read/write) the program's DATA section -
# but hey, it was interesting and amusing.
use Carp;
use English qw(-no_match_vars);
use strict;
use warnings;
open my $READER,'+<',$PROGRAM_NAME
or Carp::confess "Can't open '$PROGRAM_NAME'! $OS_ERROR";
open my $WRITER,'+<',$PROGRAM_NAME # Don't us
+e '+>'
or Carp::confess "Can't open '$PROGRAM_NAME'! $OS_ERROR";
seek $READER,tell DATA ,0;
seek $WRITER,tell DATA,0;
# The overflow buffer:
my @Buffer_a;
#print "READER: @{[tell $READER ]} \n";
while (<$READER>) {
#print "Read: '$_'\n";
# Read (past tense) a line - buffer its replacement ...
{
# Modify the line here!
my $Update_s="x s $_";
push @Buffer_a,$Update_s;
};
#print "WRITER: @{[tell $WRITER ]} \n";
# Write from the overflow buffer if we can ...
while (@Buffer_a && tell($READER)-tell($WRITER) > length $Buff
+er_a[0]) {
# Enough room to write $Buffer_a[0] so write it ...
#print "Writing '$Buffer_a[0]'\n";
print {$WRITER} shift @Buffer_a
or Carp::confess "Error while writing \$WRITER: $OS_ER
+ROR";
#print "WRITER: @{[tell $WRITER]} \n";
};
#print "READER: @{[tell $READER]} \n";
};
# Nothing more to read ...
close $READER
or Carp::confess "Can't close '$PROGRAM_NAME'! $OS_ERROR";
#print "WRITER: @{[tell $WRITER]} \n";
# If there's anything in the buffer write it ...
while (@Buffer_a) {
#print "Writing '$Buffer_a[0]'\n";
print {$WRITER} shift @Buffer_a
or Carp::confess "Error while writing \$WRITER: $OS_ERROR"
+;
#print "WRITER: @{[tell $WRITER]} \n";
};
# Truncate the file, in case, what we're writing is shorter than w
+hat we read
truncate $WRITER,tell$WRITER;
# ... and close
close $WRITER
or Carp::confess "Can't close '$PROGRAM_NAME'! $OS_ERROR";
exit;
__END__
0
1
2
3
4
5
6
7
8
9
| [reply] [d/l] |
Re: Is it possible to modify __DATA__ via the DATA file handle or otherwise?
by sundialsvc4 (Abbot) on Feb 09, 2018 at 19:29 UTC
|
I strongly recommend that, if the data can be changed, it belongs in an external file ... not in the Perl source-code. In many shops, source-code is both version-controlled and write-protected, for very obvious reasons. Source-code is sacrosanct, and data which occurs within the source-code file is “part of the source-code.” If, instead, it is “really data,” IMHO it does not belong there. (To me, the __DATA__ construct serves the very-useful purpose that DATA statements served in the BASIC programs of yesteryear ... as a convenient place to store fixed data that was used for initialization or reference purposes.) | [reply] |
|
| [reply] |