mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 03:25:11 +01:00 
			
		
		
		
	Fix #5226 by adding CSRF checking to api reqToken and add CSRF to the POST header for deadline (#5250)
* Add CSRF checking to reqToken and place CSRF in the post for deadline creation Fixes #5226, #5249 * /api/v1/admin/users routes should have reqToken middleware
This commit is contained in:
		
							parent
							
								
									57a8440db3
								
							
						
					
					
						commit
						7096085f2b
					
				| @ -39,8 +39,8 @@ func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) { | |||||||
| 		OwnerID:     keyOwner.ID, | 		OwnerID:     keyOwner.ID, | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token="+token, | 	req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token=%s", | ||||||
| 		keyOwner.Name, newPublicKey.ID) | 		keyOwner.Name, newPublicKey.ID, token) | ||||||
| 	session.MakeRequest(t, req, http.StatusNoContent) | 	session.MakeRequest(t, req, http.StatusNoContent) | ||||||
| 	models.AssertNotExistsBean(t, &models.PublicKey{ID: newPublicKey.ID}) | 	models.AssertNotExistsBean(t, &models.PublicKey{ID: newPublicKey.ID}) | ||||||
| } | } | ||||||
| @ -51,7 +51,7 @@ func TestAPIAdminDeleteMissingSSHKey(t *testing.T) { | |||||||
| 	session := loginUser(t, "user1") | 	session := loginUser(t, "user1") | ||||||
| 
 | 
 | ||||||
| 	token := getTokenForLoggedInUser(t, session) | 	token := getTokenForLoggedInUser(t, session) | ||||||
| 	req := NewRequestf(t, "DELETE", "/api/v1/admin/users/user1/keys/%d?token="+token, models.NonexistentID) | 	req := NewRequestf(t, "DELETE", "/api/v1/admin/users/user1/keys/%d?token=%s", models.NonexistentID, token) | ||||||
| 	session.MakeRequest(t, req, http.StatusNotFound) | 	session.MakeRequest(t, req, http.StatusNotFound) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -73,8 +73,8 @@ func TestAPIAdminDeleteUnauthorizedKey(t *testing.T) { | |||||||
| 
 | 
 | ||||||
| 	session = loginUser(t, normalUsername) | 	session = loginUser(t, normalUsername) | ||||||
| 	token = getTokenForLoggedInUser(t, session) | 	token = getTokenForLoggedInUser(t, session) | ||||||
| 	req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token="+token, | 	req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token=%s", | ||||||
| 		adminUsername, newPublicKey.ID) | 		adminUsername, newPublicKey.ID, token) | ||||||
| 	session.MakeRequest(t, req, http.StatusForbidden) | 	session.MakeRequest(t, req, http.StatusForbidden) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -143,7 +143,8 @@ func TestGit(t *testing.T) { | |||||||
| 
 | 
 | ||||||
| 			session := loginUser(t, "user1") | 			session := loginUser(t, "user1") | ||||||
| 			keyOwner := models.AssertExistsAndLoadBean(t, &models.User{Name: "user2"}).(*models.User) | 			keyOwner := models.AssertExistsAndLoadBean(t, &models.User{Name: "user2"}).(*models.User) | ||||||
| 			urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys", keyOwner.Name) | 			token := getTokenForLoggedInUser(t, session) | ||||||
|  | 			urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys?token=%s", keyOwner.Name, token) | ||||||
| 
 | 
 | ||||||
| 			dataPubKey, err := ioutil.ReadFile(keyFile + ".pub") | 			dataPubKey, err := ioutil.ReadFile(keyFile + ".pub") | ||||||
| 			assert.NoError(t, err) | 			assert.NoError(t, err) | ||||||
|  | |||||||
| @ -8,6 +8,8 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/go-macaron/csrf" | ||||||
|  | 
 | ||||||
| 	"code.gitea.io/git" | 	"code.gitea.io/git" | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/base" | 	"code.gitea.io/gitea/modules/base" | ||||||
| @ -97,6 +99,17 @@ func (ctx *APIContext) SetLinkHeader(total, pageSize int) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // RequireCSRF requires a validated a CSRF token | ||||||
|  | func (ctx *APIContext) RequireCSRF() { | ||||||
|  | 	headerToken := ctx.Req.Header.Get(ctx.csrf.GetHeaderName()) | ||||||
|  | 	formValueToken := ctx.Req.FormValue(ctx.csrf.GetFormName()) | ||||||
|  | 	if len(headerToken) > 0 || len(formValueToken) > 0 { | ||||||
|  | 		csrf.Validate(ctx.Context.Context, ctx.csrf) | ||||||
|  | 	} else { | ||||||
|  | 		ctx.Context.Error(401) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // APIContexter returns apicontext as macaron middleware | // APIContexter returns apicontext as macaron middleware | ||||||
| func APIContexter() macaron.Handler { | func APIContexter() macaron.Handler { | ||||||
| 	return func(c *Context) { | 	return func(c *Context) { | ||||||
|  | |||||||
| @ -2595,6 +2595,10 @@ function updateDeadline(deadlineString) { | |||||||
|         data: JSON.stringify({ |         data: JSON.stringify({ | ||||||
|             'due_date': realDeadline, |             'due_date': realDeadline, | ||||||
|         }), |         }), | ||||||
|  |         headers: { | ||||||
|  |             'X-Csrf-Token': csrf, | ||||||
|  |             'X-Remote': true, | ||||||
|  |         }, | ||||||
|         contentType: 'application/json', |         contentType: 'application/json', | ||||||
|         type: 'POST', |         type: 'POST', | ||||||
|         success: function () { |         success: function () { | ||||||
|  | |||||||
| @ -174,11 +174,15 @@ func repoAssignment() macaron.Handler { | |||||||
| 
 | 
 | ||||||
| // Contexter middleware already checks token for user sign in process. | // Contexter middleware already checks token for user sign in process. | ||||||
| func reqToken() macaron.Handler { | func reqToken() macaron.Handler { | ||||||
| 	return func(ctx *context.Context) { | 	return func(ctx *context.APIContext) { | ||||||
| 		if true != ctx.Data["IsApiToken"] { | 		if true == ctx.Data["IsApiToken"] { | ||||||
| 			ctx.Error(401) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  | 		if ctx.IsSigned { | ||||||
|  | 			ctx.RequireCSRF() | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		ctx.Context.Error(401) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -635,7 +639,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||||
| 					m.Post("/repos", bind(api.CreateRepoOption{}), admin.CreateRepo) | 					m.Post("/repos", bind(api.CreateRepoOption{}), admin.CreateRepo) | ||||||
| 				}) | 				}) | ||||||
| 			}) | 			}) | ||||||
| 		}, reqAdmin()) | 		}, reqToken(), reqAdmin()) | ||||||
| 
 | 
 | ||||||
| 		m.Group("/topics", func() { | 		m.Group("/topics", func() { | ||||||
| 			m.Get("/search", repo.TopicSearch) | 			m.Get("/search", repo.TopicSearch) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user