vpn otp 폼 입력값 기반으로 제출
This commit is contained in:
+69
-2
@@ -191,6 +191,71 @@ runs:
|
|||||||
curl -k -sS --http1.1 -A "$UA" "$@"
|
curl -k -sS --http1.1 -A "$UA" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
build_otp_post_body() {
|
||||||
|
python3 - "$1" "$2" <<'PY'
|
||||||
|
from html.parser import HTMLParser
|
||||||
|
import sys
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
html_file, otp_code = sys.argv[1], sys.argv[2]
|
||||||
|
|
||||||
|
class FormParser(HTMLParser):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.forms = []
|
||||||
|
self.current = None
|
||||||
|
|
||||||
|
def handle_starttag(self, tag, attrs):
|
||||||
|
attrs = {k.lower(): (v if v is not None else "") for k, v in attrs}
|
||||||
|
if tag.lower() == "form":
|
||||||
|
self.current = {"attrs": attrs, "inputs": []}
|
||||||
|
self.forms.append(self.current)
|
||||||
|
elif tag.lower() == "input" and self.current is not None:
|
||||||
|
self.current["inputs"].append(attrs)
|
||||||
|
|
||||||
|
def handle_endtag(self, tag):
|
||||||
|
if tag.lower() == "form":
|
||||||
|
self.current = None
|
||||||
|
|
||||||
|
parser = FormParser()
|
||||||
|
with open(html_file, encoding="utf-8", errors="ignore") as f:
|
||||||
|
parser.feed(f.read())
|
||||||
|
|
||||||
|
form = None
|
||||||
|
for candidate in parser.forms:
|
||||||
|
names = {field.get("name", "") for field in candidate["inputs"]}
|
||||||
|
if "ga_code_attempt" in names:
|
||||||
|
form = candidate
|
||||||
|
break
|
||||||
|
if form is None:
|
||||||
|
raise SystemExit("OTP form not found")
|
||||||
|
|
||||||
|
data = []
|
||||||
|
seen = set()
|
||||||
|
for field in form["inputs"]:
|
||||||
|
name = field.get("name", "")
|
||||||
|
if not name:
|
||||||
|
continue
|
||||||
|
field_type = field.get("type", "text").lower()
|
||||||
|
if field_type in {"button", "image", "file"}:
|
||||||
|
continue
|
||||||
|
if field_type in {"checkbox", "radio"} and "checked" not in field:
|
||||||
|
continue
|
||||||
|
value = field.get("value", "")
|
||||||
|
if name == "ga_code_attempt":
|
||||||
|
value = otp_code
|
||||||
|
data.append((name, value))
|
||||||
|
seen.add(name)
|
||||||
|
|
||||||
|
if "ga_code_attempt" not in seen:
|
||||||
|
data.append(("ga_code_attempt", otp_code))
|
||||||
|
if "vhost" not in seen:
|
||||||
|
data.append(("vhost", "standard"))
|
||||||
|
|
||||||
|
print(urllib.parse.urlencode(data))
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
debug_print_otps() {
|
debug_print_otps() {
|
||||||
echo "DEBUG OTP 확인용 코드 (unix-time=$(date +%s))"
|
echo "DEBUG OTP 확인용 코드 (unix-time=$(date +%s))"
|
||||||
for otp_offset in 0 -1 1; do
|
for otp_offset in 0 -1 1; do
|
||||||
@@ -255,12 +320,14 @@ runs:
|
|||||||
if [ "$DEBUG_OTP" = "true" ]; then
|
if [ "$DEBUG_OTP" = "true" ]; then
|
||||||
echo "DEBUG generated OTP offset=${otp_offset}: ${OTP_CODE} (unix-time=$(date +%s))"
|
echo "DEBUG generated OTP offset=${otp_offset}: ${OTP_CODE} (unix-time=$(date +%s))"
|
||||||
fi
|
fi
|
||||||
|
OTP_POST_BODY="$WORKDIR/03-otp-post-${otp_offset}.body"
|
||||||
|
build_otp_post_body "$WORKDIR/02-otp.html" "$OTP_CODE" > "$OTP_POST_BODY"
|
||||||
rm -f "$TOKEN_HEADERS" "$WORKDIR/04-token.body"
|
rm -f "$TOKEN_HEADERS" "$WORKDIR/04-token.body"
|
||||||
|
|
||||||
curl_common -L -b "$COOKIE_JAR" -c "$COOKIE_JAR" \
|
curl_common -L -b "$COOKIE_JAR" -c "$COOKIE_JAR" \
|
||||||
-X POST "$VPN_HOST/my.policy" \
|
-X POST "$VPN_HOST/my.policy" \
|
||||||
--data-urlencode "ga_code_attempt=$OTP_CODE" \
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||||
--data-urlencode "vhost=standard" \
|
--data-binary "@$OTP_POST_BODY" \
|
||||||
-o "$WORKDIR/03-webtop-${otp_offset}.html"
|
-o "$WORKDIR/03-webtop-${otp_offset}.html"
|
||||||
|
|
||||||
curl_common -b "$COOKIE_JAR" -c "$COOKIE_JAR" \
|
curl_common -b "$COOKIE_JAR" -c "$COOKIE_JAR" \
|
||||||
|
|||||||
Reference in New Issue
Block a user