2012年3月30日 星期五

使用ASP呼叫C#寫的COM元件

相關文章,請 google keyword: c# 建立 com dll asp create object

目前專案有一個需求, 要把舊系統搬到ipv6 的環境下運作, 其中一個遇到的問題就是ftp 元件, 這次的目標是要寫一個跟舊系統一模一樣的 COM.


●【 Step 1 】
┃  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
┃ 先上 http://www.codeproject.com 取得一個別人寫好的 ftpclient class.
請 google keyword: codeproject ftpclient


●【 Step 2 】
┃  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
┃ 參考看看這篇教學文章:
┃ → http://smilelight-tw.blogspot.com/2011/06/c-dll-vb6.html
◆ 依照教學文章裡的步驟, 在 Assembly Information 裡的 COM-Visible checkbox 打勾.
◆ 設置(Build)項目屬性裡, 把註冊 COM Interop checkbox 打勾.


●【 Step 3 】
┃  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
┃ 上面文章沒有使用 簽名(Signing) 的功能, 所以在其他電腦註冊 com 元件時會出現下面的提示訊息:



◆ 解法很簡單, 請執行 sn.exe 指令, 產生簽名檔:
"C:\PROGRA~1\Microsoft SDKs\Windows\v7.0A\bin\sn.exe" -k c:\yourAppName.snk

◆ 在專案設定裡的 簽名(Signing) 分頁中選取剛才產生的 yourAppName.snk 文件.


●【 Step 4 】
┃  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
┃ 最後一個步驟了, 註冊C#寫的DLL是不能用regsvr32的,要用regasm,格式為:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /codebase  c:\yourProject\yourAppName.dll

如果程式寫錯, 要移除可以下指令:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /unregister c:\yourProject\yourAppName.dll






━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
◆ 結論 ◆
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. 幾乎大部份的 .net 寫的 class 都可以轉換成 com 供 asp 呼叫.
2. 請避免使用「多形」(Polymorphism)的 method, 舊系統對多形的支援度似乎不太好.
3. 請避免在「建構方法(建構式)」(Constructor)裡使用參數, 舊系統對建構式的支援度似乎不太好.
4. 可以使用在 ipv6 上的 ftp com 寫好了.

vb6 與 ipv6 多處無法支援

目前專案有一個需求, 要把舊系統搬到 ipv6 的環境下運作, 其中一個遇到的問題就是 ftp 元件, 我先挑戰使用 vb6 call Windows user mode API:

Public Declare Function FtpPutFile Lib "wininet.dll" Alias "FtpPutFileA" (ByVal hFtpSession As Long, ByVal lpszLocalFile As String, ByVal lpszRemoteFile As String, ByVal dwFlags As Long, ByVal dwContext As Long) As Boolean


在 ftp filezilla server 看到的 log 如下:
- (not logged in) (fe80::21f:29ff:feec:8116)> Connected, sending welcome message...
- (not logged in) (fe80::21f:29ff:feec:8116)> 220-FileZilla Server version 0.9.41 beta
- (not logged in) (fe80::21f:29ff:feec:8116)> 220-written by Tim Kosse (Tim.Kosse@gmx.de)
- (not logged in) (fe80::21f:29ff:feec:8116)> 220 Please visit http://sourceforge.net/projects/filezilla/
- (not logged in) (fe80::21f:29ff:feec:8116)> USER ipv6ftptest
- (not logged in) (fe80::21f:29ff:feec:8116)> 331 Password required for ipv6ftptest
- (not logged in) (fe80::21f:29ff:feec:8116)> PASS ***********
- ipv6ftptest (fe80::21f:29ff:feec:8116)> 230 Logged on
- ipv6ftptest (fe80::21f:29ff:feec:8116)> TYPE I
- ipv6ftptest (fe80::21f:29ff:feec:8116)> 200 Type set to I
- ipv6ftptest (fe80::21f:29ff:feec:8116)> EPRT |2|fe80::21f:29ff:feec:8116%10|1039|
- ipv6ftptest (fe80::21f:29ff:feec:8116)> 501 Syntax error, not a valid IPv6 address
- ipv6ftptest (fe80::21f:29ff:feec:8116)> disconnected.

說明: 使用 ipv6 的 address 是可以 login, 但是固定在 EPRT 指令時就會出錯, 但下這行指令是被手包在 API 裡無法修改, 結論: 改用 .net 開發, 這年頭好像沒有人在用 vb6 做開發...

2012年3月28日 星期三

出現在 HTTP_USER_AGENT 的 Blind SQL Injection 漏洞

出現在 HTTP_USER_AGENT 的 Blind SQL Injection 漏洞, 理論上這個情況是不會發現, 如果把 user agent 當作是一個 input, 而且執行的 web app "直接" 把 user-agent 的值 串成 sql 來執行, 就有可能發生 sql injection.

檢測報告的畫面:



修改方式, 透過下面的副程式把程式停掉, 或修改執行的流程即可.

sub checkHTTP_USER_AGENT()
dim isMatchPattern
isMatchPattern = not True

dim HTTP_USER_AGENT
HTTP_USER_AGENT = trim("" & Request.ServerVariables("HTTP_USER_AGENT"))

if not isMatchPattern then
if instr(HTTP_USER_AGENT,"'") > 0 then
isMatchPattern = true
end if
if instr(HTTP_USER_AGENT,"""") > 0 then
isMatchPattern = true
end if
end if

if isMatchPattern then
call EndAsp()
end if
end sub

2012年3月26日 星期一

Cross Site Scripting 攻擊的解法之一

要解決 Cross Site Scripting 方法很多,
下面示範一個範例+解法,


客戶的系統需要一個表單(Form):



我們寫的程式碼如下:



如果使用者輸入的值為: " onclick="alert(123)" bad="
執行出來的畫面如下:

說明: 去點輸入框, 真的會執行 alert(123)


執行出來的 html tag 如下:

說明: 紅色底線是我們輸入的值, 剛好可以做雙引號的跳脫.


===============================
解法如下:
1. 原本的程式碼:
<%=encodeInputBox(publisher)%>
修改為:
<%=encodeInputBox(publisher)%>


2.增加一個副程式:
function encodeInputBox(byval inputText)
if len(inputText) > 0 then
inputText=replace(inputText,"""","&#34;")
inputText=replace(inputText,"'","&#39;")
end if
encodeInputBox = inputText
end function


(修改後)執行出來的畫面如下:



(修改後)執行出來的 html tag 如下:



結論: 成功阻擋Cross Site Scripting 的攻擊.
心得: 這個 Cross Site Scripting 跟 SQL Injection 一樣, 都是直接執行了 user input 的文字裡有跳脫的控制字元, 只要處理一下 user input 的文字再輸出即可避開 Cross Site Scripting.

2012年3月19日 星期一

SqlDataReader 與 DbDataReader 的差別

資料來源:
http://social.msdn.microsoft.com/forums/en-US/adodotnetdataproviders/thread/a8ed157d-e93c-4a8d-83a4-78645614b4ac/

DamPee sad:
The IDataReader is an Interface. This means that it only contains a signature of the class structure. Every class which implements this interface need to implement the same methods.
In this way you can call any class and be sure that they all support the same functionality.

as MSDN states in the IDataReader, this interface
provides a means of reading one or more forward-only streams of result sets obtained by executing a command at a data source, and is implemented by .NET Framework data providers that access relational databases.
If you search for the members of the IDataReader, you will see that properties like e.g. IsClosed and RecordsAffected and also methods like e.g. Close, NextResult and Read should be implemented when a class derives from from the IDataReader interface.

The DBDataReader is a class which implements this interface. According to msdn
reads a forward-only stream of rows from a data source.
If you look at the signature of the DbDataReader class,

public abstract class DbDataReader : MarshalByRefObject, IDataReader,
IDisposable, IDataRecord, IEnumerable


you will notice that the DbDataReader implements the IDataReader interface. You can be sure that this class will have all methods as described in the IDataReader members.
But there is more. The DbDataReader class is a abstract class, which means that you can not create an object of this class (can not be instantiated). This is only intended to use as a base class for other classes. But is does implement already some functionality. Something which can not be done in an interface.

You can find on msdn the derived classes of the DbDataReader Class. You will find there the e.g. SqlDataReader class.

The SqlDataReader class inherits from the DbDataClass and adds some (Microsoft) SQL-server specific code. So, the SqlDataReader is a class which provides a way of reading a forward-only stream of rows from a (Microsoft) SQLServer database.

When to use: it depends on the situation, but most of the time you will use the SqlDataReader Class.
If you write your own dataobject you can interit from the abstract DbDataReader class. Or if you want to implement all code yourself and only need the functionanlity of the IDataReader interface, you use this one.
It is ofcourse possible to cast an object back to the interface if you don't know the exact type, but you do know that the interface is implemented. But that would take us a bit to far at this very moment.

網址裡的相對路徑 ..../../ = ./ 但 ../..../ 不等於 ..../../

網址裡的相對路徑 ..../../ = ./
但 ../..../ 不等於 ..../../
.../../ = ..../../

相關 html 語法的測試如下:

2012年3月16日 星期五

怎樣防止別人用ipc$和系統預設共享入侵

方案 A:一種辦法是把ipc$和系統預設共享都刪除了。但重起後還會有。這就需要改註冊表。
1. 先把已有的刪除
net share ipc$ /del
net share admin$ /del
net share c$ /del
…………(有幾個分割區刪幾個)

2. 禁止建立空連接
首先運行regedit, 設定主鍵[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA]把RestrictAnonymous(DWORD)的鍵值改為:00000001

3, 禁止自動打開系統預設共享
對於 windows server版, 設定主鍵[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters]把AutoShareServer(DWORD)的鍵值改為:00000000
對於 windows pro版, 則是[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters]把AutoShareWks(DWORD)的鍵值改為:00000000

方案 B:另一種是關閉ipc$和系統預設共享依賴的服務(不推薦)
net stop lanmanserver
可能會有提示說, XXX服務也會關閉是否繼續。因為還有些次要的服務依賴於lanmanserver。一般情況按y繼續就可以了。

利用getobject("WINNT")獲得了系統用戶和系統進程的列表, 這個列表可能會被駭客利用, 停用的方法是:
【開始→程序→管理工具→服務】, 找到Workstation, 停止它, 禁用它。


方案 C:最簡單的辦法是設置複雜密碼, 防止通過ipc$窮舉密碼。但如果你有其他漏洞, ipc$將為進一步入侵提供方便。

方案 D:還有一個辦法就是裝防火牆, 或者Port過濾(ipsec)
過配置本地策略來禁止139/445 Port的連接, 每一項服務都對應相應的Port, 比如眾如周知的WWW服務的Port是80, smtp是25, ftp是21。


附註: 上面4個方案, 只有 B方案對透過80 Port 進來的駭客有效, 因為駭客的程式是在本機上被執行。



第2關就是要禁止執行 shell command:
卸載 WScript 的元件, 透過下面的指令 卸載WScript:
regsvr32/u C:\WINNT\System32\wshom.ocx
regsvr32/u C:\WINNT\system32\shell32.dll


本機執行 asp 透過 ADSI, 取得本機帳號相關設定:



如果直接停用掉 Workstation 服務, 並設定相關依存的服務為手動啟動. 重新執行 asp, 新的執行畫面如下:



相關文章:
ADSI GetObject queries may fail from ASP but work from VBScript
http://support.microsoft.com/kb/278836/en-us

google 關鍵字:
asp GetObject WinNT://



建議解法:
1. 建議禁用 windwos 內建的 WScript 的 shell 元件.
2. 如果主機沒有在使用網芳功能的話, 停用掉 Workstation 服務.
3. web server, 不允許寫入的地方, 都要設定好禁止寫入.
4. 所有的上傳的程式, 在上傳時都要增加上傳副名的檢查, 禁止可以被執行的程式被上傳.
5. 建議別把帳號的密碼, 或密碼規則, 或密碼的提示放在 Description 欄位裡. 因為透過程式可以查詢的到, 而且如果程式在執行時權限夠大的話還可以重設某個帳號的密碼.
6. 有在使中的執行排程的帳號, 權限要設好, 最好是設成 Guest 的群組而且還可以完成專案交待的任務.
7. 透過 alert 通報機制, 使用小工具定時排程檢查主機上的程式內容 md5(檢查有無被修改) 與 資料夾的檔案清單(檢查有無被刪除或上傳).

2012年3月14日 星期三

char 0 在檔案上傳時對附檔名的影響

●【資料來源】
 ┃  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ┃ → http://wenku.baidu.com/view/362e2fd028ea81c758f578b5.html
 ┃ → http://www.hack50.com/stu/sort091/sort0103/63093.html


 ●【WinSock Expert 工具下載】
 ┃  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ┃ → http://www.dxqsoft.com/we/index.htm


 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ◆ 簡介 ◆
 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
一般的程式語言裡, 對字串的定義是遇到 “\0”(00)時, 就代表字串結束, 在 \0 (00) 之後的符號都會被乎略(刪除), 由於上傳檔案時可以修改 client 端的檔案名稱, 加入 \0, 讓上傳的程式誤判要上傳的檔案的附檔名.


 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ◆ 上傳元件測試 ◆
 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ●【TABS.Upload】
 ┃  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ◎ <source code>
 ┃
response.write "<br/>(upload object) filname: " & Form.FileName & vbcrlf
response.write "<br/>(upload object) filname len: " & len(Form.FileName) & vbcrlf
response.write "<br/>(upload object) filname binary len: " & lenb(Form.FileName) & vbcrlf
response.write "<br/>(upload object) filname right 4 char: " & right(Form.FileName,4) & vbcrlf
fullfilename = Form.FileName
response.write "<br/>(asp variable) filname right 4 char: " & right(cstr(fullfilename),4) & vbcrlf
 ┃
 ◎ <執行結果>
 ┃

說明: chr(0) 攻擊無效, 程式判斷 user 上傳的檔案是 .asp


 ●【UpDownExpress.FileUpload】
 ┃  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ◎ <source code>
 ┃
response.write "<br/>current upload object: UpDownExpress.FileUpload" & vbcrlf
response.write "<br/>(upload object) filname: " & xup.Attachments(1).FileName & vbcrlf
response.write "<br/>(upload object) filname len: " & len(xup.Attachments(1).FileName) & vbcrlf
response.write "<br/>(upload object) filname binary len: " & lenb(xup.Attachments(1).FileName) & vbcrlf
response.write "<br/>(upload object) filname right 4 char: " & right(xup.Attachments(1).FileName,4) & vbcrlf
fullfilename = xup.Attachments(1).FileName
response.write "<br/>(asp variable) filname right 4 char: " & right(cstr(fullfilename),4) & vbcrlf
 ┃
 ◎ <執行結果>
 ┃

說明: chr(0) 攻擊無效, 程式判斷 user 上傳的檔案是 .asp


 ●【ADODB.Stream】
 ┃  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ◎ <source code>
 ┃
response.write "<br/>(upload object) filname: " & xup.Form(uItem).FileName & vbcrlf
response.write "<br/>(upload object) filname right 4 char: " & right(xup.Form(uItem).FileName,4) & vbcrlf
response.write "<br/>(upload object) filname: " & xup.Form(uItem).FileName & vbcrlf
response.write "<br/>(upload object) filname len: " & len(xup.Form(uItem).FileName) & vbcrlf
response.write "<br/>(upload object) filname binary len: " & lenb(xup.Form(uItem).FileName) & vbcrlf
response.write "<br/>(upload object) filname right 4 char: " & right(xup.Form(uItem).FileName,4) & vbcrlf
fullfilename = xup.Form(uItem).FileName
response.write "<br/>(asp variable) filname right 4 char: " & right(cstr(fullfilename),4) & vbcrlf
 ┃
 ◎ <執行結果>
 ┃

說明: chr(0) 攻擊有效, 程式無法判斷 user 上傳的檔案是 .asp


 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ◆ 結論 ◆
 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1.透過 ADODB.Stream 自行開發的 upload component 需要針對 filename 多增加 chr(0) 的處理.
2.目前是透過 IIS 6 做測試, 比較舊的 IIS 5沒試過, 不確定測試結果是否一樣.
3.其他的程式語言, 沒試過, 不確定測試結果是否一樣.

2012年3月13日 星期二

php 無法輸出正確的 content type 的設定方式

; PHP's built-in default is text/html
default_mimetype = "text/html"

如果, 沒有把 buffering=Off 註解掉, content-type 都只能輸出為 text/html, 無法使用 text/xml, 設定方式參考下列的值:
; Output buffering allows you to send header lines (including cookies) even
; after you send body content, at the price of slowing PHP's output layer a
; bit. You can enable output buffering during runtime by calling the output
; buffering functions. You can also enable output buffering for all files by
; setting this directive to On. If you wish to limit the size of the buffer
; to a certain size - you can use a maximum number of bytes instead of 'On', as
; a value for this directive (e.g., output_buffering=4096).
;output_buffering = Off
output_buffering = 4096

2012年3月5日 星期一

A 站台的條列頁+內容頁,從 B站台取得.

需求: 假設 A站台(客戶網站), 與 B站台(可能是外部網站,或客戶的其他子網站)使用相同的架構. 現在 A 站的 99號節點,要顯示 B站台 33號節點內容. 很像是成語 "移花接木" 的感覺.

解法1: B 站台的資料, 倒進 A 站台.
說明:
1.讓 B站台提供 RSS,
2.在 A站台設排程讀取 B站台 RSS內容進 A站台 database 中.


解法2: A站台直接讀取 B站台 topic list 的資料.
說明:
1.在 A站台的節點(或主題單元) xml 設定檔設定 ExtraListUrl(條列頁) + ExtraDataUrl(內容頁) tag, 把 value 設定為 B站台的 topic list 資料.
2.修改 A站台的的 topic list 程式, 在輸出 topic list 先讀取看看 ExtraListUrl 有值的話, 就讀取 ExtraListUrl 裡設定的 URL 裡的值, 直接輸出.
3.修改 A站台的的 article 程式, 在輸出 article 先讀取看看 ExtraDataUrl 有值的話, 就讀取 ExtraDataUrl 裡設定的 URL 裡的值, 直接輸出.
4.調整要輸出的 block 裡的參數, 要把 B站台的識別用的參數(例如節點), 換成 A站台目前正被執行中的參數.


心得, 如果頁面在輸出時, 是套用 XML 來產生的話, 不同區塊的 block 可能可以直接與其他系統(ap)做共用, 但是這個架構有一個很大的缺點, 就是無法做 page 在 buffer 狀態下的 flush, 一定必須跑完所有的 block 所有的 code 之後, client 端的 browser才看的到畫面.

例如: 傳統的程式架構, 假設您輸出的 html 不是透過 table tag 輸出的情況下, 假設您有10個 block, 每一個 block 的處理時間需要1秒, 每一個 block 的 html 傳輸到 client 端的 browser , browser 可以直接顯示接收到部分的block, 意思是說 browser 可以每秒顯示出一個 block. 反之如果是用 xml + xsl 的架構, browser 只能在10秒後, 一次把10個block 顯示出來.

Facebook 留言板