Using PromoDJ for Justice

    imageGood afternoon. I want to share the story that happened to me just yesterday, but first things first.


    1. Introduction
    2. Possible activities
    	2.1. Promotion value wrapping
    	2.2. Spamming
    	2.3. Vote for comments
    3. Methods of implementation
    4. Preparing to register accounts
    	4.1. basic information
    	4.2. Captcha
    	4.3. Email Addresses
    	4.4. Constants
    5. Scripts and their work
    	5.1. Account registrar
    	5.2. Authorizer
    	5.3. Getting user signatures
    	5.4. User Signature Shell
    6. Conclusion
    	6.1. Work results
    	6.2. PromoDJ Administration Response
    	6.3. The last word
    7. Toolkit


    I believe that many of you are aware of the existence of the PromoDJ portal (PDJ for short), who is not familiar with it - it's okay, now I will explain everything. The site is a social network for musicians and DJs, photographers and singers, and a lot for anyone else, where each of them can upload their material for evaluation, and registered users to evaluate and discuss this material. PDJ is a great platform for a beginner music project, so we are registered there.

    By nature, I am a very curious person, I was always interested in knowing what and how it works, where what holes in the protection and how it can be used, there was free time, so PDJ was chosen as the object for study. But before starting the research, I sat down and thought, “And what benefit can one get from this?”

    For myself, I have identified several areas:
    1. Wrap value promorank;
    2. Spam
    3. Vote for comments.
    I must say right away that I settled on the latter, but I will describe all the directions.

    Possible activities

    Promotion value wrapping

    Promorank is a personal rating of coolness, it is used to form a common top of artists, a top by style and by activity. The cheating of this value would not give us anything: the quality of the music would remain the same, ideological ideas would not increase, the number of visitors and listening, too, and after the recent innovations on PDJ, it became theoretically impossible to wind up the rating. The fact is that recently, in order to vote for one or another artist, thereby increasing his promorank, you need to authorize your account, for this you need to specify your mobile number to which the coveted code will come.

    He added this line of activity only to have more points. I don’t like spam, and you, I think, too, so I don’t consider spamming, and in general I think this is the dirtiest and lowest thing.

    Vote for comments

    PromoDJ is, first of all, a social network, here people are free to express their opinion and attitude through comments, blog posts and rating comments.

    After I thought about evaluating the comments, I seemed to look at everything that was happening from a different angle. Recently, I began to meet discussions on PDJ forums, where one or another user unfairly received cons for their comments, not one, not two, but about 20, after which inadequate users, without reading the text of the discussion, grabbed the baton and continued to put cons and harmless the comment went beyond -100. After these thoughts, I decided to become Superman, to become Batman and Robin in one person, James Bond with a license to change the rating of comments, a fighter for justice, horror flying on the wings of the night, bearing retribution in the name of the Moon.

    A vivid example of an adequate and absolutely correct (from the discussion) comment:
    A little later, the same comment:

    Implementation methods

    Before starting to run around the city in swimming trunks, a mask and a black raincoat, I decided to study how you can realize your plan and from which direction it is better to approach this. At that time I knew for sure that a request to increase or decrease the rating of a comment comes without reloading the pages, which means that some kind of javascript library was used that generated and sent a post, or maybe get, a request to the server PDJ.

    Let's take a closer look:
    The following parameters are sent in a POST request:

    Where, digest is a unique parameter for each registered user (in some cases, I will call it a signature), which consists of a user id and thirty-two character hashes; commentID - comment number; vote - rating mode, "1" - plus the comment, "-1" - minus the comment.

    Then I ended the user’s session on the site and tried to vote for some kind of comment, which, in fact, I succeeded. It meant a lot to me, now, for example, I knew that I would not have to log in to the site to vote for a particular comment, everything was done with one request with three parameters.

    All the necessary knowledge was obtained, but there was a question about digest - unique user identifiers, voices were not passed on invalid signatures, and with one signature you can vote for the selected comment only once. A suitable and the only way I found was to register several fake accounts for using their signatures for voting.

    Preparing for Account Registration

    basic information

    The registration page on PromoDJ looks very massive, there are a lot of all sorts of items, input elements, selects and checkboxes. Empirically, I quickly determined which parameters needed to be passed for successful registration; they turned out to be:
    $ postfiends = array (
        "row [login]" => "", // login
        "row [password1]" => "", // password
        "row [password2]" => "", // password, again
        "row [email]" => "", // e-mail
        "row [i]" => "", // first name
        "row [f]" => "", // last name
        "row [sex]" => "", // gender, can be man or woman
        "row [iam_clubber]" => "1", // status: clubber
        "row [iam_listener]" => "1", // status: listener
        "crow [company_kind] "=>" none ", // no, I do not represent the company
        " crow [title] "=>"", // organization name
        " crow [countryID] "=>" 3159 ", // country code
        " crow [regionID] "=>" 0 ", // region code (not specified)
        " crow [cityID] "=> "0", // city code (not specified)
        "crow [metroID]" => "0", // metro station code (not specified)
        "crow [street]" => "", // street, house
        "crow [tel]" => "", // contact phone
        "crow [fax]" => "", // fax
        "crow [www]" => "", // site
        "row [styleID]" => "", // most of all I like the style (code from list)
        "row [nick]" => "", // nickname
        "row [title]" => "", // address of the page on
        "row [about]" => "", // about myself
        "row [icq]" => "", // icq
        "row [skype]" => "", // skype
        "row [countryID] "=>" 3159 ", // country code
        " row [regionID] "=>" 0 ", // region code (not specified)
        " row [cityID] "=>" 0 ", // code city ​​(not specified)
        "row [metroID]" => "0", // metro station code (not specified)
        "row [invite]" => "", // magic code
        "row [agreed]" => "1", // yes, I agree with the rules of the site
        "respond" => "", // response to captcha
        "key" => "" // hash of captcha
    The choice of the “clubber” and “listener” statuses is not accidental, these statuses do not require confirmation from the administration, and there is no need for extra attention in this matter. For example, in order to pass confirmation of the status of “musician”, you need to write in detail about your activities, it will be strange if the administration sees requests coming one after another with the same description.


    Going down to the end of the questionnaire, the last paragraph, we find a captcha that vilely bends the text, making it difficult to determine static:

    As I wrote above, in the registration request, it’s not only the response to the captcha that the hash itself sends. The same hash is used to generate the picture: the

    hash is unique and you can register for it only once, changing the hash leads to a change in the text in the picture. Visually, I couldn’t determine the algorithm by which the answer to the captcha can be obtained from the hash, so I suggested three further development steps:
    1. Create a table consisting of a valid pair (hash + response);
    2. Try to determine the algorithm for obtaining the response from the hash;
    3. Search for a captcha recognition implementation of this type.
    Create a table consisting of a valid pair (hash + answer): very long and tedious, plus you have to write an additional script, this option can only be considered if there are volunteers to work with.

    Trying to determine the algorithm for obtaining from the hash the answer: it is rather difficult to implement, or impossible at all, because some hash algorithm can be used, and even with the use of salt. Not an option.

    Look for an implementation of recognition of captcha of this type: it never worked and did not use similar libraries, this option can be used.

    While I was discussing this topic, I accidentally discovered that if the hash is less than 32 characters, then the picture will be with four zeros, having determined this, I just have to check whether the stub for this case is worth PDJ or not. To do this, in the page code, I changed the necessary parameters and successfully registered a new account.

    Email Addresses

    I decided not to search for registrars of electronic mailboxes, not to write them myself and not to search for those who sell databases, not to send trojans to friends and acquaintances, why? Yandex will do everything for us.


    Almost everything is ready to register accounts, it remains to collect the missing data, namely:
    1. List of names to register;
    2. Codes of musical styles;
    3. A small user-agents list.
    As a list of names, I used a large nickname database found on the Internet. Other data:
    $ uagents = array (
        "Opera / 9.20 (Windows NT 6.0; U; en)",
        "Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.50",
        "Mozilla / 4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.1) Opera 7.02 ",
        " Mozilla / 5.0 (Windows; U; Windows NT 5.1; en-US; rv: 1.7.5) Gecko / 20060127 Netscape / 8.1 ",
        " Mozilla / 5.0 ( X11; U; Linux i686; en-US; rv: Gecko / 20061205 Iceweasel / (Debian- + dfsg-2) ",
        " Opera / 10.00 (X11; Linux i686; U; en) Presto / 2.2.0 ");
    $ styles = explode (";", "88; 2; 4; 7; 6; 14; 31; 15; 18; 23; 25; 27; 28; 8; 24; 29; 30; 44; 46; 47; 49; 37; 1; 80; 16 ");

    Scripts and their work

    Account registrar

    set_time_limit (0);
    $ magic = 0;
    $ i = 1;
    $ fp = fopen ('names.txt', 'rb');
    while (($ line = @fgets ($ fp))! == false) {
        // $ pdgparams = "";
        $ postfiends ["row [login]"] = $ postfiends ["row [password1]"] = $ postfiends ["row [password2]"] = $ postfiends ["row [nick]"] = $ postfiends ["row [ title] "] = trim ($ line);
        $ postfiends ["row [email]"] = $ postfiends ["row [login]"]. "@";
        $ postfiends ["row [sex]"] = (rand (0,1)? "man": "woman");
        $ postfiends ["row [styleID]"] = $ styles [rand (0, sizeof ($ styles) -1)];
        $ postfiends ["key"] = $ magic + $ i;
        // foreach ($ postfiends as $ key_name => $ key_value)
        // $ pdgparams. = '&'. $ key_name. '='. $ key_value;
        $ ci = curl_init ();
        curl_setopt ($ ci, CURLOPT_USERAGENT, $ uagents [rand (0, sizeof ($ uagents) -1)]);
        curl_setopt ($ ci, CURLOPT_CONNECTTIMEOUT, 30);
        curl_setopt ($ ci, CURLOPT_TIMEOUT, 30);
        curl_setopt ($ ci, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt ($ ci, CURLOPT_POST, TRUE);
        curl_setopt ($ ci, CURLOPT_POSTFIELDS, $ postfiends);
        curl_setopt ($ ci, CURLOPT_URL, "");
        curl_exec ($ ci);
        curl_close ($ ci);
        $ i ++;
        sleep (rand (5.25));

    While the script is running, notifications of successful registration come:


    In order not to cause any suspicions at all and not to say goodbye in a moment with all the accounts, I decided to authorize everyone. To do this, I exported all the letters from the mail client, then pulled out links from them and got a list of a huge number of records.

    Getting user signatures

    The process of obtaining a signature consisted of several steps:
    1. User authorization, through the form on the login page;
    2. Go to the main page of PromoDJ;
    3. Extract digest parameter from page code.
    This process took about two and a half - three hours, but this is a plus - I was never banned, I did not receive any notifications from the administration about any violations and none of the accounts, for all the time, was deleted.

    User Signature Shell

    To vote for comments, I made a convenient shell where I could specify the address of the comment and what to do with it - put a plus or minus.

    On the settings page, you can specify the operating mode:

    In automatic mode, after clicking on the “Run” button, all available hashes are voted for the specified comment, in manual mode it is possible to select any hash you like from the list and vote on it:


    Work results

    Random goodness and love were also sown throughout PromoDJ.

    PromoDJ Administration Response

    After I sent a letter to the portal’s technical support, I couldn’t think that it would all end with the fact that, for my curiosity, they would give me a premium account and branding, which will come in handy for our music project.

    The last word

    The described vulnerability due to which account registration was performed was closed a few minutes after my letter.

    Thank you for reading to the very end. Good luck and see you in new articles!


    In the process of work were used:

    Also popular now: