diff --git a/app.py b/app.py
@@ -4,10 +4,21 @@ import re
import urllib.parse
import requests
import os
+import shodan as shodan_lib
+import ipaddress
from flask_paginate import Pagination, get_page_args
from datetime import datetime, timedelta
from flask import Flask, render_template, request
from modules.County_Codes import country_code_to_korean
+from dateutil.parser import parse
+from bs4 import BeautifulSoup
+from datetime import datetime, timedelta
+from pytz import timezone
+
+def get_unique_words(title):
+ # 여기서는 제목을 공백으로 분리하여 단어를 추출하였습니다.
+ # 필요에 따라 더 복잡한 토큰화 도구를 사용할 수 있습니다.
+ return set(title.split(' '))
# 국가 코드를 한국어 국가 이름으로 변환하는 함수
def get_korean_country_name(country_code):
@@ -84,12 +95,27 @@ def news():
per_page_parameter='per_page')
# Bing Search v7 API endpoint
- url = "https://api.cognitive.microsoft.com/bing/v7.0/news/search"
- headers = {"Ocp-Apim-Subscription-Key": os.getenv("ec6fd8d4f6cb4263be9c7062fd398f91")}
+ subscription_key = os.environ['BING_SEARCH_V7_SUBSCRIPTION_KEY']
+ url = 'https://api.bing.microsoft.com/v7.0/news/search'
+ headers = {"Ocp-Apim-Subscription-Key": subscription_key}
+ days = request.args.get('days', default='Day')
+
+ # Get the topics from the form
+ topics = request.args.getlist('topics')
+ days = request.args.get('days', default='Day')
+
+ # If no topics selected, set a default
+ if not topics:
+ topics = ["보안"]
+
+ # Generate the query string
+ query = " OR ".join(topics)
+
params = {
- "q": "해킹 OR 해커 OR 멀웨어 OR 취약점",
- "count": 50,
- "freshness": "Day",
+ "q": query,
+ "mkt": "ko-KR",
+ "count": 100,
+ "freshness": days,
"textFormat": "Raw",
"safeSearch": "Off"
}
@@ -98,18 +124,103 @@ def news():
response.raise_for_status()
news_data = response.json()["value"]
- # Convert published time to datetime object
+ def get_unique_words(title):
+ return set(title.split(' '))
+
+ unique_news_data = []
for news in news_data:
- news["datePublished"] = datetime.strptime(news["datePublished"], "%Y-%m-%dT%H:%M:%S.%fZ")
+ title = news['name']
+ unique_words = get_unique_words(title)
+
+ if any(sum(word in get_unique_words(existing_news['name']) for word in unique_words) >= 2 for existing_news in unique_news_data):
+ continue
+ unique_news_data.append(news)
+
+ # Convert published time to datetime object
+ for news in unique_news_data:
+ # Convert the 'datePublished' string to a datetime object
+ date_published = parse(news["datePublished"])
+ # Format the datetime object to a string with only the date
+ news["datePublished"] = date_published.strftime('%Y-%m-%d')
+
# Paginate news
- total = len(news_data)
- pagination_news = news_data[offset: offset + per_page]
+ total = len(unique_news_data)
+ pagination_news = unique_news_data[offset: offset + per_page]
pagination = Pagination(page=page, per_page=per_page, total=total,
css_framework='bootstrap4')
return render_template('news.html', news=pagination_news, page=page,
- per_page=per_page, pagination=pagination)
+ per_page=per_page, pagination=pagination, selected_topics=topics, days=days)
+
+@app.route('/shodan', methods=['GET', 'POST'])
+def shodan():
+ results = None
+ template_name = 'shodan.html'
+
+ if request.method == 'POST':
+ query = request.form.get('query')
+ if not query:
+ results = "Please enter an IP address or a domain name."
+ else:
+ shodan_api_key = "aDVXje74ussQwMO5JP4NmkNmssL1sjCI" # Replace with your Shodan API Key
+ api = shodan_lib.Shodan(shodan_api_key)
+
+ try:
+ ipaddress.ip_address(query)
+ # If the above line of code doesn't raise an exception, it means that the input is a valid IP address
+ try:
+ results = api.host(query)
+ except shodan_lib.APIError as e:
+ results = f"No information available for that IP: {query}"
+ except ValueError:
+ # If the input is not a valid IP address, it might be a domain name
+ try:
+ results = api.search(query)
+ template_name = 'shodan_domain.html' # Use a different template for domain names
+ except shodan_lib.APIError as e:
+ results = f"Error: {e}"
+ except shodan_lib.APIError as e:
+ results = f"Error: {e}"
+
+
+ return render_template(template_name, results=results)
+
+@app.route('/krcert')
+def krcert():
+ url = "https://www.krcert.or.kr/kr/bbs/list.do?menuNo=205020&bbsId=B0000133"
+ response = requests.get(url)
+ soup = BeautifulSoup(response.text, 'html.parser')
+
+ table = soup.find('div', {'class': 'tbl'}).find('table')
+ if table is None:
+ return "Table not found on the page."
+
+ rows = table.find_all('tr')[1:] # get all rows except the header row
+ posts = []
+
+ for row in rows:
+ cols = row.find_all('td')
+ if len(cols) >= 5:
+ title_tag = cols[1].find('a')
+ date_tag = cols[4]
+
+ # Check if title_tag or date_tag is None before calling get_text
+ if title_tag is None or date_tag is None:
+ continue
+
+ title = title_tag.get_text(strip=True)
+ date = date_tag.get_text(strip=True)
+
+ post_date = datetime.strptime(date, "%Y-%m-%d")
+
+ if (datetime.now() - post_date).total_seconds() <= 518400:
+ posts.append((title, date))
+
+ if not posts:
+ return "No new posts in the last 48 hours."
+
+ return render_template('krcert.html', posts=posts)
if __name__ == '__main__':
app.run()
diff --git a/templates/ascii_to_char.html b/templates/ascii_to_char.html
@@ -36,11 +36,14 @@
<a class="nav-link" href="/ascii_to_char">ASCII Code Converter</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="/utf8_decoder">UTF-8 Decorder</a>
+ <a class="nav-link" href="/utf8_decoder">UTF-8 Decoder</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/news">News</a>
</li>
+ <li class="nav-item">
+ <a class="nav-link" href="/shodan">Shodan</a>
+ </li>
</ul>
</div>
</nav>
diff --git a/templates/index.html b/templates/index.html
@@ -33,15 +33,17 @@
<a class="nav-link" href="/ascii_to_char">ASCII Code Converter</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="/utf8_decoder">UTF-8 Decorder</a>
+ <a class="nav-link" href="/utf8_decoder">UTF-8 Decoder</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/news">News</a>
</li>
+ <li class="nav-item">
+ <a class="nav-link" href="/shodan">Shodan</a>
+ </li>
</ul>
</div>
</nav>
-
<div class="container">
<h1 class="my-3">IP to Country</h1>
<form method="post">
diff --git a/templates/krcert.html b/templates/krcert.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <title>KRCERT</title>
+ <!-- Bootstrap CSS -->
+ <link
+ href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
+ rel="stylesheet"
+ />
+ </head>
+ <body>
+ <nav class="navbar navbar-expand-lg navbar-light bg-light">
+ <a class="navbar-brand" href="#">Navigation</a>
+ <button
+ class="navbar-toggler"
+ type="button"
+ data-toggle="collapse"
+ data-target="#navbarNav"
+ aria-controls="navbarNav"
+ aria-expanded="false"
+ aria-label="Toggle navigation"
+ >
+ <span class="navbar-toggler-icon"></span>
+ </button>
+ <div class="collapse navbar-collapse" id="navbarNav">
+ <ul class="navbar-nav">
+ <li class="nav-item active">
+ <a class="nav-link" href="/">IP & Domain Country Finder</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/ascii_to_char">ASCII Code Converter</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/utf8_decoder">UTF-8 Decoder</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/news">News</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/shodan">Shodan</a>
+ </li>
+ </ul>
+ </div>
+ </nav>
+
+ <div class="container">
+ <h1 class="mt-5">KRCERT Posts</h1>
+ <table class="table mt-4">
+ <thead>
+ <tr>
+ <th>Title</th>
+ <th>Date</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for result in results %}
+ <tr>
+ <td>{{ result.title }}</td>
+ <td>{{ result.date }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </div>
+ <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
+ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
+ </body>
+</html>
diff --git a/templates/news.html b/templates/news.html
@@ -33,14 +33,32 @@
<a class="nav-link" href="/ascii_to_char">ASCII Code Converter</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="/utf8_decoder">UTF-8 Decorder</a>
+ <a class="nav-link" href="/utf8_decoder">UTF-8 Decoder</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/news">News</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/shodan">Shodan</a>
</li>
</ul>
</div>
</nav>
+ <form method="GET" action="/news">
+ <!-- 기타 필드 -->
+ <label><input type="checkbox" name="topics" value="보안" {% if '보안' in selected_topics %} checked {% endif %}> 보안</label>
+ <label><input type="checkbox" name="topics" value="해킹" {% if '해킹' in selected_topics %} checked {% endif %}> 해킹</label>
+ <label><input type="checkbox" name="topics" value="해커" {% if '해커' in selected_topics %} checked {% endif %}> 해커</label>
+ <label><input type="checkbox" name="topics" value="멀웨어" {% if '멀웨어' in selected_topics %} checked {% endif %}> 멀웨어</label>
+ <label><input type="checkbox" name="topics" value="랜섬웨어" {% if '랜섬웨어' in selected_topics %} checked {% endif %}> 랜섬웨어</label>
+ <label><input type="checkbox" name="topics" value="취약점" {% if '취약점' in selected_topics %} checked {% endif %}> 취약점</label>
+ <select name="days">
+ <option value="Day" {% if days == 'Day' %} selected {% endif %}>24 시간</option>
+ <option value="Week" {% if days == 'Week' %} selected {% endif %}>7 일</option>
+ <option value="Month" {% if days == 'Month' %} selected {% endif %}>30 일</option>
+ </select>
+ <input type="submit" value="검색">
+ </form>
<div class="container">
<h1 class="my-4">News</h1>
diff --git a/templates/shodan.html b/templates/shodan.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <title>Shodan Search</title>
+ <!-- Bootstrap CSS -->
+ <link
+ href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
+ rel="stylesheet"
+ />
+ </head>
+
+ <body>
+ <nav class="navbar navbar-expand-lg navbar-light bg-light">
+ <a class="navbar-brand" href="#">Navigation</a>
+ <button
+ class="navbar-toggler"
+ type="button"
+ data-toggle="collapse"
+ data-target="#navbarNav"
+ aria-controls="navbarNav"
+ aria-expanded="false"
+ aria-label="Toggle navigation"
+ >
+ <span class="navbar-toggler-icon"></span>
+ </button>
+ <div class="collapse navbar-collapse" id="navbarNav">
+ <ul class="navbar-nav">
+ <li class="nav-item active">
+ <a class="nav-link" href="/">IP & Domain Country Finder</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/ascii_to_char">ASCII Code Converter</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/utf8_decoder">UTF-8 Decoder</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/news">News</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/shodan">Shodan</a>
+ </li>
+ </ul>
+ </div>
+ </nav>
+
+ <div class="container">
+ <h1 class="mt-5">Shodan Search</h1>
+ <form method="POST">
+ <div class="mb-3">
+ <label for="query" class="form-label">IP / Domain</label>
+ <input
+ type="text"
+ class="form-control"
+ id="query"
+ name="query"
+ required
+ />
+ </div>
+ <button type="submit" class="btn btn-primary">Search</button>
+ </form>
+ {% if results %}
+ <h2 class="my-4">Results</h2>
+ <table class="table">
+ <thead>
+ <tr>
+ <th>Key</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for key, value in results.items() %} {% if value is mapping %} {%
+ for sub_key, sub_value in value.items() %}
+ <tr>
+ <td>{{ key }}.{{ sub_key }}</td>
+ <td>{{ sub_value }}</td>
+ </tr>
+ {% endfor %} {% elif value is iterable and value is not string %} {%
+ for element in value %} {% if element is mapping %} {% for sub_key,
+ sub_value in element.items() %}
+ <tr>
+ <td>{{ key }}[{{ loop.index }}].{{ sub_key }}</td>
+ <td>{{ sub_value }}</td>
+ </tr>
+ {% endfor %} {% else %}
+ <tr>
+ <td>{{ key }}[{{ loop.index }}]</td>
+ <td>{{ element }}</td>
+ </tr>
+ {% endif %} {% endfor %} {% else %}
+ <tr>
+ <td>{{ key }}</td>
+ <td>{{ value }}</td>
+ </tr>
+ {% endif %} {% endfor %}
+ </tbody>
+ </table>
+ {% endif %}
+ </div>
+
+ <!-- Optional JavaScript -->
+ <!-- jQuery first, then Popper.js, then Bootstrap JS -->
+ <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
+ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
+ </body>
+</html>
diff --git a/templates/shodan_domain.html b/templates/shodan_domain.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <title>Shodan Search</title>
+ <link
+ href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
+ rel="stylesheet"
+ />
+ </head>
+ <body>
+ <nav class="navbar navbar-expand-lg navbar-light bg-light">
+ <a class="navbar-brand" href="#">Navigation</a>
+ <button
+ class="navbar-toggler"
+ type="button"
+ data-toggle="collapse"
+ data-target="#navbarNav"
+ aria-controls="navbarNav"
+ aria-expanded="false"
+ aria-label="Toggle navigation"
+ >
+ <span class="navbar-toggler-icon"></span>
+ </button>
+ <div class="collapse navbar-collapse" id="navbarNav">
+ <ul class="navbar-nav">
+ <li class="nav-item active">
+ <a class="nav-link" href="/">IP & Domain Country Finder</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/ascii_to_char">ASCII Code Converter</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/utf8_decoder">UTF-8 Decoder</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/news">News</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/shodan">Shodan</a>
+ </li>
+ </ul>
+ </div>
+ </nav>
+
+ <div class="container">
+ <h1 class="mt-5 mb-5">Shodan Search</h1>
+ <form method="POST">
+ <div class="form-group">
+ <label for="query">IP / Domain</label>
+ <input
+ type="text"
+ class="form-control"
+ id="query"
+ name="query"
+ placeholder="Enter an IP address or a domain name"
+ />
+ </div>
+ <button type="submit" class="btn btn-primary">Search</button>
+ </form>
+ <hr />
+ {% if results %}
+ <h2 class="mt-5 mb-5">Results</h2>
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th>Key</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for match in results['matches'] %} {% for key, value in
+ match.items() %}
+ <tr>
+ <td>{{ key }}</td>
+ <td>{{ value }}</td>
+ </tr>
+ {% endfor %} {% endfor %}
+ </tbody>
+ </table>
+ {% endif %}
+ </div>
+ <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
+ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
+ </body>
+</html>
diff --git a/templates/utf8_decoder.html b/templates/utf8_decoder.html
@@ -33,11 +33,14 @@
<a class="nav-link" href="/ascii_to_char">ASCII Code Converter</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="/utf8_decoder">UTF-8 Decorder</a>
+ <a class="nav-link" href="/utf8_decoder">UTF-8 Decoder</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/news">News</a>
</li>
+ <li class="nav-item">
+ <a class="nav-link" href="/shodan">Shodan</a>
+ </li>
</ul>
</div>
</nav>
|