feat: added first commit malpacks
parent
98cba0c8c2
commit
a88420f2d9
|
@ -0,0 +1,22 @@
|
||||||
|
import json
|
||||||
|
|
||||||
|
with open('/path/to/list/malicious/pkgs.txt', 'r') as file:
|
||||||
|
lines = file.read().splitlines()
|
||||||
|
|
||||||
|
with open('database.json', 'r') as file:
|
||||||
|
existing_data = json.load(file)
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
new_object = {
|
||||||
|
"type": "pypi",
|
||||||
|
"name": line,
|
||||||
|
"url": "https://github.com/DataDog/malicious-software-packages-dataset"
|
||||||
|
}
|
||||||
|
existing_data.append(new_object)
|
||||||
|
|
||||||
|
with open('database_new.json', 'w') as file:
|
||||||
|
json.dump(existing_data, file, indent=4)
|
||||||
|
|
||||||
|
print("Data appended and saved to database_new.json")
|
||||||
|
|
||||||
|
# This script is used to append data to the database.json file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import json
|
||||||
|
|
||||||
|
with open("../../database.json", "r") as json_file:
|
||||||
|
data = json.load(json_file)
|
||||||
|
|
||||||
|
type_counts = {}
|
||||||
|
|
||||||
|
for item in data:
|
||||||
|
item_type = item.get("type")
|
||||||
|
if item_type:
|
||||||
|
if item_type in type_counts:
|
||||||
|
type_counts[item_type] += 1
|
||||||
|
else:
|
||||||
|
type_counts[item_type] = 1
|
||||||
|
|
||||||
|
for item_type, count in type_counts.items():
|
||||||
|
print(f"{item_type}: {count}")
|
54
README.md
54
README.md
|
@ -1,2 +1,52 @@
|
||||||
# malware-package-scanner
|
# Malpacks
|
||||||
Tools to find malicious packages
|
Tools to find malicious packages inside package manager (PyPI, npm, and Gem)
|
||||||
|
|
||||||
|
## Total data
|
||||||
|
* npm: 1823
|
||||||
|
* pypi: 5985
|
||||||
|
* gem: 725
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
Simply clone the repository, install requirements and run the script
|
||||||
|
|
||||||
|
* $ git clone https://github.com/daffainfo/malpacks
|
||||||
|
* $ pip3 install -r requirements.txt
|
||||||
|
* $ python3 main.py
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Available options:
|
||||||
|
* `--all` option
|
||||||
|
|
||||||
|
To scan all the package managers (PyPI, npm, and Gem)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```bash
|
||||||
|
$ python3 main.py --all
|
||||||
|
```
|
||||||
|
|
||||||
|
* `--packages` option
|
||||||
|
|
||||||
|
Define package manager to test (PyPI, npm, and Gem)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```bash
|
||||||
|
$ python3 main.php --packages npm,pypi
|
||||||
|
```
|
||||||
|
|
||||||
|
## To-Do List
|
||||||
|
- [ ] Scan a file that contain list of packages
|
||||||
|
- [ ] Scan requirements.txt (Python)
|
||||||
|
- [ ] Scan package.json (npm)
|
||||||
|
- [ ] More output options
|
||||||
|
- [ ] JSON
|
||||||
|
- [ ] YAML
|
||||||
|
- [ ] Add more package manager
|
||||||
|
- [x] PyPI
|
||||||
|
- [x] npm
|
||||||
|
- [x] Gem
|
||||||
|
- [ ] Go
|
||||||
|
- [ ] Composer
|
||||||
|
- [ ] Add more malicious packages
|
||||||
|
- [x] https://blog.phylum.io/phylum-discovers-another-attack-on-pypi/
|
||||||
|
- [x] https://www.reversinglabs.com/blog/mining-for-malicious-ruby-gems
|
||||||
|
- [ ] https://github.com/DataDog/malicious-software-packages-dataset
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,16 @@
|
||||||
|
from colorama import Fore, Style
|
||||||
|
|
||||||
|
def banner():
|
||||||
|
banner = Fore.BLUE + """
|
||||||
|
# # ## # ##### ## #### # # ####
|
||||||
|
## ## # # # # # # # # # # # #
|
||||||
|
# ## # # # # # # # # # #### ####
|
||||||
|
# # ###### # ##### ###### # # # #
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
# # # # ###### # # # #### # # ####
|
||||||
|
|
||||||
|
Version: 1.0.0
|
||||||
|
Author: daffainfo
|
||||||
|
"""
|
||||||
|
|
||||||
|
print(banner + Style.RESET_ALL)
|
|
@ -0,0 +1,55 @@
|
||||||
|
import json
|
||||||
|
from colorama import Fore, Style
|
||||||
|
from packages import npm, pypi, gem
|
||||||
|
|
||||||
|
npm_packages = []
|
||||||
|
pypi_packages = []
|
||||||
|
gem_packages = []
|
||||||
|
|
||||||
|
def scan(args):
|
||||||
|
|
||||||
|
if args.all:
|
||||||
|
npm_packages = npm.list_all_npm_packages()
|
||||||
|
pypi_packages = pypi.list_all_pypi_packages()
|
||||||
|
gem_packages = gem.list_all_gem_packages()
|
||||||
|
check('npm', npm_packages)
|
||||||
|
check('pypi', pypi_packages)
|
||||||
|
check('gem', gem_packages)
|
||||||
|
|
||||||
|
if args.packages:
|
||||||
|
packages_type = args.packages.split(',')
|
||||||
|
for package_type in packages_type:
|
||||||
|
if package_type == 'npm':
|
||||||
|
npm_packages = npm.list_all_npm_packages()
|
||||||
|
check('npm', npm_packages)
|
||||||
|
elif package_type == 'pypi':
|
||||||
|
pypi_packages = pypi.list_all_pypi_packages()
|
||||||
|
check('pypi', pypi_packages)
|
||||||
|
elif package_type == 'gem':
|
||||||
|
gem_packages = gem.list_all_gem_packages()
|
||||||
|
check('gem', gem_packages)
|
||||||
|
else:
|
||||||
|
print(Fore.RED + f"[!] Unknown package type: {package_type}")
|
||||||
|
print(Style.RESET_ALL)
|
||||||
|
|
||||||
|
def check(package_type, package_names):
|
||||||
|
with open('database.json') as json_file:
|
||||||
|
database = json.load(json_file)
|
||||||
|
|
||||||
|
print(Fore.YELLOW + f"[!] Checking {package_type} packages...")
|
||||||
|
|
||||||
|
found_count = 0
|
||||||
|
for package in database:
|
||||||
|
package_type_in_db = package.get('type', '')
|
||||||
|
package_name = package.get('name', '')
|
||||||
|
package_url = package.get('url', '')
|
||||||
|
|
||||||
|
if package_type == package_type_in_db and package_name in package_names:
|
||||||
|
print(Fore.RED + f"[+] Package found: {package_name}")
|
||||||
|
print(Fore.RED + f"[+] Advisory: {package_url}")
|
||||||
|
print(Style.RESET_ALL)
|
||||||
|
found_count = found_count + 1
|
||||||
|
|
||||||
|
if found_count == 0:
|
||||||
|
print(Fore.GREEN + f"[+] No malicious {package_type} packages found.")
|
||||||
|
print(Style.RESET_ALL)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,20 @@
|
||||||
|
import argparse
|
||||||
|
from colorama import Fore, Style
|
||||||
|
from core import scanner, cli
|
||||||
|
|
||||||
|
def main():
|
||||||
|
cli.banner()
|
||||||
|
parser = argparse.ArgumentParser(description='Specify scan parameters.')
|
||||||
|
|
||||||
|
parser.add_argument('--all', action='store_true', help='Scanning all package managers')
|
||||||
|
parser.add_argument('--packages', type=str, help='Define package manager to test', default="")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if not args.all and not args.packages:
|
||||||
|
parser.error('Please specify either --all or --packages')
|
||||||
|
|
||||||
|
scanner.scan(args)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,30 @@
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def list_all_gem_packages():
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['gem', 'list'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||||
|
|
||||||
|
if result.returncode == 0:
|
||||||
|
# Split the captured output into lines to get package lines
|
||||||
|
package_lines = result.stdout.split('\n')
|
||||||
|
|
||||||
|
# Initialize an empty list to store package names
|
||||||
|
package_names = []
|
||||||
|
|
||||||
|
# Print only the package names
|
||||||
|
for package_line in package_lines:
|
||||||
|
package_info = package_line.strip().split(' ')
|
||||||
|
if len(package_info) > 0:
|
||||||
|
package_name = package_info[0]
|
||||||
|
package_names.append(package_name)
|
||||||
|
|
||||||
|
return package_names # Return the list of package names
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("Error:", result.stderr)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("An error occurred:", e)
|
||||||
|
|
||||||
|
# packages_array = list_all_gem_packages()
|
||||||
|
# print(packages_array)
|
|
@ -0,0 +1,32 @@
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def list_all_npm_packages():
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['npm', 'ls', '-g'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||||
|
|
||||||
|
if result.returncode == 0:
|
||||||
|
# Split the captured output into lines to get package lines
|
||||||
|
package_lines = result.stdout.split('\n')
|
||||||
|
|
||||||
|
# Initialize an empty list to store package names
|
||||||
|
package_names = []
|
||||||
|
|
||||||
|
# Print only the package names without directory structure
|
||||||
|
for package_line in package_lines:
|
||||||
|
package_name = package_line.strip()
|
||||||
|
if package_name and package_name != '/usr/local/lib':
|
||||||
|
package_name = package_line.split('@')[0].strip()
|
||||||
|
package_name = package_name.replace('├──', '').replace('└──', '').strip()
|
||||||
|
if package_name:
|
||||||
|
package_names.append(package_name)
|
||||||
|
|
||||||
|
return package_names # Return the list of package names
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("Error:", result.stderr)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("An error occurred:", e)
|
||||||
|
|
||||||
|
#packages_array = list_all_npm_packages()
|
||||||
|
#print(packages_array)
|
|
@ -0,0 +1,30 @@
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def list_all_pypi_packages():
|
||||||
|
try:
|
||||||
|
# Run the 'pip freeze' command and capture its output
|
||||||
|
result = subprocess.run(['pip3', 'freeze', '--all'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||||
|
|
||||||
|
if result.returncode == 0:
|
||||||
|
# Split the captured output into lines to get package names
|
||||||
|
package_lines = result.stdout.split('\n')
|
||||||
|
|
||||||
|
# Initialize an empty list to store package names
|
||||||
|
package_names = []
|
||||||
|
|
||||||
|
# Append package names to the list
|
||||||
|
for package_line in package_lines:
|
||||||
|
package_name = package_line.split('==')[0] # Extract the package name
|
||||||
|
if package_name:
|
||||||
|
package_names.append(package_name)
|
||||||
|
|
||||||
|
return package_names # Return the list of package names
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("Error:", result.stderr)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("An error occurred:", e)
|
||||||
|
|
||||||
|
# packages_array = list_all_pypi_packages()
|
||||||
|
# print(packages_array)
|
|
@ -0,0 +1 @@
|
||||||
|
colorama==0.4.4
|
Loading…
Reference in New Issue