ค้นหาไฟล์ที่ผู้ใช้ไม่สามารถอ่านได้?


12

ฉันต้องการค้นหาไฟล์ที่ผู้ใช้บางรายไม่สามารถอ่านได้

สมมติว่าชื่อผู้ใช้คือ "user123" และอยู่ในกลุ่มชื่อ "user123" ฉันต้องการค้นหาไฟล์ที่ถ้าพวกเขาเป็นเจ้าของโดย user123 มี u + r บน; ความล้มเหลวที่ถ้าไฟล์เป็นกลุ่มผู้ใช้ 123 ควรมี g + r ใน; ความล้มเหลวที่มันสามารถมี o + r บน

เนื่องจาก GNU find มี "- อ่านได้" ฉันสามารถทำสิ่งนี้ได้:

sudo -u user123 find /start ! -readable -ls

อย่างไรก็ตามกระบวนการต้องดำเนินการโดยผู้ใช้ที่ไม่มีสิทธิ์เข้าถึง sudo ดังนั้นฉันจึงลองทำสิ่งนี้: (มันไม่ตรวจสอบ o + r แต่นั่นไม่สำคัญในตอนนี้)

find /start \( -user user123 ! -perm -u=r  \) -o \( -group user123 ! -perm -g=r  \) -ls

แต่มันจะแสดงรายการไฟล์นี้:

272118    4 -rw-------   1 user123   user123       3243 Jul  3 19:50 /start/blah/blah/file.txt

ไฟล์นี้เป็นไฟล์เดียวที่อยู่ภายใต้/startที่เป็นเจ้าของโดย user123 พร้อมกับg=roff มันเป็นถ้าพบคือตีความเป็น-u=r-g=r

ฉันตัดสินใจลองย้อนกลับตรรกะและทดสอบnot ( truth )แทน:

find /etc/puppet ! \( \( -user puppet -perm -u=r  \) -o \( -group puppet -perm -g=r \) -o \( -perm -o=r \) \)  -ls

ได้ผลจริง!

เหตุใดต้นฉบับดั้งเดิมจึงfindล้มเหลว มันเป็นข้อผิดพลาดในfind(ไม่น่า) หรือเป็นตรรกะที่ผิด?

ปรับปรุง:ฉันมีเหตุผลที่ไม่ถูกต้อง ตามที่ระบุไว้ด้านล่างตั้งแต่! (A || B || C) == (! A&&! B&&! C) เหล่านี้เป็นสองข้อความที่เทียบเท่ากัน:

find /start ! \( \( -user user123 -perm -u=r \) -o \( -group user123 -perm -g=r \) -o \( ! \( -user user123 -o -group user123 \) -perm -o=r \) \) -ls
find /start ! \( -user user123 -perm -u=r \) ! \( -group user123 -perm -g=r \) ! \( ! \( -user user123 -o -group user123 \) -perm -o=r \) -ls

เป้าหมายของฉันคือไม่ต้องทดสอบผู้ใช้ / กลุ่มสองครั้ง สิ่งที่ฉันต้องการจริงๆคือโครงสร้างที่ซับซ้อนกว่านั้นอีกซึ่งอาจเป็นไปได้ก็ต่อเมื่อมีตัวดำเนินการ -xor ฉันสามารถสร้าง xor จากและ / หรือ / ไม่ แต่มันจะซับซ้อนกว่าโซลูชันทั้งสองข้างต้น


1
แม้ตรรกะที่สองเป็นความผิดเพราะมันจะบอกว่ามีการเข้าถึงไฟล์ที่มีpuppet --wxrwxrwx puppet puppet
Stéphane Chazelas

คำตอบ:


7

ตรรกะไม่ถูกต้อง คุณคิดว่าไฟล์นี้ไม่ควรอยู่ในรายการเพราะเป็นของเจ้าของuser123และมีการrตั้งค่าบิตของผู้ใช้ อย่างไรก็ตามมีการระบุไว้เนื่องจากตรงกับเกณฑ์ที่สอง (เป็นของกลุ่มuser123และมีการrตั้งค่าบิตของกลุ่ม)

เวอร์ชันที่สองของคุณใช้งานได้เนื่องจากกฎข้อหนึ่งของเดอมอร์แกน : การคัดค้าน ORing เชิงตรรกะของกลุ่มคำสั่งนั้นมีเหตุผลเทียบเท่ากับ ANDing การปฏิเสธของแต่ละคำสั่ง ในคำอื่น ๆ :

 ! ( A || B || C ) == ( !A && !B && !C )

ดังนั้นการทำงานfindกำลังมองหาไฟล์ที่

  • ไม่ (เป็นของผู้ใช้user123และสามารถอ่านได้โดยผู้ใช้ดังกล่าว) และ
  • ไม่ (เป็นเจ้าของโดยกลุ่มuser123และอ่านได้โดยกลุ่มดังกล่าว) และ
  • ไม่สามารถอ่านได้ทั่วโลก

ในขณะที่แรกfindกำลังมองหาไฟล์ที่

  • เป็นเจ้าของโดยผู้ใช้user123และไม่สามารถอ่านได้โดยผู้ใช้ดังกล่าวหรือ
  • เป็นของกลุ่มuser123และไม่สามารถอ่านได้โดยกลุ่มดังกล่าวหรือ (ถ้าคุณทำเสร็จแล้ว)
  • ไม่สามารถอ่านได้ทั่วโลก

ดังนั้นไฟล์ที่ตรงกับเกณฑ์ 3 ข้อใด ๆ ข้างต้น (และไม่จำเป็นต้องทั้งหมด) จะแสดงรายการตามที่คุณเห็น

แก้ไข

บังเอิญ (หลังจากดูโปรไฟล์ของคุณ) ฉันเป็นแฟนตัวยงของหนังสือ O'Reilly ของคุณ :)


ขอบคุณสำหรับการวิเคราะห์ ใช่มันเป็นการใช้ผิดกฎของมอร์แกน ฉันพยายามทำ( !A && !B && !C )แต่ฉันย้าย!เข้าไปด้านในของแต่ละส่วนซึ่งไม่ถูกต้อง ขอบคุณ!
TomOnTime

ป.ล. ฉันดีใจที่คุณเป็นแฟนหนังสือของฉัน! ฉันอยากรู้ว่าคุณอ่านมันภาษาใด
TomOnTime

@TomOnTime ภาษาอังกฤษแน่นอน ฉันพยายามอ่านหนังสือในภาษาต้นฉบับถ้าฉันสามารถช่วยได้
โจเซฟอาร์

8

ยังมีอีกหลายสิ่งที่ต้องพิจารณาเพื่อตรวจสอบว่าผู้ใช้มีการเข้าถึงไฟล์ผ่านเส้นทางที่กำหนดหรือไม่:

  • เจ้าของไฟล์
  • กลุ่มของไฟล์
  • ACLs ในไฟล์
  • uid, gid และ gids เสริมของผู้ใช้
  • ค้นหาการเข้าถึงองค์ประกอบเส้นทางใด ๆ ที่นำไปสู่ไฟล์นั้น
  • ไม่ว่าจะเป็นไฟล์ที่เป็น symlink
  • การอนุญาตใช้แตกต่างกันสำหรับผู้ใช้ id 0
  • คุณลักษณะด้านความปลอดภัยที่มากขึ้นเช่น SELinux ...

จริง ๆ แล้วเปลี่ยน uids และ gids ทั้งหมดไปเป็นของผู้ใช้และตรวจสอบมันเป็นเรื่องยากมากที่จะใช้ตรรกะเดียวกันกับที่ระบบทำ

ด้วย zsh คุณสามารถทำได้ (เป็น root):

readable() (
  USERNAME=$u
  [ -r "$REPLY" ]
)
u=some-user
print -rl -- **/*(DoN^+readable)

หรือด้วยperl:

find . -print0 | sudo -u some-user perl -Mfiletest=access -l -0ne '
  print unless -r'

นั่นคือในทั้งสองกรณีให้เรียงลำดับต้นไม้ไดเรกทอรีเป็นrootแต่ทดสอบการเข้าถึงไฟล์ในฐานะผู้ใช้ที่เกี่ยวข้อง

เล่นfind -readableเป็นsome-userจะไม่ได้อยู่ในกรณีที่มันจะไม่สามารถที่จะไปผ่านมาไดเรกทอรีที่ผู้ใช้ไม่มีการเข้าถึงหรือไม่มีสิทธิ์ในการอ่าน ( แต่อาจจะเข้าถึง)

แม้ว่าจะพิจารณาเฉพาะการอนุญาตและความเป็นเจ้าของไฟล์เท่านั้น (และไม่ใช่ ACLs หรือส่วนประกอบพา ธ ... ) คุณต้องมีอย่างน้อย (ที่นี่ไวยากรณ์ GNU):

u=some-user; g=$(id -G "$u" | sed 's/ / -o -group /g'); IFS=" "
find . ! \( -user "$u" -perm -u=r -o \
          ! -user "$u" \( -group $g \) -perm -g=r -o \
          ! -user "$u" ! \( -group $g \) -perm -o=r \)

แนวคิดที่ว่าถ้าผู้ใช้เป็นเจ้าของไฟล์สิทธิ์อื่น ๆ ทั้งหมดนั้นไม่เกี่ยวข้อง ถ้าไม่เช่นนั้นหากไฟล์นั้นเป็นของกลุ่มโดยกลุ่มของผู้ใช้ใด ๆ การอนุญาต "อื่น ๆ " นั้นไม่เกี่ยวข้อง


1
ข้อดีของ ACL และปัจจัยอื่น ๆ การประเมินที่ถูกต้องเพียง 100% เพราะใช้รหัสเคอร์เนลเดียวกับaccess() open()ดังนั้นจึงsudo -u user123 find /start -readableเป็นทางออกที่ดีที่สุดหากsudoเป็นตัวเลือก
TomOnTime

1
@TomOnTime ไม่ถ้าคุณใช้sudo -u user123 find -readableมันจะไม่รายงานไฟล์ในไดเรกทอรีที่คุณไม่สามารถป้อนหรือในไดเรกทอรีที่คุณไม่สามารถอ่านได้ (ดังนั้นจะมีการลบเชิงลบและการบวกเท็จ) ว่าทำไมฉันขอแนะนำให้ใช้zshสำหรับลงมาต้นไม้ไดเรกทอรีเป็นรากและทำaccess()( [ -r ... ]) เป็นผู้ใช้จริง (การตั้งค่า$USERNAMEในzshการเปลี่ยนแปลงทั้งหมด UIDs GIDS และเหมือนsudoจะ)
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.