Skip navigation

Category Archives: Cybersecurity

ONYPHE has made available a free API and free MMDB download of their new Geolocus database. It provided IP address metadata in the form of:

{
    "abuse":
    [
        "amzn-noc-contact@amazon.com",
        "aws-routing-poc@amazon.com",
        "aws-rpki-routing-poc@amazon.com",
        "trustandsafety@support.aws.com"
    ],
    "asn": "AS14618",
    "continent": "NA",
    "continentname": "North America",
    "country": "US",
    "countryname": "United States",
    "domain":
    [
        "amazon.com",
        "amazonaws.com",
        "aws.com"
    ],
    "ip": "3.215.138.152",
    "isineu": 0,
    "latitude": "37.09024",
    "location": "37.09024,-95.712891",
    "longitude": "-95.712891",
    "netname": "AMAZON-IAD",
    "organization": "Amazon Data Services NoVa",
    "physical_asn": "AS14618",
    "physical_continent": "NA",
    "physical_continentname": "North America",
    "physical_country": "US",
    "physical_countryname": "United States",
    "physical_isineu": 0,
    "physical_latitude": "37.09024",
    "physical_location": "37.09024,-95.712891",
    "physical_longitude": "-95.712891",
    "physical_organization": "Amazon.com, Inc.",
    "physical_subnet": "3.208.0.0/12",
    "physical_timezone": "America/Chicago",
    "subnet": "3.208.0.0/12",
    "timezone": "America/Chicago"
}

Since it’s way more efficient to use the MMDB file than the API, I built a cross-platform CLI tool for it: https://codeberg.org/hrbrmstr/geolocus-cli.

also with binary releases: https://codeberg.org/hrbrmstr/geolocus-cli/releases

Code is also available via Tangled Knot: https://tangled.sh/@hrbrmstr.dev/geolocus-cli

Usage:

# Download the latest Geolocus database
geolocus-cli download

# Look up IPs from a file
geolocus-cli lookup -i ips.txt -o results.json

# Process IPs from stdin and output to stdout
cat ips.txt | geolocus-cli lookup

# Output in CSV format
geolocus-cli lookup -i ips.txt -f csv -o results.csv

# Output in JSONL format (one JSON object per line)
geolocus-cli lookup -i ips.txt -f jsonl -o results.jsonl

# Disable session caching
geolocus-cli lookup -i ips.txt --no-cache

CLI options:

Commands:
  download    Download a fresh copy of the geolocus.mmdb database
  lookup      Lookup and enrich IP addresses from a file or stdin

Options:
  -h, --help              Show help information
  -i, --input <file>      Input file containing IP addresses (one per line)
  -o, --output <file>     Output file for results (defaults to stdout)
  -f, --format <format>   Output format: json, csv, or jsonl (default: json)
  --no-cache              Disable IP caching for the current session

Chris Krebs, the former director of the Cybersecurity and Infrastructure Security Agency (CISA), was fired by Donald Trump in 2020 for publicly affirming that the presidential election was secure and free from widespread fraud. Fast-forward to April 2025: Trump, now back in the White House, issued an executive order revoking Krebs’ security clearances and ordering a federal investigation into his conduct, specifically targeting both Krebs and his employer, SentinelOne. The order also suspended clearances for other SentinelOne employees and threatened the company’s ability to do business with the government.

Krebs responded by resigning from SentinelOne to fight the administration’s campaign against him, stating, “This is a fight for democracy, freedom of expression, and the rule of law. I’m ready to give it my all”. SentinelOne’s stock dropped, and the chilling effect on the broader cybersecurity sector was immediate and palpable.

The Industry’s Response: Silence, Not Solidarity

Despite Krebs’ reputation for professionalism and integrity, the cybersecurity industry has, with rare exceptions, responded with silence. Reuters reached out to 33 major cybersecurity firms and three industry groups—only one responded with a comment. Industry leaders, major vendors, and conference organizers have largely avoided public statements. Even companies with direct ties to Krebs, such as Microsoft and CrowdStrike, declined to comment.

This silence is not just disappointing—it’s dangerous. The executive order against Krebs is not merely a personal vendetta; it is a test of constitutional norms and the independence of the cybersecurity profession. By targeting Krebs for telling the truth, the administration is sending a message: dissent—especially when it contradicts the preferred political narrative—will be punished. The industry’s lack of response is, in effect, complicity.

Why This Matters

  • Chilling Effect: If a high-profile, well-respected figure like Krebs can be targeted for doing his job, no one in the industry is safe. The message is clear: toe the line or risk your career and your company’s future.
  • Erosion of Trust: Cybersecurity is built on trust and integrity. If practitioners cannot speak the truth without fear of retaliation, the entire profession is undermined.
  • Precedent for Authoritarianism: The use of executive power to punish private citizens and companies for protected speech is a hallmark of authoritarianism. The industry’s silence enables further overreach.

What Every RSA Attendee Should Do

RSA Conference 2025’s theme is “Many Voices. One Community.” But a community that stays silent in the face of injustice is not united—it is complicit. Every attendee, whether you’re a practitioner, vendor, or “A-lister,” has a responsibility to meet this moment.

When you visit vendor booths or encounter cybersecurity leaders and influencers at RSA, ask them:

  • What are you and your company doing to publicly support Chris Krebs and SentinelOne?
  • How are you defending the principles of free speech and professional integrity in cybersecurity?
  • Are you willing to risk contracts, revenue, or reputation to stand up for what’s right?
  • What concrete actions will you take to ensure that truth-telling cybersecurity professionals are protected, not punished?

Don’t let them dodge. Don’t accept platitudes.

If you’re a vendor or a leader: issue a public statement. Sign an open letter. Organize a session or a panel on defending professional independence. Use your platform—on stage, on social media, in the press—to call out this abuse of power.

If you’re an attendee: demand answers. Refuse to let silence be the industry’s answer to authoritarian overreach.

Remember: Silence is not safety. Silence is capitulation. If the cybersecurity community cannot defend its own when the truth is under attack, then what exactly are we protecting?

This is your moment. Don’t waste it.

A long, long time ago
I can still remember
How those CVEs would make me smile
And I knew if I had my chance
To patch a vuln or take a stance
Maybe we’d be secure for a while

But April ides made me shiver
With each leaked memo and press release delivered
Bad news on the doorstep
Couldn’t take one more step

I can’t remember if I sighed
When I read about the program’s demise
But something broke me deep inside
The day the CVE died

So bye, bye, MITRE’s CVE pie
Checked the vuln feed in my Feely
But the Feedly ran dry
And them good old nerds were drinking whiskey and rye
Singin’, “This’ll be the day that I sigh
This’ll be the day that I sigh”

Did you write the book of flaws
And do you have faith in CISA’s cause
As the budget fails you so?
Do you believe in NVD
Can it save our infosec sanity
Now that MITRE’s left out in the cold?

Well, I know you’re chasing vulns with me
Saw your commits in the CVE tree
We both diffed those exploit clues
Man, I miss those vuln ID blues

I was a lonely analyst on the hunt
With a zero-day and a coffee cup
But I knew I was out of luck
The day the CVE died

I started singing
Bye, bye, MITRE’s CVE pie
Checked the vuln feed in my Feely
But the Feedly ran dry
And them good old nerds were drinking whiskey and rye
Singin’, “This’ll be the day that I sigh
This’ll be the day that I sigh”

Now for twenty-five years we’ve been on our own
But the funding’s gone, the seeds are sown
That’s not how it used to be
When MITRE sang for DHS
And catalogued every software mess
In a voice that came from you and me

Oh, and while the vendors looked around
The hackers stole the thorny crown
No verdict was returned
And the vuln world, it just burned
And while defenders read advisories
The attackers practiced in the dark
And we sang dirges in the park
The day the CVE died

We were singing
Bye, bye, MITRE’s CVE pie
Checked the vuln feed in my Feely
But the Feedly ran dry
And them good old nerds were drinking whiskey and rye
Singin’, “This’ll be the day that I sigh
This’ll be the day that I sigh”

Helter skelter before the summer swelter
The KEV flew off with no shelter
Zero-days high and falling fast
It landed foul on the grass
The vendors tried for a forward pass
With MITRE on the sidelines in a cast

Now the half-time air was sweet perfume
While the Red Team played a marching tune
We all got up to dance
Oh, but we never got the chance
‘Cause the vendors tried to take the field
The bug bounty band refused to yield
Do you recall what was revealed
The day the CVE died?

We started singing
Bye, bye, MITRE’s CVE pie
Checked the vuln feed in my Feely
But the Feedly ran dry
And them good old nerds were drinking whiskey and rye
Singin’, “This’ll be the day that I sigh

Oh, and there we were all in one place
A generation lost in cyberspace
With no time left to start again
So come on: Jack be nimble, Jack be quick
Jack Flash sat on a candlestick
‘Cause fire is the hacker’s only friend

Oh, and as I watched it on the stage
My hands were clenched in fists of rage
No angel born in hell
Could break that budget spell
And as the flames climbed high into the night
To light the sacrificial rite
I saw Musk laughing with delight
The day the CVE died

He was singing
Bye, bye, MITRE’s CVE pie
Checked the vuln feed in my Feely
But the Feedly ran dry
And them good old nerds were drinking whiskey and rye
Singin’, “This’ll be the day that I sigh

I met a dev who sang the blues
And I asked her for some happy news
But she just smiled and turned away
I went down to the sacred store
Where I’d checked for CVEs before
But the sysadmin said the feeds wouldn’t play

And in the streets, the hackers screamed
The CISOs cried, and the devs all dreamed
But not a word was spoken
The patching chain was broken
And the three things I admire most:
The patch, the fix, and the vuln disclosure post
They caught the last train for the coast
The day the CVE died

And they were singing
Bye, bye, MITRE’s CVE pie
Drove my vuln feed to the levee
But the levee ran dry
And them good old nerds were drinking whiskey and rye
Singin’, “This’ll be the day that I sigh
This’ll be the day that I sigh”

ICERAID (iceraid[.]us) presents itself as a “GovFi protocol” that purportedly delegates intelligence gathering tasks from law enforcement to citizens. According to their materials, it rewards users with cryptocurrency tokens for capturing and uploading images of alleged “criminal illegal alien activity” and other suspected criminal behavior to their platform.

The platform claims to operate on the Solana blockchain, with users receiving ICERAID tokens for submitting photos through their app. Their marketing positions this as helping “take the strain off law enforcement” by allowing citizens to provide real-time data. The project launched a token sale that allegedly sold over 65 million ICERAID tokens, with plans for a validator staking program using Raydium LP tokens.

In February 2025, ICERAID announced a bounty program specifically targeting New York City, offering 2,000 ICERAID tokens for each photograph of “suspicious activities related to illegal immigration”. Users must connect a Solana-compatible wallet like Phantom to receive rewards after uploading images to the ICERAID Explorer.

I did some spelunking and dropped a bunch of info/artifacts on the fairly pathetic crypto scam initiative over at Codeberg.

On March 10, 2025, Xitter experienced major service disruptions throughout the day. Users couldn’t access the platform on both mobile apps and the website. Here’s what happened and why it matters.

What Happened?

X suffered multiple waves of outages starting early Monday morning:

  • First wave: Around 6:00 AM Eastern Time, affecting about 20,000 users
  • Second wave: Around 10:00 AM ET, with over 40,000 users reporting problems
  • Third wave: Between 11:00 AM and noon, affecting nearly 30,000 users

People trying to use Xitter saw loading symbols, error messages saying “Something went wrong. Try reloading,” or couldn’t access the service at all.

Who Was Behind It?

A pro-Palestinian hacking group called Dark Storm Team claimed responsibility for the attack. They posted on their Telegram channel: “Twitter has been taken offline by Dark Storm Team,” along with screenshots showing connection failures from different global locations.

Dark Storm Team has been active since around 2023 and is known for targeting organizations in Israel, Europe, and the United States. According to security experts, the group specializes in DDoS attacks and has a pro-Palestinian orientation.

What Did Elon Musk Say?

Elon Musk, Xitter’s owner, acknowledged the attack several hours after it began: “There was (still is) a massive cyberattack against Xitter. We get attacked every day, but this was done with a lot of resources. Either a large, coordinated group and/or a country is involved.”

Later, in an interview with Fox Business, Musk made a controversial claim connecting the attack to Ukraine: “We’re not sure exactly what happened but there was a massive cyberattack to try and bring down the Xitter system with IP addresses originating in the Ukraine area.” He provided no evidence to support this claim.

What Was the Reaction?

Cybersecurity experts expressed significant skepticism about Musk’s Ukraine claim:

  • They pointed out that attack origin IP addresses can be easily masked or manipulated
  • Attackers routinely route activities through compromised systems in other countries

Ukrainian officials firmly denied any involvement. Oleksii Merezhko, chairman of Ukraine’s parliamentary Foreign Affairs Committee, stated that the Ukrainian government had “absolutely” no part in the alleged cyberattack on Xitter.

Ed Krassenstein, who claimed to have communicated with Dark Storm’s leader, contradicted Musk’s assertion. According to screenshots shared online, the group responded to the Ukraine claim by saying: “Elon Musk must provide evidence for his claim, and we will provide evidence for ours.” They allegedly threatened further attacks, warning “We can attack again. A stronger attack this time, not only on Xitter but Tesla and others.”

What Type of Attack Was It?

The incident was a distributed denial-of-service (DDoS) attack. These attacks work by:
– Overwhelming a platform’s servers with excessive traffic
– Causing slowdowns or complete outages by exhausting available resources
– Using compromised devices (forming a “botnet”) to send overwhelming amounts of data

Cybersecurity experts described this attack as “far beyond simple DoS attempts,” involving “full-scale DDoS assaults, combined with sophisticated botnet activity, credential stuffing, API abuse, and targeted application-layer attacks designed to cripple operations.”

How Did Xitter Respond?

Xitter implemented Cloudflare’s DDoS protection services to mitigate the impact. This defensive measure introduced captcha verification for suspicious IP addresses generating too many requests. By evening, the platform had largely recovered, though some users continued to experience intermittent issues.

I’m not surprised Cloudflare helps protect Nazis, but it’d be nice to live in a universe where they all crawled back under their rocks for good.

I mentioned this new app over at the newsletter but it deserves a mention on the legacy blog.

CVESky is a tool to explore CVE chatter on Bluesky. At work, we’re ingesting the Bluesky Jetstream and watching for CVE chatter, excluding daft bots that just regurgitate new NVD CVEs.

There are six cards for the current and past five days of chatter, with CVEs displayed in descending order of activity. Tapping on a CVE provides details, and the ability to explore the CVE on Bluesky, Feedly, CIRCL’s Vuln Lookup, and — if present in our data — GreyNoise.

At the bottom of the page is a 30-day heatmap of CVE chatter. Tap on any populated square to see all the Bluesky chatter for that CVE.

This is similar to, but slightly different to the most excellent CVE Crowd, which monitors the Mastodonverse for CVE chatter.

The code behind the site also maintains a Bluesky list containing all the folks who chatter about CVEs on Bluesky.

Comments? Questions? Bugs? Feature requests? Hit up research@greynoise.io.

VulnCheck has some new, free API endpoints for the cybersecurity community.

Two extremely useful ones are for their extended version of CISA’s KEV, and an in-situ replacement for NVD’s sad excuse for an API and soon-to-be-removed JSON feeds.

There are two ways to work with these APIs. One is retrieve a “backup” of the entire dataset as a ZIP file, and the other is to use the API to retrieve individual CVEs from each “index”.

You’ll need a free API key from VulnCheck to use these APIs.

All code shown makes the assumption that you’ve stored your API key in an environment variable named VULNCHECK_API_KEY.

After the curl examples, there’s a section on a small Golang CLI I made to make it easier to get combined extended KEV and NVDv2 CVE information in one CLI call for a given CVE.

Backups

Retrieving the complete dataset is a multi-step process. First you make a call to the specific API endpoint for each index to backup. That returns some JSON with a temporary, AWS pre-signed URL (a method to grant temporary access to files stored in AWS S3) to download the ZIP file. Then you download the ZIP file, and finally you extract the contents of the ZIP file into a directory. The output is different for the NVDv2 and extended KEV indexes, but the core process is the same.

NVDv2

Here’s a curl idiom for the NVDv2 index backup. The result is a directory of uncompressed JSON that’s in the same format as the NVDv2 JSON feeds.

# Grab the temporary AWS pre-signed URL for the NVDv2 index and then download the ZIP file.
curl \
  --silent \
  --output vcnvd2.zip --url "$(
    curl \
      --silent \
      --cookie "token=${VULNCHECK_API_KEY}" \
      --header 'Accept: application/json' \
      --url "https://api.vulncheck.com/v3/backup/nist-nvd2" | jq -r '.data[].url'
    )"

rm -rf ./nvd2

# unzip it
unzip -q -o -d ./nvd2 vcnvd2.zip

# uncompress the JSON files
ls ./nvd2/*gz | xargs gunzip

tree ./nvd2
./nvd2
├── nvdcve-2.0-000.json
├── nvdcve-2.0-001.json
├── nvdcve-2.0-002.json
├── nvdcve-2.0-003.json
├── nvdcve-2.0-004.json
├── nvdcve-2.0-005.json
├── nvdcve-2.0-006.json
├── nvdcve-2.0-007.json
├── nvdcve-2.0-008.json
├── nvdcve-2.0-009.json
├── nvdcve-2.0-010.json
├── nvdcve-2.0-011.json
├── nvdcve-2.0-012.json
├── nvdcve-2.0-013.json
├── nvdcve-2.0-014.json
├── nvdcve-2.0-015.json
├── nvdcve-2.0-016.json
├── nvdcve-2.0-017.json
├── nvdcve-2.0-018.json
├── nvdcve-2.0-019.json
├── nvdcve-2.0-020.json
├── nvdcve-2.0-021.json
├── nvdcve-2.0-022.json
├── nvdcve-2.0-023.json
├── nvdcve-2.0-024.json
├── nvdcve-2.0-025.json
├── nvdcve-2.0-026.json
├── nvdcve-2.0-027.json
├── nvdcve-2.0-028.json
├── nvdcve-2.0-029.json
├── nvdcve-2.0-030.json
├── nvdcve-2.0-031.json
├── nvdcve-2.0-032.json
├── nvdcve-2.0-033.json
├── nvdcve-2.0-034.json
├── nvdcve-2.0-035.json
├── nvdcve-2.0-036.json
├── nvdcve-2.0-037.json
├── nvdcve-2.0-038.json
├── nvdcve-2.0-039.json
├── nvdcve-2.0-040.json
├── nvdcve-2.0-041.json
├── nvdcve-2.0-042.json
├── nvdcve-2.0-043.json
├── nvdcve-2.0-044.json
├── nvdcve-2.0-045.json
├── nvdcve-2.0-046.json
├── nvdcve-2.0-047.json
├── nvdcve-2.0-048.json
├── nvdcve-2.0-049.json
├── nvdcve-2.0-050.json
├── nvdcve-2.0-051.json
├── nvdcve-2.0-052.json
├── nvdcve-2.0-053.json
├── nvdcve-2.0-054.json
├── nvdcve-2.0-055.json
├── nvdcve-2.0-056.json
├── nvdcve-2.0-057.json
├── nvdcve-2.0-058.json
├── nvdcve-2.0-059.json
├── nvdcve-2.0-060.json
├── nvdcve-2.0-061.json
├── nvdcve-2.0-062.json
├── nvdcve-2.0-063.json
├── nvdcve-2.0-064.json
├── nvdcve-2.0-065.json
├── nvdcve-2.0-066.json
├── nvdcve-2.0-067.json
├── nvdcve-2.0-068.json
├── nvdcve-2.0-069.json
├── nvdcve-2.0-070.json
├── nvdcve-2.0-071.json
├── nvdcve-2.0-072.json
├── nvdcve-2.0-073.json
├── nvdcve-2.0-074.json
├── nvdcve-2.0-075.json
├── nvdcve-2.0-076.json
├── nvdcve-2.0-077.json
├── nvdcve-2.0-078.json
├── nvdcve-2.0-079.json
├── nvdcve-2.0-080.json
├── nvdcve-2.0-081.json
├── nvdcve-2.0-082.json
├── nvdcve-2.0-083.json
├── nvdcve-2.0-084.json
├── nvdcve-2.0-085.json
├── nvdcve-2.0-086.json
├── nvdcve-2.0-087.json
├── nvdcve-2.0-088.json
├── nvdcve-2.0-089.json
├── nvdcve-2.0-090.json
├── nvdcve-2.0-091.json
├── nvdcve-2.0-092.json
├── nvdcve-2.0-093.json
├── nvdcve-2.0-094.json
├── nvdcve-2.0-095.json
├── nvdcve-2.0-096.json
├── nvdcve-2.0-097.json
├── nvdcve-2.0-098.json
├── nvdcve-2.0-099.json
├── nvdcve-2.0-100.json
├── nvdcve-2.0-101.json
├── nvdcve-2.0-102.json
├── nvdcve-2.0-103.json
├── nvdcve-2.0-104.json
├── nvdcve-2.0-105.json
├── nvdcve-2.0-106.json
├── nvdcve-2.0-107.json
├── nvdcve-2.0-108.json
├── nvdcve-2.0-109.json
├── nvdcve-2.0-110.json
├── nvdcve-2.0-111.json
├── nvdcve-2.0-112.json
├── nvdcve-2.0-113.json
├── nvdcve-2.0-114.json
├── nvdcve-2.0-115.json
├── nvdcve-2.0-116.json
├── nvdcve-2.0-117.json
├── nvdcve-2.0-118.json
├── nvdcve-2.0-119.json
├── nvdcve-2.0-120.json
└── nvdcve-2.0-121.json

1 directory, 122 files

VulnCheck’s Extended KEV

Here’s a curl idiom for the extended KEV index backup. The result is a directory with a single uncompressed JSON that’s in an extended format of what’s in the CISA KEV JSON.s

# Grab the temporary AWS pre-signed URL for the NVDv2 index and then download the ZIP file.
curl \
  --silent \
  --output vckev.zip --url "$(
    curl \
      --silent \
      --cookie "token=${VULNCHECK_API_KEY}" \
      --header 'Accept: application/json' \
      --url "https://api.vulncheck.com/v3/backup/vulncheck-kev" | jq -r '.data[].url'
    )"

rm -rf ./vckev

# unzip it
unzip -q -o -d ./vckev vckev.zip

tree ./vckev
./vckev
└── vulncheck_known_exploited_vulnerabilities.json

1 directory, 1 file

Retrieving Information On Individual CVEs

While there are other, searchable fields for each index, the primary use case for most of us is getting information on individual CVEs. The API calls are virtually identical, apart from the selected index.

NOTE: the examples pipe the output through jq to make the API results easier to read.

NVDv2

curl \
  --silent \
  --cookie "token=${VULNCHECK_API_KEY}" \
  --header 'Accept: application/json' \
  --url "https://api.vulncheck.com/v3/index/nist-nvd2?cve=CVE-2024-23334" | jq
{
  "_benchmark": 0.056277,
  "_meta": {
    "timestamp": "2024-03-23T08:47:17.940032202Z",
    "index": "nist-nvd2",
    "limit": 100,
    "total_documents": 1,
    "sort": "_id",
    "parameters": [
      {
        "name": "cve",
        "format": "CVE-YYYY-N{4-7}"
      },
      {
        "name": "alias"
      },
      {
        "name": "iava",
        "format": "[0-9]{4}[A-Z-0-9]+"
      },
      {
        "name": "threat_actor"
      },
      {
        "name": "mitre_id"
      },
      {
        "name": "misp_id"
      },
      {
        "name": "ransomware"
      },
      {
        "name": "botnet"
      },
      {
        "name": "published"
      },
      {
        "name": "lastModStartDate",
        "format": "YYYY-MM-DD"
      },
      {
        "name": "lastModEndDate",
        "format": "YYYY-MM-DD"
      }
    ],
    "order": "desc",
    "page": 1,
    "total_pages": 1,
    "max_pages": 6,
    "first_item": 1,
    "last_item": 1
  },
  "data": [
    {
      "id": "CVE-2024-23334",
      "sourceIdentifier": "security-advisories@github.com",
      "vulnStatus": "Modified",
      "published": "2024-01-29T23:15:08.563",
      "lastModified": "2024-02-09T03:15:09.603",
      "descriptions": [
        {
          "lang": "en",
          "value": "aiohttp is an asynchronous HTTP client/server framework for asyncio and Python. When using aiohttp as a web server and configuring static routes, it is necessary to specify the root path for static files. Additionally, the option 'follow_symlinks' can be used to determine whether to follow symbolic links outside the static root directory. When 'follow_symlinks' is set to True, there is no validation to check if reading a file is within the root directory. This can lead to directory traversal vulnerabilities, resulting in unauthorized access to arbitrary files on the system, even when symlinks are not present.  Disabling follow_symlinks and using a reverse proxy are encouraged mitigations.  Version 3.9.2 fixes this issue."
        },
        {
          "lang": "es",
          "value": "aiohttp es un framework cliente/servidor HTTP asíncrono para asyncio y Python. Cuando se utiliza aiohttp como servidor web y se configuran rutas estáticas, es necesario especificar la ruta raíz para los archivos estáticos. Además, la opción 'follow_symlinks' se puede utilizar para determinar si se deben seguir enlaces simbólicos fuera del directorio raíz estático. Cuando 'follow_symlinks' se establece en Verdadero, no hay validación para verificar si la lectura de un archivo está dentro del directorio raíz. Esto puede generar vulnerabilidades de directory traversal, lo que resulta en acceso no autorizado a archivos arbitrarios en el sistema, incluso cuando no hay enlaces simbólicos presentes. Se recomiendan como mitigaciones deshabilitar follow_symlinks y usar un proxy inverso. La versión 3.9.2 soluciona este problema."
        }
      ],
      "references": [
        {
          "url": "https://github.com/aio-libs/aiohttp/commit/1c335944d6a8b1298baf179b7c0b3069f10c514b",
          "source": "security-advisories@github.com",
          "tags": [
            "Patch"
          ]
        },
        {
          "url": "https://github.com/aio-libs/aiohttp/pull/8079",
          "source": "security-advisories@github.com",
          "tags": [
            "Patch"
          ]
        },
        {
          "url": "https://github.com/aio-libs/aiohttp/security/advisories/GHSA-5h86-8mv2-jq9f",
          "source": "security-advisories@github.com",
          "tags": [
            "Exploit",
            "Mitigation",
            "Vendor Advisory"
          ]
        },
        {
          "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/ICUOCFGTB25WUT336BZ4UNYLSZOUVKBD/",
          "source": "security-advisories@github.com"
        },
        {
          "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/XXWVZIVAYWEBHNRIILZVB3R3SDQNNAA7/",
          "source": "security-advisories@github.com",
          "tags": [
            "Mailing List"
          ]
        }
      ],
      "metrics": {
        "cvssMetricV31": [
          {
            "source": "nvd@nist.gov",
            "type": "Primary",
            "cvssData": {
              "version": "3.1",
              "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
              "attackVector": "NETWORK",
              "attackComplexity": "LOW",
              "privilegesRequired": "NONE",
              "userInteraction": "NONE",
              "scope": "UNCHANGED",
              "confidentialityImpact": "HIGH",
              "integrityImpact": "NONE",
              "availabilityImpact": "NONE",
              "baseScore": 7.5,
              "baseSeverity": "HIGH"
            },
            "exploitabilityScore": 3.9,
            "impactScore": 3.6
          },
          {
            "source": "security-advisories@github.com",
            "type": "Secondary",
            "cvssData": {
              "version": "3.1",
              "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
              "attackVector": "NETWORK",
              "attackComplexity": "HIGH",
              "privilegesRequired": "NONE",
              "userInteraction": "NONE",
              "scope": "UNCHANGED",
              "confidentialityImpact": "HIGH",
              "integrityImpact": "NONE",
              "availabilityImpact": "NONE",
              "baseScore": 5.9,
              "baseSeverity": "MEDIUM"
            },
            "exploitabilityScore": 2.2,
            "impactScore": 3.6
          }
        ]
      },
      "weaknesses": [
        {
          "source": "security-advisories@github.com",
          "type": "Primary",
          "description": [
            {
              "lang": "en",
              "value": "CWE-22"
            }
          ]
        }
      ],
      "configurations": [
        {
          "nodes": [
            {
              "operator": "OR",
              "cpeMatch": [
                {
                  "vulnerable": true,
                  "criteria": "cpe:2.3:a:aiohttp:aiohttp:*:*:*:*:*:*:*:*",
                  "versionStartIncluding": "1.0.5",
                  "versionEndExcluding": "3.9.2",
                  "matchCriteriaId": "CC18B2A9-9D80-4A6E-94E7-8FC010D8FC70"
                }
              ]
            }
          ]
        },
        {
          "nodes": [
            {
              "operator": "OR",
              "cpeMatch": [
                {
                  "vulnerable": true,
                  "criteria": "cpe:2.3:o:fedoraproject:fedora:39:*:*:*:*:*:*:*",
                  "matchCriteriaId": "B8EDB836-4E6A-4B71-B9B2-AA3E03E0F646"
                }
              ]
            }
          ]
        }
      ],
      "_timestamp": "2024-02-09T05:33:33.170054Z"
    }
  ]
}

VulnCheck’s Extended KEV

curl \
  --silent \
  --cookie "token=${VULNCHECK_API_KEY}" \
  --header 'Accept: application/json' \
  --url "https://api.vulncheck.com/v3/index/vulncheck-kev?cve=CVE-2024-23334" | jq
{
  "_benchmark": 0.328855,
  "_meta": {
    "timestamp": "2024-03-23T08:47:41.025967418Z",
    "index": "vulncheck-kev",
    "limit": 100,
    "total_documents": 1,
    "sort": "_id",
    "parameters": [
      {
        "name": "cve",
        "format": "CVE-YYYY-N{4-7}"
      },
      {
        "name": "alias"
      },
      {
        "name": "iava",
        "format": "[0-9]{4}[A-Z-0-9]+"
      },
      {
        "name": "threat_actor"
      },
      {
        "name": "mitre_id"
      },
      {
        "name": "misp_id"
      },
      {
        "name": "ransomware"
      },
      {
        "name": "botnet"
      },
      {
        "name": "published"
      },
      {
        "name": "lastModStartDate",
        "format": "YYYY-MM-DD"
      },
      {
        "name": "lastModEndDate",
        "format": "YYYY-MM-DD"
      },
      {
        "name": "pubStartDate",
        "format": "YYYY-MM-DD"
      },
      {
        "name": "pubEndDate",
        "format": "YYYY-MM-DD"
      }
    ],
    "order": "desc",
    "page": 1,
    "total_pages": 1,
    "max_pages": 6,
    "first_item": 1,
    "last_item": 1
  },
  "data": [
    {
      "vendorProject": "aiohttp",
      "product": "aiohttp",
      "shortDescription": "aiohttp is an asynchronous HTTP client/server framework for asyncio and Python. When using aiohttp as a web server and configuring static routes, it is necessary to specify the root path for static files. Additionally, the option 'follow_symlinks' can be used to determine whether to follow symbolic links outside the static root directory. When 'follow_symlinks' is set to True, there is no validation to check if reading a file is within the root directory. This can lead to directory traversal vulnerabilities, resulting in unauthorized access to arbitrary files on the system, even when symlinks are not present.  Disabling follow_symlinks and using a reverse proxy are encouraged mitigations.  Version 3.9.2 fixes this issue.",
      "vulnerabilityName": "aiohttp aiohttp Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')",
      "required_action": "Apply remediations or mitigations per vendor instructions or discontinue use of the product if remediation or mitigations are unavailable.",
      "knownRansomwareCampaignUse": "Known",
      "cve": [
        "CVE-2024-23334"
      ],
      "vulncheck_xdb": [
        {
          "xdb_id": "231b48941355",
          "xdb_url": "https://vulncheck.com/xdb/231b48941355",
          "date_added": "2024-02-28T22:30:21Z",
          "exploit_type": "infoleak",
          "clone_ssh_url": "git@github.com:ox1111/CVE-2024-23334.git"
        },
        {
          "xdb_id": "f1d001911304",
          "xdb_url": "https://vulncheck.com/xdb/f1d001911304",
          "date_added": "2024-03-19T16:28:56Z",
          "exploit_type": "infoleak",
          "clone_ssh_url": "git@github.com:jhonnybonny/CVE-2024-23334.git"
        }
      ],
      "vulncheck_reported_exploitation": [
        {
          "url": "https://cyble.com/blog/cgsi-probes-shadowsyndicate-groups-possible-exploitation-of-aiohttp-vulnerability-cve-2024-23334/",
          "date_added": "2024-03-15T00:00:00Z"
        }
      ],
      "date_added": "2024-03-15T00:00:00Z",
      "_timestamp": "2024-03-23T08:27:47.861266Z"
    }
  ]
}

vccve

There’s a project on Codeberg that has code and binaries for macOS, Linux, and Windows for a small CLI that gets you combined extended KEV and NVDv2 information all in one call.

The project README has examples and installation instructions.

If you’ve got ? on this blog (directly, or via syndication) you’d have to have been living under a rock to not know about the libwebp supply chain disaster. An unfortunate casualty of inept programming just happened to be any app in the Electron ecosystem that doesn’t undergo bleeding-edge updates.

Former cow-orker Tom Sellers (one of the best humans in cyber) did a great service to the macOS user community with tips on how to stay safe on macOS. His find + strings + grep combo was superbly helpful and I hope many macOS users did the command line dance to see how negligent their app providers were/are.

But, you still have to know what versions are OK and which ones are not to do that dance. And, having had yet-another immune system invasion (thankfully, not COVID, again) on top of still working through long COVID (#protip: you may be over the pandemic, but I guarantee it’s not done with you/us for a while) which re-sapped mobility energy, I put my sedentary time to less woesome use by hacking together a small, Golang macOS CLI to help ferret out bad Electron-based apps you may have installed.

I named it positron, since that’s kind of the opposite of Electron, and I was pretty creativity-challenged today.

It does virtually the same thing as Tom’s strings and grep does, just in a single, lightweight, universal, signed macOS binary.

When I ran it after the final build, all my Electron-based apps were ?. After deleting some, and updating others, this is my current status:

$ find /Applications -type f -name "*Electron Framework*" -exec ./positron "{}" \;
/Applications/Signal.app: Chrome/114.0.5735.289 Electron/25.8.4 ?
/Applications/Keybase.app: Chrome/87.0.4280.141 Electron/11.5.0 ?
/Applications/Raindrop.io.app: Chrome/102.0.5005.167 Electron/19.0.17 ?
/Applications/1Password.app: Chrome/114.0.5735.289 Electron/25.8.1 ?
/Applications/Replit.app: Chrome/116.0.5845.188 Electron/26.2.1 ?
/Applications/lghub.app: Chrome/104.0.5112.65 Electron/20.0.0 ?

It’s still on you to do the find (cooler folks run fd) since I’m not about to write a program that’ll rummage across your SSDs or disc drives, but it does all the MachO inspection internally, and then also does the SemVer comparison to let you know which apps still suck at keeping you safe.

FWIW, the Keybase folks did accept a PR for the libwebp thing, but darned if I will spend any time building it (I don’t run it anymore, anyway, so I should just delete it).

The aforementioned signed, universal, macOS binary is in the GitLab releases.

Stay safe out there!