Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/scanner/classes/Auth.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ private function tryToAuthenticate()
$passwordHashFromCookie = $_COOKIE['antimalware_password_hash'];
return ($passwordHashFromCookie === $passwordHash);
} elseif (!empty($_POST['password'])) {
$passwordHashFromPost = hash('sha256', $_POST['password']);
$passwordHashFromPost = $this->getHash($_POST['password']);
if ($passwordHashFromPost === $passwordHash) {
$this->setPasswordHashCookie($passwordHash);
return true;
Expand All @@ -88,12 +88,21 @@ private function tryToAuthenticate()
private function setNewPassword($password)
{
if (!file_exists($this->passwordHashFilepath)) {
$passwordHash = hash('sha256', $password);
$passwordHash = $this->getHash($password);
file_put_contents2($this->passwordHashFilepath, "<?php die('Forbidden'); ?>\n" . $passwordHash);
$this->setPasswordHashCookie($passwordHash);
}
}

private function getHash($text)
{
if (function_exists('hash')) {
return hash('sha256', $text);
} else {
return sha1($text);
}
}

public function auth()
{
$result = false;
Expand Down
14 changes: 13 additions & 1 deletion src/scanner/classes/FileInfo.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function getInfoByName($filePath)
$this->size = filesize($filePath);

if ($this->size <= $this->MAX_FILE_SIZE_FOR_HASHING) {
$this->md5 = hash_file('md5', $filePath);
$this->md5 = function_exists('hash_file') ? hash_file('md5', $filePath) : md5_file($filePath);
}
}
}
Expand Down Expand Up @@ -69,6 +69,18 @@ public function __toString()
$data = array($this->name, $this->size, $this->ctime, $this->mtime, $this->owner, $this->group, $this->access, $this->md5);
return implode(';', $data);
}

public function info()
{
$str = '';
$fields = array('md5', 'size', 'ctime', 'mtime', 'owner', 'group', 'access');

foreach ($fields as $field) {
$str .= ';' . $field . '=' . $this->$field;
}

return $str;
}
}


8 changes: 4 additions & 4 deletions src/scanner/classes/FileList.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ private function fileExecutor($filePath, $type, $actionType)
{
if ($actionType === $this->ACTION_PROCESS) {
$fileinfo = new FileInfo($filePath);
$fileinfoNode = $fileinfo->getXMLNode();
//$fileinfoNode = $fileinfo->getXMLNode();

if ($this->GENERATE_FILE_QUEUE && is_file($fileinfo->absoluteName)) {
$queue_entry = $fileinfo->absoluteName . ' ' . $fileinfo->md5 . PHP_EOL;
$queue_entry = $fileinfo->absoluteName . ' ' . $fileinfo->info() . PHP_EOL;
file_put_contents2($this->tmpQueueFilename, $queue_entry, 'a');
}

$this->dom->documentElement->appendChild($this->dom->importNode($fileinfoNode, true));
//$this->dom->documentElement->appendChild($this->dom->importNode($fileinfoNode, true));
$this->filesFound++;
} else if ($actionType === $this->ACTION_SKIP) {
// TODO: Do something with skipped item
Expand All @@ -73,7 +73,7 @@ private function fileExecutor($filePath, $type, $actionType)

public function getXMLFilelist()
{
$result = implode('', file($this->AJAX_TMP_FILE));
$result = '';
$this->cleanUp();

return $result;
Expand Down
112 changes: 68 additions & 44 deletions src/scanner/classes/MalwareDetector.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ function detectMalware($filePath, &$foundFragment, &$pos, $startTime, $timeout,
}
}

$content = implode('', file($filePath));
$content = file_get_contents($filePath);

$fileToBeScannedSignatureList = array(
'<?php',
Expand Down Expand Up @@ -235,48 +235,69 @@ function parseXml($xmlFilename)

function repackXMLLog()
{
global $projectRootDir;
$xml = new XMLWriter();
$xml->openMemory();
$xml->setIndent(true);
$xml->startDocument('1.0', 'utf-8');
$xml->startElement('website_info');

$xmlLogFilename = $this->XML_LOG_FILENAME;
$xml = $this->parseXml($xmlLogFilename);
$xpath = new DOMXpath($xml);
$dom = $this->parseXml($this->XML_LOG_FILENAME);

if (!is_file($this->MALWARE_LOG_FILENAME)) {
die(basename(__FILE__) . ': cannot open ' . $this->MALWARE_LOG_FILENAME . ' during repacking');
}
$xml->writeRaw($dom->saveXML($dom->getElementsByTagName('server_environment')->item(0)));
$xml->writeRaw($dom->saveXML($dom->getElementsByTagName('cms_list')->item(0)));

$lines = file($this->MALWARE_LOG_FILENAME);
$xml->startElement('files');

foreach ($lines as $lineNum => $line) {
#Example /home/www/badcode.tk/web_root/robots.txt.dist;detected=;pos=-1;snippet=
$data = explode(';', $line);
$filePath = $data[0];
$detected = substr($data[1], strlen('detected='));
if ($detected) {
$pos = substr($data[2], strlen('pos='));
$snippet = trim(substr($data[3], strlen('snippet=')));
file_put_contents2($this->XML_LOG_FILENAME, $xml->flush());

#Getting current element in DOM
$relativePath = str_replace($_SERVER['DOCUMENT_ROOT'], '.', $filePath);
$filePathNode = $xpath->query('/website_info/files/file/path[text()="' . $relativePath . '"]')->item(0);
$fileinfoNode = $filePathNode->parentNode;
$file = new SplFileObject($this->MALWARE_LOG_FILENAME);
$file->setFlags(SplFileObject::DROP_NEW_LINE);

if (!$fileinfoNode) {
die("XML path error filePath={$filePath} relativePath={$relativePath} projectRootDir={$projectRootDir} docRoot={$_SERVER['DOCUMENT_ROOT']}");
}
$buffer = '';

#Adding detection info to DOM
if ($fileinfoNode) {
$fileinfoNode->setAttribute('detected', $detected);
$fileinfoNode->setAttribute('snippet', $snippet);
$fileinfoNode->setAttribute('pos', $pos);
}
foreach ($file as $line) {
#Example /home/www/badcode.tk/web_root/robots.txt.dist ;md5=6e2807094b485c6fdf1fda4862bac22d;size=497;ctime=1436097435;mtime=1320843774;owner=lol;group=users;access=0755;detected=;pos=-1;snippet=
if (empty($line)) continue;

$p = strrpos($line, ' ');
$filePath = substr($line, 0, $p);
$fileInfo = substr($line, $p + 1);

preg_match_all('@;(\w+)=([^;]*)@', $fileInfo, $matches);

$data = array_combine($matches[1], $matches[2]);
$data['path'] = str_replace($_SERVER['DOCUMENT_ROOT'], '.', $filePath);

$xml->startElement('file');

if ($data['detected']) {
$xml->writeAttribute('detected', $data['detected']);
$xml->writeAttribute('snippet', $data['snippet']);
$xml->writeAttribute('pos', $data['pos']);
}

$fields = array('path', 'size', 'ctime', 'mtime', 'owner', 'group', 'access', 'md5');

foreach ($fields as $field) {
$xml->writeElement($field, $data[$field]);
}

$xml->endElement();

$buffer .= $xml->flush();

if (32000 < strlen($buffer)) {
file_put_contents2($this->XML_LOG_FILENAME, $buffer, 'a');
$buffer = '';
}
}

$xml->save($xmlLogFilename);
$xml->endElement();
$xml->endDocument();

return $xml->saveXML();
$buffer .= $xml->flush();

file_put_contents2($this->XML_LOG_FILENAME, $buffer, 'a');
}

function buildQuarantineArchive()
Expand Down Expand Up @@ -339,9 +360,12 @@ function malwareScanRound()

$fh = fopen($this->QUEUE_FILENAME, 'r');
$offset = 0;
$numFilesScanned = 0;

if (file_exists($this->QUEUE_OFFSET_FILENAME)) {
$offset = (int)file_get_contents($this->QUEUE_OFFSET_FILENAME);
$o = explode(' ', file_get_contents($this->QUEUE_OFFSET_FILENAME));
$offset = (int) $o[0];
$numFilesScanned = (int) $o[1];
fseek($fh, $offset);
}

Expand All @@ -351,9 +375,8 @@ function malwareScanRound()
}

$queueText = fread($fh, filesize($this->QUEUE_FILENAME) - $offset);
$queueLines = explode("\n", $queueText);

$numFilesScanned = 0;
$queueLines = explode(PHP_EOL, $queueText, -1);
$numFilesLeft = count($queueLines);

if (count($queueLines) < 1) {
fclose($fh);
Expand All @@ -370,15 +393,17 @@ function malwareScanRound()

$offset += strlen($line) + 1;

$fileinfo = explode(' ', $line);
$p = strrpos($line, ' ');

$filePath = $fileinfo[0];
$fileHash = $fileinfo[1];
$filePath = substr($line, 0, $p);
$fileInfo = substr($line, $p + 1);

$snippet = '';
$fileExtension = pathinfo(basename($filePath), PATHINFO_EXTENSION);

$res = $this->detectMalware($filePath, $snippet, $pos, $this->SCRIPT_START, $this->MAX_EXECUTION_DURATION, $fileExtension);
$numFilesScanned++;
$numFilesLeft--;
switch ($res) {
case 'no_need_to_check':
break;
Expand All @@ -387,12 +412,11 @@ function malwareScanRound()
case 'skipped':
break;
case 'timeout':
file_put_contents2($this->QUEUE_OFFSET_FILENAME, $offset);
file_put_contents2($this->QUEUE_OFFSET_FILENAME, $offset . ' ' . $numFilesScanned);
$this->throwTimeout($filePath);
break;
default:
$numFilesScanned++;
$content = $filePath . ';detected=' . $res . ';pos=' . $pos . ';snippet=' . base64_encode($snippet) . PHP_EOL;
$content = $filePath . ' ' . $fileInfo . ';detected=' . $res . ';pos=' . $pos . ';snippet=' . base64_encode($snippet) . PHP_EOL;
file_put_contents2($this->MALWARE_LOG_FILENAME, $content, 'a');

if ($res) {
Expand All @@ -401,14 +425,14 @@ function malwareScanRound()
}
}

file_put_contents2($this->QUEUE_OFFSET_FILENAME, $offset);
file_put_contents2($this->QUEUE_OFFSET_FILENAME, $offset . ' ' . $numFilesScanned);
fclose($fh);

if (count($queueLines) <= 1) {
return $this->finishMalwareScan();
}

$data = array('filesScannedThisTime' => $numFilesScanned, 'filesLeft' => count($queueLines), 'lastFile' => $filePath);
$data = array('filesScannedThisTime' => $numFilesScanned, 'filesLeft' => $numFilesLeft, 'lastFile' => $filePath);
$result = json_encode(array('type' => 'getSignatureScanResult', 'status' => 'inProcess', 'data' => $data, 'phpError' => $php_errormsg));
return $result;

Expand Down
5 changes: 2 additions & 3 deletions src/scanner/static/js/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,11 @@ $(document).ready(function(){
if (response.status == 'inProcess')
{
lastScannedFile = response.data.lastFile;
numberFilesScannedThisTime = parseInt(response.data.filesScannedThisTime)
numberFilesScanned = parseInt(response.data.filesScannedThisTime)
numberFilesLeft = parseInt(response.data.filesLeft)
numberFilesScanned += numberFilesScannedThisTime;

if (!numberFilesToScan) {
numberFilesToScan = numberFilesLeft + numberFilesScannedThisTime;
numberFilesToScan = numberFilesLeft + numberFilesScanned;
}

signatureScanProgress = numberFilesScanned * 100 / numberFilesToScan;
Expand Down