JAVA /00檔案路徑截斷漏洞與分析for windows並對.NET比較

來源:互聯網
上載者:User

AUTHOR:kj021320
TEAM: I.S.T.O

JAVA WEB檔案上傳 是取使用者提交的檔案名稱字而不是從random取隨機器數字 就值得注意了
跟以前ASP+ADO.STREAM的上傳漏洞同理
因為 WINDOWS平台不支援 帶有/00字元的檔案目錄或者檔案名稱字
所以 JAVA雖然與平台無關 但是他底層操作的時候必定是調用平台的API 所以就會難免有些與平台關聯的
安全隱患或者漏洞令 JAVA語言開發人員不能一一顧及周全 OK 下面是一個簡單的代碼例子

String filepath="c://kj021320.jsp"+(char)0+".txt";
System.out.println(filepath);
FileOutputStream fos=new FileOutputStream(filepath);
fos.write("hello".getBytes());
fos.close();
byte [] b=new byte[100];
int i=0;
FileInputStream fis=new FileInputStream(filepath);
i=fis.read(b);
out.println(new String(b,0,i));
fis.close();

然後看看有什麼輸出。

OK 以上都做了代碼的測試 下面我們來分析JVM最終調用流程
來從源到內部核心實現
首先 分析FileOutputStream 類建構函式
//這個構造方法調用了 另一個建構函式
public FileOutputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null, false);
}
//以下就是被調用另外建構函式的具體實現
public FileOutputStream(File file, boolean append)throws FileNotFoundException
{
String name = (file != null ? file.getPath() : null);
SecurityManager security = System.getSecurityManager();
if (security != null) {
    security.checkWrite(name);//做安全檢查 JAVA沙箱裡面是否有許可權寫
}
if (name == null) {
    throw new NullPointerException();
}
fd = new FileDescriptor();
this.append = append;
if (append) {
    openAppend(name);//調用 openAppend
} else {
    open(name); //調用open
}
}

分析完了上面 FileOutputStream類裡面的2個構造方法 我們可以繼續跟蹤進去
看看 open openAppend的實現

private native void open(String name) throws FileNotFoundException;
private native void openAppend(String name) throws FileNotFoundException;
不過很讓我們遺憾。兩個方法都是本地代碼實現~ 到這裡就結束了嗎。不~  JDK6以前的原始碼SUN公司是沒有公布的。但是我們可以去下載
OPENJDK http://openjdk.java.net/ 裡面的全部原始碼估計都 大同小異的。
開啟 openjdk原始碼 openjdk/j2se/src/windows/native/java/io/FileOutputStream_md.c 目錄下面會有
FileOutputStream 這個類的JNI實現
Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this, jstring path) {
    fileOpen(env, this, path, fos_fd, O_WRONLY | O_CREAT | O_TRUNC);
}
調用了 fileOpen 繼續跟蹤進去,這個函數是在io_util_md.c 這個檔案裡面實現的
void fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags){
    jlong h = winFileHandleOpen(env, path, flags);
    if (h >= 0) {
        SET_FD(this, h, fid);
    }
}
看來又調用了 winFileHandleOpen 這個函數 估計裡面肯定也是調用WIN32API來建立檔案 不用說了,繼續

jlong winFileHandleOpen(JNIEnv *env, jstring path, int flags){
    const DWORD access =
 (flags & O_RDWR)   ? (GENERIC_WRITE | GENERIC_READ) :
 (flags & O_WRONLY) ?  GENERIC_WRITE :
 GENERIC_READ;
    const DWORD sharing =
 FILE_SHARE_READ | FILE_SHARE_WRITE;
    const DWORD disposition =
 /* Note: O_TRUNC overrides O_CREAT */
 (flags & O_TRUNC) ? CREATE_ALWAYS :
 (flags & O_CREAT) ? OPEN_ALWAYS   :
 OPEN_EXISTING;
    const DWORD  maybeWriteThrough =
 (flags & (O_SYNC | O_DSYNC)) ?
 FILE_FLAG_WRITE_THROUGH :
 FILE_ATTRIBUTE_NORMAL;
    const DWORD maybeDeleteOnClose =
        (flags & O_TEMPORARY) ?
        FILE_FLAG_DELETE_ON_CLOSE :
        FILE_ATTRIBUTE_NORMAL;
    const DWORD flagsAndAttributes = maybeWriteThrough | maybeDeleteOnClose;
    HANDLE h = NULL;

    if (onNT) {
        WCHAR *pathbuf = pathToNTPath(env, path, JNI_TRUE);
        if (pathbuf == NULL) {
            /* Exception already pending */
            return -1;
        }
        h = CreateFileW(
            pathbuf,  /* Wide char path name */
            access,  /* Read and/or write permission */
            sharing,  /* File sharing flags */
            NULL,  /* Security attributes */
            disposition,        /* creation disposition */
            flagsAndAttributes, /* flags and attributes */
            NULL);
        free(pathbuf);
    } else {
        WITH_PLATFORM_STRING(env, path, _ps) {
            h = CreateFile(_ps, access, sharing, NULL, disposition,
                           flagsAndAttributes, NULL);
        } END_PLATFORM_STRING(env, _ps);
    }
    if (h == INVALID_HANDLE_VALUE) {
        int error = GetLastError();
        if (error == ERROR_TOO_MANY_OPEN_FILES) {
            JNU_ThrowByName(env, JNU_JAVAIOPKG "IOException",
                            "Too many open files");
            return -1;
        }
        throwFileNotFoundException(env, path);
        return -1;
    }
    return (jlong) h;
}
//簡單看一下以上的代碼 最終都是調用 CreateFileW 來建立一個檔案
而他採用 pathToNTPath 這個函數來對路徑進行轉換裡面也沒有對/00字元過濾導致在windows平台下面這個漏洞

OK 那現在我們來看看.NET的表現。 首先分析他的檔案操作類
開啟一個 Reflector.exe 反編譯器 FileStream的建構函式太多我就不貼出來了 他最終會調用Path類的方法進行驗證
internal static void CheckInvalidPathChars(string path)
{
    if (-1 != path.IndexOfAny(InternalInvalidPathChars))
    {
        throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars"));
    }
}
以上代碼 如果包含了非法字元。會拋出一個異常~
看看 InternalInvalidPathChars 是怎麼定義的
InternalInvalidPathChars = new char[] { '"', '<', '>', '|', '/0', '/b', '/x0010', '/x0011', '/x0012', '/x0014', '/x0015', '/x0016', '/x0017', '/x0018', '/x0019' };
呵呵 看來 .NET 在 MS平台上面做得更充分

呵呵。 YY一下
WINDOWS:"555~~JAVA你不懂我的心。"
JAVA:"汗~~~......"
.NET:"我的地盤我做主...嘎嘎"
 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.