16-09-06

本日のコード(1)[Python]

# 何もimportする必要がない
table_name = "my_name_is_table"
enc = table_name.encode("hex")
print(enc)
print(enc.decode("hex"))

phrase = "this_phrase_is_yours"
cip = phrase.encode("rot_13")
print(cip.decode("rot_13"))

# rot_47はない
# print(phrase.encode("rot_47"))    # LookupError

msg = "flag{actually_num_of_chars_is_65}"
b64 = msg.encode("base64")
print(b64)
print(b64.decode("base64"))

何もimportする必要がない。

Write-upを読んだ(1)

Internetwache CTF 2016 : The Secret Store

Column truncation attackについての問題。
以下、簡易的に環境を作ってみる(MySQL)。

-- ユーザー名とパスワードに文字数制限がある
-- (というかそのようなカラムを定義する)
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
username VARCHAR(32) NOT NULL,
password VARCHAR(64) NOT NULL,
is_admin BOOLEAN NOT NULL,
PRIMARY KEY(id)
);

-- adminを登録しておく
INSERT INTO users VALUES(NULL, "admin", "honyarara", true);
<!-- トップページ -->
<body>
    
    <!-- ログインフォーム -->
    <p>Login</p>
    <form action="./login.php" method="POST">
        Username: <input type="text" name="username"><br>
        Password: <input type="password" name="password"><br>
        <input type="submit" value="Login">
    </form>

    <!-- 新規登録 -->
    <p>Create new account</p>
    <form action="./createac.php" method="POST">
        Username: <input type="text" name="username"><br>
        Password: <input type="password" name="password"><br>
        <input type="submit" value="Create new account">
    </form>

</body>
<?php
/* login.php */
/* ログインページ */
$username = @$_POST["username"];
$password = @$_POST["password"];
if ($username == false or $password == false) {
    die("Login failed");
}

/* DB接続 */
$dsn = "mysql:host=localhost;dbname=drill1;" .
    "charset=utf8";
$db = new PDO($dsn, $dbuser, $dbpass);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db->setAttribute(PDO::ATTR_ERRMODE,
    PDO::ERRMODE_EXCEPTION);

/* ユーザーを検索 */
$sql = $db->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$sql->execute([$username, $password]);
$result = $sql->fetchAll();
if (count($result) > 0) {
    echo "Login user: " . htmlspecialchars($username,
        ENT_QUOTES, "UTF-8") . "<br>";
    echo "Password: " . str_repeat("*", strlen($password)) . "<br>";
} else {
    die("Login error\n");
}

/* 接続を閉じる */
$stmt = null;
$db = null;
?>
<?php
/* createac.php */
/* 会員を登録する */
$username = @$_POST["username"];
$password = @$_POST["password"];
if ($username == false or $password == false) {
    die("Login failed");
}

/* DB接続 */
$dsn = "mysql:host=localhost;dbname=drill1;" .
    "charset=utf8";
$db = new PDO($dsn, $dbuser, $dbpass);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db->setAttribute(PDO::ATTR_ERRMODE,
    PDO::ERRMODE_EXCEPTION);

/* ユーザーを検索 */
$sql = $db->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$sql->execute([$username, $password]);
$result = $sql->fetchAll();
if (count($result) > 0) {
    echo "Login user: " . htmlspecialchars($username,
        ENT_QUOTES, "UTF-8") . "<br>";
    echo "Password: " . str_repeat("*", strlen($password)) . "<br>";
} else {
    die("Login error\n");
}

/* 接続を閉じる */
$stmt = null;
$db = null;
?>

上の環境でusername="admin" + " " * 27 + "x"(33文字)を登録すると、
DB内では(カラムが最大32文字のため)ユーザー名が"admin"として登録される。
本来ならhtml&サーバー側で値の文字数をチェックする。