You can use a recursive cte, but I guess you will have to break the cyclicity. Following a rough approach to it - on first glance it looked as expected, but you will have to modify it e.g. if you want to pivot the friends per group or whatever:
DECLARE @t TABLE(ID int, FriendID int)
INSERT INTO @t VALUES (1,2), (2,1), (1,3), (2,3), (4,5), (5,4)
;WITH cteDist AS(
SELECT DISTINCT CASE WHEN ID > FriendID THEN FriendID ELSE ID END AS ID, CASE WHEN ID > FriendID THEN ID ELSE FriendID END AS FriendID
FROM @t
),
cteTop AS(
SELECT DISTINCT i.ID
FROM cteDist i
LEFT JOIN cteDist f ON f.FriendID = i.ID
WHERE f.ID IS NULL
),
cteGroups AS(
SELECT ID, ID AS FriendID
FROM cteTop
UNION ALL
SELECT c.ID, f.FriendID
FROM cteGroups c
INNER JOIN cteDist f ON f.ID = c.FriendID
)
SELECT DISTINCT ID, FriendID
FROM cteGroups
ORDER BY 1, 2
OPTION (MAXRECURSION 0)