セキュリティ

C で、バイト列を画面に文字列で表示する方法

ここでは、作成したバイト列(バイナリ)のハッシュ値を表示する方法を考えてみよう。

#include #include #include int main(int argc, char** argv) {
unsigned char hash[SHA_DIGEST_LENGTH];
unsigned char* b;
unsigned char* s = "string string string";
int i, dlen;

dlen = strlen(s);

if ((b = (unsigned char *)malloc(dlen)) == NULL) {
    return (-1);
}

memcpy(b, s, dlen);
SHA1(b, dlen, hash);
printf("hash: ");
<strong>for(i = 0; i < SHA_DIGEST_LENGTH; i++) {
printf("%02X", *(hash + i));
}</strong>
printf("\n");
free(b);
}

上の内容を hashtest.c とかいう名前で保存して、

gcc -lssl hashtest.c

とコンパイルすればよい。コンパイルすると a.out というファイルができるから ./a.out [Enter キー] で実行してみよう。

続きを読む

ウェブサイト構築時のセキュリティのポイント

IPA(独立行政法人情報処理推進機構)の「安全なウェブサイトの作り方」というドキュメントは、なかなかまとまっていて、良い。すべてのウェブアプリ開発者は目を通しておくべきだ。ここではこのドキュメントから注意点をピックアップしてまとめてみた。

  1. SQL インジェクション
  2. OS コマンド・インジェクション
  3. パス名パラメータの未チェック/ディレクトリ・トラバーサル
  4. セッション・ハイジャック
  5. クロスサイト・スクリプティング
  6. クロスサイト・リクエスト・フォージェリ (CSRF)
  7. HTTP ヘッダ・インジェクション
  8. メールの第三者中継

続きを読む

SSL/TLS の暗号化通信シーケンス

インターネットで最も使われている暗号化通信は SSL/TLS であろう。SSL は Secure Socket Layer の略で、TLS は Transport Layer Security の略、前者はバージョン3まで Netscape によって作られ、後者は IETF で仕様が策定されているものである。

続きを読む

PHP で、sha1 のハッシュ値を求める方法

以下のコードを参考のこと。sha1 なので 160ビットの固定長の値は仕様であり、画面への出力は 40バイト固定長の16進数の文字列である(160ビット=160 / 8ビット=バイナリ 20バイト→人間の目に見える形式だとテキスト文字列 40バイト)。

<?php $content = "ここに HTML などのコンテンツが入る"; $digest = sha1($content); // コンテンツのハッシュ値 (16進数) print $digest; ?>
続きを読む

Perl で、JavaScript と連動してサーバにアクセスログを残す方法

ウェブページへのアクセスログを記録する方法は、いろいろな方法があると思う。もっとも簡単なのは Apache などのウェブサーバが自動的に記録するログをチェックすることで、これには何の手間もいらない。しかし、レンタルサーバなどでログが自由に扱えない場合はどうしたらいいのだろう?

そのひとつが、画像としてリンクされている Perl などの CGI を呼び出す方法だ。利用者に知られずこっそりとアクセスログを取るには 1x1 ピクセルの画像をそのウェブページの背景と共に表示してしまえば、そのウェブページのソースをチェックされない限り、ほとんどの場合は気づかれずにすむだろう。

そんなわけで、以下のように JavaScript と対応する Perl スクリプトで、アクセスログを記録する仕組みを作ってみた。ログの形式は Apache に準拠する(たぶん)。

続きを読む

Visual C++ (Win32) で、SHA1 のハッシュ値を取得する方法

以下がサンプルコード。Win32 Crypto API を使うコンソールアプリです。

// HashTest.cpp : Defines the entry point for the console application. // Copyright (c) 2005, 2006 twinkle.cc All Rights Reserved. // https://perltips.twinkle.cc/ // perltips@gmail.com #include "stdafx.h" #include #include #include int _tmain(int argc, _TCHAR* argv[]) {
#define BUFFER_LEN 253
#define SHA1LEN  20

PCHAR    pcMessage;
DWORD    ccMessage;

DWORD dwStatus = 0;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
BYTE pbHash[SHA1LEN];
BYTE pbRandom[BUFFER_LEN];
DWORD cbHash = 0;
CHAR pcDigits[] = "0123456789ABCDEF";
CHAR pcHash[SHA1LEN * 2 + 1];

//Get handle to the crypto provider
if (!CryptAcquireContext(&hProv,
    NULL,
    NULL,
    PROV_RSA_FULL,
    CRYPT_VERIFYCONTEXT))
{
    dwStatus = GetLastError();
    goto done;
}

// Get a random value
if( CryptGenRandom(
    hProv,
    BUFFER_LEN,
    pbRandom))
{
    printf("%d bytes of random data have been generated.\n", BUFFER_LEN);
}
else
{
    dwStatus = GetLastError();
    printf("Random bytes were not correctly generated.\n");
    goto done;
}

if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
{
    dwStatus = GetLastError();
    goto done;
}

if (!CryptHashData(hHash, pbRandom, BUFFER_LEN, 0))
{
    dwStatus = GetLastError();
    printf("CryptHashData failed: %d\n", dwStatus); 
    goto done;
}

cbHash = SHA1LEN;
if (CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &cbHash, 0))
{
    printf("SHA1 hash is: ");
    for (DWORD i = 0; i < cbHash; i++)
    {
        pcHash[i * 2]      = pcDigits[pbHash[i] >> 4];
        pcHash[i * 2 + 1 ] = pcDigits[pbHash[i] & 0xf];
        pcHash[i * 2 + 2 ] = '\0';
    }
    printf("%s\n", pcHash);
}
else
{
    dwStatus = GetLastError();
    printf("CryptGetHashParam failed: %d\n", dwStatus); 
}

done:

CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);

WCHAR pwcMessage[BUFFER_LEN];
MultiByteToWideChar(CP_ACP, 0, pcHash, sizeof(pcHash), pwcMessage, sizeof(pwcMessage));
ccMessage = ( DWORD ) wcslen( pwcMessage );

if( ( pcMessage = ( PCHAR ) malloc( ccMessage + 1 ) ) )
{
    WideCharToMultiByte( CP_ACP, 0, pwcMessage, -1, pcMessage, ccMessage + 1, NULL, NULL );
    printf("malloc ok: %s\n", pcMessage);
}
else
{
    printf("Not enough memory");
    dwStatus = ERROR_NOT_ENOUGH_MEMORY;
}

return dwStatus;
}
続きを読む

Perl で、RADIUS クライアントを作る。

Radius サーバに接続するためには、そのホスト名とシークレットが必要である。シークレットは Radius サーバへのパスワードみたいなもの。以下のコードでは $r に Radius クライアントのオブジェクトが入り、その後で $USENAME と $PASSWORD を使って $HOST にアクセスしている。

使用するモジュール use Authen::Radius; #!/usr/bin/perl use Authen::Radius; our $HOST = '1.1.1.1'; our $USERNAME = 'perltips'; our $PASSWORD = 'password'; our $SECRET = 'testing123'; # First Trial $r = new Authen::Radius(Host => $HOST,
                    Secret => $SECRET,
                    Debug  => 1,
                    TimeOut=> 10);
# 前座。ユーザー名とパスワードのチェックをしてみる。 print "auth result=", $r->check_pwd($USERNAME,
                                $PASSWORD,
                                $HOST), "\n";
# Authen::Radius->load_dictionary(); # 本番。ユーザー名とパスワードのチェックを設定する。 $r->add_attributes (
            { Name => 'UserName',       Value => $USERNAME },
            { Name => 'Password',       Value => $PASSWORD },
# { Name => 'NAS-IP-Address', Value => '1.1.1.2' } # # RFC 2865 https://www.ietf.org/rfc/rfc2865.txt calls this attribute # User-Password. Check your local RADIUS dictionary to find ); # ユーザー名とパスワードの組み合わせ (アトリビュート:属性) を、ACCESS_REQUEST で送る。 # そうすると返事が返って来るので recv_packet で受け取る。 $r->send_packet(ACCESS_REQUEST) and $type = $r->recv_packet(); print "server response type = $type\n"; # サーバから送られてきたアトリビュートを表示してみる。 for $a ($r->get_attributes()) {
    print "attr: name=$a->{'Name'} value=$a->{'Value'}\n";
}
続きを読む

Perl で、.htaccess のパスワードを生成する方法

Apache の場合の基本認証(BASIC 認証)、.htaccess の仕組みで使うパスワードは Perl で生成できる。

以下のコードを実行するとユーザー名「guest」に対するパスワード「password」は、毎回違った暗号文字列が出力されるが、それでも Apache はきちんと処理する。

#!/usr/bin/perl our $id = 'guest'; our $password = 'password'; our $password_file = '.htpasswd'; # Perl の crypt 関数に使える SALT の文字は a~z、A~Z、0~9、「.」と「/」 my @salt = ('a'..'z','A'..'Z','0'..'9','.','/'); #乱数初期化関数は srand srand; # SALT を作る。 my $seed1 = int(rand(64)); my $seed2 = int(rand(64)); my $salt = $salt[$seed1] . $salt[$seed2]; # crypt 関数の仕様は crypt(テキスト, SALT) $crypt_password = crypt($password, $salt); # .htpasswd ファイルに書き出す。 open(OUT, ">$password_file") || die; print OUT "$id:$crypt_password\n"; close(OUT); # 表示してみる。 print "$id:$crypt_password\n";

1つのパスワードに対する暗号化された文字列の種類は 4,096通りある。これは、アルファベット小文字 26 通り+アルファベット大文字 26 通り+数字 10 通り+記号 2 通り=64 通りで、SALT は 2文字で構成されるため、64×64 = 4,096 通り、ということからくる。

続きを読む
セキュリティ を購読