Archive

Archive for February, 2015

อ่านบัตรประชาชน smartcard โดยใช้ python

February 8th, 2015 8 comments

ผมเขียนเรื่องนี้สำหรับเป็น guideline สำหรับคนที่อยากอ่านข้อมูลในบัตรประชาชนนะครับ

ข้อมูลทั้งหมดได้มาจากคุณพุฒิพงศ์ ซึ่งเป็นคนพัฒนาโปรแกรม นี้ ครับ

ผมเมลไปถามแกหน้าด้าน ๆ เลยครับว่าทำยังไง แกก็ตอบมาแบบละเอียดเลยครับ

เลยไหน ๆ ก็ไหน ๆ ละขอเขียนทิ้งไว้ก็แล้วกันครับเผื่อมีคนอยากทราบวิธี

ผมใช้ lib ของ python pyscard ครับ วิธีการใช้ดูจาก documentation เลยครับ

ตัวอย่างเป็นการอ่านข้อมูลในส่วน public ของ smart card

# -*- coding: cp874 -*-
from smartcard.CardConnection import CardConnection
from smartcard.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.util import toHexString, toBytes

import ธรรมดาครับ

cardtype = AnyCardType()
cardrequest = CardRequest( timeout=1, cardType=cardtype )

cardservice = cardrequest.waitforcard()

cardservice.connection.connect()

เชื่อมต่อไปยัง reader ดูว่ามีการ์ดเสียบอยู่นะ

SELECT = [0x00, 0xA4, 0x04, 0x00, 0x08]
THAI_ID_CARD = [0xA0, 0x00, 0x00, 0x00, 0x54, 0x48, 0x00, 0x01]
REQ_CID = [0x80, 0xb0, 0x00, 0x04, 0x02, 0x00, 0x0d]
REQ_THAI_NAME = [0x80, 0xb0, 0x00, 0x11, 0x02, 0x00, 0x64]
REQ_ENG_NAME = [0x80, 0xb0, 0x00, 0x75, 0x02, 0x00, 0x64]
REQ_GENDER = [0x80, 0xb0, 0x00, 0xE1, 0x02, 0x00, 0x01]
REQ_DOB = [0x80, 0xb0, 0x00, 0xD9, 0x02, 0x00, 0x08]
REQ_ADDRESS = [0x80, 0xb0, 0x15, 0x79, 0x02, 0x00, 0x64]
REQ_ISSUE_EXPIRE = [0x80, 0xb0, 0x01, 0x67, 0x02, 0x00, 0x12]

DATA = [REQ_CID,REQ_THAI_NAME,REQ_ENG_NAME,REQ_GENDER,REQ_DOB,
REQ_ADDRESS,REQ_ISSUE_EXPIRE]

ตรงนี้เป็นคำสั่งในการขอข้อมูลครับ คือ ขั้นตอนการขอข้อมูลจากการ์ดจะเป็น

1. ฉันจะอ่านบัตรประชาชนนะนายใช่บัตรประชาชนรึเปล่า
2. บัตรตอบมาว่าใช่หรือไม่
3. โอเค ฉันอยากได้ข้อมูลเลข 13 หลักที่มีความยาว x
4. บัตรตอบกลับมาว่าฉันมีข้อมูลนี้ ยาว x
5. ขอดูข้อมูลหน่อยละกัน
6. บัตรส่งข้อมูลให้

apdu = SELECT+THAI_ID_CARD
f = open(‘temp.txt’,’w’)

response, sw1, sw2 = cardservice.connection.transmit( apdu )
#print ‘response: ‘, response, ‘ status words: ‘, “%x %x” % (sw1, sw2)

อันนี้เป็นข้อ 1-2 ครับ ดูตรง sw1 กับ sw2 ครับ ถ้าโอเคจะตอบกลับมาเป็น

0x90 xx หรือ 0x61 xx ซึ่ง 90 คือโอเค ส่วน 61 คือ โอเคแต่มีข้อมูล xx ไบต์นะ

#print ‘response: ‘, response, ‘ status words: ‘, “%x %x” % (sw1, sw2)
for d in DATA:
response, sw1, sw2 = cardservice.connection.transmit( d )
print sw1
if sw1 == 0x61:

ไล่ขอข้อมูลใน list DATA ส่วนนี้สังเกตว่าบัตรตอบกลับมาว่า 0x61 มีข้อมูลอีก xx นะ
เริ่มจาก cid

GET_RESPONSE = [0X00, 0XC0, 0x00, 0x00 ]
apdu = GET_RESPONSE + [sw2]

ตรงนี้ขอดูข้อมูลที่บอกว่ามีหน่อย

print ‘sending ‘ + toHexString(apdu)
response, sw1, sw2 = cardservice.connection.transmit( apdu )
print ‘response: ‘, toHexString(response), ‘ status words: ‘, “%x %x” % (sw1, sw2)
result = “”
for i in response:
result = result+chr(i)
f.write(result.strip()+”\n”)

ส่วนนี้แค่ไล่อ่านจนครบทุกข้อมูล จริง ๆ จะมีรูปภาพอีกครับแต่ไม่ได้ทำไว้เพราะอายุบัตรค่อนข้างนาน

รูปในบัตรจะดูห่างจากตัวจริงเยอะไป


Categories: Programming Tags:

ความปลอดภัยของ mail server

February 6th, 2015 Comments off

ปัญเอิญเมลที่ทำงานมีปัญหามีเมลตีกลับแบบนี้ครับ

This message was created automatically by mail delivery software.

A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) failed:

This message was created automatically by mail delivery software.

A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) failed:

xxx@gmail.com

Unrouteable address

Google เจอว่าไอ้ Unrouteable address นี่หลัก ๆ แล้วเกิดจากการที่ ส่งเมลเกินโควต้าที่ทำหนดใน server

ซึ่งผมลองส่งเมลโดยใช้ telnet ส่งเมลได้โดยไม่ต้อง authen ครับ สรุปคงมีคนแอบใช้ไปส่งเมลอื่น ๆ จนเกินโควต้าจนเกิด error ดังกล่าวขึ้นครับ

ซึ่งเราสามารถกำหนด เมลผู้ส่ง ผู้รับได้ตามใจ ถามว่าอันตรายมากไหมก็ไม่มากครับแต่อาจจะเอาไปประยุกต์ใช้
เกี่ยวกับพวก spam หรือ phishing ได้ วิธีแก้ก็ให้ทาง hosting config ให้ authen ก่อนส่งเมลทุกครั้งครับ

Categories: Security Tags: