UPD: Zip - Do not extract symbolic links that point outside the target directory

This commit is contained in:
Alexander Koblov 2025-10-27 21:26:31 +03:00
commit 520c66620e
2 changed files with 37 additions and 4 deletions

View file

@ -2212,8 +2212,10 @@ end;
procedure TAbTarArchive.ExtractItemAt(Index: Integer; const UseName: string);
var
AFileName: String;
AFileName : String;
LinkTarget : String;
OutStream : TStream;
PathType : TPathType;
CurItem : TAbTarItem;
begin
{ Check the index is not out of range. }
@ -2265,8 +2267,23 @@ begin
end;
end;
AB_FMODE_FILELINK: begin
if not CreateSymLink(CurItem.LinkName, UseName) then
AB_FMODE_FILELINK:
begin
LinkTarget := NormalizePathDelimiters(CurItem.LinkName);
PathType := GetPathType(LinkTarget);
if PathType in [ptRelative, ptAbsolute] then
begin
if PathType = ptAbsolute then
AFileName := LinkTarget
else begin
AFileName := GetAbsoluteFileName(ExtractFilePath(UseName), LinkTarget);
end;
if not IsInPath(BaseDirectory, AFileName, True, True) then
raise EInvalidOpException.Create(EmptyStr);
end;
if not CreateSymLink(LinkTarget, UseName) then
raise EOSError.Create(mbSysErrorMessage(GetLastOSError));
end;
end;

View file

@ -162,6 +162,7 @@ uses
AbWinZipAes,
Inflate64Stream,
DCOSUtils,
DCStrUtils,
DCClassesUtf8,
DCConvertEncoding;
@ -1215,6 +1216,8 @@ procedure AbUnzip(Sender : TObject; Item : TAbZipItem; const UseName : string);
{create the output filestream and pass it to DoExtract}
var
LinkTarget : String;
PathType : TPathType;
AbsolutePath : String;
ZipArchive : TAbZipArchive;
InStream, OutStream : TStream;
begin
@ -1232,10 +1235,23 @@ begin
try {OutStream}
DoExtract(ZipArchive, Item, InStream, OutStream);
SetString(LinkTarget, TMemoryStream(OutStream).Memory, OutStream.Size);
LinkTarget := CeRawToUtf8(LinkTarget);
LinkTarget := NormalizePathDelimiters(CeRawToUtf8(LinkTarget));
finally {OutStream}
OutStream.Free;
end; {OutStream}
PathType := GetPathType(LinkTarget);
if PathType in [ptRelative, ptAbsolute] then
begin
if PathType = ptAbsolute then
AbsolutePath := LinkTarget
else begin
AbsolutePath := GetAbsoluteFileName(ExtractFilePath(UseName), LinkTarget);
end;
if not IsInPath(ZipArchive.BaseDirectory, AbsolutePath, True, True) then
raise EInvalidOpException.Create(EmptyStr);
end;
if not CreateSymLink(LinkTarget, UseName, UInt32(Item.NativeFileAttributes)) then
RaiseLastOSError;
except