2015-11-06 16 views
21

TL; DR token của user có thể chứa trong một Token tài sản (ví dụ, someIdentity.Token) WindowsIdentity 's được giả mạo như vậy:Có thể đánh lừa mã WindowsIdentity này bằng cách sử dụng sai người dùng không?

var validated = new WindowsIdentity(someIdentity.Token); 

... sẽ trở lại một trường hợp mà tuyên bố để đại diện cho một người dùng trên thực tế, chưa được xác thực, và chưa có IsAuthenticated đặt true, hợp lệ .Name.User thuộc tính, v.v ...?

Dưới đây tôi đặt một vài ranh giới về điều này; có lẽ không thể hoàn toàn chống giả mạo.


Câu chuyện đầy đủ:

Trong this answer, Damien_The_Unbeliever khéo léo chứng minh rằng một số mã của tôi có thể bị lừa tin rằng nó đã có một người dùng xác thực hợp lệ trong một trường hợp WindowsIdentity khi nó thì không. Dài truyện ngắn, mã của tôi đã giả định rằng nếu Thread.CurrentPrincipal.Identity là một thể hiện của WindowsIdentityIsAuthorizedtrue, mà nó đại diện cho một người dùng xác thực và tôi có thể dựa vào các SID trong .User:

WindowsIdentity identity = Thread.CurrentPrincipal == null 
    ? null 
    : Thread.CurrentPrincipal.Identity as WindowsIdentity; 

if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) { 
    // ...use and trust the SID in identity.User, the 
    // username in identity.Name, etc.... 
} 

(Có một lý do mã này . đang sử dụng các chủ đề chứ không phải là WindowsIdentity.GetCurrent())

mã của mình để lừa đó (thay đổi chút ít):

var ident = WindowsIdentity.GetCurrent(); 
Thread.CurrentPrincipal = new WindowsPrincipal(ident); 
var fakeSid = new SecurityIdentifier("S-1-3-0"/* E.g., some SID you want to trick me into believing is the real user */); 
typeof(WindowsIdentity).GetField("m_user", BindingFlags.Instance | BindingFlags.NonPublic) 
    .SetValue(ident, fakeSid); 

Và chắc chắn eno ugh, nếu bạn làm điều đó thì hãy gọi mã của tôi ở trên, mã của tôi bị lừa. Kudos Damien.

Vì vậy, trong thời trang thật sự chạy đua vũ trang, đây là mã sửa đổi của tôi mà bắt spoof và phủ nhận nó:

WindowsIdentity identity = Thread.CurrentPrincipal == null 
    ? null 
    : Thread.CurrentPrincipal.Identity as WindowsIdentity; 

if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) { 
    var validated = new WindowsIdentity(identity.Token); 
    if (!validated.User.Equals(identity.User) || !validated.IsAuthenticated || validated.IsAnonymous) { 
     // Something fishy is going on, don't trust it 
    } else { 
     // Good! Use the validated one 
     identity = validated; 
     // ...use and trust the SID in identity.User, the 
     // username in identity.Name, etc.... 
    } 
} 

Như bạn thấy, mà mất Token từ bản sắc được cung cấp và tạo ra một mớiWindowsIdentity bằng cách sử dụng mã thông báo đó. Nếu các SID của danh tính khớp nhau, chúng tôi tiếp tục, tin tưởng vào một SID được xác thực. (Các documentation for WindowsIdentity(IntPtr token) nói rằng giá trị ban đầu của IsAuthenticated sẽ false, nhưng điều đó chỉ đơn giản là sai trong các thử nghiệm của tôi giả sử tôi đã tạo ra nó với một mã thông báo người dùng hợp lệ.)

Cách duy nhất tôi có thể thấy rằng có thể bị lừa sẽ với một mã thông báo người dùng giả mạo mà vẫn vượt qua các xác nhận hợp lệ của Windows với nó. Điều đó dường như không xảy ra với tôi. Nhưng sau đó, đây là một lĩnh vực vô minh đối với tôi.


Ranh giới:

Tôi nên lưu ý rằng tôi chỉ chụp cho một mức độ single sign-on an ninh ở đây, làm dilience do của tôi. Nếu một ứng dụng độc hại đã khởi động thành công việc chặn các cuộc gọi hệ thống/Windows bị xâm phạm, thì không có nhiều khả năng tôi sẽ làm được điều đó.Như Damien đã chỉ ra trong các bình luận về câu hỏi khác, anh ta có lẽ có thể xây dựng một container chứa hoàn toàn bỏ qua việc đặt tên mạnh (và do đó có thể cho tôi một loại hoàn toàn giả mạo WindowsIdentity). Đủ công bằng. Sự hoàn hảo giết chết. Tôi chỉ không muốn để cánh cửa mở ra như một chiếc Damien vui lòng chứng minh. Nếu tôi phát hành một hệ thống và nó đã bị tấn công trong lĩnh vực đó một cách dễ dàng, tôi sẽ khá xấu hổ về điều đó. :-)

+4

Ngoài khả năng của tôi để trả lời, nhưng câu hỏi tuyệt vời! Vui mừng khi thấy câu trả lời được đưa ra :) – levelonehuman

+0

@levelonehuman Suy nghĩ của tôi chính xác! –

+2

"Skeet không làm hỏng tôi ngay bây giờ!" ;-) –

Trả lời

6

Để chứng minh điều này là có thể thực hiện được, hãy sử dụng tiện ích bổ sung Visual Studio có tên "Microsoft Fakes" (tên chính nó có nghĩa là rất nhiều ...).

Chính sách giả mạo được gắn với các tính năng thử nghiệm của Visual Studio, nhưng nó sẽ chứng minh điểm. Bạn có thể làm theo các hướng dẫn chuẩn để thiết lập một dự án, và thêm một bản lắp ráp cho Hệ thống (trong thực tế hệ thống mscorlib +)

Đây là mã của bạn trong một dự án thư viện (tôi đã sử dụng ngoại lệ ở khắp mọi nơi vì điều kiện kiểm tra dễ dàng hơn ...).

namespace ClassLibrary1 
{ 
    public class Class1 
    { 
     public static void MyCheck() 
     { 
      WindowsIdentity identity = Thread.CurrentPrincipal == null 
       ? null 
       : Thread.CurrentPrincipal.Identity as WindowsIdentity; 

      if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) 
      { 
       var validated = new WindowsIdentity(identity.Token); 
       if (!validated.User.Equals(identity.User) || !validated.IsAuthenticated || validated.IsAnonymous) 
        throw new Exception("Something fishy is going on, don't trust it"); 
       else 
        throw new Exception("Good! Use the validated one. name is:" + validated.Name); 
      } 
      else 
       throw new Exception("not in"); 
     } 
    } 
} 

Đây là mã thử nghiệm trong dự án thử nghiệm:

namespace UnitTestProject1 
{ 
    [TestClass] 
    public class UnitTest1 
    { 
     [TestMethod] 
     public void TestMethod1() 
     { 
      using (ShimsContext.Create()) 
      { 
       System.Security.Principal.Fakes.ShimWindowsIdentity.AllInstances.NameGet = (i) => 
       { 
        return "Simon the hacker"; 
       }; 

       WindowsIdentity wi = WindowsIdentity.GetCurrent(); // this is the real one "Simon". 
       Thread.CurrentPrincipal = new WindowsPrincipal(wi); 

       Class1.MyCheck(); 
      } 
     } 
    } 
} 

Đây là cách bố trí dự án trong Visual Studio:

enter image description here

Ngoài ra hãy chắc chắn rằng bạn thay đổi mscorlib. tệp giả tạo được tạo tự động như sau:

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/" Diagnostic="true" TargetFrameworkVersion="v4.6"> 
    <Assembly Name="mscorlib" /> 
    <ShimGeneration> 
    <Clear /> 
    <Add Namespace="System.Security.Principal" /> 
    </ShimGeneration> 
</Fakes> 

Điều đó có nghĩa là tôi muốn toàn bộ không gian tên System.Security.Principal bị bẻ khóa và tôi đề nghị bạn sử dụng khung 4.6 cho cả hai dự án và thêm thuộc tính TargetFrameworkVersion tương ứng.

Bây giờ, khi bạn chạy các kiểm tra, đây là những gì bạn sẽ thấy:

enter image description here

Ok, trong kịch bản cụ thể của bạn, tôi không thể sử dụng hàng giả, nhưng công nghệ cơ bản nó chỉ dựa vào định tuyến lại tất cả các API (nó thấp hơn .NET trong thực tế, nó được gọi là Detours) Tôi tin và cho phép tất cả các hackery này.

Tóm lại: nếu nó chạy trên máy của tôi, tôi có thể hack nó (trừ khi tôi không có quyền truy cập vật lý vào máy của mình).

+0

Cảm ơn. Theo Damien chỉ ra trong bình luận về câu hỏi khác, anh ta có thể xây dựng một container chứa hoàn toàn bỏ qua việc đặt tên mạnh (và do đó có thể cho tôi một loại WindowsIdentity hoàn toàn giả). * Nhưng nó distrubing (nếu không hoàn toàn ngạc nhiên) rằng nó là dễ dàng.Dựa trên nhận xét của Damien, tôi đã nghĩ rằng tôi có thể xác thực mã thông báo bằng cách sử dụng các cuộc gọi Windows không được quản lý - nhưng điều đó chỉ đẩy vấn đề trở lại một lớp, quá trình gọi có thể chặn * chúng *. Hoặc chỉ cần chỉnh sửa bytecode của hội đồng của tôi để bỏ qua kiểm tra. –

+1

Oh cảm ơn vì điều đó, tôi đã sửa lỗi - :) –

+0

Vì vậy, cho * "nếu nó chạy trên máy của tôi, tôi có thể hack nó" *, trong ý kiến ​​chuyên môn đầy đủ, có kinh nghiệm của bạn, nơi tôi vẽ đường? Hệ thống được đề cập là "bình thường" nhưng sẽ chạy trong ngữ cảnh kết hợp người dùng nơi một số người dùng thực sự không nên xem một số thông tin trong đó trong khi những người khác có thể. Chúng tôi không nói về tài liệu được phân loại ở đây (nếu chúng tôi, tất nhiên, nó sẽ nằm trên một máy và mạng được phân loại), nhưng vẫn còn. Đi trước và sử dụng danh tính tôi đã được đưa ra? Làm kiểm tra tối thiểu của tôi trong câu hỏi? Mã không được quản lý? Nó * có thể * bị lừa, tôi chỉ cố gắng tìm ra dòng ... :-) –

Các vấn đề liên quan