á¨ááááľ á¨ááá á°á áááľáŁ áŁá áŞáŤáą áĽá á´ááŽáá
BPF áá¨áááľáᣠá°á áááľá áĽá ááĽááľá áłáŤáľáá á¨áááá áááŤáá áááá ááááľ áá°áŁáᢠá áá ááááŤáľáŁ á¨á¨ááá ááá˘áá˝ á á´áŽáá ááľáĽ á BPF ááŽááŤáá˝ á¨áá°áááľá á´áŽáá ááŁáŞáŤáá˝á á áá°áá á á á´áŽáá ááľáĽ á¨áá°áąá áááá áááťáťá ááááĽááąá áá áá áĽáŠ ááłáĽ áá áĽáá á áľá á áá áᢠá áá áááŤá ááľáĽ á´áŽáá áá áĽáá°áá áĽá áĽáá´áľ áĽá á áá áĽáá°ááá áĽááĽáŤáŤáá. á¨á፠BPF ááŽááŤáá˝á á áá áá á´áŽáá ááŁáŞáŤáá˝á áĽáá´áľ áĽáá°áá˝á áááŤá. á¨á፠á áá áááááľ á°á áááľ áááá˝ á á¨ááá ááľáĽ á¨á°áŤá°áąáľá á áĽáŽ á¨á°á°áŠ BPF ááá ááá˝á áĽáááá¨áłááá˘
á¨ááááľ á´áŠáŞá˛ áááá˝ (LSM) á¨á°ááŤáŠ á¨á°á áááľ áá´áá˝á á°á¨ááá á á á á ááአááá°áá á á¨ááŤáááá á¨á°ááŁá áľáĽáľáŚá˝á á¨ááŤááἠáááá ááᢠLSM áĽáá° ApparmorᣠSELinux áĽá Tomoyo áŁá á¨á¨ááá ááá áá áá á ááĽáł áá áá ááťááá˘
á¨ááááľá á á á á áááŤá¨áľ áĽááááá˘
áŁá áŞáá˝
á¨ááááľ á¨á˝ááłáá˝ áááľ á ááľá á¨á°áá°á á°ááŁá ááá¨ááá áአáአáá°áľá áááľ ááľá áľ á ááĽáᾠᣠáá áá፠ááá áąááľ áłáá áá ᣠááá áá°áąá áአáááľá¨á ᣠá¨áĽááľ áĽáľáá á¨ááááľ áĽá áá°áąá á ááłááľ á°ááŁáŤáľá áĽáá˛áá˝á ááááľ ááᢠáááłáᣠáááá¨áťá áአáá°áĽ ááááľ áŤáá áľáŁ 80 áá áᣠáá°áąá áĽáá° root á¨áááľ ááá ᣠá ááá á¨CAP_NET_BIND_SERVICE á á á ááľá áľ áá˝ááá˘
main.go á¨ááŁá ᨠGo ááŽááŤáá á áľáĄá áľáĄ-
package main
import (
"net/http"
"log"
)
func main() {
log.Fatalf("%v", http.ListenAndServe(":80", nil))
}
áá ááŽááŤá á áááľ 80 áá á¨á¤á˝á˛á˛á á áááá áŤááááá (áá áአáá°áĽ áá)ᢠáĽááá áá á¨á°á ááᨠá áá áá˛áŤáá áĽáá°áŤááá-
$ go build -o capabilities main.go
$ ./capabilities
ááá ááᣠáĽá á¨áľá ááĽáśá˝á áĽá¨á°á á áľááááᣠáá áŽáľ áá°áĄá á ááŤáŤáá áľ áá áľá á°áľ áááĽáŤááĄ-
2019/04/25 23:17:06 listen tcp :80: bind: permission denied
exit status 1
capsh (áźá á áľá°áłáłáŞ) á¨á°áá°á á¨á˝ááł áľáĽáľáĽ áŤáá áźá á¨ááŤááľ ááłáŞáŤ ááá˘
á áá á ááŁáᣠáá°á á˛á áĽáá°á°ááááᣠáá á¨áľá ááĽáśá˝á á¨ááľá áľ ááá ᣠᨠcap_net_bind_á áááááľá á á á á ááŽááŤá ááľáĽ áŤááľ ááá áááŽá˝ áá á áá á¨áĽ áአáአá¨áá°áĽ áľáľáľáá ááááľ áá˝ááᢠáá áá áááľá¨á ááŽááŤáá˝áá á áŤá ááŤáŤá áĽáá˝ááááĄ-
# capsh --caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep'
--keep=1 --user="nobody"
--addamb=cap_net_bind_service -- -c "./capabilities"
áá á áĄáľá á áĽááą áĽáá¨áłáá˘
- capsh - áŤáá áĽáá° áźá áá áá.
- âcaps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' - á°á áááá áááἠáľáááĽá (áĽáá° root ááŽáĽ áľáááááá)ᣠcap_net_bind_serviceá áĽá á¨á°á áá ááłáááŤáá á áľááá á¨ááá¨á á˝ááłá áĽááááááᢠáľá áááá áááľá cap_setuid áĽá cap_setgidá˘
- -keep=1 - á¨áľá áá፠á˛ááአá¨á°áŤááľá á˝ááłáá˝ ááá¨áľ áĽááááááá˘
- âuser=ânobodyâ â ááŽááŤáá á¨ááŤáľáŹá°á á¨áá¨á¨áť á°á áá ááá á ááááá˘
- âaddamb=cap_net_bind_service - á¨áľá áááł á¨áá¨áŠ á áá á°ááá á˝ááłáá˝á áá˝áłáľá áŤáááá˘
- - -c "./capabilities" - ááŽááŤáá áĽáť áŤááą.
á¨á°ááá á˝ááłáá˝ á¨á áá ááŽááŤá execve () á áá áá á˛áá˝á á ááá˝ ááŽááŤáá˝ á¨ááááą áአááááľ á˝ááłáá˝ áá¸áᢠáááŤáŤá á¨á°ááá°áá¸á á˝ááłáá˝ áĽáť ááá á áá á áááá áĽáá° á áŤáŁá˘ á˝ááłáá˝ ááááą áá˝áá.
á --caps á ááŤá ááľáĽ áŤááá á á á á¨áááš á áá +eip áá áááľ áĽáá°áá áĽáŤá°áĄ ááááᢠá á áá áááá°á áĽááá áŁáá˛áŤáá˝ áĽá á áá áááááĄ-
- ááá á á áá áľ (p);
- áá á ááá áááá (á );
- á ááá˝ áá°áśá˝ ááá¨áľ áá˝áá (i).
á¨áŹá_ááľ_á˘ááľ_á áááááľá áá áá áľááááááᣠáá áá á e áŁáá˛áŤ ááľá¨á á ááĽáᢠá¨ááŤá áááá á áľáĽáá ááľáĽ áĽááááŤáá. áá á¨á˝ááłáá áááľáŽá˝ áŤáľáŹáłá áĽá á i áŁáá˛áŤ ááááľ ááľá¨á á ááĽáᢠá áá¨á¨áťáᣠáŁá áŞá áĽáá˛áá áĽáááááá (áá áá áŠá áá˛áá áłáááá á á°á¨áá) á p. ᨠcap_net_bind_service+eip áááľááá˘
ss á áá áá áá¤áąá áá¨ááἠáá˝áá. áá¤áąá áľáá˝ áĽááłáĽá¨á á ááš áá áĽáá˛ááŁá áᣠááá áá á°áŤáŤáĽ á¨áááá á¨áá°áĽ áĽá á¨á°á áá ááłáá፠á¨0 áá áŤáłáŤáᣠá áá áááł 65áĄ
# ss -tulpn -e -H | cut -d' ' -f17-
128 *:80 *:*
users:(("capabilities",pid=30040,fd=3)) uid:65534 ino:11311579 sk:2c v6only:0
á áá ááłá ááľáĽ áŤáá áĽáá áááá, ááá áá libcap á áá áá áźá ááá áá˝áá. áá áá áá¨áᣠman 3 libcap áááá¨áąá˘
ááŽááŤáá˝á á áá˝áá áľ áá áĽááá áá ááá˘á ááŽááŤá á áá áŤá áľ áá á¨ááŤáľááááľá áááá áŁá áŞáá˝ á áľááľá á áŤáá á ᢠá á°á¨ááŞá, áĽááá áŁá áŞáŤáľ á á á˛áľ áľáŞáśá˝ ááľáĽ áááᥠáá˝áá.
á¨ááŽááŤáá˝áá á á á á¨á áá ááá¨áłáľáŁ Kprobeá á cap_capable kernel á°ááŁá á¨ááŤááááá BCC á á á áŤáá ááłáŞáŤ ááá°áľ áĽáá˝ááááĄ-
/usr/share/bcc/tools/capable
TIME UID PID TID COMM CAP NAME AUDIT
10:12:53 0 424 424 systemd-udevd 12 CAP_NET_ADMIN 1
10:12:57 0 1103 1101 timesync 25 CAP_SYS_TIME 1
10:12:57 0 19545 19545 capabilities 10 CAP_NET_BIND_SERVICE 1
á cap_capable kernel á°ááŁá ááľáĽ bpftraceá áŁáá ááľ ááľáá kprobe á áá áá á°ááłáłá ááá ááłáŤáľ áĽáá˝ááááĄ-
bpftrace -e
'kprobe:cap_capable {
time("%H:%M:%S ");
printf("%-6d %-6d %-16s %-4d %dn", uid, pid, comm, arg2, arg3);
}'
| grep -i capabilities
á¨ááŽááŤáá˝á á˝ááłáὠᨠkprobe á áá á¨áá áá á¨áá¨á°ááá á¨áá°á ááá áŤáľááŁááĄ
12:01:56 1000 13524 capabilities 21 0
12:01:56 1000 13524 capabilities 21 0
12:01:56 1000 13524 capabilities 21 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 10 1
á ááľá°áá áááľ áá°áą á¨ááááá¸á áĽááśá˝ á˛áá áá áá ááľ á¨áŚá˛áľ áŤááá ááľá°áśá˝á á¨ááŤáŤáľáľ á ááá áááá á¨áŚá˛áľ áŤááá áźáŽá˝ áĽá á áá¨á¨áťá á áľáááá á¨áŚá˛áľ áŁáá˛áŤ (á áá¤áą á¨áá¨á¨áť) áá° 1. á á á á˛ááἠáĽááŤááᢠá¨áááááá CAP_NET_BIND_SERVICE ááᣠáĽáą á ááá ááľáĽ áŁáá á¨á¨ááá ááá áŽáľ ááľáĽ áá/uapi/linux/ability.h á¨áá፠10 áá ááááťáá˘
/* Allows binding to TCP/UDP sockets below 1024 */
/* Allows binding to ATM VCIs below 32 */
#define CAP_NET_BIND_SERVICE 10<source lang="go">
á á á á ááá áááł áĽáá˛á°áŠ áááľáťá áĽáá° runC ááá Docker áá áŽáá´áááŽá˝ á ááŽáŤ á°á áľ áĽá áá áááááŁááá áá á¨ááááąáľ áĽá áá°áá áŞáŤáá˝á ááááľ á¨ááŤáľááááľá á˝ááłáá˝ áĽáť ááᢠá ááľ áá°áá áŞáŤ á¨á°áá°á á˝ááłáá˝ á˛áááᣠDocker --cap-add á áá áá ááŤáááŁá¸á áá˝áááĄ
docker run -it --rm --cap-add=NET_ADMIN ubuntu ip link add dummy0 type dummy
áá áľááá ááŤáŁáá ᨠCAP_NET_ADMIN á á á áá°á ááᣠáá á ᨠdummy0 á áááá˝á ááá¨áá á¨á ááłá¨ áá¨áĽ ááááá áĽáá˛áŤáá á áŤáľá˝áááá˘
á¨áááĽáá ááá áĽáá° ááŁáŤáľ áŤá áŁá áŞáŤáľá áĽáá´áľ áá áá áĽááłááĽá áŤáłáŤá, ááá áá á¨á°áᨠáá´ á áá áá á¨áŤáłá˝áá ááŁáŞáŤáá˝ á ááŽááŤá ááá°áá á áŤáľá˝ááá.
á´ááŽáá
á´áŽáá á´ááŠá áŽáááá˛ááá á¨ááŤááááľ á˛áá á ááááľ á¨ááá ááľáĽ á¨áá°áá á á¨á°á áááľ á˝áá á˛áá ááá˘áá˝ á¨á°áá°á á¨áľáááľ áĽáŞáá˝á áĽáá˛áŤáŁáŠ áŤáľá˝áá¸ááᢠááá áĽááłá á´áŽáá á¨ááááľ áá á¨áááłá°á á˘ááá á¨á°áá°á á¨áľáááľ áĽáŞáá˝á á¨ááľá°áłá°á á˝ááłá á¨áĽááą áá á˛ááłá°á á¨á áá á°áááá áŤá°ááááá˘
á¨á´ááŽáá áĽá ááááľ áŁá áŞáŤáľ áĽááľá ááľ á¨ááááŁá á á áá°áá áĽá áĽááá áá á¨áááąá á ááŤá¨áŚá˝ áĽá á áááááľ á ááľ áá ááááᢠáááłáᣠááá°áą á¨CAP_NET_ADMIN á á á ááľá áľ áľááá áááá ááááá á¨áśáŹáľ áááááśá˝á áĽáá˛áá á á áľáááąááľáŁ ááá á áĽá ááá á4 á¨áľáááľ áĽáŞáá˝á˘
á¨á´ááŽáá ááŁáŞáŤ áá´ á SECOMP_MODE_FILTER áááł á áá°áŠ ᨠBPF ááŁáŞáŤáá˝ áá á¨á°áá°á¨á° áá, áĽá á¨áľáááľ áĽáŞ ááŁáŞáŤ áĽáá° ááŹáśá˝ á á°ááłáłá ááááľ áá¨áááá.
á´áŽáá ááŁáŞáŤáá˝ á PR_SET_SECOMP ááá á áŠá prctl á áá áá ááŤááᢠáĽááá ááŁáŞáŤáá˝ á á´ááŽáá_áłáł ááá á áá°áá¨áá ááĽáŤááłááą á¨á´ááŽáá ááŹáľ á¨ááá¸á á¨BPF ááŽááŤá ááá ááááᢠáá ááá á á¨áááłá¨áŞáŤ á ááá´áá¸áᣠá áľáááą áĽáŞ áá á¨á áááŁáŁáŞ áááŞáŤ á áá áĽá á˘á á áľáľáľáľ á¨áľáááľ áĽáŞ áá᪠áĽá´áśá˝á áááᣠáĽáá° uint64 ááááťáá˘
á linux/seccomp.h ááá ááľáĽ áŤáá á¨á¨ááá ááá áŽáľ á¨á´ááŽáá_áłáł ááá á áá á áááľáááĄ-
struct seccomp_data {
int nr;
__u32 arch;
__u64 instruction_pointer;
__u64 args[6];
};
á¨áá ááá á áá¨áľ áĽáá°ááľá˝ááᣠá áľáááľ áĽáŞáŁ ááááŽáš ááá áááąáá á ááŁáá ááŁáŤáľ áĽáá˝áááá˘
áĽáŤááłááąá á¨á´ááŽá ááŹáľ á¨á°áá á á áá ááŁáŞáŤá á¨áá¨á¨áť ááłá áááľá¨á áĽá ááĽá áá ááľá¨á áĽááłáá áľ áá¨ááá áááá á áá áľá˘ á¨áá¨á¨áťá ááłá á á ááľ á¨ááááť áááá˝ (áááł áŽáśá˝) ááááťá.
- SECCOMP_RET_KILL_PROCESS - á áá ááááŤáľ áŤáá°ááá á¨áľáááľ áĽáŞ áŤáŁáŤ á áá áá˛áŤáá á á ááá áá°áąá áááľááá˘
- SECCOMP_RET_KILL_THREAD - á áá ááááŤáľ áŤáá°á°áŤ á¨áľáááľ áĽáŞ áŤáŁáŤ á áá áá˛áŤáá á¨á ááá áá áŤáááŁáá˘
â SECCOMP_RET_KILL â á á˝á á SECCOMP_RET_KILL_THREADᣠááá á°áłááááľ áááŤáá˘
- SECCOMP_RET_TRAP - á¨áľáááľ áĽáŞá á¨á°á¨áá¨á áá, áĽá SIGSYS (ááĽá á¨áľáááľ áĽáŞ) ááááľ áá° áá áŤá á°ááŁá áááŤá.
- SECCOMP_RET_ERRNO - á¨áľáááľ áĽáŞá á áá°á°áŤá áĽá ᨠSECCOMP_RET_DATA ááŁáŞáŤ ááááť áá á á¨áá áá° á°á ááá áŚáł áĽáá° áľá á°áľ áá áá°ááááᢠáĽáá° áľá á°áą áááľá¤, á¨á°ááŤáŠ á¨áľá á°áľ áááá˝ ááááłá. á¨áľá á°áľ ááĽáŽá˝ áááá á áááĽáá ááá ááá§áá˘
- SECCOMP_RET_TRACE - áŤáá áá°áľ ááá¨áľ áĽá ááááŁá á á¨áľáááľ áĽáŞ á˛á°á¨á áááĽáá Ptrace áááááŤáá áááłáá áá á ááᢠáá¨áłá°áŤ áŤáá°ááá, áľá á°áľ á°áááś áááŁá, errno áá° -ENOSYS á°áááĽáŻá, áĽá á¨áľáááľ áĽáŞá á áá°á°áŤá.
- SECCOMP_RET_LOG - á¨áľáááľ áĽáŞá á°ááľáˇá áĽá á°áááá§áá˘
- SECCOMP_RET_ALLOW - á¨áľáááľ áĽáŞ á ááá ááááłáá˘
ptrace á¨áá°áąá á áááá á¨áá¨áłá°á áĽá á¨áááŁá á á˝ááł áŁáá áá°áľ ááľáĽ á¨áá¨áłá°áŤ áá´áá˝á ááá°áá á á¨áľáááľ áĽáŞ ááᢠá¨ááľáľá ááŽááŤá áá¤áłá á áá ááááľ á áááá áá á°á˝áĽá ááŤáłáľá áĽá á¨áąáŤ áá á°á¨ áľááľáł ááááŚá˝á ááťáťá áá˝ááᢠá á´ááŽáá á ááľ ááľáĽáŁ ptrace áĽá á áá á¨áááá á SECOMP_RET_TRACE áááł áŽáľ á˛áá°ááľ ááᣠáľááá áááááŤá á¨áľáááľ áĽáŞáá áĽááłáá°áŤ áĽá á¨áŤáąá á áááᎠáĽáá˛á°ááĽá áŤá°áááá˘
á¨á°á¨ááľ áľá á°áśá˝
á¨áá áá° áá á¨á´áŽáá áá á áá°áŠá áľ áá á¨á°ááŤáŠ áľá á°áśá˝ áŤááĽáááłá, áĽááá á á SECCOMP_RET_ERRNO á áááľ á¨ááááť áá á°ááá°á ááłááá. áľá á°áľá áŞáááľ áááľá¨áᣠá¨á´ááŽáá á˛áľá°á áĽáŞ á¨1 ááá -0 ááááłáá˘
á¨áá¨á°ááľ áľá á°áśá˝ ááአáá˝áá:
- EACCESS - á°áአá¨áľáááľ áĽáŞ ááľá¨á á ááááľááľáᢠáá áĽááá áá á¨áá¨á°á°á á¨CAP_SYS_ADMIN áአááĽáśá˝ áľáááá ááá ááá_new_privs prctl á áá áá áľááá°ááá áá (áľááá á áá áĽáááááŤáá)á˘
- EFAULT - áŤáá ááááŽá˝ (args á seccomp_data ááá á) áľáááá á áľáŤáť á¨áá¸áá;
- EINVAL - áĽáá á áŤáľ ááááŤáśá˝ ááአáá˝áá:
- á¨á°á á¨áá ááá á ááłáá á ááá á áá áŁáá áá á á á¨ááá á áá°ááá;
- á¨á°ááášáľ áŁáá˛áŤáá˝ áá°á á¨áá ááá áá á áá°áá;
-áááá BPF_ABSá áŤáŤáľáłááŁááá áá á¨á°á áá°á ááŤáŤáť áá á˝ááŽá˝ á ááŁáá á á¨á´ááŽáá_áłáł ááá á áá á áá áἠáá˝ááá˘
- áá° ááŁáŞáŤá á¨á°ááá áááŞáŤáá˝ áĽááľ á¨á¨áá°áá áá ááŁá;
- ENOMEM - ááŽááŤáá áááľáŹáľ á á áá á°á¨ áľááľáł á¨áá;
- EOPNOTSUPP - áááá á SECCOMP_GET_ACTION_AVAIL áľáááą áĽáá°ááá á ááááˇá, ááá áá á¨ááá á áááá ááľáĽ ááááľá á áá°ááá;
- ESRCH - áá áĽá¨áľ á áááłá°á áá á˝áá á°áá á¨;
- ENOSYS - á¨SECOMP_RET_TRACE áĽááá áá á¨á°áŤáŤá ááá áá¨áłá°áŤ á¨ááá˘
prctl á¨á°á áá-áŚáł ááŽááŤá á¨á°áá°á á¨áá°áąá áá áłáá˝ áĽáá° áŁááľ á˘áá˛áŤáááᣠá¨áá áľáᣠá°á áááą á¨á°á á á áľááľ áááł (á´áŽáá)ᣠáአááĽáśá˝áŁ á¨ááá ááá áśá˝áŁ ááá° áŤá á¨áá°áąá áá áłáá˝ áĽáá˛ááŁá á (áĽáá˛áŤááá áĽá áĽáá˛áŤáá) á¨ááŤáľá˝á á¨áľáááľ áĽáŞ ááá˘
á´áŽáá áá áá° á¨áá áŞáŤ á´áááá áááľáá áá˝ááᣠáá á áá°ááᢠá´áŽáá á°á áááá˝ á¨áá áŞáŤ áá´á áĽáá˛áŤáłáĽáŠ á¨ááŤáľá˝á áááá፠ááᢠá áá á á´áŽáá á˛áľá°á áĽáŞ á ááĽáł á¨áá ፠ááŁáŞáŤ á áá áá á¨á°á áá ááľá°ááĽá ááŽááŤáá˝ áĽáá´áľ áĽáá°ááá አáĽáááá¨áľá˘
á¨BPF á´ááŽá ááŁáŞáŤ ááłá
á¨áá áá°á á¨á°áĽáŤáŠáľá áááľ áľáááśá˝ áĽáá´áľ ááááľ áĽáá°ááťá áĽááłáŤáá-
â á ááłáááš áá á áááľá¨áľ á¨á°ááŤáŠ á¨ááááť áŽáśá˝ áá áĽáá° ááŁáŞáŤ á¨ááŤáááá á¨á´ááŽáá BPF ááŽááŤá áĽáá˝ááá á˘
- prctl á áá áá ááŁáŞáŤáá ááŤá.
á ááááŞáŤ á°á¨á áŤáľááá˝á á¨áá°á á á¤á°-áá˝áááľ áĽá á¨ááááľ á¨ááá áŤáľáááááłááĄ-
#include <errno.h>
#include <linux/audit.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <linux/unistd.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <unistd.h>
áá á ááłá á¨ááá¨áá á ááľáŁ á¨ááá á CONFIG_SECOMP áĽá CONFIG_SECOMP_FILTER áá° y á¨á°ááá ᨠáááá áá¨ááἠá ááĽáᢠá áá ፠áá˝á áá áĽáá°áá áŤá ááááľ ááľá¨á áá˝áá-
cat /proc/config.gz| zcat | grep -i CONFIG_SECCOMP
á¨á°áá¨á áŽáľ áŁá áááľ ááá install_filter á°ááŁá ááᢠá¨ááááŞáŤá ááá á¨áĽáá ᨠBPF ááŁáŞáŤ áááŞáŤáá˝á ááááĄ-
static int install_filter(int nr, int arch, int error) {
struct sock_filter filter[] = {
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, arch))),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3),
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, nr))),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (error & SECCOMP_RET_DATA)),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
};
áááŞáŤááš á¨áááááľ á linux/filter.h ááá ááľáĽ á¨á°ááášáľá BPF_STMT áĽá BPF_JUMP áááŽáá˝á á áá áá ááá˘
áááŞáŤáášá áĽáááá˘
- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, arch))) - áľááṠᨠBPF_LD áááá áĽá áá¨ááťá á BPF_W áá áááᣠá¨ááŹáľ áá¨á á¨áááá á áá ááŤáŤáť BPF_ABS áá ááá˘
- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_Kᣠá áľáľáŁ 0ᣠ3) - BPF_JEQ á á áá áá á BPF_K accumulator áá ááľáĽ áŤáá á¨á ááá´áá¸á áĽá´áľ á¨á áľáľ áá áĽáŠá áááá áŤá¨áááŁáᢠáĽáá°á፠á¨áááŁá ááŤáŤáť 0 áá° ááŁáŠ áááŞáŤ áááááŁáá áŤááá áá á ááŤáŤáť 3 (á áá á ááŁá) áá áááá ááááŤáąá á áľáľ á ááááľáá˘
- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) - ᨠBPF_LD á BPF_W áá ááá áááá áĽá áá¨ááťá áá á á BPF_ABS áá ááŤáŤáť ááľáĽ á¨áááá á¨áľáááľ áĽáŞ ááĽá ááá˘
- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) - á¨áľáááľ áĽáŞ ááĽáá á¨á°áááá áĽá´áľ áá áŤááłáľáŤá. áĽáŠá á¨áá áá°áááĽáá áááŞáŤ áááą áĽá á¨áľáááľ áĽáŞáá áŤá°ááááᣠá áá áá፠á¨áľáááľ áĽáŞáá á SECOMP_RET_ALLOW ááá áłáá˘
- BPF_STMT(BPF_RET + BPF_KᣠSECCOMP_RET_ERRNO | (áľá á°áľ áĽá SECCOMP_RET_DATA)) - ááŽááŤáá á BPF_RET áŤáááŁá áĽá á áá¤áąá SECCOMP_RET_ERRNO á¨áľá á°áą á°áááá ááĽá áá áľá á°áľ áááĽáŤáá˘
- BPF_STMT(BPF_RET + BPF_KᣠSECCOMP_RET_ALLOW) - ááŽááŤáá á BPF_RET áŤáááŁá áĽá á¨áľáááľ áĽáŞá SECCOMP_RET_ALLOWá á áá áá áĽáá˛ááá ááá áłáá˘
á´áŽáá CBPF ááá˘
á¨á°ááá ᨠELF ááá ááá JIT á¨á°á ááᨠC ááŽááŤá ááá á¨áááŞáŤáá˝ áááá ááá áĽá á áá áĽáá°ááá áĽáŤá°áĄ ááá áá˝ááá˘ááá áááľ ááááŤáśá˝ á á.
⢠á ááááŞáŤáŁ á´ááŽá á˛á˘áá¤á (ááá˛á BPF) áá ááá áĽáá eBPF á áá°ááᣠáá áááľáĄ ááá ááááŚá˝ á¨ááľáᣠááá áá á¨áá¨á¨áťáá áľááľ áá¤áľ ááá¨áá¸áľ á á°áŁáłá˘ áĽáť ááᣠá ááłáá áá áĽáá°ááłá¨áá˘
⢠ááá°áᣠá´áŽáá ᨠBPF áááŞáŤáá˝á áľááľá á ááá á ááĽáł ááá áá áĽáá áá á¨ááᢠá¨á°á ááááŁá¸á áááŽáá˝ áĽááá á áááŞáŤáá˝ á ááŽááŤáá á°áľáá á áá ááááľ áĽáá˛áááš áŤáááá˘
áá á áľáĽá°áŁ ááá¨áłáľ á°á¨á᪠áĽáá á¨áááᣠá°ááłáłá ááá á¨ááŤá°áááá pseudocode áŤáľáĄá áľáĄ-
if (arch != AUDIT_ARCH_X86_64) {
return SECCOMP_RET_ALLOW;
}
if (nr == __NR_write) {
return SECCOMP_RET_ERRNO;
}
return SECCOMP_RET_ALLOW;
á socket_filter ááá á ááľáĽ áŤááá á¨ááŁáŞáŤ áŽáľ á¨áááš á ááᣠáŽáąá áĽá á¨á°á°ááá á¨ááŁáŞáŤáá ááááľ á¨áŤá sock_fprog áááá áŤáľáááááłáᢠáá á¨ááἠááá á áá°áą á áá áĽáá˛áŤááľ áááá áĽáá° áááľ áŤáľáááááĄ-
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
.filter = filter,
};
á install_filter á°ááŁá ááľáĽ á ááľ ááá áĽáť áááŤá - ááŽááŤáá áŤáą ááŤá! áá áá áááľá¨á á°á áááą á¨á°á á á á¨áŽáááá˛áá áááłá áááľááŁáľ PR_SET_SECOMPá áĽáá° á ááŤá á ááá°áľ prctl áĽáá ááááᢠá¨ááŤá á SECCOMP_MODE_FILTER á áááľ á¨ááŽá á°áááá ááľáĽ á¨ááááá ááŁáŞáŤáá áĽáá˛áá áááłáá áĽáááá¨ááááĄ
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
perror("prctl(PR_SET_SECCOMP)");
return 1;
}
return 0;
}
á áá¨á¨áťááŁá¨áĽáá install_filter á°ááŁá ááá áá áĽáá˝ááááŁá¨á፠á ááľ áá PR_SET_NO_NEW_PRIVSá áá áá á áááá ááááááľ prctl á áá áá áĽá á¨á áťááľ áá°áśá˝ á¨ááááťá¸á á¨á áá áአááĽáśá˝á á¨ááŤááá áľá áááł ááľáááľ á ááĽáᢠá áá á ááŤááᾠᨠroot ááĽáśá˝ áłááá¨á á install_filter á°ááŁá ááľáĽ á¨áá¨á°ááľá ᨠprctl áĽáŞáá˝ ááľá¨á áĽáá˝áááá˘
á áá ᨠinstall_filter á°ááŁá áá°áá áĽáá˝áááᢠᨠX86-64 á ááá´áá¸á áá á¨ááááą áááá á¨áľáááľ áĽáŞáá˝ áĽáá˝á áĽá áááá áá¨áŤáá˝ á¨ááŤááľ áááľ áĽááľáĽá˘ ááŁáŞáŤáá á¨áŤáá á áá á¨ááááŞáŤáá áá᪠áĽá´áľ á áá áá ááá¸áá áĽáááĽááá-
int main(int argc, char const *argv[]) {
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
perror("prctl(NO_NEW_PRIVS)");
return 1;
}
install_filter(__NR_write, AUDIT_ARCH_X86_64, EPERM);
return system(argv[1]);
}
áĽáááá. ááŽááŤáá˝áá ááá ááá áááá ááá gcc ááá áá áĽáá˝ááá á ááááá ááááľ áá.c áááá áŤá áአá ááŤáŽá˝ áá ááá áĽáť ááá˘
clang main.c -o filter-write
áĽáá°á°áááá á ááŽááŤá ááľáĽ áŤááľá áááá áá¤áśá˝ á áá°ááᢠáá áá áááá¨á á ááľ ááá á¨ááŤáᣠááŽááŤá áŤáľáááááłá - ls áĽáŠ áĽáŠ áááľááᢠááľáŽá áĽáá°áá áá á¨ááłá°ááááĄ-
ls -la
total 36
drwxr-xr-x 2 fntlnz users 4096 Apr 28 21:09 .
drwxr-xr-x 4 fntlnz users 4096 Apr 26 13:01 ..
-rwxr-xr-x 1 fntlnz users 16800 Apr 28 21:09 filter-write
-rw-r--r-- 1 fntlnz users 19 Apr 28 21:09 .gitignore
-rw-r--r-- 1 fntlnz users 1282 Apr 28 21:08 main.c
áľáá ! á¨áá áá á á፠ááŽááŤáá˝áá áá áá áá áááľááᥠá ááá ááááľáá á¨ááááááá ááŽááŤá áĽáá° ááááŞáŤá áá¨áŤá¨áŞáŤ áĽáááááá˘
./filter-write "ls -la"
á˛á°áá á áá ááŽááŤá áá á áá áŁáś áá¤áľ áŤáľááá. ááá áá áá áĽá¨á°á¨á°á° áĽááłá ááá¨áľ strace ááá áá áĽáá˝ááááĄ-
strace -f ./filter-write "ls -la"
á¨áĽáŤá áá¤áľ á áŁá á áá áá, ááá áá á¨áĽáą á°ááłá ááá á EPERM áľá á°áľ ááááŚá˝ áĽáá°áłááą áŤáłáŤá - áĽá áŤááááá á°ááłáłá áá. áá áááľ ááŽááŤá ááá ááá á áŤááŁá ááááŤáąá á¨á áá áľáááľ áĽáŞá ááľá¨áľ á áá˝áá.
[pid 25099] write(2, "ls: ", 4) = -1 EPERM (Operation not permitted)
[pid 25099] write(2, "write error", 11) = -1 EPERM (Operation not permitted)
[pid 25099] write(2, "n", 1) = -1 EPERM (Operation not permitted)
á áá Seccomp BPF áĽáá´áľ áĽáá°áá°áŤ á°á¨áľá°áá áĽá á áĽáą áá ááľá¨á áĽáá°áá˝á áĽáŠ ááłáĽ á áááľ. áá áá áááá ááá áá á¨cBPF ááá á eBPF á°ááłáłá ááá ááłáŤáľ á ááááá?
áľá á˘á˘áá¤á ááŽááŤáá˝ á˛áŤáľáĄáŁ áĽá á°áá˝ á ááá á˝áá á á áľá°áłáłáŞ áአááĽáśá˝ áĽáá°áŤá áŤáľáŁáᢠáá ááá፠á á á ááá áĽáááľ á˘áááᣠá¨ááá á¨á˘á˘áá¤á áĽááá˝á á á°ááŤáŠ á°á¨ááá˝ ááá á á á¨á°ááŤáŠ áá´áá˝á áá áááᢠáĽááá áá´áá˝ BPF LSM ááĽááśá˝ ááŁáá.
BPF LSM ááĽááśá˝
á¨áĽáááľ ááľá°áśá˝á á¨áĽá-ááá-áááá°á ááľáľá ááá á¨áĽáŁ LSM ááĽááśá˝á á˝áá°-ááłáĽ á°ááŁáŤá áŤá°áááᢠááá á áĽáŞ á á´áááŤá á¨áľáááľ áĽáŞ áá áááłá°áááŁááá áá áľáááą áŤáąá á¨áťá áĽá á¨áá á¨á° áááľ áá á¨á°ááá° ááᢠLSM á¨á áĽáľáľáŤáá˝á ááĽááĽá á á°ááŤáŠ á ááá´áá¸á áá áŤá á¨áľáááľ áĽáŞáá˝ áá á˛ááá á¨ááŤááĽá á˝ááŽá˝á áááľáááľ á¨áá¨áłá áľ á á˛áľ á áá°-ááłáĽ áá°áŁáá˘
áá á˝áá á ááťáá áľ áá á¨ááá ᨠBPF ááŽááŤáá˝ áá á¨á°ááŤá á°áŁáľ ááá ááá˝ á ááľáŁ áĽá SELinux áĽááąá á¨áá°áá á¨á á áĽáŽááἠLSM áĽáť ááá˘
á¨ááĽááśáš ááá áŽáľ á ááá ááľáĽ áŁáá á¨á¨ááá áá ááľáĽ áááá/linux/security.h:
extern int security_bpf(int cmd, union bpf_attr *attr, unsigned int size);
extern int security_bpf_map(struct bpf_map *map, fmode_t fmode);
extern int security_bpf_prog(struct bpf_prog *prog);
extern int security_bpf_map_alloc(struct bpf_map *map);
extern void security_bpf_map_free(struct bpf_map *map);
extern int security_bpf_prog_alloc(struct bpf_prog_aux *aux);
extern void security_bpf_prog_free(struct bpf_prog_aux *aux);
áĽáŤááłááłá¸á á á°ááŤáŠ á¨á áááá á°á¨ááá˝ áá áŤá-
- security_bpf - á¨á°áá¸á BPF á¨áľáááľ áĽáŞáá˝á á¨ááááŞáŤ áá°áť áŤá¨áááá;
-security_bpf_map - á¨ááá ááŤááłá á¨ááá ááá á˛áááľ áááľáťá;
-security_bpf_prog - á¨ááá áá˘á˘á¤áá¤á ááŽááŤá á¨ááá ááá á˛áááľ áááľáťá;
â security_bpf_map_alloc â á BPF áŤááłáá˝ ááľáĽ áŤáá á¨á°á áááľ ááľá ááááŠá áŤá¨áááŁáá˘
- security_bpf_map_free - á¨á°á áááľ ááľáŠ á BPF áŤááłáá˝ ááľáĽ áá¸áłáąá áŤá¨áááŁáá˘
â security_bpf_prog_alloc â á¨á°á áááľ ááľáŠ á BPF ááŽááŤáá˝ ááľáĽ ááááŠá áŤá¨áááŁáá˘
-security_bpf_prog_free - á¨á°á áááľ ááľáŠ á BPF ááŽááŤáá˝ ááľáĽ áá¸áłáąá áŤá¨áááŁáá˘
á áá ᣠáá áá áá áľáá ᣠáĽá áĽáá¨áłáá-ᨠLSM BPF interceptors á áľá°ááᣠáŤáá ááłáĽ ááĽáŤááłááą eBPF ááá áĽá á áá°áĄ áĽáá°áá˝á áá ᣠáá á á°áᢠááĽáśá˝ áŤáá¸á áĽáť á áŤááśá˝ áĽá ááŽááŤáá˝ áá áľáŤáá˝á áá¨ááá áĽáá°áá˝á áŤá¨áááŁáá˘
áá áááŤ
á°á áááľ ááá á á ááááá˝ááľ ááá áá á á ááľ áá á-á¨ááľáá-áááá ááááľ á°ááŁáŤá ááľá¨á á¨ááľá˝ááľ ááá á áá°ááᢠáľáááśá˝á á á°ááŤáŠ á°á¨ááá˝ áĽá á á°ááŤáŠ ááááśá˝ áá¨áá¨á ááťá á áľááá áá. áĽáłááá áŁáłááá á¨áľáá áąá á°á áááľ ááá á á á¨áá áá ááááľ á¨á°ááŤáŠ á¨áĽá á á°á¨ááá˝á á¨á°ááŤá¨ áŚáł áá°áŤááľ áľááá á¨á ááľ á°á¨á á°á áááľá ááááľ á á ááá áľáááąá ááááľ á ááá áľáᢠááááš ááá˘áá˝ á¨á°ááŤáŠ á¨ááĽááĽáŽá˝ áĽá á¨ááłá°áť ááĽáŚá˝á áľáĽáľáĽ á ááľá áľ áĽáŠ áľáŤ á°áá°ááᢠááĽááĽáŽá˝ áá áĽáá°áá áĽá á¨áĽááą áá áááľáŤáľ BPF ááŽááŤáá˝á áĽáá´áľ áĽáá°áá áá áĽáŠ áááᤠáĽáá°á°á áááľ á°áľá áĽáá°ááááá˘
áľá á°áŤá˛áŤá
á´áŞáľ áŤááŹáŤ á Netlify áá CTO ááᢠá áśá¨á áľáá ááľáĽ á°ááˇá áĽá á Runc, Go áĽá BCC ááłáŞáŤáá˝ áĽá áááá˝ áááľ ááá ááŽáááśá˝ áĽáľááľ á áľá°áá˝áŚ á áľááá. á Docker ááŽáááśá˝ áĽá á Docker áááá áľá-áá áłá áááľ áá á áá°áŤá áľáŤ ááłáááᢠá´áŞáľ áľá áá ááŁá ááŤáá˝ á áŁá áááłá áĽá áááá á ááťá¸áá ááááťá¸áľ áááááá˘
ááŹáá áááłá á Sysdig áááľ ááá áĄáľá áá áá°áŤáᣠáĽáą á áááááľ áŤá°áŽá¨á ááᎠáá ááᣠá¨ááááľ á¤á°á áŽáááá˛áá áááá´á˝á ááŽáááľ áŽáá´ááá Runtime á°á áááľá áĽá áŤáá°ááá° ááááŤá á á¨ááá ááá áĽá eBPFᢠáĽáą áá°á¨ááá áľáááśá˝áŁ ááśááľáá á¨á°ááḠá ááłá¨ áá¨áĽáŁ á¨ááááľ á¨ááá áĽá á¨á ááťá¸á áľáá°á á áŁá áááłáá˘
Âť áľá áá˝áá á°á¨á᪠áá¨á áĽáŁááá áááĽá
Âť
Âť
á Khabrozhiteli á áŠáá áá 25% á áá˝ - ááááľ
á¨áá˝ááá á¨áá¨ááľ áľáŞáľ á˛á¨áá, á˘-áá˝áá áá° á˘áá áááŤá.
ááá: hab.com