wordpress mass scanner на коленке

Discussion in 'PHP' started by ckpunmkug, 6 Oct 2018.

  1. ckpunmkug

    ckpunmkug Member

    Joined:
    20 Mar 2017
    Messages:
    72
    Likes Received:
    72
    Reputations:
    10
    Изобразил в исходниках концепт, который многопоточно пингует и загружает index.php, а по index.php определяет наличие вордпресса; изготовлен из компонентов доступных на любом vds c wordpress.

    По умолчанию в php у apache отключена pcntl_fork, что не даёт процессу двоиться. Тем не менее есть способ запускать множество процессов за раз.
    Запустим в apache и протестируем возможность запуска.
    Code:
    <?php
    $cmd = "/bin/ping -c 4 127.0.0.1 > /dev/null";
    $descriptorspec = array(['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']);
    $pipes = [];
    $proc = proc_open($cmd, $descriptorspec, $pipes);
    
    do {
        $status = proc_get_status($proc);
    } while ($status['running']);
    
    echo "exitcode = {$status['exitcode']}";
    proc_close($proc);
    
    proc_open - возвращает управление скрипту не дожидась окончания работы запущенной программы и это позволяет запустить 254 раза ping почти одновременно.
    php ./ping.php 192.168.0 > ./ip.lst
    Code:
    <?php
    $network = $argv[1];
    
    function ping($ip)
    {
        $cmd = "/bin/ping -c 4 {$ip} > /dev/null";
        $descriptorspec = array(STDIN, STDOUT, STDERR);
        $pipes = [];
        $proc = proc_open($cmd, $descriptorspec, $pipes);
        return $proc;
    }
    
    $PROC = [];
    for ($number = 1; $number < 255; $number++ ) {
        $ip = "{$network}.{$number}";
        $PROC[$number] = ['resource' => null, 'exitcode' => null];
        $PROC[$number]['resource'] = ping($ip);
    }
    
    $result = [];
    while (count($PROC) > 0) {
        file_put_contents("php://stderr", sprintf("\r%03d", count($PROC)), FILE_APPEND);
       
        foreach($PROC as $index => $proc) {
            $status = proc_get_status($proc['resource']);
            if (!$status['running']) {
                $PROC[$index]['exitcode'] = $status['exitcode'];
                $result[$index] = $PROC[$index]['exitcode'];
                proc_close($proc['resource']);
                unset($PROC[$index]);
            }
        }
    }
    
    foreach ($result as $number => $exitcode) {
        if ($exitcode == 0) {
            echo "{$network}.{$number}\n";
        }
    }
    
    php ./wget.php ./ip.lst ./data/
    Code:
    <?php
    
    $ip_list_filename = $argv[1];
    $data_dirname = $argv[2];
    
    function wget(string $url, string $filename) {
        $user_agent = '"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0"';
        $cmd = "wget -q -O {$filename} -t 0 -T 4 -U {$user_agent} -Q 1M {$url}";
       
        $descriptorspec = array(STDIN, STDOUT, STDERR);
        $pipes = [];
        $proc = proc_open($cmd, $descriptorspec, $pipes);
        return $proc;
    }
    
    $IP = file($ip_list_filename, FILE_IGNORE_NEW_LINES);
    if (!is_array($IP)) {
        user_error("can't load ip addresses from file");
        exit(1);
    }
    
    $PROC = [];
    foreach ($IP as $index => $ip) {
        $PROC[$index] = ['resource' => null, 'exitcode' => null];
        $url = "http://{$ip}/index.php";
        $filename = "{$data_dirname}/{$ip}";
        $PROC[$index]['resource'] = wget($url, $filename);
    }
    
    while (count($PROC) > 0) {
        file_put_contents("php://stderr", sprintf("\r%03d", count($PROC)), FILE_APPEND);
       
        foreach($PROC as $index => $proc) {
            $status = proc_get_status($proc['resource']);
            if (!$status['running']) {
                proc_close($proc['resource']);
                unset($PROC[$index]);
            }
        }
    }
    
    У WP есть замечательная особенность папка wp-contents
    php ./is_wp.php ./data/
    Code:
    <?php
    
    $dirname = $argv[1];
    
    function is_wp(string $html)
    {
        $DOMDocument = new DOMDocument();
        if (@$DOMDocument->loadHTML($html) === false) {
            user_error("can't load HTML to DOMDocument");
            return false;
        }
    
        $DOMNodeList = $DOMDocument->getElementsByTagName("link");
        foreach ($DOMNodeList as $node) {
            foreach($node->attributes as $attribute) {
                if(
                    $attribute->name == 'href' &&
                    preg_match('/wp\-content/', $attribute->value) == 1
                ) {
                    return true;
                }
            }
        }
    }
    
    $FILENAME = scandir($dirname);
    if (!is_array($FILENAME)) {
        user_error("can't get filenames from directory");
        exit(1);
    }
    
    foreach ($FILENAME as $filename) {
        if (!is_file("{$dirname}/{$filename}")) {
            continue;
        }
       
        $html = file_get_contents("{$dirname}/{$filename}");
        if (is_string($html) && !empty($html) && is_wp($html)) {
            echo "{$dirname}/{$filename}\n";
        }
    }
    
    Фича всей задумки в том что ping и wget на дебианах есть всегда, а энмапа может и не быть.